【问题标题】:How to join 2 or more .WAV files together programmatically?如何以编程方式将 2 个或多个 .WAV 文件连接在一起?
【发布时间】:2011-10-10 06:40:42
【问题描述】:

我需要能够将 2 个或多个 .wav 文件合并为一个 .wav 文件。我必须使用 C# 以编程方式执行此操作(不能选择第 3 方产品)。我知道 System.Media.SoundPlayer 类,但我不想播放 .wav,而只是创建它。

【问题讨论】:

    标签: c# audio wav


    【解决方案1】:

    这是一个使用 NAudio 构建的基本 WAV 连接函数。这将确保仅连接数据块(与另一个答案中链接的this CodeProject article 中的代码示例不同)。它还可以保护您免受连接不同格式的 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();
            }
        }
    
    }
    

    【讨论】:

    • 好样本...我确认 wavformat 比较没有按预期工作,正如 davidair 所指出的那样。
    • 在将 nuget Naaudio 添加到项目中并使用上述功能合并一个构建错误之后。 “无法解析来自“System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”的“System.Runtime.InteropServices.StandardOleMarshalObject”引用。为什么会这样?
    • 为什么不把这个添加到库中??
    【解决方案2】:

    对马克回答的评论:

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

    if (!reader.WaveFormat.Equals(waveFileWriter.WaveFormat))
    

    或者,您可以将阅读器包装在 WaveFormatConversionStream 中并完全摆脱格式检查(不确定它是否适用于所有场景,但我能够成功测试它)。

    【讨论】:

      【解决方案3】:

      查看这个 codeproject 示例,它似乎正是您所需要的,并很好地解释了如何做到这一点:

      Concatenating Wave Files Using C# 2005

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

      编辑:我没有使用它的经验,也不是专家。我刚刚看到这篇文章,并认为它可能有用。请参阅 Mark Heath 的答案以获得更好的解决方案

      【讨论】:

      • ty,看起来像我要找的东西。
      • 我建议不要使用本文中的代码。它假定 fmt 块总是完全相同的长度,并且数据块在所有 WAV 文件中出现在完全相同的位置。它假定不存在其他块。对于 WAV 文件,这些都不是理所当然的,因此很容易创建垃圾 WAV 文件。
      • @MarkHeath 我遇到了完全相同的问题,它创建了一个合并但不受支持的 wav 文件,但它适用于 android,不适用于 ios。任何有其他想法的人都可以提出建议。提前致谢。
      【解决方案4】:

      How to join .Wav files together使用

          private void JoinWav()
          {
              string[] files = new string[] { "1990764-ENG-CONSEC-RESPONSE7.WAV","1990764-ND_A.WAV", "1990764-SIGHT-SP.WAV",
                  "1990764-SP-CONSEC-RESPONSE6.WAV","1990764-VOCABWORD-004-12-SP.WAV","bi-consec-1-successful.wav",
                  "bi-transition-instruct.wav","nd_B.wav","sightreceived_B.wav","teststamp_A.wav" };
              AudioCompressionManager.Join("res.wav", files);
          }
      

      【讨论】:

      • 什么是 AudioCompressionManager ?
      • 它的核心是什么?
      【解决方案5】:

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

              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);
              }
          }
      

      【讨论】:

        猜你喜欢
        • 2015-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多