/// <summary> /// Split multi-channel WAV file into single channel WAV files. /// </summary> /// <param name="fileName">Input WAV file name.</param> /// <param name="outputPath">Output WAV files path.</param> /// <param name="ct">Cancellation token.</param> /// <returns>The total processed bytes.</returns> public long SplitWavFile(string fileName, string outputPath, CancellationToken ct) { long countBytesTotal = 0; long countBytes = 0; var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); var header = WavFileInfo.ReadFileHeader(fs); Progress(0.0); countBytes += header.HeaderSize; countBytesTotal += header.HeaderSize; string fileNameOnly = Path.GetFileNameWithoutExtension(fileName); string[] outputFileNames = new string[header.NumChannels]; WavChannel[] channels = new WavChannel[header.NumChannels]; int countChannels = 0; if (header.IsExtensible == false) { for (int c = 0; c < header.NumChannels; c++) { string numnber = (c + 1).ToString("D2"); var ch = new WavChannel("Channel" + numnber, "CH" + numnber, 0); channels[c] = ch; } } else { foreach (WavChannel ch in WavFileHeader.WavMultiChannelTypes) { if (((uint)ch.Mask & header.ChannelMask) != 0) { channels[countChannels++] = ch; } } } for (int p = 0; p < channels.Count(); p++) { outputFileNames[p] = outputPath + fileNameOnly + "." + channels[p].ShortName + ".wav"; } long dataSize = header.Subchunk2Size; int bufferSize = (int)header.ByteRate; int channelBufferSize = (int)(header.ByteRate / header.NumChannels); byte[] buffer = new byte[bufferSize]; byte[][] channelBuffer = new byte[header.NumChannels][]; int copySize = header.BlockAlign / header.NumChannels; var outputFiles = new FileStream[header.NumChannels]; var mh = WavFileInfo.GetMonoWavFileHeader(header); for (int c = 0; c < header.NumChannels; c++) { channelBuffer[c] = new byte[channelBufferSize]; outputFiles[c] = new FileStream(outputFileNames[c], FileMode.Create, FileAccess.ReadWrite); WavFileInfo.WriteFileHeader(outputFiles[c], mh); } var cleanUp = new Action(() => { fs.Dispose(); for (int c = 0; c < header.NumChannels; c++) { outputFiles[c].Dispose(); } }); for (long i = 0; i < dataSize; i += bufferSize) { int n = fs.Read(buffer, 0, bufferSize); if (n > 0) { int[] count = new int[header.NumChannels]; for (int j = 0; j < n; j += header.BlockAlign) { for (int c = 0; c < header.NumChannels; c++) { for (int k = 0; k < copySize; k++) { channelBuffer[c][count[c]++] = buffer[j + (c * copySize) + k]; } } } for (int c = 0; c < header.NumChannels; c++) { outputFiles[c].Write(channelBuffer[c], 0, count[c]); } if (ct.IsCancellationRequested) { cleanUp(); ct.ThrowIfCancellationRequested(); } countBytes += n; countBytesTotal += n; Progress((countBytes / fs.Length) * 100.0); } } cleanUp(); return(countBytesTotal); }
/// <summary> /// Split multi-channel WAV file into single channel WAV files. /// </summary> /// <param name="fileName">Input WAV file name.</param> /// <param name="outputPath">Output WAV files path.</param> /// <param name="ct">Cancellation token.</param> /// <returns>The total processed bytes.</returns> public long SplitWavFile(string fileName, string outputPath, CancellationToken ct) { long countBytesTotal = 0; long countBytes = 0; var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); var header = WavFileInfo.ReadFileHeader(fs); Progress(0.0); countBytes += header.HeaderSize; countBytesTotal += header.HeaderSize; string fileNameOnly = Path.GetFileNameWithoutExtension(fileName); string[] outputFileNames = new string[header.NumChannels]; WavChannel[] channels = new WavChannel[header.NumChannels]; int countChannels = 0; if (header.IsExtensible == false) { for (int c = 0; c < header.NumChannels; c++) { string chNum = (c + 1).ToString("D2"); var ch = new WavChannel("Channel" + chNum, "CH" + chNum, 0); channels[c] = ch; } } else { foreach (WavChannel ch in WavFileHeader.WavMultiChannelTypes) { if (((uint)ch.Mask & header.ChannelMask) != 0) { channels[countChannels++] = ch; } } } for (int p = 0; p < channels.Count(); p++) { outputFileNames[p] = outputPath + fileNameOnly + "." + channels[p].ShortName + ".wav"; } long dataSize = header.Subchunk2Size; int bufferSize = (int)header.ByteRate; int channelBufferSize = (int)(header.ByteRate / header.NumChannels); byte[] buffer = new byte[bufferSize]; byte[][] channelBuffer = new byte[header.NumChannels][]; int copySize = header.BlockAlign / header.NumChannels; var outputFiles = new FileStream[header.NumChannels]; var mh = WavFileInfo.GetMonoWavFileHeader(header); for (int c = 0; c < header.NumChannels; c++) { channelBuffer[c] = new byte[channelBufferSize]; outputFiles[c] = new FileStream(outputFileNames[c], FileMode.Create, FileAccess.ReadWrite); WavFileInfo.WriteFileHeader(outputFiles[c], mh); } var cleanUp = new Action(() => { fs.Close(); fs.Dispose(); for (int c = 0; c < header.NumChannels; c++) { outputFiles[c].Close(); outputFiles[c].Dispose(); } }); for (long i = 0; i < dataSize; i += bufferSize) { int n = fs.Read(buffer, 0, bufferSize); if (n > 0) { int[] count = new int[header.NumChannels]; for (int j = 0; j < n; j += header.BlockAlign) { for (int c = 0; c < header.NumChannels; c++) { for (int k = 0; k < copySize; k++) { channelBuffer[c][count[c]++] = buffer[j + (c * copySize) + k]; } } } for (int c = 0; c < header.NumChannels; c++) { outputFiles[c].Write(channelBuffer[c], 0, count[c]); } if (ct.IsCancellationRequested) { cleanUp(); ct.ThrowIfCancellationRequested(); } countBytes += n; countBytesTotal += n; Progress((countBytes / fs.Length) * 100.0); } } cleanUp(); return countBytesTotal; }