locked
how to transform the raw PCM byte from Microphone to a wave file RRS feed

  • Question

  • Hi everybody, I am trying to transform the raw PCM i got from the Microphone class into a wave file. I heard that all i need is to add a wave header. here is my code so far: in this code: stream is a MemoryStream that contains the raw PCM bytes from the Microphone. I write after that the contents of "fs" into a wave file, but it is not working. Can anybody help me about what i do wrong? Thanks in advance. short channel = 1; short BitsPerSample = 16; fs = new MemoryStream(); BinaryWriter bw = new BinaryWriter(fs); bw.Write(new char[4] { 'R', 'I', 'F', 'F' }); bw.Write(38+stream.Length); bw.Write(new char[8] { 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' }); bw.Write((int)16); bw.Write((short)1); bw.Write(channel); bw.Write(microphone.SampleRate); bw.Write((int)(microphone.SampleRate * ((BitsPerSample * channel) / 8))); bw.Write((short)((BitsPerSample * channel) / 8)); bw.Write(BitsPerSample); bw.Write(new char[4] { 'd', 'a', 't', 'a' }); bw.Write(stream.Length); bw.Write(stream.ToArray());
    Saturday, February 5, 2011 10:16 AM

Answers

  • I can't say that I see what's wrong with your code at first glance. I was writing a wave header on a desktop and came up with this code that works. Since it is written for a desktop you would need to modify it to use IsolatedStorage instead of a file stream.

    BTW: You may want to enable RichText editing in your profile so that you can insert code without loosing formatting. It's hard to read that code all on one line. 
    Saturday, February 5, 2011 2:27 PM
  • I've removed the code from the original link. For any one else looking for it note that you can find it over at CodeProject.com.

    Thursday, March 31, 2011 5:14 AM

All replies

  • I can't say that I see what's wrong with your code at first glance. I was writing a wave header on a desktop and came up with this code that works. Since it is written for a desktop you would need to modify it to use IsolatedStorage instead of a file stream.

    BTW: You may want to enable RichText editing in your profile so that you can insert code without loosing formatting. It's hard to read that code all on one line. 
    Saturday, February 5, 2011 2:27 PM
  • Hi Joel, your code work perfectly thanks a lot!
    Saturday, February 5, 2011 4:07 PM
  • Hi Joel,your code work perfectlythanks a lot!
    Hi Maxime.
    How did you do it?
    I have the following code for creating wave file and adding header:
     private void navToPlayButton_Click(object sender, EventArgs e) 
            { 
                IsolatedStorageFile isolatedStorage = IsolatedStorageFile.GetUserStoreForApplication(); 
                var soundData = this.CreateSinWave(44000, 120, TimeSpan.FromSeconds(60), 1d); 
                using (var fs = isolatedStorage.CreateFile("somewavefile.wav")) 
                { 
                    this.WriteHeader(fs, soundData.Length, 1, 44100); 
                    fs.Write(soundData, 0, soundData.Length); 
                    fs.Close(); 
                } 
     
                NavigationService.Navigate(new Uri("/PlayWave.xaml", UriKind.RelativeOrAbsolute)); 
            } 

    and the following code to play the wave file:
    void PlayWave_Loaded(object sender, RoutedEventArgs e) 
            { 
                IsolatedStorageFile isolatedStorage = IsolatedStorageFile.GetUserStoreForApplication(); 
                using (var stream = isolatedStorage.OpenFile("somewavefile.wav", System.IO.FileMode.Open)) 
                { 
                    var effect = SoundEffect.FromStream(stream); 
                    FrameworkDispatcher.Update(); 
                    effect.Play(); 
                    //media.SetSource(stream); 
                    //media.Play(); 
                }             
            } 

    in the case of SoundEffect I gain InvalidOperationException

       at Microsoft.Xna.Framework.Audio.WavFile.ParseWavHeader() 
       at Microsoft.Xna.Framework.Audio.WavFile..ctor(Stream source) 
       at Microsoft.Xna.Framework.Audio.WavFile.Open(Stream stream) 
       at Microsoft.Xna.Framework.Audio.SoundEffect..ctor(Stream stream) 
       at Microsoft.Xna.Framework.Audio.SoundEffect.FromStream(Stream stream) 
       at SilverlightMicrophoneSample.PlayWave.PlayWave_Loaded(Object sender, RoutedEventArgs e) 
       at System.Windows.CoreInvokeHandler.InvokeEventHandler(Int32 typeIndex, Delegate handlerDelegate, Object sender, Object args) 
       at MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, String eventName) 
     

    When I sue MediaElement I hear only a syren.

    Best regards.
    Tuesday, February 15, 2011 3:25 PM
  • Issue solved.
    Thursday, February 17, 2011 8:28 AM
  • How did you solve the problem? I have the same issue. Andre
    Monday, March 28, 2011 8:05 PM
  • How did you solve the problem? I have the same issue.Andre

    There was a bug in the code I shared where an incorrect calculation of the size of a data chunk would cause problems. Thing is even with the faulty size calculation the wave file could still be used in some situations, so I didn't notice it at first because I was using it in the situations where it made no difference. The correct WriteWaveHeader function should look like this. 

    public static void WriteHeader( 
         System.IO.Stream targetStream,  
         int byteStreamSize,  
         int channelCount,  
         int sampleRate) 
     
        int byteRate = sampleRate*channelCount*BYTES_PER_SAMPLE; 
        int blockAlign = channelCount*BYTES_PER_SAMPLE; 
     
        targetStream.Write(RIFF_HEADER,0,RIFF_HEADER.Length); 
        targetStream.Write(PackageInt(byteStreamSize+44-8, 4), 0, 4); 
     
        targetStream.Write(FORMAT_WAVE, 0, FORMAT_WAVE.Length); 
        targetStream.Write(FORMAT_TAG, 0, FORMAT_TAG.Length); 
        targetStream.Write(PackageInt(16,4), 0, 4);//Subchunk1Size     
     
        targetStream.Write(AUDIO_FORMAT, 0, AUDIO_FORMAT.Length);//AudioFormat    
        targetStream.Write(PackageInt(channelCount, 2), 0, 2); 
        targetStream.Write(PackageInt(sampleRate, 4), 0, 4); 
        targetStream.Write(PackageInt(byteRate, 4), 0, 4); 
        targetStream.Write(PackageInt(blockAlign, 2), 0, 2); 
        targetStream.Write(PackageInt(BYTES_PER_SAMPLE*8), 0, 2); 
        //targetStream.Write(PackageInt(0,2), 0, 2);//Extra param size 
        targetStream.Write(SUBCHUNK_ID, 0, SUBCHUNK_ID.Length); 
        targetStream.Write(PackageInt(byteStreamSize, 4), 0, 4); 

    Tuesday, March 29, 2011 1:20 AM
  • Thanks Joel, Am I right in saying that this is the only Method I need? CreateSinWave is not needed if I already have my byte[] from the microphone? I still can't get it to work but I'll keep trying. Thanks
    Tuesday, March 29, 2011 2:27 AM
  • Thanks Joel, Am I right in saying that this is the only Method I need?


    You are. 

    CreateSinWave is not needed if I already have my byte[] from the microphone? I still can't get it to work but I'll keep trying. Thanks


    Don't know what you can be doing wrong there. This out to help you out though.

    I made a minimalistic voice recorder[^] that I made for a CodeProject.com article. I've not finished the article yet but you can have a look at the code and the draft that I've written up so far. This saves the wave file in WAV format and uses the SoundEffect class to reload it. I did put the code through the certification process just to make sure it met minimum requirements. But the UI is currently ugly and the code has some comments and unused methods that need to be removed; the best looking part of this program at this time is it's archaic icon (which I got from an artist in exchange for a burrito).

    I'll leave it on the download site for the next 48 hours. After that I am removing it and any one that wants it will have to find the final version on CodeProject.com.
    Tuesday, March 29, 2011 1:07 PM
  • You rock! This works great!.
    Tuesday, March 29, 2011 1:54 PM
  • I've removed the code from the original link. For any one else looking for it note that you can find it over at CodeProject.com.

    Thursday, March 31, 2011 5:14 AM
  • What is it called so I can rate you 5 stars? Is it up there now? Andre
    Thursday, March 31, 2011 11:29 AM

  • What is it called so I can rate you 5 stars? Is it up there now?Andre



    Thursday, March 31, 2011 2:08 PM