Error after saving .wav file

351 views Asked by At

I'm using irrKlang to get audio input from a mic. That part works great, but I'm having problems saving the output to a .wav...

The wave file appears to save ok, but it doesn't seem to play. I'm wondering if my header is some how formatted wrong:

    private void SaveWave(string path, AudioFormat format, byte[] waveData)
    {
        //Play the audio for testing purposes
        ss = engine0.AddSoundSourceFromPCMData(waveData, "sound", format);
        engine0.Play2D(ss, true, false, false);

        // write wave header 
        ushort formatType = 1;
        ushort numChannels = (ushort)format.ChannelCount;
        ulong sampleRate = (ulong)format.SampleRate;
        ushort bitsPerChannel = (ushort)(format.SampleSize * 8);
        ushort bytesPerSample = (ushort)format.FrameSize;
        ulong bytesPerSecond = (ulong)format.BytesPerSecond;
        ulong dataLen = (ulong)format.SampleDataSize;

        const int fmtChunkLen = 16;
        const int waveHeaderLen = 4 + 8 + fmtChunkLen + 8;

        ulong totalLen = waveHeaderLen + dataLen;
        ///
        FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write);
        BinaryWriter bw = new BinaryWriter(fs);
        byte[] riff = System.Text.Encoding.ASCII.GetBytes("RIFF");
        bw.Write(riff);
        bw.Write(totalLen);
        byte[] fmt = System.Text.Encoding.ASCII.GetBytes("WAVEfmt ");
        bw.Write(fmt);
        bw.Write(fmtChunkLen);
        bw.Write(formatType);
        bw.Write(numChannels);
        bw.Write(sampleRate);
        bw.Write(bytesPerSecond);
        bw.Write(bytesPerSample);
        bw.Write(bitsPerChannel);
        byte[] data = System.Text.Encoding.ASCII.GetBytes("data");
        bw.Write(data);
        bw.Write(waveData.Length);
        bw.Write(waveData);
        bw.Close();
        fs.Close();
    }
1

There are 1 answers

2
Vishnu Prasad V On

You're writing the string headers wrong.

BinaryWriter.Write(string) is not meant for writing like this. According to this msdn article, it prefixes it's length to the string before it writes.

You need to write those headers as bytes.

Do it like these,

byte[] riff= System.Text.Encoding.ASCII.GetBytes("RIFF");
bw.Write(riff);
byte[] fmt = System.Text.Encoding.ASCII.GetBytes("WAVEfmt ");
bw.Write(fmt);
// Remove the space in "data " to "data"
//byte[] data= System.Text.Encoding.ASCII.GetBytes("data ");
byte[] data= System.Text.Encoding.ASCII.GetBytes("data");
bw.Write(data);

Rest of the headers seem fine.

Hope this helps you