如何在winrt中播放重叠的音频?

Posted

技术标签:

【中文标题】如何在winrt中播放重叠的音频?【英文标题】:How to play overlapping audio in winrt? 【发布时间】:2013-08-29 05:05:11 【问题描述】:

我正在从 wp8 移植一个应用程序,该应用程序需要播放可以重叠的各种声音。到目前为止我发现的唯一方法是使用 MediaElement,但这不允许重叠声音。

问题 - 用于播放重叠音频的最简单和最好的音频引擎是什么?理想情况下,我需要一个小例子来说明如何做到这一点。

我研究过 WASAPI (http://code.msdn.microsoft.com/windowsapps/Windows-Audio-Session-22dcab6b),但它似乎不支持简单播放?

也许我可以包装 MediaFoundation 并从 winrt 调用它? (MediaEngine audio playback on WinRT)

这是我现在的代码,但是当我播放新声音时,它会切断之前播放的声音,而不是混合它们。

    ThreadUtility.runOnUiThread(
      async delegate()
      
        // TODO doesn't allow sounds to overlap!
        Uri uri = new Uri(R.base_uri, R.raw.URI_PREFIX + resourceId);
        StorageFile storageFile =
          await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(
          uri);
        MediaElement element = new MediaElement();

        var randomAccessStream = await storageFile.OpenReadAsync();

        element.SetSource(randomAccessStream, storageFile.ContentType);
        element.Volume = volume;
        element.PlaybackRate = pitch;
        //TODO element.Pan = pan;
        element.Play();
      
    );

解决方案(根据 Filip 的回答):

在页面类中:

      var mediaElements = new LinkedList<MediaElement>();
      
        for (int channel = 0; channel < TeacherSoundGroover.NUM_CHANNELS; channel++)
        
          var mediaElement = new MediaElement();
          mediaElements.add(mediaElement);

          // Must be in the tree otherwise it won't overlap!
          m_titlePanel.Children.Add(mediaElement);
        
      
      m_soundPlayer = new MySoundPlayer(mediaElements);
    

在 MySoundPlayer 类中:

    ThreadUtility.runOnUiThread(
      async delegate()
      
        Uri uri = new Uri(R.base_uri, R.raw.URI_PREFIX + resourceId);
        StorageFile storageFile =
          await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(
          uri);

        if(m_mediaElements != null)
        
          int count = m_mediaElements.size();
          if (count > 0)
          
            int channel = m_nextMediaElementToUse % count;
            m_nextMediaElementToUse++;
            MediaElement element = m_mediaElements.get(channel);

            var randomAccessStream = await storageFile.OpenReadAsync();

            element.Stop();
            element.DefaultPlaybackRate = rate;
            element.SetSource(randomAccessStream, storageFile.ContentType);
            element.Volume = volume;
            element.Balance = pan;
            element.Play();
          
        
      
    );

【问题讨论】:

【参考方案1】:

最简单的做法是使用多个 MediaElement 控件,尽管这可能不会给您想要的结果。如果您想避免创建 C++/CX WinRT 组件,最好的方法是直接或通过 SharpDX 使用 XAudio2。

【讨论】:

我已经在创建多个 MediaElement 控件 --- 参见上面的代码 sn-p。我去看看SharpDX,谢谢 MediaElement 确实允许使用多个控件实例同时播放多个音轨。也许所有都需要添加到 UI 树中? 实际上,这确实有效!奇怪的是需要将它们添加到树中。将使用解决方案代码更新我上面的问题。

以上是关于如何在winrt中播放重叠的音频?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Audio Units 播放多个重叠的短音频文件

如何在收到推送通知而不实施 PushNotification 触发任务时播放自定义声音

如何修复 iPhone 应用程序中的多个音频流造成失真?

按钮单击音频启动和停止 JS

如何在WPF中调用Windows 10/11 API(UWP/WinRT)

如何在iphone中同时播放音频和视频