Binjal Shah
Binjal Shah

Reputation: 311

Audio recorder issue in Windows Phone 8

First of all if something done wrong then forgive me, I am new in this platform. Here is a good and working example of voice recorder for those who want. I have created audio recorder feature in windows phone 8, everything works fine, but how do I get that audio extention,audio name and audio length in the sense of time? for more details see my code:

private Microphone microphone = Microphone.Default;
    private byte[] buffer;                                  
    private MemoryStream stream = new MemoryStream();       
    private SoundEffectInstance soundInstance;              
    private bool soundIsPlaying = false;

    private BitmapImage blankImage;
    private BitmapImage microphoneImage;
    private BitmapImage speakerImage;

 public App()
    {
        InitializeComponent();

        DispatcherTimer dt = new DispatcherTimer();
        dt.Interval = TimeSpan.FromMilliseconds(33);
        dt.Tick += dt_Tick;
        dt.Start();

        microphone.BufferReady += microphone_BufferReady;

        blankImage = new BitmapImage(new Uri("Img/blank.png", UriKind.RelativeOrAbsolute));
        microphoneImage = new BitmapImage(new Uri("Img/microphone.png", UriKind.RelativeOrAbsolute));
        speakerImage = new BitmapImage(new Uri("Img/speaker.png", UriKind.RelativeOrAbsolute));      
    }

 void dt_Tick(object sender, EventArgs e)
    {
        try { FrameworkDispatcher.Update(); }
        catch { }

        if (true == soundIsPlaying)
        {
            if (soundInstance.State != SoundState.Playing)
            {
                // Audio has finished playing
                soundIsPlaying = false;

                // Update the UI to reflect that the 
                // sound has stopped playing
                SetButtonStates(true, true, false);
                UserHelp.Text = "press play\nor record";
                StatusImage.Source = blankImage;
            }
        }
    }

 void microphone_BufferReady(object sender, EventArgs e)
    {
        microphone.GetData(buffer);

        stream.Write(buffer, 0, buffer.Length);

    }

 private void recordButton_Click(object sender, EventArgs e)
    {
        microphone.BufferDuration = TimeSpan.FromMilliseconds(500);


        buffer = new byte[microphone.GetSampleSizeInBytes(microphone.BufferDuration)];

        string audiofile = Convert.ToBase64String(buffer);
        string audiosize = stream.Length.ToString();

        stream.SetLength(0);

        microphone.Start();

        SetButtonStates(false, false, true);
        UserHelp.Text = "record";
        StatusImage.Source = microphoneImage;
        btnAdd.Visibility = Visibility.Collapsed;
    }

 private void playButton_Click(object sender, EventArgs e)
    {
        if (stream.Length > 0)
        {
            // Update the UI to reflect that
            // sound is playing
            SetButtonStates(false, false, true);
            UserHelp.Text = "play";
            StatusImage.Source = speakerImage;

            // Play the audio in a new thread so the UI can update.
            Thread soundThread = new Thread(new ThreadStart(playSound));
            soundThread.Start();
            btnAdd.Visibility = Visibility.Visible;
        }

    }

 private void stopButton_Click(object sender, EventArgs e)
    {
        if (microphone.State == MicrophoneState.Started)
        {
            // In RECORD mode, user clicked the 
            // stop button to end recording
            microphone.Stop();
        }
        else if (soundInstance.State == SoundState.Playing)
        {
            // In PLAY mode, user clicked the 
            // stop button to end playing back
            soundInstance.Stop();
        }

        SetButtonStates(true, true, false);
        UserHelp.Text = "ready";
        StatusImage.Source = blankImage;

        btnAdd.Visibility = Visibility.Visible;
    }

    private void playSound()
    {

        SoundEffect sound = new SoundEffect(stream.ToArray(), microphone.SampleRate, AudioChannels.Mono);
        soundInstance = sound.CreateInstance();
        soundIsPlaying = true;
        soundInstance.Play();
    }

private void SetButtonStates(bool recordEnabled, bool playEnabled, bool stopEnabled)
    {
        (ApplicationBar.Buttons[0] as ApplicationBarIconButton).IsEnabled = recordEnabled;
        (ApplicationBar.Buttons[1] as ApplicationBarIconButton).IsEnabled = playEnabled;
        (ApplicationBar.Buttons[2] as ApplicationBarIconButton).IsEnabled = stopEnabled;
    }

Upvotes: 2

Views: 345

Answers (1)

meneses.pt
meneses.pt

Reputation: 2616

I followed an example online and I noticed there are somethings missing from your code.

You should have these two methods also:

    public void WriteWavHeader(int sampleRate)
    {
        const int bitsPerSample = 16;
        const int bytesPerSample = bitsPerSample / 8;
        var encoding = System.Text.Encoding.UTF8;

        // ChunkID Contains the letters "RIFF" in ASCII form (0x52494646 big-endian form).
        stream.Write(encoding.GetBytes("RIFF"), 0, 4);

        // NOTE this will be filled in later
        stream.Write(BitConverter.GetBytes(0), 0, 4);

        // Format Contains the letters "WAVE"(0x57415645 big-endian form).
        stream.Write(encoding.GetBytes("WAVE"), 0, 4);

        // Subchunk1ID Contains the letters "fmt " (0x666d7420 big-endian form).
        stream.Write(encoding.GetBytes("fmt "), 0, 4);

        // Subchunk1Size 16 for PCM. This is the size of therest of the Subchunk which follows this number.
        stream.Write(BitConverter.GetBytes(16), 0, 4);

        // AudioFormat PCM = 1 (i.e. Linear quantization) Values other than 1 indicate some form of compression.
        stream.Write(BitConverter.GetBytes((short)1), 0, 2);

        // NumChannels Mono = 1, Stereo = 2, etc.
        stream.Write(BitConverter.GetBytes((short)1), 0, 2);

        // SampleRate 8000, 44100, etc.
        stream.Write(BitConverter.GetBytes(sampleRate), 0, 4);

        // ByteRate = SampleRate * NumChannels * BitsPerSample/8
        stream.Write(BitConverter.GetBytes(sampleRate * bytesPerSample), 0, 4);

        // BlockAlign NumChannels * BitsPerSample/8 The number of bytes for one sample including all channels.
        stream.Write(BitConverter.GetBytes((short)(bytesPerSample)), 0, 2);

        // BitsPerSample 8 bits = 8, 16 bits = 16, etc.
        stream.Write(BitConverter.GetBytes((short)(bitsPerSample)), 0, 2);

        // Subchunk2ID Contains the letters "data" (0x64617461 big-endian form).
        stream.Write(encoding.GetBytes("data"), 0, 4);

        // NOTE to be filled in later
        stream.Write(BitConverter.GetBytes(0), 0, 4);
    }


    public void UpdateWavHeader()
    {
        if (!stream.CanSeek) throw new Exception("Can't seek stream to update wav header");

        var oldPos = stream.Position;

        // ChunkSize 36 + SubChunk2Size
        stream.Seek(4, SeekOrigin.Begin);
        stream.Write(BitConverter.GetBytes((int)stream.Length - 8), 0, 4);

        // Subchunk2Size == NumSamples * NumChannels * BitsPerSample/8 This is the number of bytes in the data.
        stream.Seek(40, SeekOrigin.Begin);
        stream.Write(BitConverter.GetBytes((int)stream.Length - 44), 0, 4);

        stream.Seek(oldPos, SeekOrigin.Begin);
    }

Then you should call WriteWavHeader on the recordButton_Click method, and UpdateWavHeader on the stopButton_Click after the microphone.Stop() call.

Because the microphone returns PCM data, what these headers do is turn the stream into a wav file, which you can later save in Isolated Storage, for example.

Below is the code to save the file to IsolatedStorage:

    private void SaveToIsolatedStorage(string filename)
    {
        // first, we grab the current apps isolated storage handle
        IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();

        // we give our file a filename
        string strSaveName = filename;

        // if that file exists... 
        if (isf.FileExists(strSaveName))
        {
            // then delete it
            isf.DeleteFile(strSaveName);
        }

        // now we set up an isolated storage stream to point to store our data
        var isfStream = new IsolatedStorageFileStream(strSaveName, FileMode.Create, IsolatedStorageFile.GetUserStoreForApplication());

        isfStream.Write(stream.ToArray(), 0, stream.ToArray().Length);

        // ok, done with isolated storage... so close it
        isfStream.Close();
    }

Upvotes: 3

Related Questions