日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

directsound抓取麦克风PCM数据封装类

發(fā)布時(shí)間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 directsound抓取麦克风PCM数据封装类 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
directsound抓取麥克風(fēng)PCM數(shù)據(jù)封裝類
網(wǎng)上有很多方法從麥克風(fēng)讀取PCM數(shù)據(jù),不想一一舉例。只是在這里發(fā)布一個(gè)我自己寫的directsound的麥克風(fēng)PCM數(shù)據(jù)采集類,通過它,可以很方便的利用directsound技術(shù)把麥克風(fēng)的數(shù)據(jù)采集到,而且本身,開發(fā)者不必太在意自己會不會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, 0, 0, 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è)置正確,就可以自動開始采集音頻數(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è)對象就是用來采集音頻數(shù)據(jù)的 } ; 在OnInitDialog類中,我們可以使用如下初始化方法: 打開mic,同時(shí)初始化directsound: m_cap_ado.Open() ; 開始采集聲音就是: m_cap_ado.GrabAudioFrames(TRUE, this) ; 調(diào)用它以后,只要你重載了上面的那個(gè)函數(shù),directsound就會周期性的從麥克采集數(shù)據(jù),然后調(diào)用該函數(shù)。 停止聲音采集是: m_cap_ado.GrabAudioFrames(FALSE, NULL) ; 關(guān)閉mic,同時(shí)釋放directsound: m_cap_ado.Close() ; 就這么簡單的幾步,就可以完成麥克風(fēng)的音頻數(shù)據(jù)采集。 有問題歡迎大家多多交流。

總結(jié)

以上是生活随笔為你收集整理的directsound抓取麦克风PCM数据封装类的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。