<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    最簡單的視音頻播放示例8:DirectSound播放PCM

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    本文記錄DirectSound播放音頻的技術。DirectSound是Windows下最常見的音頻播放技術。目前大部分的音頻播放應用都是通過DirectSound來播放的。本文記錄一個使用DirectSound播放PCM的例子。
    注:一位仁兄已經提醒我DirectSound已經計劃被XAudio2取代了。后來考證了一下發現確有此事。因此在下次更新中考慮加入XAudio2播放PCM的例子。本文仍然記錄一下DirectSound這位“元老”。

    RFID設備管理軟件

     

    DirectSound簡介

    DirectSound是微軟所開發DirectX的組件之一,可以在Windows 操作系統上錄音,并且記錄波形音效(waveform sound)。目前DirectSound 是一個成熟的API ,提供許多有用的功能,例如能夠在較高的分辨率播放多聲道聲音。
    DirectSound3D(DS3D)最早是1993年與 DirectX 3 一起發表的。DirectX 8以后的DirectSound和DirectSound3D的(DS3D)被合稱DirectX Audio。


    DirectSound有以下幾種對象:

    對象

    數量

    作用

    主要接口

    設備

    每個應用程序只有一個設備對象

    用來管理設備,創建輔助緩沖區

    IDirectSound8

    輔助緩沖區

    每一個聲音對應一個輔助緩沖區

    用來管理一個靜態的或者動態的聲音流,然后在主緩沖區中混音

    IDirectSoundBuffer8,

    IDirectSound3DBuffer8,

    IDirectSoundNotify8

    主緩沖區

    一個應用程序只有一個主緩沖區

    將輔助緩沖區的數據進行混音,并且控制3D參數.

    IDirectSoundBuffer,

    IDirectSound3DListener8



    DirectSound播放音頻的流程

    使用DirectSound播放音頻一般情況下需要如下步驟:

    1. 初始化

    1) 創建一個IDirectSound8接口的對象
    2) 設置協作級
    3) 創建一個主緩沖對象
    4) 創建一個副緩沖對象
    5) 創建通知對象
    6) 設置通知位置

    7) 開始播放

    2. 循環播放聲音

    1) 數據填充至副緩沖區

    2) 等待播放完成

    下面結合詳細分析一下上文的流程。


    1. 初始化
    1) 創建一個IDirectSound8接口的對象

    通過DirectSoundCreate8()方法可以創建一個設備對象。這個對象通常代表缺省的播放設備。DirectSoundCreate8()函數原型如下。

    [cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片  
    1. HRESULT DirectSoundCreate8(  
    2.      LPCGUID lpcGuidDevice,  
    3.      LPDIRECTSOUND8 * ppDS8,  
    4.      LPUNKNOWN pUnkOuter  
    5. )  


    參數的含義如下:
    lpcGuidDevice:要創建的設備對象的GUID。可以指定為NULL,代表默認的播放設備。
    ppDS8:返回的IDirectSound8對象的地址。
    pUnkOuter:必須設為NULL。
    例如如下代碼即可創建一個IDirectSound8接口的對象

    [cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片  
    1. IDirectSound8 *m_pDS=NULL;    
    2. DirectSoundCreate8(NULL,&m_pDS,NULL);  


    2) 設置協作級
    Windows 是一個多任務環境,同一時間有多個應用程序去訪問設備。通過使用協作級別,DirectSound可以確保應用程序不會在別的設備使用時去訪問,每個 DirectSound應用程序都有一個協作級別,這個級別決定著訪問硬件的權限。
    在創建一個設備對象以后,必須通過用IDirectSound8的SetCooperativeLevel()設置協作權限,否則將聽不到聲音。SetCooperativeLevel()的原型如下

    [cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片  
    1. HRESULT SetCooperativeLevel(  
    2.  HWND hwnd,  
    3.  DWORD dwLevel  
    4. )  


    參數的含義如下:
    hwnd:應用程序窗口句柄。
    dwLevel:支持以下幾種級別。
    DSSCL_EXCLUSIVE:與DSSCL_PRIORITY具有相同的作用。
    DSSCL_NORMAL:正常的協調層級標志,其他程序可共享聲卡設備進行播放。
    DSSCL_PRIORITY:設置聲卡設備為當前程序獨占。
    DSSCL_WRITEPRIMAR:可寫主緩沖區,此時副緩沖區就不能進行播放處理,即不能將次緩沖區的數據送進混聲器,再輸出到主緩沖區上。這是最完全控制聲音播放的方式。


    3) 創建一個主緩沖對象
    使用IDirectSound8的CreateSoundBuffer()可以創建一個IDirectSoundBuffer接口的主緩沖區對象。CreateSoundBuffer()的原型如下。

    [cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片  
    1. HRESULT CreateSoundBuffer(  
    2.  LPCDSBUFFERDESC pcDSBufferDesc,  
    3.  LPDIRECTSOUNDBUFFER * ppDSBuffer,  
    4.  LPUNKNOWN pUnkOuter  
    5. )  


    參數的含義如下:
    pcDSBufferDesc:描述聲音緩沖的DSBUFFERDESC結構體的地址
    ppDSBuffer:返回的IDirectSoundBuffer接口的對象的地址。
    pUnkOuter:必須設置為NULL。
    其中涉及到一個描述聲音緩沖的結構體DSBUFFERDESC,該結構體的定義如下:

    [cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片  
    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格式文件頭的指針。
    設置DSBUFFERDESC完畢后,就可以使用CreateSoundBuffer()創建主緩沖了。示例代碼如下:

    [cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片  
    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在CODE上查看代碼片派生到我的代碼片  
    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在CODE上查看代碼片派生到我的代碼片  
    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在CODE上查看代碼片派生到我的代碼片  
    1. HRESULT SetNotificationPositions(  
    2.          DWORD dwPositionNotifies,  
    3.          LPCDSBPOSITIONNOTIFY pcPositionNotifies  
    4. )  


    參數含義如下。
    dwPositionNotifies:DSBPOSITIONNOTIFY結構體的數量。既包含幾個通知的位置。
    pcPositionNotifies:指向DSBPOSITIONNOTIFY結構體數組的指針。
    再這里涉及到一個結構體DSBPOSITIONNOTIFY,它描述了通知的位置。DSBPOSITIONNOTIFY的定義如下。

    [cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片  
    1. typedef struct DSBPOSITIONNOTIFY {  
    2.     DWORD dwOffset;  
    3.     HANDLE hEventNotify;  
    4. } DSBPOSITIONNOTIFY;  


    它的成員的含義如下。
    dwOffset:通知事件觸發的位置(距離緩沖開始位置的偏移量)。
    hEventNotify:觸發的事件的句柄。


    7) 開始播放
    使用IDirectSoundBuffer8的SetCurrentPosition ()可以設置播放的位置。SetCurrentPosition ()原型如下

    [cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片  
    1. HRESULT SetCurrentPosition(  
    2.          DWORD dwNewPosition  
    3. )  


    其中dwNewPosition是播放點與緩沖區首個字節之間的偏移量。
    使用IDirectSoundBuffer8的Play ()可以開始播放音頻數據。Play ()原型如下。

    [cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片  
    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在CODE上查看代碼片派生到我的代碼片  
    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:鎖定的緩存的大小。
    ppvAudioPtr1:獲取到的指向緩存數據的指針。
    pdwAudioBytes1:獲取到的緩存數據的大小。
    ppvAudioPtr2:沒有用到,設置為NULL。
    pdwAudioBytes2:沒有用到,設置為0。
    dwFlags:暫時沒有研究。


    UnLock()函數的原型如下。

    [cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片  
    1. HRESULT Unlock(  
    2.          LPVOID pvAudioPtr1,  
    3.          DWORD dwAudioBytes1,  
    4.          LPVOID pvAudioPtr2,  
    5.          DWORD dwAudioBytes2  
    6. )  


    參數含義如下。
    pvAudioPtr1:通過Lock()獲取到的指向緩存數據的指針。
    dwAudioBytes1:寫入的數據量。
    pvAudioPtr2:沒有用到。

    dwAudioBytes2:沒有用到。

    2) 等待播放完成

    根據此前設置的通知機制,使用WaitForMultipleObjects()等待緩沖區中的數據播放完畢,然后進入下一個循環。


    播放音頻流程總結

    DirectSound播放PCM音頻數據的流程如下圖所示。

     RFID設備管理軟件



    其中涉及到的幾個結構體之間的關系如下圖所示。
     

    RFID設備管理軟件




    代碼

    貼上源代碼。

    [cpp] view plaincopy在CODE上查看代碼片派生到我的代碼片  
    1. /** 
    2.  * 最簡單的DirectSound播放音頻的例子(DirectSound播放PCM) 
    3.  * Simplest Audio Play DirectSound (DirectSound play PCM)  
    4.  * 
    5.  * 雷霄驊 Lei Xiaohua 
    6.  * leixiaohua1020@126.com 
    7.  * 中國傳媒大學/數字電視技術 
    8.  * Communication University of China / Digital TV Technology 
    9.  * http://blog.csdn.net/leixiaohua1020 
    10.  * 
    11.  * 本程序使用DirectSound播放PCM音頻采樣數據。 
    12.  * 是最簡單的DirectSound播放音頻的教程。 
    13.  * 
    14.  * 函數調用步驟如下:  
    15.  * 
    16.  * [初始化] 
    17.  * DirectSoundCreate8(): 創建一個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(): 開始播放。 
    27.  * 
    28.  * [循環播放數據] 
    29.  * IDirectSoundBuffer8->Lock(): 鎖定副緩沖區,準備寫入數據。 
    30.  * fread(): 讀取數據。 
    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.  * 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 file\n");  
    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 %7d of buffer\n",offset);  
    162.         }  
    163.         res = WaitForMultipleObjects (MAX_AUDIO_BUF, m_event, FALSE, INFINITE);  
    164.     }  
    165.   
    166.     return 0;  
    167. }  



    運行結果

    代碼運行之后,會彈出一個“控制臺”對話框如下圖所示。同時音頻設備里面可以聽到播放的聲音。

    RFID設備管理軟件


     

    下載

    代碼位于“Simplest Media Play”中

     

    SourceForge項目地址:https://sourceforge.net/projects/simplestmediaplay/

    CSDN下載地址:http://download.csdn.net/detail/leixiaohua1020/8054395

     

    上述工程包含了使用各種API(Direct3D,OpenGL,GDI,DirectSound,SDL2)播放多媒體例子。其中音頻輸入為PCM采樣數據。輸出至系統的聲卡播放出來。視頻輸入為YUV/RGB像素數據。輸出至顯示器上的一個窗口播放出來。
    通過本工程的代碼初學者可以快速學習使用這幾個API播放視頻和音頻的技術。
    一共包括了如下幾個子工程:
    simplest_audio_play_directsound:  使用DirectSound播放PCM音頻采樣數據。
    simplest_audio_play_sdl2:  使用SDL2播放PCM音頻采樣數據。
    simplest_video_play_direct3d:  使用Direct3D的Surface播放RGB/YUV視頻像素數據。
    simplest_video_play_direct3d_texture:使用Direct3D的Texture播放RGB視頻像素數據。
    simplest_video_play_gdi:  使用GDI播放RGB/YUV視頻像素數據。
    simplest_video_play_opengl:  使用OpenGL播放RGB/YUV視頻像素數據。
    simplest_video_play_opengl_texture: 使用OpenGL的Texture播放YUV視頻像素數據。
    simplest_video_play_sdl2:  使用SDL2播放RGB/YUV視頻像素數據。

     

    from:http://blog.csdn.net/leixiaohua1020/article/details/40540147

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全