DirectSound学习笔记,最简便易行的视音频播放示例
分类:澳门新萄京

DirectSound是DirectX组件之朝气蓬勃,提供了对音频设备的破获和播放技能,同不经常候它也是唯生龙活虎多少个辅助Xp系统的点子技能之豆蔻年华。 DirectSound重要有以下特征:

正文记录DirectSound播放音频的技艺。DirectSound是Windows下最广泛的节拍播放技巧。近来一大半的节奏播放应用都以透过DirectSound来播放的。本文记录叁个选取DirectSound播放PCM的例证。
注:一个人老兄已经提醒小编DirectSound已经安插被X奥迪(Audi卡塔尔国o2替代了。后来考证了瞬间意识确有那一件事。由此在后一次更新初级中学完成学业生升学考试虑投入X奥迪(Audi卡塔尔(قطر‎o2播放PCM的例子。本文如故记录一下DirectSound这位“元老”。

DirectSound设备

优点:

澳门新萄京 1

 

  • 广播音频低延迟
  • 硬件能源调节
  • 同时播放多个声音。
  • 支配硬件缓冲区的应用优先级(DirectSound使用缓冲区来播放音频)。
  • 模拟3D节奏碰到。
  • 动态改换音响效果(回声、和声等)。
  • 破获音频输入设备声音位wav(多为PCM数据,未经压缩)。

 

DirectSound设备对象表示三个播放设备,它被用来治本设施和创设声音缓冲区。

缺点:

DirectSound简介

DirectSound是微软所付出DirectX的零器件之一,能够在Windows 操作系统上录音,并且记录波形音响效果(waveform sound)。近年来DirectSound 是贰个早熟的API ,提供大多实用的功用,比方能够在较高的分辨率播放多声道音响。
DirectSound3D(DS3D)最初是壹玖玖伍年与 DirectX 3 一齐发布的。DirectX 8今后的DirectSound和DirectSound3D的(DS3D)被合称DirectX 奥迪o。

DirectSound有以下两种对象:

对象

数量

作用

主要接口

设备

每个应用程序只有一个设备对象

用来管理设备,创建辅助缓冲区

IDirectSound8

辅助缓冲区

每一个声音对应一个辅助缓冲区

用来管理一个静态的或者动态的声音流,然后在主缓冲区中混音

IDirectSoundBuffer8,

IDirectSound3DBuffer8,

IDirectSoundNotify8

主缓冲区

一个应用程序只有一个主缓冲区

将辅助缓冲区的数据进行混音,并且控制3D参数.

IDirectSoundBuffer,

IDirectSound3DListener8

多个应用程序可感到相通的动静设备创立对象。当输入聚焦于应用程序间的改换时,音频输出自动从叁个应用程序流转变来此外应用程序流。因而,当输入聚集于变化时,应用程序不必一再地播报和制动踏板它们的缓冲区。

  • 只好播放wav音频文件。

DirectSound播放音频的流水生产线

应用DirectSound播放音频通常情形下须要如下步骤:

  1. 初始化

1卡塔尔 创制四个IDirectSound8接口的对象
2卡塔尔(قطر‎ 设置协作级
3卡塔尔 创造一个主缓冲对象
4卡塔尔(英语:State of Qatar) 创设贰个副缓冲对象
5卡塔尔 创制文告对象
6卡塔尔 设置公告地点

7卡塔尔(قطر‎ 最先广播

  1. 循环播放音响

1卡塔尔(قطر‎ 数据填充至副缓冲区

2卡塔尔(英语:State of Qatar) 等待播放完毕

上边结合详细剖判一下上文的流水生产线。

1. 初始化
1卡塔尔(قطر‎ 创立三个IDirectSound8接口的靶子

透过DirectSoundCreate8(卡塔尔(英语:State of Qatar)方法能够成立三个设施对象。那几个指标日常代表缺省的播音设备。DirectSoundCreate8(卡塔尔(英语:State of Qatar)函数原型如下。

[cpp] view plaincopy澳门新萄京 2澳门新萄京 3

 

  1. HRESULT DirectSoundCreate8(  
  2.      LPCGUID lpcGuidDevice,  
  3.      LPDIRECTSOUND8 * ppDS8,  
  4.      LPUNKNOWN pUnkOuter  
  5. )  

参数的意思如下:
lpcGuidDevice:要开创的装置对象的GUID。能够钦赐为NULL,代表暗许的播音设备。
ppDS8:重临的IDirectSound8对象的地点。
pUnkOuter:必需设为NULL。
举个例子如下代码就可以创立贰个IDirectSound8接口的对象

[cpp] view plaincopy澳门新萄京 4澳门新萄京 5

 

  1. IDirectSound8 *m_pDS=NULL;    
  2. DirectSoundCreate8(NULL,&m_pDS,NULL);  

2卡塔尔(英语:State of Qatar) 设置协作级
Windows 是贰个多职分遇到,同期有五个应用程序去拜谒设备。通过选取合营等第,DirectSound能够保障应用程序不会在其他设施选用时去拜候,每个DirectSound应用程序都有叁个合作品级,这几个等级决定着访谈硬件的权能。
在开创八个装置对象今后,务必透过用IDirectSound8的SetCooperativeLevel(卡塔尔国设置同盟权限,不然将听不到声音。SetCooperativeLevel(卡塔尔(英语:State of Qatar)的原型如下

[cpp] view plaincopy澳门新萄京 6澳门新萄京 7

 

  1. HRESULT SetCooperativeLevel(  
  2.  HWND hwnd,  
  3.  DWORD dwLevel  
  4. )  

参数的意思如下:
hwnd:应用程序窗口句柄。
dwLevel:援救以下三种品级。
DSSCL_EXCLUSIVE:与DSSCL_PMuranoIOPRADOITY具有相通的作用。
DSSCL_NORMAL:寻常的和谐层级标记,其余程序可分享声卡设备开展播放。
DSSCL_P昂CoraIOKoleosITY:设置声卡设备为如今景序独自占领。
DSSCL_W奇骏ITEP奥迪Q7IMAOdyssey:可写主缓冲区,那时副缓冲区就无法进行广播处理,即无法将次缓冲区的数额送进混声器,再出口到主缓冲区上。这是最完全调整声音播放的法子。

3卡塔尔 创制多少个主缓冲对象
利用IDirectSound8的CreateSoundBuffer(卡塔尔(قطر‎能够成立一个IDirectSoundBuffer接口的主缓冲区对象。CreateSoundBuffer(卡塔尔(英语:State of Qatar)的原型如下。

[cpp] view plaincopy澳门新萄京 8澳门新萄京 9

 

  1. HRESULT CreateSoundBuffer(  
  2.  LPCDSBUFFERDESC pcDSBufferDesc,  
  3.  LPDIRECTSOUNDBUFFER * ppDSBuffer,  
  4.  LPUNKNOWN pUnkOuter  
  5. )  

参数的含义如下:
pcDSBufferDesc:描述声音缓冲的DSBUFFE福特ExplorerDESC构造体的地址
ppDSBuffer:重返的IDirectSoundBuffer接口的对象之处。
pUnkOuter:必得设置为NULL。
内部提到到贰个陈述声音缓冲的布局体DSBUFFE君越DESC,该构造体的概念如下:

[cpp] view plaincopy澳门新萄京 10澳门新萄京 11

 

  1. typedef struct _DSBUFFERDESC  
  2. {  
  3.     DWORD           dwSize;  
  4.     DWORD           dwFlags;  
  5.     DWORD           dwBufferBytes;  
  6.     DWORD           dwReserved;  
  7.     LPWAVEFORMATEX  lpwfxFormat;  
  8. } DSBUFFERDESC  

简短解释一下此中的变量的意义:
dwSize:布局体的朗朗上口。务必开头化该值。
dwFlags:设置声音缓存的性情。有超级多取舍,能够组成使用,就不生机勃勃一列出了。详细的参数能够查看文书档案。
dwBufferBytes:缓冲的高低。
dwReserved:保留参数,暂且并未用。
lpwfxFormat:指向贰个WAVE格式文件头的指针。
安装DSBUFFEWranglerDESC完结后,就可以采纳CreateSoundBuffer(卡塔尔(英语:State of Qatar)创制主缓冲了。示例代码如下:

[cpp] view plaincopy澳门新萄京 12澳门新萄京 13

 

  1. DSBUFFERDESC dsbd;  
  2. memset(&dsbd,0,sizeof(dsbd));  
  3. dsbd.dwSize=sizeof(dsbd);  
  4. dsbd.dwFlags=DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY |DSBCAPS_GETCURRENTPOSITION2;  
  5. dsbd.dwBufferBytes=MAX_AUDIO_BUF*BUFFERNOTIFYSIZE;   
  6. //WAVE Header  
  7. dsbd.lpwfxFormat=(WAVEFORMATEX*)malloc(sizeof(WAVEFORMATEX));  
  8. dsbd.lpwfxFormat->wFormatTag=WAVE_FORMAT_PCM;     
  9. /* format type */  
  10. (dsbd.lpwfxFormat)->nChannels=channels;            
  11. /* number of channels (i.e. mono, stereo...) */  
  12. (dsbd.lpwfxFormat)->nSamplesPerSec=sample_rate;       
  13. /* sample rate */  
  14. (dsbd.lpwfxFormat)->nAvgBytesPerSec=sample_rate*(bits_per_sample/8)*channels;   
  15. /* for buffer estimation */  
  16. (dsbd.lpwfxFormat)->nBlockAlign=(bits_per_sample/8)*channels;          
  17. /* block size of data */  
  18. (dsbd.lpwfxFormat)->wBitsPerSample=bits_per_sample;       
  19. /* number of bits per sample of mono data */  
  20. (dsbd.lpwfxFormat)->cbSize=0;  
  21.   
  22.   
  23. //Creates a sound buffer object to manage audio samples.   
  24. HRESULT hr1;  
  25. if( FAILED(m_pDS->CreateSoundBuffer(&dsbd,&m_pDSBuffer,NULL))){     
  26.     return FALSE;  
  27. }  

4卡塔尔 创设贰个副缓冲对象
行使IDirectSoundBuffer的QueryInterface(卡塔尔(قطر‎能够收获二个IDirectSoundBuffer8接口的靶子。IDirectSoundBuffer8的GUID为IID_IDirectSoundBuffer8。示例代码如下。

[cpp] view plaincopy澳门新萄京 14澳门新萄京 15

 

  1. IDirectSoundBuffer *m_pDSBuffer=NULL;  
  2. IDirectSoundBuffer8 *m_pDSBuffer8=NULL;  
  3. ...  
  4. if( FAILED(m_pDSBuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID*)&m_pDSBuffer8))){  
  5.     return FALSE ;  
  6. }  

5卡塔尔 创设布告对象
采纳IDirectSoundBuffer8的QueryInterface(卡塔尔国能够赢得叁个IDirectSoundNotify8接口的指标。IDirectSoundBuffer8的GUID为IID_IDirectSoundNotify。示例代码如下。

[cpp] view plaincopy澳门新萄京 16澳门新萄京 17

 

  1. IDirectSoundBuffer8 *m_pDSBuffer8=NULL;  
  2. IDirectSoundNotify8 *m_pDSNotify=NULL;    
  3. …  
  4. if(FAILED(m_pDSBuffer8->QueryInterface(IID_IDirectSoundNotify,(LPVOID*)&m_pDSNotify))){  
  5.     return FALSE ;  
  6. }  

一句话回顾一下通报对象的功力:当DirectSound缓冲区中的数据播放完成后,告知系统应该填充新的数据。

6卡塔尔国 设置通告地点
利用IDirectSoundNotify8的SetNotificationPositions(卡塔尔(قطر‎能够设置文告的职责。SetNotificationPositions(卡塔尔国的原型如下。

[cpp] view plaincopy澳门新萄京 18澳门新萄京 19

 

  1. HRESULT SetNotificationPositions(  
  2.          DWORD dwPositionNotifies,  
  3.          LPCDSBPOSITIONNOTIFY pcPositionNotifies  
  4. )  

参数含义如下。
dwPositionNotifies:DSBPOSITIONNOTIFY构造体的多寡。既包蕴多少个文告的岗位。
pcPositionNotifies:指向DSBPOSITIONNOTIFY构造体数组的指针。
再这里涉及到多少个布局体DSBPOSITIONNOTIFY,它描述了通告的岗位。DSBPOSITIONNOTIFY的概念如下。

[cpp] view plaincopy澳门新萄京 20澳门新萄京 21

 

  1. typedef struct DSBPOSITIONNOTIFY {  
  2.     DWORD dwOffset;  
  3.     HANDLE hEventNotify;  
  4. } DSBPOSITIONNOTIFY;  

它的分子的意思如下。
dwOffset:布告事件触发的职位(间距缓冲初步地方的偏移量)。
h伊夫ntNotify:触发的平地风波的句柄。

7卡塔尔(قطر‎ 开头广播
应用IDirectSoundBuffer8的SetCurrentPosition (卡塔尔能够安装播放的岗位。SetCurrentPosition (卡塔尔国原型如下

[cpp] view plaincopy澳门新萄京 22澳门新萄京 23

 

  1. HRESULT SetCurrentPosition(  
  2.          DWORD dwNewPosition  
  3. )  

内部dwNewPosition是播放点与缓冲区第一个字节之间的偏移量。
运用IDirectSoundBuffer8的Play (卡塔尔(قطر‎可以起来播放音频数据。Play (卡塔尔国原型如下。

[cpp] view plaincopy澳门新萄京 24澳门新萄京 25

 

  1. HRESULT Play(  
  2.          DWORD dwReserved1,  
  3.          DWORD dwPriority,  
  4.          DWORD dwFlags  
  5. )  

参数含义:
dwReserved1:保留参数,必得取0。
dwPriority:优先级,常常景况下取0就可以。
dwFlags:标识位。近来遍布的是DSBPLAY_LOOPING。当播放至缓冲区最后的时候,重新从缓冲区始发处开播。

2. 巡回播放音响
1卡塔尔(قطر‎ 数据填充至副缓冲区

数据填充至副缓冲区早前,供给先使用Lock(卡塔尔国锁定缓冲区。然后就足以动用fread(卡塔尔(قطر‎,memcpy(卡塔尔等艺术将PCM音频采集样板数据填充至缓冲区。数据填充落成后,使用Unlock(卡塔尔国废除对缓冲区的锁定。
Lock(卡塔尔国函数的原型如下。

[cpp] view plaincopy澳门新萄京 26澳门新萄京 27

 

  1. HRESULT Lock(  
  2.          DWORD dwOffset,  
  3.          DWORD dwBytes,  
  4.          LPVOID * ppvAudioPtr1,  
  5.          LPDWORD  pdwAudioBytes1,  
  6.          LPVOID * ppvAudioPtr2,  
  7.          LPDWORD pdwAudioBytes2,  
  8.          DWORD dwFlags  
  9. )  

参数的意义如下。
dwOffset:锁定的内部存款和储蓄器与缓冲区首地址之间的偏移量。
dwBytes:锁定的缓存的轻重。
ppv奥迪oPtr1:获取到的指向缓存数据的指针。
pdw奥迪oBytes1:获取到的缓存数据的高低。
ppv奥迪oPtr2:未有使用,设置为NULL。
pdw奥迪oBytes2:未有运用,设置为0。
dwFlags:暂无色金属商量所究。

UnLock(卡塔尔国函数的原型如下。

[cpp] view plaincopy澳门新萄京 28澳门新萄京 29

 

  1. HRESULT Unlock(  
  2.          LPVOID pvAudioPtr1,  
  3.          DWORD dwAudioBytes1,  
  4.          LPVOID pvAudioPtr2,  
  5.          DWORD dwAudioBytes2  
  6. )  

参数含义如下。
pv奥迪(Audi卡塔尔(قطر‎oPtr1:通过Lock(卡塔尔国获取到的针对缓存数据的指针。
dw奥迪(Audi卡塔尔国oBytes1:写入的数据量。
pv奥迪oPtr2:未有用到。

dw奥迪(Audi卡塔尔国oBytes2:未有用到。

2卡塔尔 等待播放完成

依据早先安装的照看机制,使用WaitForMultipleObjects(卡塔尔(英语:State of Qatar)等待缓冲区中的数据播放完成,然后步入下四个巡回。

枚举声音设备

此地大家说说设备操作这一块儿。

播音音频流程总计

DirectSound播放PCM音频数据的流程如下图所示。

 澳门新萄京 30

里头提到到的多少个结构体之间的关联如下图所示。  

澳门新萄京 31

 

1. 输出设备操作

在DirectSound中,贰个装置对象就表示一个音频设备,播放设备对象对应播放设备,输入设备对象对应输入设备。因为DirectSound使用COM左券,由此每种设备对象都用接口来表示。这里IDirectSound8以此接口就代表了一个输出设备对象,应用程序能够对同一个音频设备成立三个配备对象来张开音频输出操作。旧版本的DirectSound使用的是IDirectSound接口,相比较前边三个差了一些作用。

代码

贴上源代码。

[cpp] view plaincopy澳门新萄京 32澳门新萄京 33

 

  1. /** 
  2.  * 最简便易行的DirectSound播放音频的例子(DirectSound播放PCM) 
  3.  * Simplest Audio Play DirectSound (DirectSound play PCM)  
  4.  * 
  5.  * 雷霄骅 Lei Xiaohua 
  6.  * leixiaohua1020@126.com 
  7.  * 中国外贸大学/数字TV技术 
  8.  * Communication University of China / Digital TV Technology 
  9.  *  
  10.  * 
  11.  * 本程序选择DirectSound播放PCM音频采集样本数据。 
  12.  * 是最简易的DirectSound播放音频的科目。 
  13.  * 
  14.  * 函数调用步骤如下:  
  15.  * 
  16.  * [初始化] 
  17.  * DirectSoundCreate8(卡塔尔(英语:State of Qatar): 创立三个DirectSound对象。 
  18.  * SetCooperativeLevel(卡塔尔(قطر‎: 设置合营权限,否则未有声息。 
  19.  * IDirectSound8->CreateSoundBuffer(卡塔尔国: 创制一个主缓冲区对象。 
  20.  * IDirectSoundBuffer->QueryInterface(IID_IDirectSoundBuffer8..):  
  21.  *          成立二个副缓冲区对象,用来囤积要播放的动静数据文件。 
  22.  * IDirectSoundBuffer8->QueryInterface(IID_IDirectSoundNotify..):  
  23.  *          成立文告对象,公告应用程序钦定播放地点已经完成。 
  24.  * IDirectSoundNotify8->SetNotificationPositions(卡塔尔: 设置通告地方。 
  25.  * IDirectSoundBuffer8->SetCurrentPosition(卡塔尔(قطر‎: 设置播放的早先点。 
  26.  * IDirectSoundBuffer8->Play(卡塔尔(英语:State of Qatar): 开首播报。 
  27.  * 
  28.  * [循环播放数据] 
  29.  * IDirectSoundBuffer8->Lock(卡塔尔(قطر‎: 锁定副缓冲区,希图写入数据。 
  30.  * fread(卡塔尔(英语:State of Qatar): 读取多少。 
  31.  * IDirectSoundBuffer8->Unlock(): 解锁副缓冲区。 
  32.  * WaitForMultipleObjects(卡塔尔国: 等待“播放地点已经高达”的通知。 
  33.  * 
  34.  * This software plays PCM raw audio data using DirectSound. 
  35.  * It's the simplest tutorial about DirectSound. 
  36.  * 
  37.  * The process is shown as follows: 
  38.  * 
  39.  * [Init] 
  40.  * DirectSoundCreate8(): Init DirectSound object. 
  41.  * SetCooperativeLevel(): Must set, or we won't hear sound. 
  42.  * IDirectSound8->CreateSoundBuffer(): Create primary sound buffer. 
  43.  * IDirectSoundBuffer->QueryInterface(IID_IDirectSoundBuffer8..):  
  44.  *          Create secondary sound buffer. 
  45.  * IDirectSoundBuffer8->QueryInterface(IID_IDirectSoundNotify..):  
  46.  *          Create Notification object. 
  47.  * IDirectSoundNotify8->SetNotificationPositions(): 
  48.  *          Set Notification Positions. 
  49.  * IDirectSoundBuffer8->SetCurrentPosition(): Set position to start. 
  50.  *DirectSound学习笔记,最简便易行的视音频播放示例8。 IDirectSoundBuffer8->Play(): Begin to play. 
  51.  * 
  52.  * [Loop to play data] 
  53.  * IDirectSoundBuffer8->Lock(): Lock secondary buffer. 
  54.  * fread(): get PCM data. 
  55. 澳门新萄京, * IDirectSoundBuffer8->Unlock(): UnLock secondary buffer. 
  56.  * WaitForMultipleObjects(): Wait for Notifications. 
  57.  */  
  58. #include <stdio.h>  
  59. #include <stdlib.h>  
  60. #include <windows.h>  
  61. #include <dsound.h>  
  62.   
  63.   
  64. #define MAX_AUDIO_BUF 4   
  65. #define BUFFERNOTIFYSIZE 192000   
  66.   
  67.   
  68. int sample_rate=44100;  //PCM sample rate  
  69. int channels=2;         //PCM channel number  
  70. int bits_per_sample=16; //bits per sample  
  71.   
  72. BOOL main(int argc,char * argv[])  
  73. {  
  74.     int i;  
  75.     FILE * fp;  
  76.     if((fp=fopen("../NocturneNo2inEflat_44.1k_s16le.pcm","rb"))==NULL){  
  77.         printf("cannot open this filen");  
  78.         return -1;  
  79.     }  
  80.   
  81.     IDirectSound8 *m_pDS=NULL;                    
  82.     IDirectSoundBuffer8 *m_pDSBuffer8=NULL; //used to manage sound buffers.  
  83.     IDirectSoundBuffer *m_pDSBuffer=NULL;     
  84.     IDirectSoundNotify8 *m_pDSNotify=NULL;        
  85.     DSBPOSITIONNOTIFY m_pDSPosNotify[MAX_AUDIO_BUF];  
  86.     HANDLE m_event[MAX_AUDIO_BUF];  
  87.   
  88.     SetConsoleTitle(TEXT("Simplest Audio Play DirectSound"));//Console Title  
  89.     //Init DirectSound  
  90.     if(FAILED(DirectSoundCreate8(NULL,&m_pDS,NULL)))  
  91.         return FALSE;  
  92.     if(FAILED(m_pDS->SetCooperativeLevel(FindWindow(NULL,TEXT("Simplest Audio Play DirectSound")),DSSCL_NORMAL)))  
  93.         return FALSE;  
  94.   
  95.   
  96.     DSBUFFERDESC dsbd;  
  97.     memset(&dsbd,0,sizeof(dsbd));  
  98.     dsbd.dwSize=sizeof(dsbd);  
  99.     dsbd.dwFlags=DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY |DSBCAPS_GETCURRENTPOSITION2;  
  100.     dsbd.dwBufferBytes=MAX_AUDIO_BUF*BUFFERNOTIFYSIZE;   
  101.     //WAVE Header  
  102.     dsbd.lpwfxFormat=(WAVEFORMATEX*)malloc(sizeof(WAVEFORMATEX));  
  103.     dsbd.lpwfxFormat->wFormatTag=WAVE_FORMAT_PCM;     
  104.     /* format type */  
  105.     (dsbd.lpwfxFormat)->nChannels=channels;            
  106.     /* number of channels (i.e. mono, stereo...) */  
  107.     (dsbd.lpwfxFormat)->nSamplesPerSec=sample_rate;       
  108.     /* sample rate */  
  109.     (dsbd.lpwfxFormat)->nAvgBytesPerSec=sample_rate*(bits_per_sample/8)*channels;   
  110.     /* for buffer estimation */  
  111.     (dsbd.lpwfxFormat)->nBlockAlign=(bits_per_sample/8)*channels;          
  112.     /* block size of data */  
  113.     (dsbd.lpwfxFormat)->wBitsPerSample=bits_per_sample;       
  114.     /* number of bits per sample of mono data */  
  115.     (dsbd.lpwfxFormat)->cbSize=0;  
  116.   
  117.     //Creates a sound buffer object to manage audio samples.   
  118.     HRESULT hr1;  
  119.     if( FAILED(m_pDS->CreateSoundBuffer(&dsbd,&m_pDSBuffer,NULL))){     
  120.         return FALSE;  
  121.     }  
  122.     if( FAILED(m_pDSBuffer->QueryInterface(IID_IDirectSoundBuffer8,(LPVOID*)&m_pDSBuffer8))){  
  123.         return FALSE ;  
  124.     }  
  125.     //Get IDirectSoundNotify8  
  126.     if(FAILED(m_pDSBuffer8->QueryInterface(IID_IDirectSoundNotify,(LPVOID*)&m_pDSNotify))){  
  127.         return FALSE ;  
  128.     }  
  129.     for(i =0;i<MAX_AUDIO_BUF;i ){  
  130.         m_pDSPosNotify[i].dwOffset =i*BUFFERNOTIFYSIZE;  
  131.         m_event[i]=::CreateEvent(NULL,false,false,NULL);   
  132.         m_pDSPosNotify[i].hEventNotify=m_event[i];  
  133.     }  
  134.     m_pDSNotify->SetNotificationPositions(MAX_AUDIO_BUF,m_pDSPosNotify);  
  135.     m_pDSNotify->Release();  
  136.   
  137.     //Start Playing  
  138.     BOOL isPlaying =TRUE;  
  139.     LPVOID buf=NULL;  
  140.     DWORD  buf_len=0;  
  141.     DWORD res=WAIT_OBJECT_0;  
  142.     DWORD offset=BUFFERNOTIFYSIZE;  
  143.   
  144.     m_pDSBuffer8->SetCurrentPosition(0);  
  145.     m_pDSBuffer8->Play(0,0,DSBPLAY_LOOPING);  
  146.     //Loop  
  147.     while(isPlaying){  
  148.         if((res >=WAIT_OBJECT_0)&&(res <=WAIT_OBJECT_0 3)){  
  149.             m_pDSBuffer8->Lock(offset,BUFFERNOTIFYSIZE,&buf,&buf_len,NULL,NULL,0);  
  150.             if(fread(buf,1,buf_len,fp)!=buf_len){  
  151.                 //File End  
  152.                 //Loop:  
  153.                 fseek(fp, 0, SEEK_SET);  
  154.                 fread(buf,1,buf_len,fp);  
  155.                 //Close:  
  156.                 //isPlaying=0;  
  157.             }  
  158.             m_pDSBuffer8->Unlock(buf,buf_len,NULL,0);  
  159.             offset =buf_len;  
  160.             offset %= (BUFFERNOTIFYSIZE * MAX_AUDIO_BUF);  
  161.             printf("this is } of buffern",offset);  
  162.         }  
  163.         res = WaitForMultipleObjects (MAX_AUDIO_BUF, m_event, FALSE, INFINITE);  
  164.     }  
  165.   
  166.     return 0;  
  167. }  

万一您的顺序只是简短地经过客户主推设备来播放音响,那么未有供给去枚举可用的配备。当您通过调用 DirectSoundCreate8 函数创造设备对象时,你可以知道钦命暗许设备。

1.1 枚举

HRESULT WINAPI DirectSoundEnumerateW(In LPDSENUMCALLBACKW pDSEnumCallback, In_opt LPVOID pContext);
typedef BOOL (CALLBACK *LPDSENUMCALLBACKW)(LPGUID, LPCWSTR, LPCWSTR, LPVOID);

大家通过DirectSoundEnumerateW这一个函数来枚举,该函数须要传入五个回调函数(原型见上),当枚举到二个装置时该回调会被调用。假设我们想世袭枚举,须求在此个回调用中回到TRUE来告诉系统,不然再次回到FALSE。另叁个参数pContext允许客商传入额外的参数,传入回调函数的终极二个实参正是这一个pContext。枚举时,DirectSound会将私下认可也认作四个独立的配备来相比较,因而暗中认可设备会被重复枚举三遍。当设备被当作暗许设备枚举时,它的GUID和设备描述字符串都为空,必要小心管理,这里自个儿平昔跳过了该次枚举:

if (DirectSoundEnumerateW(enumerateCallback, nullptr) != DS_OK) {
    ...
}

BOOL CALLBACK DirectSoundBasic::enumerateCallback(LPGUID guid,
                                              LPCWSTR deviceDescription,
                                              LPCWSTR deviceDriverModule,
                                              LPVOID context)
{
    Q_UNUSED(context);

    //  if primary device, skip it
    if (guid == nullptr)        return TRUE;

    ...
}

运作结果

代码运营之后,会弹出三个“调控台”对话框如下图所示。同期音频设备里面能够听到广播的动静。

澳门新萄京 34

 

 

1.2 创造设备对象

HRESULT WINAPI DirectSoundCreate8(In_opt LPCGUID pcGuidDevice, Outptr LPDIRECTSOUND8 *ppDS8, Pre_null LPUNKNOWN pUnkOuter);

调用DirectSoundCreate8函数,大家得以创立叁个设备对象,通过传播多少个枚举设备时获得的GUID,函数会返给大家叁个IDirectSound8接口代表设备对象:

IDirectSound8* directSound8;
if (DirectSoundCreate8(guid, &directSound8, NULL) != DS_OK) {
    std::wcout << L"[error] DirectSoundCreate8 call error!";
    return TRUE;    //  if error, skip this device
}

下载

代码坐落于“Simplest Media Play”中

 

SourceForge项目地址:

CSDN下载地址:

 

上述工程满含了使用各类API(Direct3D,OpenGL,GDI,DirectSound,SDL2)播放多媒体例子。当中音频输入为PCM采集样板数据。输出至系统的声卡播放出来。摄像输入为YUV/LX570GB像素数据。输出至显示屏上的叁个窗口播放出来。
由此本工程的代码初读书人能够火速学习应用那多少个API播放摄像和音频的手艺。
累积包括了之类多少个子工程:
simplest_audio_play_directsound:  使用DirectSound播放PCM音频采集样板数据。
simplest_audio_play_sdl2:  使用SDL2播放PCM音频采集样本数据。
simplest_video_play_direct3d:  使用Direct3D的Surface播放景逸SUVGB/YUV摄像像素数据。
simplest_video_play_direct3d_texture:使用Direct3D的Texture播放中华VGB录制像素数据。
simplest_video_play_gdi:  使用GDI播放TucsonGB/YUV录制像素数据。
simplest_video_play_opengl:  使用OpenGL播放SportageGB/YUV摄像像素数据。
simplest_video_play_opengl_texture: 使用OpenGL的Texture播放YUV摄像像素数据。
simplest_video_play_sdl2:  使用SDL2播放RAV4GB/YUV录制像素数据。

 

from:

枚举设备在以下情状是必备的:

1.3 设置设备对象优先级

HRESULT IDirectSound8::SetCooperativeLevel(HWND hwnd, DWORD dwLevel)

在接收设备对象创制缓冲区(用来捕获、播放音频)在此以前,我们须求设置设备对象的合营等第。那几个合营等第也便是顾客对器械举办操作的优先级,分为:

  • DSSCL_EXCLUSIVE: 互斥等第。对于DirectX8.0原先版本,仅播放当下使用的旋律数据,其余应用的声息不会被广播;对于DirectX8.0级之后版本,同DSSCL_PRIORITY版本。

  • DSSCL_NORMAL: 普通品级,这种品级下的应用程序具备最坦荡的多职分和能源分享表现,可是这种应用不可能改换主缓冲区音频数据格式,输出音频格式被限制为8位数据。在DirectSound中,次缓冲区用来填充应用程序要求播放的声音,主缓冲区会对多个次缓冲区(恐怕是本金和利息用的,也会有可能是此外应用的)举行混音,然后用声卡输出播放。

  • DSSCL_PRIORITY: 优先品级,可以变动主缓冲区数据格式。
  • DSSCL_WRITEPRIMARY:写主缓冲区等级,应用可以平素写入主缓冲区,那时全体次缓冲区不会被广播(要是设备的驱动是DirectSound模拟出来的,则不可能安装该等级)。

留意该函数供给传入三个窗口句柄,因为大家今天只介绍DirectSound的基本操作,作者平素传入桌面窗口的句柄并设固定DSSCL_NORMAL优先级:

if (directSound8->SetCooperativeLevel(GetDesktopWindow(), DSSCL_NORMAL) != DS_OK) {
    std::wcout << L"[error] SetCooperativeLevel call error!";
    return TRUE;
}

1. 您的应用程序供给的质量不是有着设施都能够提供的。

1.4 设备本事

HRESULT IDirectSound8::GetCaps(LPDSCAPS pDSCaps)

不等的点子播放设备具有分歧的技术,DirectSound允许大家询问设备的本事:

  • 是不是因此Microsoft认证。
  • 知不知道帮助最小最大采样率之间的具备采集样本率。
  • 当未有DirectSound驱动时模拟驱动。
  • 次第缓冲区格式(13个人、8位)。
  • 程序缓冲区声道扶植(单声道、立体声即多声道)。
  • 不精准的多寡(有个别声卡不扶持):
    • 缓冲区(静态缓冲区、流缓冲区、3D缓冲区)最大数、空闲数。
    • 声卡上的总内部存款和储蓄器数量、空闲内部存款和储蓄器数量、最大空闲块大小,

大家传给GetCaps三个DSCAPS布局体地址,然后系统就帮大家填充相应的数额,调用GetCaps前供给将DSCAPS结构体的dwSize设置为DSCAPS的分寸:

DSCAPS deviceCapability = { sizeof(deviceCapability) };
if (directSound8->GetCaps(&deviceCapability) != DS_OK) {
    std::wcout << L"[error] GetCaps call error!";
    return TRUE;
}

2. 您的应用程序要求四个或越来越多的设备。

1.5 播放器配置

HRESULT IDirectSound8::GetSpeakerConfig(LPDWORD pdwSpeakerConfig)
HRESULT IDirectSound8::SetSpeakerConfig(LPDWORD pdwSpeakerConfig)

播放器配置只可以是以下之风流浪漫:

  • DSSPEAKER_5POINT1_SURROUNDDSSPEAKER_5POINT1_BACK: 家庭影院配置,5个围绕扬声器,1个低音炮。
  • DSSPEAKER_DIRECTOUT:直接播放。
  • DSSPEAKER_HEADPHONE:头戴式动圈耳机。
  • DSSPEAKER_MONO:单声道扬声器。
  • DSSPEAKER_QUAD:4声道播放器。
  • DSSPEAKER_STEREO:立体声播放器。
  • DSSPEAKER_SURROUND:环绕播放器。
  • DSSPEAKER_7POINT1_WIDEDSSPEAKER_7POINT1_SURROUND:家庭影院配置,7个围绕扬声器,1个低音炮。

虽说MSDN文档未有写清楚,可是透过查以上宏定义大家开掘它们是按大小顺序定义的,因而不容许因此OEscort|来含有三种只怕,例子中只要调用出错直接重临TRUE表示大家三番两次枚举设备并三回九转查询那么些设备本事:

DWORD deviceSpeakerConfiguration;
if (directSound8->GetSpeakerConfig(&deviceSpeakerConfiguration) != DS_OK) {
    std::wcout << L"[error] GetSpeakerConfig call error!";
    return TRUE;
}

3. 您愿意客户可以挑选设备。

2. 周转结果

这一次我们用GUI分界面来体现实例运行的结果(出于方便思虑,以往小编会用调节台来呈现示例),为防卫顾客误操作纠正彰显的数据本人将好些个控件都disable了:

澳门新萄京 35

全体代码见链接。

 

枚举设备有多少个指标:

1. 它提出可用的硬件装置。

2. 它为每一种设备提供了一个GUID。

3. 它使您可以预知在装置被枚举的时候为它创造一个近年来设备对象,那样你能够获取器具的质量。

 

为枚举设备,你必须首先创制三个回调函数,它将在枚举各种系统设备时被调用。你可见在这里个函数中张开任何操作,何况你能够给它任性的函数名,不过你一定要依靠DSEnumCallback 的原型评释它。如果要连继续展览开枚举,那么回调函数必得再次回到TRUE,不然重临FALSE-举个例子,在找到叁个满意你要求的设备后。

 

下边这一个回调函数将各类枚举到的器械名增加到三个复选框中,并将它的GUID 作为筛选内容。前八个参数值由器材驱动器提供。第八个参数由 DirectSoundEnumerate 函数字传送入;那个参数能被用来传入任意叁十一个人的值,在那间则是复选框的窗口句柄。在Windowsx.h中定义的宏被用于向复选框中增加字符串和数量。

 

 

澳门新萄京 36BOOL CALLBACK DSEnumProc(LPGUID lpGUID, 
澳门新萄京 37         LPCTSTR lpszDesc,
澳门新萄京 38         LPCTSTR lpszDrvName, 
澳门新萄京 39         LPVOID lpContext )
澳门新萄京 40澳门新萄京 41{
澳门新萄京 42  HWND hCombo = (HWND)lpContext;
澳门新萄京 43  LPGUID lpTemp = NULL;
澳门新萄京 44 
澳门新萄京 45  if (lpGUID != NULL)  //  NULL only for "Primary Sound Driver".
澳门新萄京 46澳门新萄京 47  {
澳门新萄京 48    if ((lpTemp = (LPGUID)malloc(sizeof(GUID))) == NULL)
澳门新萄京 49澳门新萄京 50    {
澳门新萄京 51        return(TRUE);
澳门新萄京 52    }
澳门新萄京 53    memcpy(lpTemp, lpGUID, sizeof(GUID));
澳门新萄京 54  }
澳门新萄京 55 
澳门新萄京 56  ComboBox_AddString(hCombo, lpszDesc);
澳门新萄京 57  ComboBox_SetItemData(hCombo, 
澳门新萄京 58      ComboBox_FindString(hCombo, 0, lpszDesc),
澳门新萄京 59      lpTemp );
澳门新萄京 60  free(lpTemp);
澳门新萄京 61  return(TRUE);
澳门新萄京 62}
澳门新萄京 63

枚举在蕴藏复选框的对话框被伊始化时运行。借使hCombo 是复选框的句柄,hDlg 是对话框的句柄。

澳门新萄京 64if (FAILED(DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumProc,
澳门新萄京 65    (VOID*)&hCombo)))
澳门新萄京 66澳门新萄京 67{
澳门新萄京 68  EndDialog(hDlg, TRUE);
澳门新萄京 69  return(TRUE);
澳门新萄京 70}
澳门新萄京 71

本条例子中,复选框句柄之处被传到 DirectSoundEnumerate,随后被盛传回调函数。那些参数可以是你愿目的在于回调函数中访问的私自30个人值。
注 意:第二个被枚举到的设施平时称为重要声音设备,那时候回调函数的参数lpGUID 为NULL。这一个设备代表了客户在调控面板中装置的首要推荐播放设备。它被单独枚举出来是为了使应用程序能够有支持地加上“重要声音设备”到列表中,该列表用于 为顾客提供设备选取。首要设备也是经过特有的名字和GUID被枚举的。

本文由澳门新萄京发布于澳门新萄京,转载请注明出处:DirectSound学习笔记,最简便易行的视音频播放示例

上一篇:澳门新萄京配置教程,无法打开文件 下一篇:没有了
猜你喜欢
热门排行
精彩图文