• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牽著老婆滿街逛

            嚴(yán)以律己,寬以待人. 三思而后行.
            GMail/GTalk: yanglinbo#google.com;
            MSN/Email: tx7do#yahoo.com.cn;
            QQ: 3 0 3 3 9 6 9 2 0 .

            directsound抓取麥克風(fēng)PCM數(shù)據(jù)封裝類

            轉(zhuǎn)載自:http://blog.chinaunix.net/uid-8272118-id-2033248.html

            網(wǎng)上有很多方法從麥克風(fēng)讀取PCM數(shù)據(jù),不想一一舉例。只是在這里發(fā)布一個(gè)我自己寫的directsound的麥克風(fēng)PCM數(shù)據(jù)采集類,通過它,可以很方便的利用directsound技術(shù)把麥克風(fēng)的數(shù)據(jù)采集到,而且本身,開發(fā)者不必太在意自己會(huì)不會(huì)directsound編程,可以很方便的讓開發(fā)者的主要精力集中于程序本身,而不是細(xì)節(jié)。
            這個(gè)是頭文件:
            #pragma once
            #ifndef _CAPTURE_SOUND_H_
            #define _CAPTURE_SOUND_H_
            #include 
            <mmsystem.h>
            #include 
            <dsound.h>
            #define NUM_REC_NOTIFICATIONS  16
            class CAdoFrameHandler {
            public:
             
            virtual void AdoFrameData(BYTE* pBuffer, long lBufferSize) = 0 ; 
            }
            ;
            class CCaptureAudio
            {
            public:
             BOOL        m_bRecording ;  
            //recording now ? also used by event recv thread
            protected:
             LPDIRECTSOUNDCAPTURE8    m_pCapDev ;   
            //capture device ptr
             LPDIRECTSOUNDCAPTUREBUFFER m_pCapBuf ;   //capture loop buffer ptr
             LPDIRECTSOUNDNOTIFY8    m_pNotify ;   //capture auto-notify event callback handler ptr
             GUID        m_guidCapDevId ;  //capture device id
             WAVEFORMATEX      m_wfxInput;   //input wave format description struct
             DSBPOSITIONNOTIFY     m_aPosNotify[NUM_REC_NOTIFICATIONS + 1]; //notify flag array 
             HANDLE        m_hNotifyEvent;   //notify event 
             BOOL        m_abInputFmtSupported[20];
             DWORD        m_dwCapBufSize;  
            //capture loop buffer size 
             DWORD        m_dwNextCapOffset;//offset in loop buffer 
             DWORD        m_dwNotifySize;  //notify pos when loop buffer need to emit the event
             CAdoFrameHandler*     m_frame_handler ; // outer frame data dealer ptr 
            public// callback func to add enum devices string name 
             static BOOL CALLBACK enum_dev_proc(LPGUID lpGUID, LPCTSTR lpszDesc, 
                        LPCTSTR lpszDrvName, LPVOID lpContext ) ;
             
            static UINT notify_capture_thd(LPVOID data) ;
            protected:
             HRESULT InitDirectSound(GUID dev_id 
            = GUID_NULL) ; 
             HRESULT FreeDirectSound() ; 
             HRESULT InitNotifications() ; 
             HRESULT CreateCaptureBuffer(WAVEFORMATEX 
            * wfx) ; 
             HRESULT StartOrStopRecord(BOOL bStartRec) ;
             HRESULT RecordCapturedData() ; 
             
            void    SetWavFormat(WAVEFORMATEX * wfx) ;
            public:
             CCaptureAudio(
            void);
             
            ~CCaptureAudio(void);
             BOOL EnumDevices(HWND hList) ;
             BOOL Open(
            void) ; 
             BOOL Close() ; 
             
            void GrabAudioFrames(BOOL bGrabAudioFrames, CAdoFrameHandler* frame_handler) ; 
            }
            ;
            #endif
             
            下面這個(gè)是cpp文件:
            #include "StdAfx.h"
            #include 
            ".\captureaudio.h"
            #include 
            <mmsystem.h>
            #include 
            <dsound.h>
            #ifndef SAFE_DELETE
            #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
            #endif
            #ifndef SAFE_RELEASE
            #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
            #endif
            #ifndef MAX
            #define MAX(a,b)        ( (a) > (b) ? (a) : (b) )
            #endif
            CCaptureAudio::CCaptureAudio(
            void)
            {
             
            if(FAILED(CoInitialize(NULL))) /*, COINIT_APARTMENTTHREADED)))*/
             
            {
              AfxMessageBox(
            "CCaptureAudio CoInitialize Failed!\r\n"); 
              
            return;
             }

             m_pCapDev 
            = NULL ;
             m_pCapBuf 
            = NULL ;
             m_pNotify 
            = NULL ;
             
            // set default wave format PCM
             ZeroMemory( &m_wfxInput, sizeof(m_wfxInput));
             m_wfxInput.wFormatTag 
            = WAVE_FORMAT_PCM;
             m_guidCapDevId 
            = GUID_NULL ; 
             m_bRecording 
            = FALSE ; 
             m_hNotifyEvent 
            = NULL ; 
            }

            CCaptureAudio::
            ~CCaptureAudio(void)
            {
             CoUninitialize() ; 
            }

            BOOL CALLBACK CCaptureAudio::enum_dev_proc(LPGUID lpGUID, LPCTSTR lpszDesc, 
                         LPCTSTR lpszDrvName, LPVOID lpContext) 
            {
             HWND hList 
            = (HWND)lpContext;
             
            if(!hList) return FALSE ; 
             LPGUID lpTemp 
            = NULL;
             
            if (lpGUID != NULL) {
              
            // NULL only for "Primary Sound Driver".
              if ((lpTemp = (LPGUID)malloc(sizeof(GUID))) == NULL) return(TRUE);
              memcpy(lpTemp, lpGUID, 
            sizeof(GUID));
             }

             ::SendMessage(hList, CB_ADDSTRING, 
            0,(LPARAM)lpszDesc);
             ::SendMessage(hList, LB_SETITEMDATA, 
            0, (LPARAM)lpTemp) ; 
             free(lpTemp);
             
            return(TRUE);
            }

            UINT CCaptureAudio::notify_capture_thd(LPVOID data)
            {
             CCaptureAudio 
            * pado = static_cast<CCaptureAudio *>(data) ; 
             MSG   msg;
             HRESULT hr ; 
             DWORD dwResult ; 
             
            while(pado->m_bRecording) {
              dwResult 
            = MsgWaitForMultipleObjects( 1&(pado->m_hNotifyEvent), FALSE, INFINITE, QS_ALLEVENTS );
              
            switch( dwResult ) {
              
            case WAIT_OBJECT_0 + 0:
               
            // g_hNotificationEvents[0] is signaled
               
            // This means that DirectSound just finished playing 
               
            // a piece of the buffer, so we need to fill the circular 
               
            // buffer with new sound from the wav file
               if( FAILED( hr = pado->RecordCapturedData() ) ) {
                AfxMessageBox(
            "Error handling DirectSound notifications.") ; 
                pado
            ->m_bRecording = FALSE ; 
               }

               
            break;
              
            case WAIT_OBJECT_0 + 1:
               
            // Windows messages are available
               while( PeekMessage( &msg, NULL, 00, PM_REMOVE ) ) 
                 TranslateMessage( 
            &msg ); 
                 DispatchMessage( 
            &msg ); 
                
            if( msg.message == WM_QUIT ) pado->m_bRecording = FALSE ; 
               }

               
            break;
              }

             }

             AfxEndThread(
            0, TRUE) ; 
             
            return 0 ; 
            }

            BOOL CCaptureAudio::EnumDevices(HWND hList) 
            {
             
            if (FAILED(DirectSoundCaptureEnumerate (
               (LPDSENUMCALLBACK)(CCaptureAudio::enum_dev_proc),
               (VOID
            *)&hList)))
             
            {
              
            return(FALSE);
             }

             
            return (TRUE) ; 
            }

            BOOL CCaptureAudio::Open(
            void)
            {
             HRESULT hr ; 
             
            if(!m_bRecording) {
              hr 
            = InitDirectSound() ; 
             }

             
            return (FAILED(hr)) ? FALSE : TRUE ; 
            }

            BOOL CCaptureAudio::Close() 
            {
             HRESULT hr ; 
             hr 
            = FreeDirectSound() ; 
             CloseHandle(m_hNotifyEvent) ; 
             
            return (FAILED(hr)) ? FALSE : TRUE ; 
            }

            HRESULT CCaptureAudio::InitDirectSound(GUID dev_id)
            {
             HRESULT hr ; 
             m_guidCapDevId 
            = dev_id ;
             ZeroMemory( 
            &m_aPosNotify, sizeof(DSBPOSITIONNOTIFY) * (NUM_REC_NOTIFICATIONS + 1) ) ;
             m_dwCapBufSize 
            = 0 ;
             m_dwNotifySize 
            = 0 ;
             
            // Create IDirectSoundCapture using the preferred capture device
             hr = DirectSoundCaptureCreate(&m_guidCapDevId, &m_pCapDev, NULL ) ;
             
            // init wave format 
             SetWavFormat(&m_wfxInput) ;
             
            return (FAILED(hr)) ? S_FALSE : S_OK ; 
            }

            HRESULT CCaptureAudio::FreeDirectSound()
            {
             
            // Release DirectSound interfaces
             SAFE_RELEASE( m_pNotify ) ;
             SAFE_RELEASE( m_pCapBuf ) ;
             SAFE_RELEASE( m_pCapDev ) ; 
             
            return S_OK;
            }

            HRESULT CCaptureAudio::CreateCaptureBuffer(WAVEFORMATEX 
            * wfx) 
            {
             HRESULT hr;
             DSCBUFFERDESC dscbd;
             SAFE_RELEASE( m_pNotify );
             SAFE_RELEASE( m_pCapBuf );
             
            // Set the notification size
             m_dwNotifySize = MAX( 1024, wfx->nAvgBytesPerSec / 8 ) ; 
             m_dwNotifySize 
            -= m_dwNotifySize % wfx->nBlockAlign ;
             
            // Set the buffer sizes 
             m_dwCapBufSize = m_dwNotifySize * NUM_REC_NOTIFICATIONS;
             SAFE_RELEASE( m_pNotify );
             SAFE_RELEASE( m_pCapBuf );
             
            // Create the capture buffer
             ZeroMemory( &dscbd, sizeof(dscbd) );
             dscbd.dwSize        
            = sizeof(dscbd);
             dscbd.dwBufferBytes 
            = m_dwCapBufSize;
             dscbd.lpwfxFormat   
            = wfx ; // Set the format during creatation
             if( FAILED( hr = m_pCapDev->CreateCaptureBuffer( &dscbd, &m_pCapBuf, NULL ) ) )
              
            return S_FALSE ;
             m_dwNextCapOffset 
            = 0;
             
            if( FAILED( hr = InitNotifications() ) )
              
            return S_FALSE ;
             
            return S_OK;
            }

            HRESULT CCaptureAudio::InitNotifications() 
            {
             HRESULT hr; 
             
            int i ; 
             
            if( NULL == m_pCapBuf )
              
            return S_FALSE;
             
            // create auto notify event 
             m_hNotifyEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
             
            // Create a notification event, for when the sound stops playing
             if( FAILED( hr = m_pCapBuf->QueryInterface( IID_IDirectSoundNotify, (VOID**)&m_pNotify ) ) )
              
            return S_FALSE ;
             
            // Setup the notification positions
             for( i = 0; i < NUM_REC_NOTIFICATIONS; i++ ) {
              m_aPosNotify[i].dwOffset 
            = (m_dwNotifySize * i) + m_dwNotifySize - 1;
              m_aPosNotify[i].hEventNotify 
            = m_hNotifyEvent;             
             }

             
            // Tell DirectSound when to notify us. the notification will come in the from 
             
            // of signaled events that are handled in WinMain()
             if( FAILED( hr = m_pNotify->SetNotificationPositions( NUM_REC_NOTIFICATIONS, m_aPosNotify ) ) )
              
            return S_FALSE ;
             
            return S_OK;
            }

            HRESULT CCaptureAudio::StartOrStopRecord(BOOL bStartRec)
            {
             HRESULT hr;
             
            if( bStartRec ) {
              
            // Create a capture buffer, and tell the capture 
              
            // buffer to start recording   
              if( FAILED( hr = CreateCaptureBuffer( &m_wfxInput ) ) )
               
            return S_FALSE ;
              
            if( FAILED( hr = m_pCapBuf->Start( DSCBSTART_LOOPING ) ) )
               
            return S_FALSE ;
              
            // create notify event recv thread 
              AfxBeginThread(CCaptureAudio::notify_capture_thd, (LPVOID)(this)) ;
             }
             else 
              
            // Stop the capture and read any data that 
              
            // was not caught by a notification
              if( NULL == m_pCapBuf )
               
            return S_OK;
              
            // wait until the notify_event_thd thread exit and release the resources.
              Sleep(500) ;
              
            // Stop the buffer, and read any data that was not 
              
            // caught by a notification
              if( FAILED( hr = m_pCapBuf->Stop() ) )
               
            return S_OK ;
              
            if( FAILED( hr = RecordCapturedData() ) )
               
            return S_FALSE ; 
             }

             
            return S_OK;
            }

            HRESULT CCaptureAudio::RecordCapturedData() 
            {
             HRESULT hr;
             VOID
            *   pbCaptureData    = NULL;
             DWORD   dwCaptureLength;
             VOID
            *   pbCaptureData2   = NULL;
             DWORD   dwCaptureLength2;
             DWORD   dwReadPos;
             DWORD   dwCapturePos;
             LONG lLockSize;
             
            if( NULL == m_pCapBuf )
              
            return S_FALSE; 
             
             
            if( FAILED( hr = m_pCapBuf->GetCurrentPosition( &dwCapturePos, &dwReadPos ) ) )
              
            return S_FALSE;
             lLockSize 
            = dwReadPos - m_dwNextCapOffset;
             
            if( lLockSize < 0 )
              lLockSize 
            += m_dwCapBufSize;
             
            // Block align lock size so that we are always write on a boundary
             lLockSize -= (lLockSize % m_dwNotifySize);
             
            if( lLockSize == 0 )
              
            return S_FALSE;
             
            // Lock the capture buffer down
             if( FAILED( hr = m_pCapBuf->Lock( m_dwNextCapOffset, lLockSize,
                       
            &pbCaptureData, &dwCaptureLength, 
                       
            &pbCaptureData2, &dwCaptureLength2, 0L ) ) )
              
            return S_FALSE ;
             
            // call the outer data handler
             if(m_frame_handler) {
              m_frame_handler
            ->AdoFrameData((BYTE*)pbCaptureData, dwCaptureLength) ; 
             }

             
             
            // Move the capture offset along
             m_dwNextCapOffset += dwCaptureLength; 
             m_dwNextCapOffset 
            %= m_dwCapBufSize; // Circular buffer
             if( pbCaptureData2 != NULL ) {
              
            // call the outer data handler 
              if(m_frame_handler) {
               m_frame_handler
            ->AdoFrameData((BYTE*)pbCaptureData, dwCaptureLength) ; 
              }

              
            // Move the capture offset along
              m_dwNextCapOffset += dwCaptureLength2; 
              m_dwNextCapOffset 
            %= m_dwCapBufSize; // Circular buffer
             }

             
            // Unlock the capture buffer
             m_pCapBuf->Unlock( pbCaptureData,  dwCaptureLength, pbCaptureData2, dwCaptureLength2 );
             
            return S_OK;
            }

            void CCaptureAudio::SetWavFormat(WAVEFORMATEX * wfx)
            {
             
            // get the default capture wave formate 
             ZeroMemory(wfx, sizeof(WAVEFORMATEX)) ; 
             wfx
            ->wFormatTag = WAVE_FORMAT_PCM;
             
            // 8KHz, 16 bits PCM, Mono
             wfx->nSamplesPerSec = 8000 ; 
             wfx
            ->wBitsPerSample = 16 ; 
             wfx
            ->nChannels  = 1 ;
             wfx
            ->nBlockAlign = wfx->nChannels * ( wfx->wBitsPerSample / 8 ) ; 
             wfx
            ->nAvgBytesPerSec = wfx->nBlockAlign * wfx->nSamplesPerSec;
            }

            void CCaptureAudio::GrabAudioFrames(BOOL bGrabAudioFrames, CAdoFrameHandler* frame_handler) 
            {
             m_frame_handler 
            = frame_handler ; 
             m_bRecording 
            = bGrabAudioFrames ; 
             StartOrStopRecord(m_bRecording) ; 
            }
             
            使用的時(shí)候,也很簡單,我這里聲明了一個(gè)純虛類CAdoFrameHandler,這個(gè)類專門是用來讓使用者重載它的純虛函數(shù)的,只要重載了以后,設(shè)置正確,就可以自動(dòng)開始采集音頻數(shù)據(jù)了。注意,在這個(gè)類里面,我用的是8KHz,16Bits,Mono單聲道的PCM數(shù)據(jù)采集。
            使用的時(shí)候,首先:
            #include "CaptureAudio.h"
            然后:
            class CMyClass : public CAdoFrameHandler {

            public// override the CAdoFrameHandler
             void AdoFrameData(BYTE* pBuffer, long lBufferSize) ;  // 這個(gè)類重載一下,就可以采集了
             
            protected:
              CCaptureAudio   m_cap_ado ; 
            // 這個(gè)對(duì)象就是用來采集音頻數(shù)據(jù)的
            }
             ;
             
            在OnInitDialog類中,我們可以使用如下初始化方法:
             
            打開mic,同時(shí)初始化directsound:
            m_cap_ado.Open() ;
             
            開始采集聲音就是:
            m_cap_ado.GrabAudioFrames(TRUE, this) ;
            調(diào)用它以后,只要你重載了上面的那個(gè)函數(shù),directsound就會(huì)周期性的從麥克采集數(shù)據(jù),然后調(diào)用該函數(shù)。
             
            停止聲音采集是:
            m_cap_ado.GrabAudioFrames(FALSE, NULL) ;
             
            關(guān)閉mic,同時(shí)釋放directsound:
            m_cap_ado.Close() ;
             
            就這么簡單的幾步,就可以完成麥克風(fēng)的音頻數(shù)據(jù)采集。
            有問題歡迎大家多多交流。

            posted on 2012-11-23 00:11 楊粼波 閱讀(2464) 評(píng)論(1)  編輯 收藏 引用 所屬分類: 文章收藏C++

            評(píng)論

            # re: directsound抓取麥克風(fēng)PCM數(shù)據(jù)封裝類 2016-06-15 18:59 hello

            鏈接庫
            strmiids.lib Quartz.lib winmm.lib dsound.lib dxguid.lib  回復(fù)  更多評(píng)論   

            97精品国产97久久久久久免费| 久久精品www| 亚洲国产成人久久综合区| 狠狠色丁香婷婷久久综合不卡| 久久精品卫校国产小美女| 午夜视频久久久久一区| 久久九九久精品国产免费直播| 久久美女网站免费| 亚洲精品国产成人99久久| 久久国产精品成人免费| 久久国产乱子精品免费女| 久久精品成人免费网站| 国产午夜久久影院| 91久久国产视频| 国产精品久久久久乳精品爆| 国产香蕉97碰碰久久人人| 国产亚州精品女人久久久久久 | 女人高潮久久久叫人喷水| 性做久久久久久久久| 97视频久久久| 中文国产成人精品久久不卡| 亚洲AV成人无码久久精品老人| 人人狠狠综合久久88成人| 久久综合国产乱子伦精品免费| 久久久久女人精品毛片| 久久久91精品国产一区二区三区| 国产精品成人无码久久久久久 | 精品久久人人妻人人做精品| 精品久久久久国产免费 | 国产一区二区精品久久岳| 久久久久人妻精品一区三寸蜜桃| 久久久噜噜噜久久中文字幕色伊伊| 亚洲人AV永久一区二区三区久久 | 精品国产热久久久福利| 香蕉99久久国产综合精品宅男自 | 久久久久亚洲精品男人的天堂| 欧洲性大片xxxxx久久久| 97精品依人久久久大香线蕉97| 久久66热人妻偷产精品9| 国产亚洲精午夜久久久久久| 中文字幕精品无码久久久久久3D日动漫|