windows core audio apis
这个播放流程有一次当初不是很理解,做个记录,代码中的中文部分,原文档是有解释的:
To move a stream of rendering data through the endpoint buffer, the client alternately calls the IAudioRenderClient::GetBuffer method and theIAudioRenderClient::ReleaseBuffer method. The client accesses the data in the endpoint buffer as a series of data packets. The GetBuffer call retrieves the next packet so that the client can fill it with rendering data. After writing the data to the packet, the client calls ReleaseBuffer to add the completed packet to the rendering queue.
看最后一句,客户端通过执行ReleaseBuffer,来把已完成的数据包追加到渲染队列去,除了这个我估计还会做一些Realse工作比如修改某个状态等。
//-----------------------------------------------------------
// Play an audio stream on the default audio rendering
// device. The PlayAudioStream function allocates a shared
// buffer big enough to hold one second of PCM audio data.
// The function uses this buffer to stream data to the
// rendering device. The inner loop runs every 1/2 second.
//----------------------------------------------------------- // REFERENCE_TIME time units per second and per millisecond
#define REFTIMES_PER_SEC 10000000
#define REFTIMES_PER_MILLISEC 10000 #define EXIT_ON_ERROR(hres) \
if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) \
{ (punk)->Release(); (punk) = NULL; } const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioClient = __uuidof(IAudioClient);
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient); HRESULT PlayAudioStream(MyAudioSource *pMySource)
{
HRESULT hr;
REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
REFERENCE_TIME hnsActualDuration;
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;
IAudioClient *pAudioClient = NULL;
IAudioRenderClient *pRenderClient = NULL;
WAVEFORMATEX *pwfx = NULL;
UINT32 bufferFrameCount;
UINT32 numFramesAvailable;
UINT32 numFramesPadding;
BYTE *pData;
DWORD flags = 0; hr = CoCreateInstance(
CLSID_MMDeviceEnumerator, NULL,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
(void**)&pEnumerator);
EXIT_ON_ERROR(hr) hr = pEnumerator->GetDefaultAudioEndpoint(
eRender, eConsole, &pDevice);
EXIT_ON_ERROR(hr) hr = pDevice->Activate(
IID_IAudioClient, CLSCTX_ALL,
NULL, (void**)&pAudioClient);
EXIT_ON_ERROR(hr) hr = pAudioClient->GetMixFormat(&pwfx);
EXIT_ON_ERROR(hr) hr = pAudioClient->Initialize(
AUDCLNT_SHAREMODE_SHARED,
0,
hnsRequestedDuration,
0,
pwfx,
NULL);
EXIT_ON_ERROR(hr) // Tell the audio source which format to use.
hr = pMySource->SetFormat(pwfx);
EXIT_ON_ERROR(hr) // Get the actual size of the allocated buffer.
hr = pAudioClient->GetBufferSize(&bufferFrameCount);
EXIT_ON_ERROR(hr) hr = pAudioClient->GetService(
IID_IAudioRenderClient,
(void**)&pRenderClient);
EXIT_ON_ERROR(hr)
//////从这一直到下面的结束,其实发现,还要修改播放缓冲,就得固定的需要三个步骤,主要这里省的以后去分析他为什么这么做,其实这就是他固定的过程
// Grab the entire buffer for the initial fill operation.
hr = pRenderClient->GetBuffer(bufferFrameCount, &pData);
EXIT_ON_ERROR(hr) // Load the initial data into the shared buffer.
hr = pMySource->LoadData(bufferFrameCount, pData, &flags);
EXIT_ON_ERROR(hr) hr = pRenderClient->ReleaseBuffer(bufferFrameCount, flags);
EXIT_ON_ERROR(hr)
//////结束
// Calculate the actual duration of the allocated buffer.
hnsActualDuration = (double)REFTIMES_PER_SEC *
bufferFrameCount / pwfx->nSamplesPerSec; hr = pAudioClient->Start(); // Start playing.
EXIT_ON_ERROR(hr) // Each loop fills about half of the shared buffer.
while (flags != AUDCLNT_BUFFERFLAGS_SILENT)
{
// Sleep for half the buffer duration.
Sleep((DWORD)(hnsActualDuration/REFTIMES_PER_MILLISEC/2)); // See how much buffer space is available.
hr = pAudioClient->GetCurrentPadding(&numFramesPadding);
EXIT_ON_ERROR(hr) numFramesAvailable = bufferFrameCount - numFramesPadding; // Grab all the available space in the shared buffer.
hr = pRenderClient->GetBuffer(numFramesAvailable, &pData);
EXIT_ON_ERROR(hr) // Get next 1/2-second of data from the audio source.
hr = pMySource->LoadData(numFramesAvailable, pData, &flags);
EXIT_ON_ERROR(hr) hr = pRenderClient->ReleaseBuffer(numFramesAvailable, flags);
EXIT_ON_ERROR(hr)
} // Wait for last data in buffer to play before stopping.
Sleep((DWORD)(hnsActualDuration/REFTIMES_PER_MILLISEC/2)); hr = pAudioClient->Stop(); // Stop playing.
EXIT_ON_ERROR(hr) Exit:
CoTaskMemFree(pwfx);
SAFE_RELEASE(pEnumerator)
SAFE_RELEASE(pDevice)
SAFE_RELEASE(pAudioClient)
SAFE_RELEASE(pRenderClient) return hr;
}
windows core audio apis的更多相关文章
- 使用 Windows Core Audio APs 进行 Loopback Recording 并生成 WAV 文件
参考文档 COM Coding Practices Audio File Format Specifications Core Audio APIs Loopback Recording #inclu ...
- Core Audio(一)
Core Audio APIs core audio apis是vista之后引入的,不使用与之前的windows版本:core audio apis提供访问endpoint devices,比如耳机 ...
- Core Audio(二)
用户模式音频组件 在windows vista中,core audio apis充当用户模式音频子系统的基础,core audio apis作为用户模式系统组件的一个thin layer,它用来将用户 ...
- Core Audio 在Vista/Win7上实现
应用范围:Vista / win7, 不支持XP 1. 关于Windows Core Auido APIs 在Windowss Vista及Windows 7操作系统下,微软为应用程序提供了一套新的音 ...
- 使用Core Audio实现VoIP通用音频模块
最近一直在做iOS音频技术相关的项目,由于单项直播SDK,互动直播SDK(iOS/Mac),短视频SDK,都会用到音频技术,因此在这里收集三个SDK的音频技术需求,开发一个通用的音频模块用于三个SDK ...
- Core Audio(三)
音频终端设备(Audio Endpoint Devices) endpoint device指的是应用程序的数据通道上起始或终止的硬件设备,如扬声器,耳机,话筒等:沿着数据通道可能穿越一定数目的硬件和 ...
- 使用Core Audio实现对声卡输出的捕捉
涉及的接口有: IMMDeviceEnumerator IMMDevice IAudioClient IAudioCaptureClient 主要过程: 创建多媒体设备枚举器(IMMDeviceEnu ...
- (四)WebRTC手记之本地音频采集
转自:http://www.cnblogs.com/fangkm/p/4374668.html 上一篇博文介绍了本地视频采集,这一篇就介绍下音频采集流程,也是先介绍WebRTC原生的音频采集,再介绍C ...
- WebRTC手记之本地音频采集
转载请注明出处:http://www.cnblogs.com/fangkm/p/4374668.html 上一篇博文介绍了本地视频采集,这一篇就介绍下音频采集流程,也是先介绍WebRTC原生的音频采集 ...
随机推荐
- android滑动删除的多种实现方式(一)
个人习惯,先上图 同事是个妹子(这点很重要),写滑动删除动能的时候用到了SwipeLayout,然后悲催的是,滑动时间被拦截了,解决方法先不提,在(一)中先讲解SwipeLayout下载listvie ...
- ListView的性能优化之convertView和viewHolder
转载请注明出处 最近碰到的面试题中经常会碰到问"ListView的优化"问题.所以就拿自己之前写的微博客户端的程序做下优化. 自己查了些资料,看了别人写的博客,得出结论,ListV ...
- Circle - SGU 130(递推)
题目大意:一个圆上有2K个点,用K个线把他们连接起来,求出这些线最少可以把这个圆分成P部分,有N种分割方法.输出N和P. 分析:分割线一定是相互不相交的线,所以可以把这写分成两部分,f[i] += f ...
- centos7免密码登录
2台主机 192.168.30.207 Master 192.168.30.251 Node1 三台主机检查 ~/.ssh 文件夹没有则新建 ssh-keygen -t rsa 一路狂按回车,最终生成 ...
- XSS 简单理解
什么是XSS? XSS(Cross Site Scripting),即跨站脚本攻击,是一种常见于web application中的计算机安全漏洞.XSS通过在用户端注入恶意的可运行脚本,若服务器端对用 ...
- Open XML Format SDK引用
Excel的便捷使得其在非开发人员的办公中非常流行,而Excel确实也提供了很多有用的功能.很多时候我们还需要以Excel为数据源来进行处理或者将Excel作为模板来生成一些报表.在Open XML ...
- 3高并发server:多路IO之epoll
1 epoll epoll是Linux下多路复用IO接口select/poll的增强版本号,它能显著提高程序在大量并.发连接中仅仅有少量活跃的情况下的系统CPU利用率,由于它会复用文件描写叙述符 ...
- QT 读写sqllite数据库
QT 读写sqllite数据库 分类: 技术资料2014-04-10 10:39 84人阅读 评论(0) 收藏 举报 #include <QtGui/QApplication> #incl ...
- CH BR8(小学生在上课-逆元和互质数一一对应关系)
小学生在上课 总时限 11s 内存限制 256MB 出题人 jzc 提交情况 66/277 初始分值 600 锁定情况 背景 小学生在学校上数学课…… 描述 数学课上,小学生刚学会了乘除法.老师问了他 ...
- IOS-CGAffineTransformMake 矩阵变换 的运算原理
1.矩阵的基本知识: struct CGAffineTransform { CGFloat a, b, c, d; CGFloat tx, ty; }; CGAffineTransform C ...