XAudio2不仅能够进行採样率转换。还能够进行混音。所谓混音就是将多路音频混合成一路进行输出。混音主要是IXAudio2SubmixVoice进行此项功能。

数据由IXAudio2SourceVoice提交后。流向IXAudio2SubmixVoice进行採样率转换(假设须要的话),而且进行音频混合,最后形成一路採样率和IXAudio2MasteringVoice一致的音频流,由IXAudio2MasteringVoice输出到音频输出设备。

混音主要步骤:

1.初始化COM组件。

2.指定特定格式创建Mastering Voice:2通道/48K。32位深。

3.创建一个IXAudio2SubmixVoice对象,格式和mastering voice一致:作用是混合两路音频为一路,并输出到mastering voice。

4.打开多个文件来提供多路音频数据:这里使用两个文件。

5.针对每一个文件创建IXAudio2SourceVoice对象,格式为每一个文件的格式。

6.针对每一个IXAudio2SourceVoice创建IXAudio2SubmixVoice对象,并分别设置输入格式为每一个文件相应的格式,分别设置为IXAudio2SourceVoice对象的输出voice,并分别指定IXAudio2SubmixVoice对象的输出voice为第三步创建的用来混音的IXAudio2SubmixVoice对象。

主要用来採样率转换,将採样率由文件提供的採样率转为和Mastering
Voice一致的採样率。

7.分配内存,分别读取文件数据。并制定到XAUDIO2_BUFFER。

8.分别调用SubmitSourceBuffer将数据提交。

9.分别调用Start来启动Source Voice。

10.等待播放完毕。

11.释放对象和内存数据。

主要实现代码例如以下:WaveFile.h/WaveFile.cpp请到前面文章中寻找地址自行下载。

#pragma once
#include "WaveFile.h"
#include "XAudio2.h" class VoiceCallback : public IXAudio2VoiceCallback
{
public:
HANDLE hBufferEndEvent;
VoiceCallback() : hBufferEndEvent(CreateEvent(NULL, FALSE, FALSE, NULL)){}
~VoiceCallback(){ CloseHandle(hBufferEndEvent); } //Called when the voice has just finished playing a contiguous audio stream.
void OnStreamEnd() { SetEvent(hBufferEndEvent); } //Unused methods are stubs
void OnVoiceProcessingPassEnd() { }
void OnVoiceProcessingPassStart(UINT32 SamplesRequired) { }
void OnBufferEnd(void * pBufferContext) { }
void OnBufferStart(void * pBufferContext) { }
void OnLoopEnd(void * pBufferContext) { }
void OnVoiceError(void * pBufferContext, HRESULT Error) { }
}; int main(int argc, char *argv[])
{
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);;//com初始化
if (FAILED(hr))
return 0; IXAudio2 *pEngine = NULL;
hr = XAudio2Create(&pEngine);//创建引擎
if (FAILED(hr))
return 0; WAVEFORMATEX waveFormatex;//设置主声音的格式
waveFormatex.nChannels = 2;
waveFormatex.nSamplesPerSec = 48000;
waveFormatex.wBitsPerSample = 32;
waveFormatex.nAvgBytesPerSec = 384000;
waveFormatex.nBlockAlign = 8;
waveFormatex.wFormatTag = WAVE_FORMAT_PCM; IXAudio2MasteringVoice *pMasterVoice = NULL;
hr = pEngine->CreateMasteringVoice(&pMasterVoice,waveFormatex.nChannels,waveFormatex.nSamplesPerSec);//创建主声音。默认是输出当前扬声器
if (FAILED(hr))
return 0; XAUDIO2_SEND_DESCRIPTOR pSend;
pSend.pOutputVoice = pMasterVoice;//指定输出为mastering voice
pSend.Flags = XAUDIO2_SEND_USEFILTER; XAUDIO2_VOICE_SENDS pSendList;
pSendList.pSends = &pSend;
pSendList.SendCount = 1; IXAudio2SubmixVoice *pSubmixVoice = NULL;
hr = pEngine->CreateSubmixVoice(&pSubmixVoice, waveFormatex.nChannels, waveFormatex.nSamplesPerSec, 0, 0, &pSendList);//指定输出为mastering voice,作用:混音,将两路音频数据混为一路并输出到mastering voice
if (FAILED(hr))
return 0; CWaveFile waveFile1;
hr = waveFile1.Open(L"C:\\Users\\xdd\\Desktop\\时间都去哪儿了.wav", NULL, WAVEFILE_READ);//载入文件1
if (FAILED(hr))
return 0; CWaveFile waveFile2;
hr = waveFile2.Open(L"C:\\Users\\xdd\\Desktop\\1KHz-stero.wav", NULL, WAVEFILE_READ);//载入文件2
if (FAILED(hr))
return 0; WAVEFORMATEX *waveFormat1 = waveFile1.GetFormat();//获取文件格式1
WAVEFORMATEX *waveFormat2 = waveFile2.GetFormat();//获取文件格式2 pSend.pOutputVoice = pSubmixVoice;//指定输出为SubmixVoice IXAudio2SubmixVoice *pSubmixVoice1 = NULL;
hr = pEngine->CreateSubmixVoice(&pSubmixVoice1, waveFormat1->nChannels, waveFormat1->nSamplesPerSec, 0, 0, &pSendList);//指定输出为pSubmixVoice,作用:对文件1的音频数据进行重採样为mastering voice的採样率
if (FAILED(hr))
return 0; IXAudio2SubmixVoice *pSubmixVoice2 = NULL;
hr = pEngine->CreateSubmixVoice(&pSubmixVoice2, waveFormat2->nChannels, waveFormat2->nSamplesPerSec, 0, 0, &pSendList);//指定输出为pSubmixVoice,作用:对文件2的音频数据进行重採样为mastering voice的採样率
if (FAILED(hr))
return 0; pSend.pOutputVoice = pSubmixVoice1;//指定输出为pSubmixVoice1 VoiceCallback voiceCallBack1;
IXAudio2SourceVoice *pSourceVoice1 = NULL;
hr = pEngine->CreateSourceVoice(&pSourceVoice1, waveFormat1, 0, 1.0f, &voiceCallBack1,&pSendList);//创建源声音。用来提交数据.指定输出为SubmixVoice1
if (FAILED(hr))
return 0; pSend.pOutputVoice = pSubmixVoice2;//指定输出为pSubmixVoice2 VoiceCallback voiceCallBack2;
IXAudio2SourceVoice *pSourceVoice2 = NULL;
hr = pEngine->CreateSourceVoice(&pSourceVoice2, waveFormat2, 0, 1.0f, &voiceCallBack2, &pSendList);//创建源声音,用来提交数据.指定输出为SubmixVoice2
if (FAILED(hr))
return 0; DWORD size1 = waveFile1.GetSize();//获取文件的大小
BYTE *pData1 = new BYTE[size1];//申请内存空间,用于保存数据
hr = waveFile1.Read(pData1, size1, &size1);//读取文件内容
if (FAILED(hr))
return 0; DWORD size2 = waveFile2.GetSize();//获取文件的大小
BYTE *pData2 = new BYTE[size2];//申请内存空间,用于保存数据
hr = waveFile2.Read(pData2, size2, &size2);//读取文件内容
if (FAILED(hr))
return 0; XAUDIO2_BUFFER buffer1 = {0};//将读取的文件数据,赋值XAUDIO2_BUFFER
buffer1.AudioBytes = size1;
buffer1.pAudioData = pData1;
buffer1.Flags = XAUDIO2_END_OF_STREAM; XAUDIO2_BUFFER buffer2 = { 0 };//将读取的文件数据。赋值XAUDIO2_BUFFER
buffer2.AudioBytes = size2;
buffer2.pAudioData = pData2;
buffer2.Flags = XAUDIO2_END_OF_STREAM; hr = pSourceVoice1->SubmitSourceBuffer(&buffer1);//提交内存数据
if (FAILED(hr))
return 0; hr = pSourceVoice2->SubmitSourceBuffer(&buffer2);//提交内存数据
if (FAILED(hr))
return 0; hr = pSourceVoice1->Start(0);//启动源声音
if (FAILED(hr))
return 0; hr = pSourceVoice2->Start(0);//启动源声音
if (FAILED(hr))
return 0; XAUDIO2_VOICE_STATE state;
pSourceVoice1->GetState(&state);//获取状态
while (state.BuffersQueued)
{
WaitForSingleObject(voiceCallBack1.hBufferEndEvent, INFINITE);
pSourceVoice2->GetState(&state);
WaitForSingleObject(voiceCallBack2.hBufferEndEvent, INFINITE);
} pMasterVoice->DestroyVoice();//释放资源
pSubmixVoice->DestroyVoice();//
pSubmixVoice1->DestroyVoice();//
pSubmixVoice2->DestroyVoice();//
pSourceVoice1->DestroyVoice();//释放资源
pSourceVoice2->DestroyVoice();//释放资源
pEngine->Release();//释放资源
CoUninitialize();//释放资源 delete []pData1;//释放资源
pData1 = NULL; delete[]pData2;//释放资源
pData2 = NULL; return 0;
}

交流QQ:1245178753

本文地址:http://blog.csdn.net/u011417605/article/details/51051039

源代码下载:http://download.csdn.net/detail/u011417605/9480309

XAudio2学习之混音的更多相关文章

  1. WebRTC 学习之 Conference 实现混音混屏

    混音 混音的意义就是将多个音频流混成一路音频,在Conference 的实现中有分为终端实现和服务器实现. 1. 终端混音实现: 终端接受到多路(一般是多个用户)的音频流之后,在终端本地将多路音频流混 ...

  2. (二) ffmpeg filter学习--混音实现

    Audio 混音实现 从FFMPEG原生代码doc/examples/filtering_audio.c修改而来. ffmpeg版本信息 ffmpeg version N-82997-g557c0df ...

  3. 在Python中使用moviepy进行音视频剪辑混音合成时输出文件无声音问题

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 在使用moviepy进行音视频剪辑时发现输出成功但 ...

  4. [Android] 混音线程MixerThread

    MixerThread是Android音频输出的核心部分,所有Android的音频都需要经过MixerThread进行混音后再输出到音频设备. MixerThread的继承关系如下: MixerThr ...

  5. ffmpeg混音(将多个声音合成一个)命令

    ffmpeg命令中可以使用filter amix实现这个功能. 官方文档 http://ffmpeg.org/ffmpeg-filters.html 6.8 amix Mixes multiple a ...

  6. pcm混音的一种方式

    转载 混音: Mix的意思是混音,无论在自然界,还是在音频处理领域这都是非常普遍的现象.自然界里你能同时听到鸟鸣和水声,这是因为鸟鸣和水声的波形在空气中形成了叠加,耳朵听到后能区分鸟鸣和水声这两种波形 ...

  7. C#混音同时录制采集声卡和麦克风话筒

    在项目中,我们可能需要同时录制声卡的声音和麦克风的声音,比如直播间,在线教学.那么如何实现呢?当然是采用SharpCapture!下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一步: ...

  8. 2019 WebRtc AudioMixer混音流程

    本文简要说明最新版WebRtc AudioMixer混音流程. 本程序使用4个16KHz 单声道时长均大于10秒的Wav文件作为混音源,只合成前10秒的音频,输出也是16KHz单声道音频. 输入和输出 ...

  9. FL Studio带你走进混音的世界

    混音,是把多种音源整合到一个立体音轨或单音音轨中,通俗讲就是对多种声音进行调整后叠加在一起,这样可以让音乐听起来非常有层次感,尤其是在电音制作过程中,混音的质量更是起到了决定性的作用.音乐制作软件FL ...

随机推荐

  1. 【计算几何】【凸包】【极角排序】【二分】Gym - 101128J - Saint John Festival

    平面上n个红点,m个黑点,问你多少个黑点至少在一个红三角形内. 对红点求凸包后,转化为询问有多少个黑点在凸包内. 点在凸多边形内部判定,选定一个凸包上的点作原点,对凸包三角剖分,将其他的点极角排序之后 ...

  2. 【动态规划】【线段树】 Codeforces Round #426 (Div. 1) B. The Bakery

    给你一个序列,让你划分成K段,每段的价值是其内部权值的种类数,让你最大化所有段的价值之和. 裸dp f(i,j)=max{f(k,j-1)+w(k+1,i)}(0<=k<i) 先枚举j,然 ...

  3. 【bitset】【推导】hdu5961 传递

    <法一>http://blog.csdn.net/u014325920/article/details/53046890 1.判断传递的条件为:若G中有 一条边从a到b且有一条边从b到c ...

  4. Mobiscroll手机触屏日期选择器

       最近在制作jquery mobile因要用到日历控件,突然发现Mobiscroll非常不错.于是摘下来记录. A Mobiscroll是一个用于触摸设备(Android phones.iPhon ...

  5. c99柔性数组

    变长结构体 struct test { int nSize; char data[]; // 或者 char data[0];但建议使用 char data[]; 注意:c98 时不支持柔性数组,其仅 ...

  6. Android:布局实例之模仿QQ登录界面

    预览图: 准备: 1.找到模仿对象 QQ登陆界面UI下载>>>>> 2.导入工程 3.查看布局结构和使用控件 其对应效果图分布为 4.分析样式选择器 下拉箭头2种样式:点 ...

  7. Unity中Invoke 和 InvokeRepeating的区别

    Invoke() 方法是 Unity3D 的一种委托机制 如: Invoke("Test", 5);   它的意思是:5 秒之后调用 Test() 方法: 使用 Invoke() ...

  8. MATLAB/Octave中implicit conversion from real matrix to real scalar错误原因与解决

    写程序时提示 implicit conversion from real matrix to real scalar的一个warning,主要问题在于将一个矩阵当成一个标量在使用.我的程序出现这个wa ...

  9. [典型漏洞分享]结合YS业务分析使用oauth协议的风险

    结合YS业务分析oauth协议风险 问题描述: YS 使用QQ互联的openAPI实现QQ登录YS的功能,使用该功能需要在腾讯注册登录时的回调地址,根据oauth协议,用户的code或者access_ ...

  10. Nand Flash与Nor

    转:http://www.360doc.com/content/11/1215/15/1299815_172458274.shtml Flash经常在一些地方被提到,一直没认真去理解它们的区别,因此, ...