[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除外)
DeviceInputNode, 代表扬声器
FileInputNode, 代表文件,输出音频数据到文件
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 的学习记录在博客园
[UWP] 用 AudioGraph 来增强 UWP 的音频处理能力的更多相关文章
- [UWP] 用 AudioGraph 来增强 UWP 的音频处理能力——AudioFrameInputNode
上一篇心得记录中提到了 AudioGraph, 描述了一下 什么是 AudioGraph 以及其中涉及到的各种类型的 节点(Node). 这一篇就其中比较有意思的 AudioFrameInputNod ...
- [UWP小白日记-11]在UWP中使用Entity Framework Core(Entity Framework 7)操作SQLite数据库(一)
前言 本文中,您将创建一个通用应用程序(UWP),使用Entity Framework Core(Entity Framework 7)框架在SQLite数据库上执行基本的数据访问. 准备: Enti ...
- [UWP小白日记-15]在UWP手机端实时限制Textbox的输入
说实话重来没想到验证输入是如此的苦逼的一件事情. 网上好多验证都是在输入完成后再验证,我的想法是在输入的时候就限制输入,这样我就不用再写代码来验证了 应为是手机端,所以不用判断其他非法字符,直 ...
- UWP: 通过命令行启动 UWP 应用
最近在开发应用的过程中,我遇到了如标题所述的需求,其实主要是为了能够快捷启动应用,正像我们可以在"运行"对话框中可以输入一些可执行程序的名称后,就能够直接启动它:这样做,可以增加 ...
- UWP Control Toolkit Collections 求UWP工作
1. it is like wechat wait-sliderdeleteitem in iOS 看起来比较像微信删掉项 now support listview and gridview in C ...
- UWP学习目录整理
UWP学习目录整理 0x00 可以忽略的废话 10月6号靠着半听半猜和文字直播的补充看完了微软的秋季新品发布会,信仰充值成功,对UWP的开发十分感兴趣,打算后面找时间学习一下.谁想到学习的欲望越来越强 ...
- 【广州.NET社区推荐】【译】Visual Studio 2019 中 WPF & UWP 的 XAML 开发工具新特性
原文 | Dmitry 翻译 | 郑子铭 自Visual Studio 2019推出以来,我们为使用WPF或UWP桌面应用程序的XAML开发人员发布了许多新功能.在本周的 Visual Studio ...
- 【译】Visual Studio 2019 中 WPF & UWP 的 XAML 开发工具新特性
原文 | Dmitry 翻译 | 郑子铭 自Visual Studio 2019推出以来,我们为使用WPF或UWP桌面应用程序的XAML开发人员发布了许多新功能.在本周的 Visual Studio ...
- xamarin android,UWP 网络类型和IP地址
App开发经常要判断网络连通情况,并判断网络类型,获取网络IP.xamarin中可以使用Dependencies提供各平台下的方法,现把各平台代码记录如下: using System; using S ...
随机推荐
- activemq 的那些事1
#关于事务: activemq 遇到的不能消息确认的问题. Session session = connection.createSession(Boolean.FALSE, Session.AU ...
- block引用外部变量原理
block在赋值时才会生成对应的block结构体实例(结构体数据结构在编译时已经生成),赋值时会扫一遍里面引用的外部变量(嵌套block中的外部变量也算,只不过嵌套block中的外部变量会被内外两个b ...
- php状态设计模式
状态设计模式的关键就是,环境中拥有所需的全部状态对象,每个状态对象又引用了环境对象:环境对象通过维护一个当前状态属性(用于存放状态对象)从而对所需的全部状态对象产生影响. 下面演示了一个简单的状态设计 ...
- 请求不同域的数据方法:requests Jsonp cors
在需要访问不同域的接口的数据的时候,一般有两种方式: 第一种: 使用requests模块,在业务逻辑中直接访问别的域的接口,获取数据,然后将返回的数据显示到前端页面上; 这个时候,数据访问的流程是: ...
- python-imaging-tk : Depends: python-imaging (= 1.1.7-4ubuntu0.12.04.3) but 3.1.2-0ubuntu1.1 is to be installed E: Unable to corre
最近,将电脑主机升级到ubuntu16.04,但是需要用到 python-imaging-tk,先是报错: import PIL.ImageTk as ImageTkImportError: No m ...
- netty 为什么用nio 不用 aio
NIO模型 同步非阻塞 NIO有同步阻塞和同步非阻塞两种模式,一般讲的是同步非阻塞,服务器实现模式为一个请求一个线程,但客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才 ...
- 使用 Ansible 统计服务器资源利用率
使用 Ansible 统计服务器资源利用率: 3 条 shell 脚本实现统计: CPU 利用率统计: top -bn1 | grep load | awk '{printf "CPU Lo ...
- load 过高分析办法
1.top -H 找到占用cpu较高的进程2.top -Hp pid 找到该进程下占用cpu较高的线程id3.sudo -u adminjstack -F 进程id > ~/stack.txt ...
- [leetcode]90. Subsets II数组子集(有重)
Given a collection of integers that might contain duplicates, nums, return all possible subsets (the ...
- kalman滤波(三)---各种滤波的方法汇总+优化的方法
大神解答 一.前提 最一般的状态估计问题,我们会根据系统是否线性,把它们分为线性/非线性系统.同时,对于噪声,根据它们是否为高斯分布,分为高斯/非高斯噪声系统.现实中最常见的,也是最困难的问题,是非线 ...