5

我正在尝试将 WAV 文件(PCM、48kHz、4 通道、16 位)转换为单通道 WAV 文件。

我尝试像这个答案一样将 WAV 文件拆分为 4 个字节数组,并创建了一个 WaveMemoryStream ,如下所示,但不起作用。

byte[] chan1ByteArray = new byte[channel1Buffer.Length];
Buffer.BlockCopy(channel1Buffer, 0, chan1ByteArray, 0, chan1ByteArray.Length);
WaveMemoryStream chan1 = new WaveMemoryStream(chan1ByteArray, sampleRate, (ushort)bitsPerSample, 1);

我在创建 WAVE 标头时遗漏了什么吗?还是有更多将 WAV 拆分为单声道 WAV 文件的方法?

4

3 回答 3

6

基本思想是源波形文件包含交错的样本。一个用于第一个通道,一个用于第二个通道,依此类推。这是一些未经测试的示例代码,可让您了解如何执行此操作。

var reader = new WaveFileReader("fourchannel.wav");
var buffer = new byte[2 * reader.WaveFormat.SampleRate * reader.WaveFormat.Channels];
var writers = new WaveFileWriter[reader.WaveFormat.Channels];
for (int n = 0; n < writers.Length; n++) 
{
    var format = new WaveFormat(reader.WaveFormat.SampleRate,16,1);
    writers[n] = new WaveFileWriter(String.Format("channel{0}.wav",n+1), format);
}
int bytesRead;
while((bytesRead = reader.Read(buffer,0, buffer.Length)) > 0) 
{
    int offset=  0;
    while (offset < bytesRead) 
    {
        for (int n = 0; n < writers.Length; n++) 
        {
            // write one sample
            writers[n].Write(buffer,offset,2);
            offset += 2;
        }           
    }
}
for (int n = 0; n < writers.Length; n++) 
{
    writers[n].Dispose();
}
reader.Dispose();
于 2012-08-27T21:11:32.037 回答
2

根据 Mark Heath 的回答,我在一个包含 32 个通道的 32 位浮动 WAV 上苦苦挣扎,并通过简化他的建议来设法让它工作。我猜这个和平代码也适用于四声道音频 WAV 文件。

    var reader = new WaveFileReader("thirtytwochannels.wav");
    var writers = new WaveFileWriter[reader.WaveFormat.Channels];
    for (int n = 0; n < writers.Length; n++)
    {
        var format = new WaveFormat(reader.WaveFormat.SampleRate, 16, 1);
        writers[n] = new WaveFileWriter(string.Format($"channel{n + 1}.wav"), format);
    }

    float[] buffer;
    while ((buffer = reader.ReadNextSampleFrame())?.Length > 0)
    {
        for(int i = 0; i < buffer.Length; i++)
        {
            // write one sample for each channel (i is the channelNumber)
            writers[i].WriteSample(buffer[i]);
        }
    }

    for (int n = 0; n < writers.Length; n++)
    {
        writers[n].Dispose();
    }
    reader.Dispose();
于 2019-12-04T14:23:05.370 回答
1

这是我使用的一种方法,可以设置输出单声道格式,例如BitsPerSample、SampleRate

using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace DataScraper.TranscriptionCenter
{
    public class MP3ToWave
    {
        /// <summary>
        /// Converts an MP3 file to distinct wav files, using NAudio
        /// They are saved in the same directory as the MP3 file
        /// </summary>
        /// <param name="MP3FileIn">The MP3 file</param>
        /// <returns>Returns the WAV files</returns>
        public static string[] MP3FilesToTranscriptionWaveFiles(string MP3FileIn)
        {
            FileInfo MP3FileInfo = new FileInfo(MP3FileIn);
            if (MP3FileInfo.Exists == false)
                throw new Exception("File does not exist? " + MP3FileIn);
            Mp3FileReader readerMP3 = null;
            WaveStream PCMStream = null;
            WaveFileReader readerWAV = null;
            List<string> ListFilesOut = null;
            WaveFileWriter[] FileWriters = null;
            MemoryStream TempStream = null;
            WaveFormatConversionStream WaveFormatConversionStream_ = null;
            WaveFormat SaveWaveFormatMono = new WaveFormat((16 * 1000), 
                    16, 
                    1);
            try
            {
                readerMP3 = new Mp3FileReader(MP3FileInfo.FullName);
                PCMStream = WaveFormatConversionStream.CreatePcmStream(readerMP3);
                WaveFormatConversionStream_ = new WaveFormatConversionStream(new     WaveFormat(SaveWaveFormatMono.SampleRate, 
                    SaveWaveFormatMono.BitsPerSample, 
                    PCMStream.WaveFormat.Channels),
                    PCMStream);
            
                //Each filepath, each channel
                ListFilesOut = new List<string>    (WaveFormatConversionStream_.WaveFormat.Channels);
            

                //Each is a wav file out
                for (int index = 0; index <     WaveFormatConversionStream_.WaveFormat.Channels; index++)
            {
                ListFilesOut.Add(MP3FileInfo.Directory.FullName + "\\" + Path.GetFileNameWithoutExtension(MP3FileInfo.Name) + "_" + index.ToString() + ".wav");
            }

            //Initialize the writers
            FileWriters = new WaveFileWriter[WaveFormatConversionStream_.WaveFormat.Channels];
            for (int index = 0; index < WaveFormatConversionStream_.WaveFormat.Channels; index++)
            {
                FileWriters[index] = new WaveFileWriter(ListFilesOut[index], SaveWaveFormatMono);
            }


            TempStream = new MemoryStream(int.Parse("" + WaveFormatConversionStream_.Length));
            WaveFileWriter NewWriter = new WaveFileWriter(TempStream, WaveFormatConversionStream_.WaveFormat);
            byte[] BUFFER = new byte[1024];
            int ReadLength = WaveFormatConversionStream_.Read(BUFFER, 0, BUFFER.Length);
            while (ReadLength != -1 && ReadLength > 0)
            {
                NewWriter.Write(BUFFER, 0, ReadLength);
                ReadLength = WaveFormatConversionStream_.Read(BUFFER, 0, BUFFER.Length);
            }
            NewWriter.Flush();
            
            

            TempStream.Position = 0;
            readerWAV = new WaveFileReader(TempStream);
            
            float[] buffer = readerWAV.ReadNextSampleFrame();
            
            while(buffer != null && buffer.Length > 0)
            {
                for(int i = 0; i < buffer.Length; i++)
                {
                    FileWriters[i].WriteSample(buffer[i]);
                }
                buffer = readerWAV.ReadNextSampleFrame();
            }
        }
        catch (Exception em1)
        {
            throw em1;
        }
        finally
        {

            
            try
            {
                //Flush each writer and close
                for (int writercount = 0; writercount < FileWriters.Length; writercount++)
                {
                    FileWriters[writercount].Flush();
                    FileWriters[writercount].Close();
                    FileWriters[writercount].Dispose();
                }
            }
            catch
            {

            }

            try { readerWAV.Dispose(); readerWAV = null; }
            catch { }

            try { WaveFormatConversionStream_.Dispose(); WaveFormatConversionStream_ = null; }
            catch { }

            try { PCMStream.Dispose(); PCMStream = null; }
            catch { }

            try { readerMP3.Dispose(); readerMP3 = null; }
            catch { }

            try
            {
                TempStream.Close(); TempStream.Dispose();
            }
            catch
            {

            }
        }
            return ListFilesOut.ToArray();
        }
    }
}
于 2021-02-01T19:46:31.587 回答