web-dev-qa-db-ja.com

2つ以上の.WAVファイルをプログラムで結合するにはどうすればよいですか?

2つ以上の.wavファイルを1つの.wavファイルに結合する機能が必要です。これは、C#を使用してプログラムで行う必要があります(サードパーティ製品はオプションではありません)。 System.Media.SoundPlayerクラスを知っていますが、.wavを再生するのではなく、作成するだけです。

18
gangelo

NAudio を使用して構築された基本的なWAV連結関数を次に示します。これにより、データチャンクのみが連結されるようになります( このCodeProjectの記事 別の回答でリンクされているコード例とは異なります)。また、同じ形式を共有しない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();
        }
    }

}
28
Mark Heath

このcodeprojectの例を確認してください。これは、その方法についての適切な説明とともに、まさに必要なもののようです。

C#2005を使用したWaveファイルの連結

これは基本的に、すべてのwavファイルからサウンドデータを抽出して1つのチャンクにマージし、その上に新しいファイルヘッダーを追加することで構成されているようです。

編集:私はこれを使用した経験がなく、専門家でもありません。私はちょうどこの記事に出くわし、それが役に立つかもしれないと思いました。より良い解決策については、MarkHeathの回答を参照してください

1
Iain Ward

使用元 。Wavファイルを結合する方法

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

マークの答えに対する1つのコメント:

==演算子は、ウェーブ形式を比較するときに機能しないようです。これを行う方が安全です:

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

または、リーダーをWaveFormatConversionStreamでラップして、フォーマットチェックを完全に取り除くこともできます(すべてのシナリオで機能するかどうかはわかりませんが、テストに成功しました)。

1

バイト配列のみを取得する必要がある場合は、データベースまたは他の誰かに挿入します。メモリストリームを使用できます。

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