none
Recording sound to a buffer : Strange exception

    Question

  • Hi,

    I'm currently trying to register sound into a buffer in order to analyse it.

    Here is my main loop

    /// <summary>
    /// Will start recording and buffering sounds.
    /// </summary>
    async void StartRecording()
    {
        IRandomAccessStream soundStream = null;
        try
        {
            if (recorder.Recording)
            {
                recordTimer.Stop();
                Log("Stopping record ...");
                soundStream = await recorder.StopRecord();
                
                Log("Buffering stream of " + soundStream.Size.ToString() + " bytes");
                bufferStream.Enqueue(soundStream);
    
                txtQueueElements.Text = bufferStream.Count().ToString();
    
                Log("Starting record ...");
                await recorder.StartRecord();
                recordTimer.Start();
            }
            else
            {
                Log("Starting record ...");
                await recorder.StartRecord();
            }
        }
        catch (Exception ex)
        {
            // TODO : Comment afficher une erreur à l'utilisateur ?
            Log("In StartRecording : " + ex.ToString());
        }
    
    }
    

    When I let the program execute without breakpoint, I get this error on the first Bolded line :

    In StartRecording : System.Runtime.InteropServices.COMException (0xC00D4A44): Exception de HRESULT : 0xC00D4A44
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
       at View.Controlers.Recorder.<StopRecord>d__d.MoveNext()

    And when I'm going step by step with breakpoint I get this error on the second bolded line :

    A first chance exception of type "system.exception" occured in VieW.exe

    Here is the code Inside recorder.StopRecord() :

    public async Task<IRandomAccessStream> StopRecord()
    {
        if (!Recording)
        {
            return null;
        }
        else
        {
            await mediaCaptureMgr.StopRecordAsync();
            Recording = false;
            return soundStream;
        }
    }
    


    And here is the code Inside recorder.StartRecord():

    public async Task StartRecord()
    {
        try
        {
            if (!Recording)
            {
                Windows.Media.MediaProperties.MediaEncodingProfile recordProfile = null; // Record profile is not reusable (don't know why) and should not be global.
                recordProfile = Windows.Media.MediaProperties.MediaEncodingProfile.CreateWma(Windows.Media.MediaProperties.AudioEncodingQuality.Auto);
    
                SampleRate = recordProfile.Audio.SampleRate;
    
                soundStream = new InMemoryRandomAccessStream();
                await mediaCaptureMgr.StartRecordToStreamAsync(recordProfile, soundStream);
    
                Recording = true;
            }
        }
        catch(Exception ex)
        {
            Recording = false;
            throw;
        }
    }
    

    What I also noticed is that, at some point, elements in the recorded stream cannot be read anymore. I get an exception calling the method dataReader.ReadInt16() where dataReader is of type DataReader.

    Is there someone that can help me ?

    Thank you !

    Aleks

    Thursday, May 03, 2012 7:44 PM

Answers

  • Hello Aleks,

    Thanks for reporting this issue. This problem looks to be due to the fact that the finalization of the previous ASF file has not completed. For performance optimization we do not serialize the finalization of the ASF file because it can take a very long time to write out the index object of the ASF file. In this case we appear to be in the middle of writing out the index chunk when you try to re-initialize the ASF Sink. I will certainly report this behavior but this is really "by design" and you would have the same issue if you were using the WM Format SDK. Unfortunately there is no feedback event that I know of to alert you to the fact that the index object has been written and the output file closed. One really bad hack that you can try is to wait for about 3 seconds before starting the recording again. I say "bad hack" because blocking to wait for something to complete without knowing when it actually has completed is really bad programming. Since this behavior probably won't change anytime soon your best option is likely to use two different instances of the Media Capture element. This way the out of band finalization will not interfere with the restart of the next recording session.

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Thursday, May 03, 2012 11:55 PM

All replies

  • Hello Aleks,

    Thanks for reporting this issue. This problem looks to be due to the fact that the finalization of the previous ASF file has not completed. For performance optimization we do not serialize the finalization of the ASF file because it can take a very long time to write out the index object of the ASF file. In this case we appear to be in the middle of writing out the index chunk when you try to re-initialize the ASF Sink. I will certainly report this behavior but this is really "by design" and you would have the same issue if you were using the WM Format SDK. Unfortunately there is no feedback event that I know of to alert you to the fact that the index object has been written and the output file closed. One really bad hack that you can try is to wait for about 3 seconds before starting the recording again. I say "bad hack" because blocking to wait for something to complete without knowing when it actually has completed is really bad programming. Since this behavior probably won't change anytime soon your best option is likely to use two different instances of the Media Capture element. This way the out of band finalization will not interfere with the restart of the next recording session.

    I hope this helps,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Thursday, May 03, 2012 11:55 PM
  • Hello James and thank you for the reply.

    I'll try to make a new MediaCapture object. But this will not help me to know when I can start reading the stream. Waiting some amount of time is clearly not a solution and will end with performance issue.

    In my point of view, this is a really bad "by design" behavior as you are just avoiding anyone making a Windows 8 APP that will treat/analyse a signal. I'm curious to see, if rumors are right, how the Skype team will make a Windows 8 Metro Skype app ...

    I really think that you should escalate this thread and I will be happy, if necessary, to talk with someone of the WinRT team about this subject.

    Thank you.

    Aleks

    Friday, May 04, 2012 8:30 AM
  • Hello Aleks,

    I am part of the WinRT media team and as per my previous post I will certainly let the owners of the Media Capture element know about this side effect.

    You wrote: "But this will not help me to know when I can start reading the stream."

    Unfortunately I don't fully understand what this means. If you create a second Media Capture element you can start reading right away. But maybe I'm missing somthing.

    On a related note, you should not be doing real time data analysis on audio data from within a managed application and if you plan to write a real time communications style application you will need to write a custom source and sink both in C++ Cx.  Your other option is to use WASAPI. Using WASAPI is the recommended choice if your a looking for extreme low latency and complete control over the audio stack. Again you can only call the WASAPIs from C++ Cx.

    The reason that you should never do real time audio or video processing in a managed environment is due to nondeterministic finalization. This is a very important concept for you to understand as you continue to work with audio and video in the WinRT and Metro style environments. I have an extensive blog post that I would highly recommend that you read before continuing with your development. I would also recommend that you look at the real time audio and video sample that we released with the CP to understand our recommended way of doing near-real-time communications.

    Real-time communication sample
    http://code.msdn.microsoft.com/windowsapps/Simple-Communication-Sample-eac73290

    Calling the Format SDK, DirectShow, Media Foundation or the WASAPI from managed code (C#, VB.net)
    http://blogs.msdn.com/b/mediasdkstuff/archive/2009/04/01/calling-the-format-sdk-directshow-media-foundation-or-the-wasapi-from-managed-code-c-vb-net.aspx

    Thanks,

    James


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Monday, May 07, 2012 10:00 PM
  • Hello James,

    Thank you for your reply.

    What I mean by "reading the stream" I meen when I stop recording. Because, if I correctly understandood, I will get the hand on the Stream before the MediaCapture has finished writing it.

    Concerning WASAPI, I looked to the sample but, as I'm not a C++ guy, it is difficult for me to inspect all the code. I tried to find another sample simpler but I only found this one witch is for Windows 7 : http://msdn.microsoft.com/en-us/library/windows/desktop/dd940390(v=vs.85).aspx

    Do you have an easier sample that, for example, just write into a buffer a predefined amount of data ?

    I also found other post that you replied and people are agree to say that it is functionnal/possible on "any" other platform (Windows, Windows phone, Silverlight, etc.)

    Thank you for your help.

    Tuesday, May 08, 2012 8:04 PM
  • Hello Aleks,

    You can still use the file even if the ASF subsystem hasn't finished writing the index object. As you know the index object of an ASF file is located at the end of the file. It is certainly possible to "read while write" of an ASF file. In fact Windows Media Server uses this functionality extensively as does Media Center.

    Unfortunately I don't have a simple WASAPI sample for you.

    We certainly understand that a lot of managed developers really want to process raw audio. For some scenarios this might work just fine. However, if you find that you are suddenly hearing "clicks" and "pops" data is likely getting dropped due to the GC taking too long to run. I just want to make sure that you are aware that this is the expected behavior from managed code. Depending on your scenario you may only run into this issue when you run your code on a slow netbook or Windows RT device. It can be a major product quality issue and you can end up with very disappointed customers.

    I hope this helps,

    James 


    Windows Media SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Tuesday, May 08, 2012 11:57 PM
  • Hi James,

    I just change CreateWma to CreateM4a and know everything is working ...

    Aleks
    Thursday, May 10, 2012 3:09 PM