[UWP] 用 AudioGraph 來增強 UWP 的音頻處理能力


Audio Graph

AudioGraph 是 Windows.Media.Audio 命名空間下提供的音頻處理接口之一。

可以通過 AudioGraph 的靜態方法 CreateAsync 來實例化一個 AudioGraph 對象,實例化的時候需要傳入一個參數 AudioGraphSettings 來配置 AudioGraph。 Windows把系統中的音頻分成了大概12種類型:

public enum AudioRenderCategory
{
    Other = 0,
    ForegroundOnlyMedia = 1,
    BackgroundCapableMedia = 2,
    Communications = 3,
    Alerts = 4,
    SoundEffects = 5,
    GameEffects = 6,
    GameMedia = 7,
    GameChat = 8,
    Speech = 9,
    Movie = 10,
    Media = 11
}

在構造 AudioGraph 的時候選擇一種類別,可以應用 Windows 的一些優化措施(具體不知道)

創建 AudioGraph 代碼如下:

private async Task InitAudioGraph()
{
    AudioGraphSettings settings = new AudioGraphSettings(Windows.Media.Render.AudioRenderCategory.Media);
    CreateAudioGraphResult result = await AudioGraph.CreateAsync(settings);
    if (result.Status == AudioGraphCreationStatus.Success)
    {
        audioGraph = result.Graph;
    }
}

Audio Graph 如何工作

在 Audio Graph 中,可以包含各種音頻節點,包括:

  • 音頻輸入節點(Input Node), DeviceInputNode, FileInputNode, MediaSourceInputNode,AudioFrameInputNode
  • 音頻輸出節點(Output Node), AudioSubmixNode
  • 中間節點(Submix Node), DeviceOutputNode, FileOutputNode, MediaSourceOutputNode,AudioFrameOutputNode

這三種類型的節點可以按照

輸入節點--->中間節點--->輸出節點

這種順序來組合,其中中間節點可以有多個,用來完成多級的音頻數據處理。

AudioGraph 中各個節點在處理音頻數據的時候,是分段處理的,把完整的音頻數據切分成一小段一小段來處理。

數字音樂存在采樣率的概念,比如48Khz,表示一秒采樣48000次,因此每一次采樣會有一個采樣得到采樣值Sample。

AudioGraph 在處理這些采樣值的時候,會將其分組,每一個分組為一個 Quantum,默認每一個Quantum 代表10ms, 因此針對48K采樣率的音頻,每一個Quantum會有480個Sample,也就是說每一次每個音頻節點只需要處理480個采樣值,針對這480個采樣值做各種處理,比如保存,比如變換效果等。


音頻輸入節點(Input Node)

音頻輸入節點是為了獲取音頻數據,可以通過麥克風錄音,也可以直接從文件讀取,也可以從一個網絡流里獲取,甚至可以直接自己生成一個AudioFrame,自己往里面填音頻數據

1.DeviceInputNode

設備輸入節點,實際上就是麥克風。

值得注意的是同一台電腦上可能有多個音頻輸入設備,如果在創建輸入節點時不指定使用的輸入設備,將采用系統默認的。
Windows.Devices.Enumeration.DeviceInformation 下面的接口可以幫助我們選擇音頻輸入設備

public IAsyncOperation<CreateAudioDeviceInputNodeResult> CreateDeviceInputNodeAsync(MediaCategory category,AudioEncodingProperties encodingProperties, DeviceInformation device);

2.FileInputNode

public IAsyncOperation<CreateAudioFileInputNodeResult> CreateFileInputNodeAsync(IStorageFile file);

支持的音頻格式有 MP3,wav,wma,m4a

在文件輸入節點里面,可以控制播放音頻的速度,音量和播放進度

3.MediaSourceInputNode

IAsyncOperation<CreateMediaSourceAudioInputNodeResult> CreateMediaSourceAudioInputNodeAsync(MediaSource mediaSource);

MediaSource可以從多個途徑獲得,比如文件,比如網絡流等,MediaSource類有許多的靜態方法可以創建MediaSource對象,比如文件,好處是播放穩定,網絡流的話會受網絡影響,可能中斷

4.AudioFrameInputNode

個人認為這個輸入節點非常實用,用於創建音頻資源和編輯音頻會特別方便,因為它允許我們自己填充需要播放的音頻數據,接口本身不難,難點是如何生成可以播放的音頻數據。

想要讀寫一個AudioFrame中數據,需要使用 COM 接口IMemoryBufferByteAccess

[ComImport]
[Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
unsafe interface IMemoryBufferByteAccess
{
    void GetBuffer(out byte* buffer, out uint capacity);
}

因為 UWP 本質上就是 各種COM接口組成,在這種場景下直接使用 COM 可能有效率方面的考慮


音頻輸出節點(Output Node)

與輸入節點對應,存在各自的輸入節點(MediaSourceInputNode除外)

  1. DeviceInputNode, 代表揚聲器

  2. FileInputNode, 代表文件,輸出音頻數據到文件

  3. AudioFrameOutputNode, 這個應用場景我不是很明白,MSDN上這么說:

    “An example scenario for this is performing signal analysis on the audio output”


中間節點(混音節點 Submix Node)

所有的輸入節點,都有一個接口叫做:

 public void AddOutgoingConnection(IAudioNode destination);

通過這個接口,可以把輸入節點和輸出節點連接起來,最簡單的,

fileInputNode.AddOutgoingConnection(deviceOutputNode);

這么簡單一句,就實現了音樂播放,但是如果想做一些混音的話,就不是很方便了,所以需要 Submix Node.

fileInputNode.AddOutgoingConnection(submixNode);

deviceInputNode.AddOutgoingConnection(submixNode);

submixNode.AddOutgoingConnection(deviceOutputNode);

這三句代碼,可以實現把音樂文件和錄音直接混合輸出到揚聲器,當然也可以輸出到文件中。


使用場景

Audio Graph 對 UWP 處理音頻的能力是一次不錯的拓展,基於 Audio Graph,有很多好玩的使用場景,比如官方文檔里面介紹到的空間音效 Spatial Audio.

目前我自己最簡單能想到到就是可以用這個做一個簡單的電台主播助手APP,如圖:

簡易電台主播助手


參考

本文基本來自於微軟官方文檔:

Audio Graph

其中 Spatial Audio 部分的應用本文沒有介紹到,這部分需要一定的聲學知識才能玩得轉!

后續會繼續把自己對 UWP Audio 的學習記錄在博客園


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM