Directsound capturing microphone PCM Data encapsulation class

Source: Internet
Author: User
Directsound capturing microphone PCM Data encapsulation class
There are many ways to read PCM data from a microphone on the Internet. I just released a directsound microphone PCM Data Collection class I wrote here. Through this class, we can easily use directsound technology to collect microphone data, developers do not have to worry too much about whether they will program directsound. They can easily concentrate on the program itself rather than the details. This is the header file: # pragma once
# Ifndef _ capture_sound_h _
# DEFINE _ capture_sound_h _
# Include <mmsystem. h>
# Include <dsound. h> # define num_rec_configurications 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
Lpdirectsoundpolicy8 m_pnotify; // capture auto-inform y Event Callback handler PTR guid m_guidcapdevid; // capture device ID
Waveformatex m_wfxinput; // input wave format description struct dsbpositiony y m_aposnotify [num_rec_configurications + 1]; // notify flag Array
Handle m_hpolicyevent; // handle Y event
Bool m_abinputfmtsupported [20];
DWORD m_dwcapbufsize; // capture loop buffer size
DWORD m_dwnextcapoffset; // offset in loop buffer
DWORD m_dwpolicysize; // adjust y 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, lpctstr lpszdesc,
Lpctstr lpszdrvname, lpvoid lpcontext); static uint policy_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 );
}; # Below endif is the CPP file: # 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_hpolicyevent = NULL;
} Ccaptureaudio ::~ Ccaptureaudio (void)
{
Couninitialize ();
} Bool callback ccaptureaudio: enum_dev_proc (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;
Hresult hr;
DWORD dwresult;
While (pado-> m_brecording ){
Dwresult = msgwaitformultipleobjects (1, & (pado-> m_hpolicyevent), 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 events .");
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_hpolicyevent );
Return (failed (HR ))? False: true;
} Hresult ccaptureaudio: initdirectsound (guid dev_id)
{
Hresult hr;
M_guidcapdevid = dev_id; zeromemory (& m_aposnotify, sizeof (dsbpositionications y) * (num_rec_ications ications + 1 ));
M_dwcapbufsize = 0;
M_dwpolicysize = 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_p1_y );
Safe_release (m_pcapbuf); // set the notification size
M_dwpolicysize = max (1024, WFX-> navgbytespersec/8 );
M_dwpolicysize-= m_dwpolicysize % WFX-> nblockalign; // set the Buffer Sizes
M_dwcapbufsize = m_dwpolicysize * num_rec_configurications; 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 scaling y event
M_hpolicyevent = 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_ications ications; I ++ ){
M_aposnotify [I]. dwoffset = (m_dwpolicysize * I) + m_dwpolicysize-1;
M_aposnotify [I]. heventpolicy = m_hpolicyevent;
} // Tell directsound when to notify y us. The notification will come in the from
// Of signaled events that are handled in winmain ()
If (failed (hR = m_pnotify-> setnotifposipositions (num_rec_ications ications, 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 your y 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 policy_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 dwcaptureleng2;
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_dwpolicysize); If (llocksize = 0)
Return s_false; // lock the capture buffer down
If (failed (hR = m_pcapbuf-> lock (m_dwnextcapoffset, llocksize,
& Pbcapturedata, & dwcapturelength,
& Pbcapturedata2, & dwcaptureleng2, 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 + = dwcaptureleng2;
M_dwnextcapoffset % = m_dwcapbufsize; // circular buffer
} // Unlock the capture Buffer
M_pcapbuf-> unlock (pbcapturedata, dwcapturelength, pbcapturedata2, dwcaptureleng22.); Return s_ OK;
} Void ccaptureaudio: setwavformat (waveformatex * WFX)
{
// Get the default capture wave Formate
Zeromemory (WFX, sizeof (waveformatex ));
WFX-> wformattag = wave_format_pcm; // 8 kHz, 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 );
} It is also very simple to use. Here I declare a pure virtual class cadoframehandler. This class is specifically used to let users reload its pure virtual function. As long as it is reloaded, after the settings are correct, you can automatically start collecting audio data. Note that in this class, I use 8 kHz, 16 bits, and mono single-channel PCM data collection. First: # include "captureaudio. H" and then: Class cmyclass: Public cadoframehandler {... public: // override the cadoframehandler
Void adoframedata (byte * pbuffer, long lbuffersize); // This class can be reloaded to collect protected: ccaptureaudio m_cap_ado; // This object is used to collect audio data }; in the oninitdialog class, we can use the following initialization method: open mic and initialize directsound: m_cap_ado.open (); start to collect sound: m_cap_ado.grabaudioframes (true, this); after calling it, as long as you reload the function above, directsound periodically collects data from the microphone and calls the function. To stop audio collection, set m_cap_ado.grabaudioframes (false, null) to disable MIC and release directsound: m_cap_ado.close (). In just a few steps, you can complete audio data collection for the microphone. If you have any questions, please contact us.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.