NAudio, Mixing two raw audio streams into a .wav file

huangapple go评论71阅读模式
英文:

NAudio, Mixing two raw audio streams into a .wav file

问题

string path = string.Empty;
private void SaveAudioRecording()
{
    timer.Dispose();
    if (string.IsNullOrEmpty(path))
    {
        path = Directory.GetCurrentDirectory() + "\\AudioRecordings_" + clientSession.clientInfo[0];
        Directory.CreateDirectory(path);
    }

    WaveMixerStream32 mix = new WaveMixerStream32();
    foreach (var stream in new MemoryStream[] { audioOutputMemoryStream, audioInputMemoryStream })
    {
        stream.Position = 0;
        if (stream != null && stream.Length > 0 && stream.Position < stream.Length)
        {
            RawSourceWaveStream reader = new RawSourceWaveStream(stream, new WaveFormat(41100, 1));
            WaveChannel32 channel = new WaveChannel32(reader);
            mix.AddInputStream(channel);
        }
    }

    using (FileStream stream = File.Create(System.IO.Path.Combine(path, "Audio_recording_" + Directory.EnumerateFiles(path).Count().ToString() + ".wav"))
    {
        byte[] buffer = new byte[mix.Length];
        mix.Read(buffer, 0, buffer.Length);
        stream.Write(buffer, 0, buffer.Length);
        WriteWavHeader(stream, Convert.ToInt32(stream.Length));
        stream.Flush();
    }

    recordButton.IsEnabled = true;
}

private void WriteWavHeader(Stream stream, int audioDataSize)
{
    using (var writer = new BinaryWriter(stream, Encoding.UTF8, true))
    {
        writer.Write(Encoding.ASCII.GetBytes("RIFF"));
        writer.Write(audioDataSize + 36); // Total file size - 8 bytes
        writer.Write(Encoding.ASCII.GetBytes("WAVE"));
        writer.Write(Encoding.ASCII.GetBytes("fmt "));
        writer.Write(16); // Length of format data
        writer.Write((ushort)1); // PCM format
        writer.Write((ushort)1); // Not Stereo
        writer.Write(41100); // Sample rate
        writer.Write(82200); // Byte rate (Sample rate * Channels * BitsPerSample / 8)
        writer.Write((ushort)4); // Block align (Channels * BitsPerSample / 8)
        writer.Write((ushort)16); // Bits per sample
        writer.Write(Encoding.ASCII.GetBytes("data"));
        writer.Write(audioDataSize); // Size of audio data
    }
}
英文:
 string path = string.Empty;
        private void SaveAudioRecording()
        {
            timer.Dispose();
            if (string.IsNullOrEmpty(path))
            {
                path = Directory.GetCurrentDirectory() + &quot;\\AudioRecordings_&quot;+clientSession.clientInfo[0];
                Directory.CreateDirectory(path);
            }

            WaveMixerStream32 mix= new WaveMixerStream32();
            foreach (var stream in new MemoryStream[] { audioOutputMemoryStream, audioInputMemoryStream })
            {
                stream.Position = 0;
                if (stream != null &amp;&amp; stream.Length &gt; 0 &amp;&amp; stream.Position &lt; stream.Length)
                {
                    RawSourceWaveStream reader = new RawSourceWaveStream(stream,new WaveFormat(41100,1));
                    WaveChannel32 chanel = new WaveChannel32(reader);
                    mix.AddInputStream(chanel);
                }
            }


            using (FileStream stream = File.Create(System.IO.Path.Combine(path, &quot;Audio_recording_&quot; + Directory.EnumerateFiles(path).Count().ToString() + &quot;.wav&quot;)))
            {
                byte[] buffer = new byte[mix.Length];
                mix.Read(buffer, 0, buffer.Length);
                stream.Write(buffer, 0, buffer.Length);
                WriteWavHeader(stream,Convert.ToInt32(stream.Length));
                stream.Flush();
            }



            recordButton.IsEnabled = true;
        }

        private void WriteWavHeader(Stream stream, int audioDataSize)
        {
            using (var writer = new BinaryWriter(stream, Encoding.UTF8, true))
            {
                writer.Write(Encoding.ASCII.GetBytes(&quot;RIFF&quot;));
                writer.Write(audioDataSize + 36); // Total file size - 8 bytes
                writer.Write(Encoding.ASCII.GetBytes(&quot;WAVE&quot;));
                writer.Write(Encoding.ASCII.GetBytes(&quot;fmt &quot;));
                writer.Write(16); // Length of format data
                writer.Write((ushort)1); // PCM format
                writer.Write((ushort)1); // Not Stereo
                writer.Write(41100); // Sample rate
                writer.Write(82200); // Byte rate (Sample rate * Channels * BitsPerSample / 8)
                writer.Write((ushort)4); // Block align (Channels * BitsPerSample / 8)
                writer.Write((ushort)16); // Bits per sample
                writer.Write(Encoding.ASCII.GetBytes(&quot;data&quot;));
                writer.Write(audioDataSize); // Size of audio data
            }
        }

The file its ctreating is corupted, cant start it, but it do weigh a bit, the bytes do be written.

I was trying to mix two raw audio streams, into a complete .wav file, therefore writing a waveheader on it, the wave header do work, because I've tested it earlier. But now I've changed the code, which is corrupting the file.

What could possibly be the issue?

答案1

得分: 0

问题是在音频数据写入后才写入波形头部引起的。

英文:

The problem was caused by writing the waveheader after the audio data was written.

答案2

得分: 0

首先,您将标题写在数据后面,应该相反。

WriteWavHeader(stream, Convert.ToInt32(stream.Length));
stream.Write(buffer, 0, buffer.Length);

但如果只这样做,您需要调整 "audioDataSize" 以匹配数据大小。如果您将参数 "stream.Length" 保留给 WriteWavHeader 函数,它将是标题的大小,而不是数据的大小,因为此时流只包含标题数据。因此,使用 buffer.Length 代替。那是数据的大小。

WriteWavHeader(stream, Convert.ToInt32(buffer.Length));
stream.Write(buffer, 0, buffer.Length);

这应该可以解决问题。(在这种情况下,Convert.ToInt32() 调用不是必需的,因为 Length 已经是 int,如果我记得正确的话。)

英文:

First of all, you're writing the header after the data, it should be the opposite.

WriteWavHeader(stream,Convert.ToInt32(stream.Length));
stream.Write(buffer, 0, buffer.Length);

But if you do only this, you need then to adapt the "audioDataSize" to match the data size. If you keep the argument "stream.Length" to the function WriteWavHeader, it will be the size of the header, not the data, as the stream a that moment only contains the header data. So, use the buffer.Length instead. That's the data size.

WriteWavHeader(stream,Convert.ToInt32(buffer.Length));
stream.Write(buffer, 0, buffer.Length);

Should do the trick. (Convert.ToInt32() call is not mandatory in that case, Length is already a int if i remember correctly

huangapple
  • 本文由 发表于 2023年6月29日 23:11:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/76582378.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定