EDIT
With SOX:
string sox = @"C:\Program Files (x86)\sox-14-4-1\sox.exe";
string inputFile = @"D:\Brothers Vibe - Rainforest.mp3";
string outputDirectory = @"D:\splittest";
string outputPrefix = "split";
int[] segments = { 10, 15, 30 };
IEnumerable<string> enumerable = segments.Select(s => "trim 0 " + s.ToString(CultureInfo.InvariantCulture));
string @join = string.Join(" : newfile : ", enumerable);
string cmdline = string.Format("\"{0}\" \"{1}%1n.wav" + "\" {2}", inputFile,
Path.Combine(outputDirectory, outputPrefix), @join);
var processStartInfo = new ProcessStartInfo(sox, cmdline);
Process start = System.Diagnostics.Process.Start(processStartInfo);
If SOX complains about libmad (for MP3) : copy DLLs next to it, see here
Alternatively you can use FFMPEG in the same manner :
ffmpeg -ss 0 -t 30 -i "Brothers Vibe - Rainforest.mp3" "Brothers Vibe - Rainforest.wav"
(see the docs for all the details)
You can do that easily with BASS.NET :
For the code below you pass in :
- input file name
- desired duration for each segment
- output directory
- prefix to use for each segment file
The method will check whether the file is long enough for the specified segments, if yes then it will cut the file to WAVs with the same sample rate, channels, bit depth.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Un4seen.Bass;
using Un4seen.Bass.Misc;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (!Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero))
throw new InvalidOperationException("Couldn't initialize BASS");
string fileName = @"D:\Brothers Vibe - Rainforest.mp3";
var segments = new double[] {30, 15, 20};
string[] splitAudio = SplitAudio(fileName, segments, "output", @"D:\split");
}
private static string[] SplitAudio(string fileName, double[] segments, string prefix, string outputDirectory)
{
if (fileName == null) throw new ArgumentNullException("fileName");
if (segments == null) throw new ArgumentNullException("segments");
if (prefix == null) throw new ArgumentNullException("prefix");
if (outputDirectory == null) throw new ArgumentNullException("outputDirectory");
int i = Bass.BASS_StreamCreateFile(fileName, 0, 0,
BASSFlag.BASS_STREAM_PRESCAN | BASSFlag.BASS_STREAM_DECODE);
if (i == 0)
throw new InvalidOperationException("Couldn't create stream");
double sum = segments.Sum();
long length = Bass.BASS_ChannelGetLength(i);
double seconds = Bass.BASS_ChannelBytes2Seconds(i, length);
if (sum > seconds)
throw new ArgumentOutOfRangeException("segments", "Required segments exceed file duration");
BASS_CHANNELINFO info = Bass.BASS_ChannelGetInfo(i);
if (!Directory.Exists(outputDirectory)) Directory.CreateDirectory(outputDirectory);
int index = 0;
var list = new List<string>();
foreach (double segment in segments)
{
double d = segment;
long seconds2Bytes = Bass.BASS_ChannelSeconds2Bytes(i, d);
var buffer = new byte[seconds2Bytes];
int getData = Bass.BASS_ChannelGetData(i, buffer, buffer.Length);
string name = string.Format("{0}_{1}.wav", prefix, index);
string combine = Path.Combine(outputDirectory, name);
int bitsPerSample = info.Is8bit ? 8 : info.Is32bit ? 32 : 16;
var waveWriter = new WaveWriter(combine, info.chans, info.freq, bitsPerSample, true);
waveWriter.WriteNoConvert(buffer, buffer.Length);
waveWriter.Close();
list.Add(combine);
index++;
}
bool free = Bass.BASS_StreamFree(i);
return list.ToArray();
}
}
}
TODO
The extraction is not optimized, if you are concerned with memory usage, then the function should be enhanced to grab parts of a segments and write them progressively to the WaveWriter
.
Notes
BASS.NET has a nag screen, but you can request for a free registration serial at their website.
Note, install BASS.NET then make sure to copy bass.dll from the base package next to your EXE. Also, you can use pretty much any audio formats, see their website for formats plugins and how to load them (BASS_PluginLoad).