C# 如何以编程方式将2个或多个.WAV文件连接在一起?

C# 如何以编程方式将2个或多个.WAV文件连接在一起?,c#,audio,wav,C#,Audio,Wav,我需要能够将2个或多个.wav文件合并到一个.wav文件中。我必须使用C#(第三方产品不是选项)以编程方式完成这项工作。我知道System.Media.SoundPlayer类,但我不想播放.wav,而只是想创建它。看看这个codeproject示例,它似乎正是您需要的,并提供了一个很好的解释,说明了如何操作: 它似乎主要包括从所有wav文件中提取声音数据并将其合并为一个数据块,并在顶部添加一个新的文件头 编辑:我没有使用此功能的经验,也不是专家。我刚看到这篇文章,觉得它可能有用。有关更好的解

我需要能够将2个或多个.wav文件合并到一个.wav文件中。我必须使用C#(第三方产品不是选项)以编程方式完成这项工作。我知道System.Media.SoundPlayer类,但我不想播放.wav,而只是想创建它。

看看这个codeproject示例,它似乎正是您需要的,并提供了一个很好的解释,说明了如何操作:

它似乎主要包括从所有wav文件中提取声音数据并将其合并为一个数据块,并在顶部添加一个新的文件头


编辑:我没有使用此功能的经验,也不是专家。我刚看到这篇文章,觉得它可能有用。有关更好的解决方案,请参见Mark Heath的答案

这里有一个使用创建的基本WAV连接函数。这将确保仅连接数据块(与另一个答案中链接的代码示例不同)。它还可以防止连接不共享相同格式的WAV文件

public static void Concatenate(string outputFile, IEnumerable<string> sourceFiles)
{
    byte[] buffer = new byte[1024];
    WaveFileWriter waveFileWriter = null;

    try
    {
        foreach (string sourceFile in sourceFiles)
        {
            using (WaveFileReader reader = new WaveFileReader(sourceFile))
            {
                if (waveFileWriter == null)
                {
                    // first time in create new Writer
                    waveFileWriter = new WaveFileWriter(outputFile, reader.WaveFormat);
                }
                else
                {
                    if (!reader.WaveFormat.Equals(waveFileWriter.WaveFormat))
                    {
                        throw new InvalidOperationException("Can't concatenate WAV Files that don't share the same format");
                    }
                }

                int read;
                while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
                {
                    waveFileWriter.WriteData(buffer, 0, read);
                }
            }
        }
    }
    finally
    {
        if (waveFileWriter != null)
        {
            waveFileWriter.Dispose();
        }
    }

}
publicstaticvoidconcatenate(字符串输出文件、IEnumerable源文件)
{
字节[]缓冲区=新字节[1024];
WaveFileWriter WaveFileWriter=null;
尝试
{
foreach(sourceFiles中的字符串sourceFile)
{
使用(WaveFileReader=新的WaveFileReader(源文件))
{
如果(waveFileWriter==null)
{
//第一次在“创建新作家”中
waveFileWriter=新的waveFileWriter(输出文件,reader.WaveFormat);
}
其他的
{
如果(!reader.WaveFormat.Equals(waveilewriter.WaveFormat))
{
抛出新的InvalidOperationException(“无法连接不共享相同格式的WAV文件”);
}
}
int-read;
而((read=reader.read(buffer,0,buffer.Length))>0)
{
waveFileWriter.WriteData(缓冲区,0,读取);
}
}
}
}
最后
{
如果(waveFileWriter!=null)
{
waveFileWriter.Dispose();
}
}
}

对马克的回答有一点评论:

比较波形格式时,==运算符似乎不适用于我。这样做更安全:

if (!reader.WaveFormat.Equals(waveFileWriter.WaveFormat))
或者,您可以将读卡器包装在波形转换流中,并完全取消格式检查(不确定它是否适用于所有场景,但我能够成功地测试它)。


若您只需要获取字节数组,则可以将其插入数据库或其他人。您可以使用内存流:

        public static byte[] Concatenate(IEnumerable<byte[]> sourceData)
    {
        var buffer = new byte[1024 * 4];
        WaveFileWriter waveFileWriter = null;

        using (var output = new MemoryStream())
        {
            try
            {
                foreach (var binaryData in sourceData)
                {
                    using (var audioStream = new MemoryStream(binaryData))
                    {
                        using (WaveFileReader reader = new WaveFileReader(audioStream))
                        {
                            if (waveFileWriter == null)
                                waveFileWriter = new WaveFileWriter(output, reader.WaveFormat);
                            else
                                AssertWaveFormat(reader, waveFileWriter);

                            WaveStreamWrite(reader, waveFileWriter, buffer);
                        }
                    }
                }

                waveFileWriter.Flush();

                return output.ToArray();
            }
            finally
            {
                waveFileWriter?.Dispose();
            }
        }
    }

    private static void AssertWaveFormat(WaveFileReader reader, WaveFileWriter writer)
    {
        if (!reader.WaveFormat.Equals(writer.WaveFormat))
        {
            throw new InvalidOperationException("Can't concatenate WAV Files that don't share the same format");
        }
    }

    private static void WaveStreamWrite(WaveFileReader reader, WaveFileWriter writer, byte[] buffer)
    {
        int read;
        while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
        {
            writer.Write(buffer, 0, read);
        }
    }
公共静态字节[]串联(IEnumerable sourceData)
{
var buffer=新字节[1024*4];
WaveFileWriter WaveFileWriter=null;
使用(var output=newmemoryStream())
{
尝试
{
foreach(sourceData中的var binaryData)
{
使用(var audioStream=newmemoryStream(二进制数据))
{
使用(WaveileReader=新的WaveileReader(音频流))
{
如果(waveFileWriter==null)
waveFileWriter=新的waveFileWriter(输出、读卡器、波形格式);
其他的
AssertWaveFormat(读卡器、波形编写器);
WaveStreamWrite(读卡器、waveFileWriter、缓冲器);
}
}
}
waveFileWriter.Flush();
返回输出.ToArray();
}
最后
{
waveFileWriter?.Dispose();
}
}
}
私有静态void资产waveformat(waveilereader读取器、waveilewriter writer)
{
如果(!reader.WaveFormat.Equals(writer.WaveFormat))
{
抛出新的InvalidOperationException(“无法连接不共享相同格式的WAV文件”);
}
}
专用静态无效WaveStreamWrite(WaveFileReader读取器、WaveFileWriter写入器、字节[]缓冲区)
{
int-read;
而((read=reader.read(buffer,0,buffer.Length))>0)
{
writer.Write(缓冲区,0,读取);
}
}

ty,看起来像我要找的。我建议不要使用本文中的代码。它假定fmt块始终具有完全相同的长度,并且数据块在所有WAV文件中显示在完全相同的位置。它假定不存在其他块。对于WAV文件,这些都不是理所当然的,因此它可以轻松创建一个垃圾WAV文件。@MarkHeath我也遇到了同样的问题,它创建了一个合并但不受支持的WAV文件,但它在android上工作,而不是在ios上。有其他想法的人可以提出建议吗。提前谢谢。样品很好。。。我确认wavformat比较没有按照预期工作,正如davidair所指出的。在将nuget Naudio添加到项目中并使用上述函数合并一个生成错误后。“未能解析”System.Runtime.InteropServices.StandardOleMarshallObject“引用自”System,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089“为什么会发生这种情况?为什么不将其添加到库中?什么是AudioCompressionManager?它的核心是什么?”?
        public static byte[] Concatenate(IEnumerable<byte[]> sourceData)
    {
        var buffer = new byte[1024 * 4];
        WaveFileWriter waveFileWriter = null;

        using (var output = new MemoryStream())
        {
            try
            {
                foreach (var binaryData in sourceData)
                {
                    using (var audioStream = new MemoryStream(binaryData))
                    {
                        using (WaveFileReader reader = new WaveFileReader(audioStream))
                        {
                            if (waveFileWriter == null)
                                waveFileWriter = new WaveFileWriter(output, reader.WaveFormat);
                            else
                                AssertWaveFormat(reader, waveFileWriter);

                            WaveStreamWrite(reader, waveFileWriter, buffer);
                        }
                    }
                }

                waveFileWriter.Flush();

                return output.ToArray();
            }
            finally
            {
                waveFileWriter?.Dispose();
            }
        }
    }

    private static void AssertWaveFormat(WaveFileReader reader, WaveFileWriter writer)
    {
        if (!reader.WaveFormat.Equals(writer.WaveFormat))
        {
            throw new InvalidOperationException("Can't concatenate WAV Files that don't share the same format");
        }
    }

    private static void WaveStreamWrite(WaveFileReader reader, WaveFileWriter writer, byte[] buffer)
    {
        int read;
        while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
        {
            writer.Write(buffer, 0, read);
        }
    }