Windows(C#)音频开发-Windows Core Audio(WASAPI)

这篇具有很好参考价值的文章主要介绍了Windows(C#)音频开发-Windows Core Audio(WASAPI)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文的例子使用NAudio.CoreAudioApi实现,全部为C#代码

以下仅为个人理解,不一定都对,勿信~

阅读这个文档,最好具备C++知识,因为会用到Marshal命名空间进行指针操作

一、关于Windows Core Audio

Windows Core Audio API 是一种非常底层的音频API,上层应用为DirectSound或者WaveXXX接口等,WASAPI是其中的一部分。

Windows Core Audio API 构成

Multimedia Device API(MMDevice):表示系统中的音频设备节点(Audio Device Endpoint),Mmdeviceapi.h

Windows Audio Session API(WASAPI):用来操作音频设备节点之间的音频流(Audio Stream),Audioclient.h,Audiopolicy.h,Audiosessiontypes.h

DeviceTopology API:用来处理音频设备节点拓扑结构。可以设计音频设备节点之间的数据流向,Devicetopology.h

EndpointVolume API:当音频设备节点为声卡独占模式(Exclusive-mode)时,使用该API对Volume进行操作,Endpointvolume.h

以上头文件位置,XXXX\Windows SDK\include,由于效率问题,这些接口以COM形式出现,而不是.net或者.net freamwork

我的电脑中,通过VS安装Windows SDK后,头文件位置为C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\um

一些常见C#库都对其有映射,BASS.Net,NAudio。

以上接口调用顺序:

CoCreateInstance -> IMMDeviceEnumerator -> IMMDevice -> WASAPI DTAPI EVAPI

各种例子,Microsoft Learn: Build skills that open doors in your career,Windows SDK and emulator archive | Microsoft Developer

二、用户模式下的音频组件 User-Mode Audio Components

User Client:QQ音乐

User Mode:Core Audio(Audio Endpoint)、Direct Sound(High-Level API)

Kernel Mode:驱动(Audio Driver)、声音硬件(Audio Adapter)

Audio Endpoint Device:音频设备节点,对声音硬件的抽象,常见的声音硬件有喇叭、耳机、话筒、麦克风

三、Audio Endpoint Device

Audio Endpoint:表示一个声音设备

Audio Adapter:一个声音设备处理声音的流程,如A/D,D/A,输出,输入

MMDvice API用来处理和Audio Endpoint相关的操作。

实现方式:

C++

使用CoCreateInstance -> IMMDeviceEnumerator -> 其他API,包括:

IMMDevice、IMMEndpoint、IMMNotificationClient(热插拔设备)

NAudio

MMDeviceEnumerator -> MMDevice

获取到MMDevice后,调用Activate方法激活设备,随后调用WASAPI,DTAPI,EVAPI

获取到Audio Device后,就可以创建AudioClient实例进行WASAPI操作了

四、Audio Session

Audio Stream:音频流,可以为Recording 或者 Playing

Audio Session:每一个Audio Stream都对应一个Audio Stream,每一个Audio Session都对应一个Audio Device

与上文提到的IMMNotificationClient,对应Session也有事件处理接口IAudioSessionEvents,这些接口主要处理状态变化、音量变化、开始Session、结束Session等和声音处理相关的事件

获取到Audio Device后可以通过AudioSessionManager来确认系统中有哪些Session

五、Audio Stream

获取到Audio Device后,如果Activate成功,就可以得到AudioClient实例

通过AudioClient实例不仅可以获取到Audio Session,还可获取到Audio Stream

Audio Stream就是实际的音频数据,通过WASAPI对其进行操作文章来源地址https://www.toymoban.com/news/detail-797271.html

六、Audio Render Client 一个播放音频的例子

// 使用NAudio.WaveFileReader读取wav文件
// 使用FileStream也可以,不过需要自己解析Wave Chunk
// 例子中使用的wav文件为48000,32bit,2-channel,PCM
// 因此每一帧的大小 frame = 32bit / 8 * 2 = 8 bytes
var reader = new WaveFileReader(odl.FileName);

// 每次读取48000帧,也就是1秒钟
// 每帧大小为4bytes
int frame = 48000;
var bytes = new Byte[frame * 8];
reader.Read(bytes, 0, frame * 8);

// 以下为Core Audio部分,使用的是NAudio.CoreAudioAPI的C#映射

// 获取Core Audio Device遍历接口
var enumer = new NAudio.CoreAudioApi.MMDeviceEnumerator();

// 获取默认的Audio Device,Render表示输出设备,Multimedia表示多媒体设备
// 备注:Capture是录音设备,Console是交互设备,Communication是通讯设备
var device = enumer.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);

// 读取文件的WAVE配置,并初始化给输出设备
var format = reader.WaveFormat;

// Audio Device只是表示声音设备,并不是真正处理声音的抽象
// Audio Client才是处理声音的抽象
var audioClient = device.AudioClient;
audioClient.Initialize(
     AudioClientShareMode.Shared,
     AudioClientStreamFlags.None,
     10000000,
     0,
     format,
     Guid.Empty);

// 获取输出设备每次可以填充的音频缓冲区大小
// 单位是Frame,Frame与Byte的对应关系要根据WaveFormat计算
var bufferSize = audioClient.BufferSize;

// 获取输出设备
var renderclient = audioClient.AudioRenderClient;

// 填充第一帧音频输出缓冲区
// 由于Core Audio是COM接口,要用Marshal.Copy完成指针内存拷贝
var pData = renderclient.GetBuffer(frame);
Marshal.Copy(bytes, 0, pData, frame * 8);
renderclient.ReleaseBuffer(bufferSize, AudioClientBufferFlags.None);

// 开始播放音频
audioClient.Start();

// 以下为循环填充,否则只播放一次缓冲区数据
var sec = 1;

var stop = false;
while (!stop)
{
    Thread.Sleep(1000);
    reader.Read(bytes, 0, frame * 8);
    pData = renderclient.GetBuffer(frame);
    Marshal.Copy(bytes, 0, pData, frame * 8);
    renderclient.ReleaseBuffer(bufferSize, AudioClientBufferFlags.None);
}

audioClient.Stop();

renderclient.Dispose();
renderclient = null;
audioClient.Dispose();
audioClient = null;
device.Dispose();
device = null;

七、Audio Capture 一个录音的例子

// 与Audio Render部分的逻辑相同

var device = this.captureComboBox.SelectedItem as NAudio.CoreAudioApi.MMDevice;
var format = device.AudioClient.MixFormat;
var writer = new WaveFileWriter("capture.wav", format);
var audioClient = device.AudioClient;
audioClient.Initialize(
     AudioClientShareMode.Shared,
     AudioClientStreamFlags.AutoConvertPcm,
     10000000, // sec
     0,
     format,
     Guid.Empty);
var bufferSize = audioClient.BufferSize;
var captureclient = audioClient.AudioCaptureClient;

var sec = 1;

audioClient.Start();

while (!stop)
{
    // 0 表示没有录音
    var packageSize = captureclient.GetNextPacketSize();
    while (packageSize != 0)
    {
        int numFramestoRead = 0;
        AudioClientBufferFlags flags = AudioClientBufferFlags.None;
        IntPtr package = captureclient.GetBuffer(out numFramestoRead, out flags);
        captureclient.ReleaseBuffer(numFramestoRead);
        var length = numFramestoRead * 8;
        var buffer = new byte[length];
        Marshal.Copy(package, buffer, 0, length);
        writer.Write(buffer, 0, length);
        packageSize = captureclient.GetNextPacketSize();
    }
}

writer.Close();
writer.Dispose();
writer = null;

audioClient.Stop();
captureclient.Dispose();
captureclient = null;
audioClient.Dispose();
audioClient = null;
device.Dispose();
device = null;

到了这里,关于Windows(C#)音频开发-Windows Core Audio(WASAPI)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • flutter开发实战-just_audio实现播放音频暂停音频设置音量等

    flutter开发实战-just_audio实现播放音频暂停音频设置音量等 最近开发过程中遇到需要播放背景音等音频播放,这里使用just_audio来实现播放音频暂停音频设置音量等 在pubspec.yaml引入just_audio 在iOS上,video_player使用的是AVPlayer进行播放。 在Android上,video_player使用的是ExoPlayer。 2.

    2024年02月13日
    浏览(44)
  • 音频编辑开发SDK Audio DJ Studio for .NET Crack

    11.7版本--Audio DJ Studio for .NET 是 MultiMedia Soft 开发的 .NET Windows Forms 自定义控件,可以轻松地向使用 Microsoft Visual Studio 编写的 Winform 和 WPF 应用程序 添加声音播放和混音功能;由于与 DirectShow 编解码器和 BASS 库的集成,两者都允许对最常见的声音格式(如 MP3、WAV、Ogg Vorbis 和许

    2023年04月19日
    浏览(35)
  • C# Winform编程 NAudio 音频库

    项目=NuGet包管理器 搜索NAudio点击安装,自动安装依赖库。 安装成功后工具箱会新增NAudio.WinForms控件 NAudio为.NET平台下的开源库,采用ML-PL协议,开源地址:https://github.com/naudio/NAudio支持多种音频操作,可实现多种API播放与录制、多种不同音频格式、音频格式转换(重采样、位

    2024年01月23日
    浏览(45)
  • C#程序设计——Windows应用程序开发,1、初步掌握Windows应用程序的设计方法。2、掌握常用窗体控件的使用方法。

    初步掌握Windows应用程序的设计方法。 掌握常用窗体控件的使用方法。 1、设计一个Windows应用程序,创建一个用于添加学生个人基本信息的窗体,窗体下方法同时滚动信息“天行健,君子以自强不息!”。   要示如下: 如图1所示,设计窗体界面控件的布局 图1 学生信息管理

    2024年02月10日
    浏览(80)
  • 【.NET Core】C#预处理器指令

    预处理器指令 是指编译器在实际编译开始之前对信息进行预处理。通常是简化源程序在不同的环境中运行。尽管编译器没有单独的预处理器,但是本文所说的指令的处理方式与有预处理器时一样。可以使用这些指令来帮助条件编译。不同于C和C++指令,不能使用这些指令来创

    2024年01月17日
    浏览(40)
  • C# 静态构造函数未执行 .net core框架

    代码如下,在执行Encoding.GetEncoding(“gb2312”);方法后报错,说没有找到对应编码,经测试,发现是静态构造函数未执行。 将代码改成这样就恢复正常了: 推测是编译器认为静态构造函数无用,被优化掉了。 也可能是静态函数的调用方式并非在类加载时调用,而是在实例化

    2024年02月10日
    浏览(35)
  • 【C#】.net core 6.0 依赖注入生命周期

    给自己一个目标,然后坚持一段时间,总会有收获和感悟! 对于.net core而言,依赖注入生命周期有三种瞬态(Transient)、作用域(Scoped)和单例(Singleton),无论使用哪种生命周期,都需要确保对象的线程安全性,并正确地处理依赖关系。 在了解依赖注入的生命周期前,我

    2024年02月03日
    浏览(49)
  • 【c#,.NET】Entity Framework Core基础详解

    目录   一、EF Core概述 1.1 什么是ORM?  1.2 EF Core的性能怎么样  二、EF Core入门 2.1 什么是Migration数据库迁移: 2.2  EF Core数据的增删改查 2.2.1 增加数据 2.2.2 查询数据  2.2.3 修改和删除数据 三、EF Core的实体类配置 3.1 约定大于配置 3.2 EF Core两种配置方式 3.2.1 Data Annotation 3.2.2 

    2024年02月04日
    浏览(62)
  • 用 C# 实现独占音频设备降低其它程序的音量

    C#调用 Windows 辅助功能 API \\\"AccSetRunningUtilityState\\\" 函数实现音频避闪功能 音频闪避是指当自身应用程序,例如辅助功能程序,正在播放音频的时候,降低其他应用程序的音量。这样可以让用户更清楚地听到自身应用程序的音频,例如文字转语音或者导航提示。Windows API 提供了一

    2024年02月03日
    浏览(32)
  • C# 将音频PCM数据封装成wav文件

    之前实现了《C++ 将音频PCM数据封装成wav文件》,最近将其改成了C#版本。使用C#实现录音功能时还是需要写wav文件的,直接用C#实现也是比较简单的,这样可以免去不必要的依赖。 首先需要构造wav头部,wav文件音频信息全部保存在头部,我们要做的就是在PCM数据的前面加入w

    2024年02月07日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包