locked
I want to play an audio file from the assets folder.

    Question

  • I need to play an audio file called beep.wav from the VS assets folder.

    The code I have compiles and runs without errors but doesn't make a sound.

    Has anyone any idea why ?

    void beep()
    {
    
    	
    	StorageFolder^ item = KnownFolders::PicturesLibrary;
    
    	auto getFileOp = item->GetFileAsync("assets\\beep.wav");
    	getFileOp->Completed = ref new AsyncOperationCompletedHandler<StorageFile^>
        ([=](IAsyncOperation<StorageFile^>^ operation, AsyncStatus status)
      {
        auto storageFile = operation->GetResults();
    	auto openOp = storageFile->OpenAsync(FileAccessMode::Read);
        openOp->Completed = 
          ref new AsyncOperationCompletedHandler <IRandomAccessStream^>
          ([=](IAsyncOperation<IRandomAccessStream^>^ operation, AsyncStatus status)
        {
          auto istream = operation->GetResults();
          auto dr = ref new DataReader(istream);
          auto loadOp = dr->LoadAsync(istream->Size);
          loadOp->Completed = ref new AsyncOperationCompletedHandler<UINT>
            ([=](IAsyncOperation<UINT>^ operation, AsyncStatus status)
          {
    
    		    auto bytesRead = operation->GetResults();
    			test=bytesRead;
    
    			MediaElement^ media = ref new MediaElement();		
    //			media->Volume = 1; //(double)volumeSlider.Value;
    			media->SetSource(istream,".wav");	
    			media->Play();
    
    			dr->DetachStream();
    
    	  		try{
    	operation->GetResults();		//Get the result of task by forcing it.
    		  }
    		  catch(...)
    		  {
    			  return;
    		  }
    
    	  });
        });
      });
    
    
    }
    
    


    n.Wright

    Tuesday, September 24, 2013 9:38 PM

Answers

All replies

  • You need to wait until the media source has loaded into the MediaElement before you can Play it.

    Options are to set it to AutoPlay or to wait for the CurrentStateChanged event saying that it is done Opening.

    If you are likely to need the same sound frequently then pre-load it and cache the MediaElement.

    --Rob

    Tuesday, September 24, 2013 10:46 PM
    Owner
  • I changed the code as you suggested to autoplay but the file doesn't play.

    The file is definitely loaded in as I can get the numberofbytes read.

    I had a look through the output window and I get.

    1/ The application called an interface that was marshalled for a different thread

    2/ WinRT originate error (parameters: 0x8001010E, 0x00000051, 0x0348D340).


    n.Wright

    Wednesday, September 25, 2013 12:58 AM
  • You can marshal your call to the UI thread with Dispatcher::RunAsync

    --Rob

    Wednesday, September 25, 2013 1:10 AM
    Owner
  • You can marshal your call to the UI thread with Dispatcher::RunAsync

    --Rob

    It wont let me.

    I got some code for the UI thread and it crashes out with accessing location 0 error.

    	bool bRunning = true;
    
    		MessageDialog ^msgDia = ref new MessageDialog("Hello Windows 8!", "Here message for you");
    		Windows::UI::Core::CoreDispatcher ^dispatcher = CoreWindow::GetForCurrentThread() -> Dispatcher;
    		dispatcher -> RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal,
    			ref new Windows::UI::Core::DispatchedHandler(
    			[msgDia, &bRunning]{
    				msgDia->ShowAsync();
    				task<IUICommand ^> m_msgDiaShow = task<IUICommand ^>(msgDia -> ShowAsync());
    				m_msgDiaShow.then([&bRunning](IUICommand ^)
    				{
    					bRunning = false;
    				}
    				);
    			}));
    		while (bRunning)
    		{
    			CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit); 
    		}
    
    


    n.Wright

    Wednesday, September 25, 2013 8:50 PM
  • You don't say where this is crashing, but my guess is that your current thread doesn't have a CoreWindow, so CoreWindow::GetForCurrentThread returns NULL. You can get the dispatcher on your UI thread and then cache that.

    --Rob

    Wednesday, September 25, 2013 8:53 PM
    Owner
  • I have changed my code to using Renderer to get m_window which is the UI thread.

    However I still get error reading location 0.

    	bool bRunning = true;
    
    		MessageDialog ^msgDia = ref new MessageDialog("Hello Windows 8!", "Here message for you");
    
    m_window->GetForCurrentThread()->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::
    													  Normal,
    			ref new Windows::UI::Core::DispatchedHandler(
    			[msgDia, &bRunning]{
    				msgDia->ShowAsync();
    				task<IUICommand ^> m_msgDiaShow = task<IUICommand ^>(msgDia -> ShowAsync());
    				m_msgDiaShow.then([&bRunning](IUICommand ^)
    				{
    					bRunning = false;
    				}
    				);
    			})); //acess violation reading location 0 here
    		while (bRunning)
    		{
    			CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit); 
    		}
    
    
    		return;
    


    n.Wright

    Wednesday, September 25, 2013 9:33 PM
  • I should have added my app doesn't use XAML.


    n.Wright

    Wednesday, September 25, 2013 11:44 PM
  • The crash is that you're still calling CoreWindow::GetForCurrentThread (on your cached CoreWindow object), which returns 0 since the current thread doesn't have a CoreWindow. Since you've already cached the window in m_window you can call its Dispatcher directly: m_window->Dispatcher-> RunAsync.

    None of this so far is related to Xaml. The CoreWindow and CoreDispatcher are lower level concepts which are used by all Windows Store apps.

    That said, the Windows::UI::Xaml::Controls::MediaElement you are trying to use is part of Xaml.

    If you don't want to use Xaml then you can play your sound with XAudio2 .

    --Rob

    Wednesday, September 25, 2013 11:57 PM
    Owner
  • I have removed the corewindow reference and it still has the same error.

    Are you saying I need to use xaml to get the mediaelement to work ?

    	bool bRunning = true;
    
    		MessageDialog ^msgDia = ref new MessageDialog("Hello Windows 8!", "Here message for you");
    
    m_window->GetForCurrentThread()->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::
    													  Normal,
    			ref new Windows::UI::Core::DispatchedHandler(
    			[msgDia, &bRunning]{
    				msgDia->ShowAsync();
    				task<IUICommand ^> m_msgDiaShow = task<IUICommand ^>(msgDia -> ShowAsync());
    				m_msgDiaShow.then([&bRunning](IUICommand ^)
    				{
    					bRunning = false;
    				}
    				);
    			})); //access violation reading location 0 here
    		
    
    while (bRunning)
    		{
    			m_window->GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit); 
    		}
    		


    n.Wright

    Thursday, September 26, 2013 12:21 AM
  • This is the problem (probably - you haven't provided enough information to be sure, but it looks very suspicious):

    m_window->GetForCurrentThread()->Dispatcher

    There is no CoreWindow on the current thread so GetForCurrentThread() should return NULL. Since you already have a window object (m_window) you can use it directly:

    m_window->Dispatcher->...

    The MediaElement is a Xaml class and it must be in the visual tree to play sound. If you're not otherwise using Xaml in your app then you can't use the MediaElement.

    --Rob

    Thursday, September 26, 2013 12:59 AM
    Owner
  • Many thanks for your help.

    I am not currently using xaml so have decided to have a go at xaudio2.


    n.Wright

    Thursday, September 26, 2013 1:04 AM
  • It took me 3 days and then give up on mediaelement in c++ code and 30 minutes to get xaudio2 working with a wave file !!

    Great easy example here:

    http://msdn.microsoft.com/en-us/magazine/jj883962.aspx


    n.Wright


    Thursday, September 26, 2013 8:51 PM