代码之家  ›  专栏  ›  技术社区  ›  mr_blond

如何将两个wave文件合并为.NET核心中的一个?

  •  1
  • mr_blond  · 技术社区  · 7 年前

    我需要在.NET核心中合并两个wave文件。所以我选择opentk作为openal的包装。

    我尝试合并两个wave文件,每个样本的比特数和sapmle速率相同。

    1)为了做到这一点,我得到了这个 example

    2)生成2字节区域:

    var sound_data1 = LoadWave(path1, FileMode.Open), out channels, out bits_per_sample, out sample_rate);
    
    var sound_data2 = LoadWave(path2, FileMode.Open), out channels, out bits_per_sample, out sample_rate);
    

    3)对每个字节求和,然后除以2。

    for (int i = 0; i < sound_data1; i++)
    {
    result_sound_data[i] = (byte)((sound_data1[i] + sound_data2[i]) / 2);
    }
    

    4)然后:

    AL.BufferData(buffer, GetSoundFormat(channels, bits_per_sample), result_sound_data, result_sound_data.Length, sample_rate);
    
    AL.Source(source, ALSourcei.Buffer, buffer);
    AL.SourcePlay(source);
    

    最后我得到了一些损坏的声音,而不是混合信号。我该如何解决?

    1 回复  |  直到 7 年前
        1
  •  1
  •   jeroenh    7 年前

    显然,合并音频流基本上是在每个输入音频文件中提取相应样本的总和。您可以研究的源代码 this sample on codeproject . 这段代码可能不是最干净的,但似乎可以完成这项工作(我测试过)。

    除了处理wav文件头之外,输入文件数组的实际合并逻辑如下所述:

    // 8. Do the merging..
    // The basic algorithm for doing the merging is as follows:
    // while there is at least 1 sample remaining in any of the source files
    //    sample = 0
    //    for each source file
    //       if the source file has any samples remaining
    //          sample = sample + next available sample from the source file
    //    sample = sample / # of source files
    //    write the sample to the output file
    

    这在该代码示例中实现,如下所示,适用于8位示例:

    while (SamplesRemain(scaledAudioFiles))
    {
        byte sample = 0;
        for (var i = 0; i < scaledAudioFiles.GetLength(0); ++i)
        {
            if (scaledAudioFiles[i].NumSamplesRemaining > 0)
            {
                sample += scaledAudioFiles[i].GetNextSample_8bit();
            }
        }
        sample /= (byte)(scaledAudioFiles.GetLength(0));
        outputFile.AddSample_8bit(sample);
    }
    

    该示例中的代码与.NET核心完全兼容。

    如果您只想获取该代码并合并一些.wav文件,下面将介绍如何执行此操作(仍然使用有问题的示例):

        private static void Main(string[] args) => WAVFile.MergeAudioFiles(
                new[] { "file1.wav", "file2.wav", "file3.wav" },
                "result.wav",
                Path.GetTempPath()
            );