microphonedevicedriver.cpp
来自「一个语言识别引擎」· C++ 代码 · 共 636 行 · 第 1/2 页
CPP
636 行
// Class: SoundResources
// Method: (public)_uninitialize
// Description:
//--------------------------------------------------------------------------------------
int SoundResources::_uninitialize (void)
{
_bmutex.wait ();
m_InRecord = false;
mixerClose(m_MixerHandle); // Close mixer
waveInReset(m_WaveInHandle); // Reset the wave input device
if(_rawBuffer != NULL){
delete[] _rawBuffer; // Delete the shared buffer
_rawBuffer = NULL;
}
_bmutex.post ();
return 1;
}
int SoundResources::_init (const SoundOpenParameters& params)
{
//----------------------------------------------------------------------
// Initalize local parameters with the open params. It the open param
// is != 0 then the local param is updated if not the default value is
// used.
// Default configuration:
// 16-bit, 44KHz, stereo
//----------------------------------------------------------------------
if (params.m_Channels != 0) channels = params.m_Channels;
if (params.m_SamplesPerSec != 0) freqSample = params.m_SamplesPerSec;
if (params.m_BitsPerSample != 0) nBitsSample = params.m_BitsPerSample;
if (params.m_BufferLength != 0) dwBufferLength = params.m_BufferLength;
//----------------------------------------------------------------------
// Initialize the wave in
//----------------------------------------------------------------------
m_waveFormat.wFormatTag = WAVE_FORMAT_PCM;
m_waveFormat.nChannels = channels;
m_waveFormat.nSamplesPerSec = freqSample;
m_waveFormat.wBitsPerSample = nBitsSample;
m_waveFormat.nBlockAlign = m_waveFormat.nChannels * (m_waveFormat.wBitsPerSample/8);
m_waveFormat.nAvgBytesPerSec = m_waveFormat.nSamplesPerSec * m_waveFormat.nBlockAlign;
m_waveFormat.cbSize = 0;
m_err = waveInOpen(&m_WaveInHandle,
WAVE_MAPPER,
&m_waveFormat,
(DWORD)params.m_callbackthread_identifier, //Here I have to add the thread ID
(DWORD)this,
CALLBACK_THREAD);
if (m_err != MMSYSERR_NOERROR) {
printf("Can't open WAVE In Device! %d",m_err);
return(-2);
}
//----------------------------------------------------------------------
// Initialize Mixter
//----------------------------------------------------------------------
m_err = mixerOpen(&m_MixerHandle,
(DWORD)m_WaveInHandle,
0,
0,
MIXER_OBJECTF_HWAVEIN);
if (m_err != MMSYSERR_NOERROR) {
printf("yarpsounddriver: Device does not have mixer support! -- %08X\n", m_err);
}
//----------------------------------------------------------------------
// Print all the present lines in the audio interface
//----------------------------------------------------------------------
printf("MicrophoneDeviceDriver: LINES PRESENT\n");
_print_dst_lines();
//----------------------------------------------------------------------
// This device should have a WAVEIN destination line. Let's get its ID so
// that we can determine what source lines are available to record from
//----------------------------------------------------------------------
m_mixerLine.cbStruct = sizeof(MIXERLINE);
m_mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
m_err = mixerGetLineInfo((HMIXEROBJ)m_MixerHandle,
&m_mixerLine,
MIXER_GETLINEINFOF_COMPONENTTYPE);
if (m_err != MMSYSERR_NOERROR) {
printf("Device does not have a WAVE recording control! -- %08X\n", m_err);
}
m_numSrc = m_mixerLine.cConnections; // Get how many source lines are available from which to record.
m_err = _select_line(MIXERLINE_COMPONENTTYPE_SRC_LINE); //select default source line
if (m_err == -1){ //Not line found, trying the auxiliary....
m_err = _select_line(MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY);
}
if (m_err != 1)
printf("MicrophoneDeviceDriver: Atention Source line not found!!!\n");
//----------------------------------------------------------------------
// Initialize the local buffers
//----------------------------------------------------------------------
_bmutex.wait ();
_rawBuffer = new unsigned char [dwBufferLength];
// ACE_ASSERT (_rawBuffer != NULL);
_bmutex.post ();
return 1;
}
// === FUNCTION ======================================================================
//
// Name: RES
//
// Description: This is a convenient function to recover the pointer to the SoundResources
// object
//
// Author: Ing. Carlos Beltran
// Revision: none
// =====================================================================================
inline SoundResources& RES(void *res)
{
return *(SoundResources *)res;
}
//--------------------------------------------------------------------------------------
// Class: SoundResources
// Method: acquireBuffer
// Description: This method blocks the access to the lockable buffer. This allows to
// obtain access to a clear copy without DMA interferences
//--------------------------------------------------------------------------------------
int SoundResources::acquireBuffer (void *buffer)
{
_bmutex.wait ();
(*(unsigned char **)buffer) = _rawBuffer;
return 1;
}
//--------------------------------------------------------------------------------------
// Class: SoundResources
// Method: releaseBuffer
// Description: This method release the mutex controlling the exclusive access to the
// buffer containing the data, thus the thread can write in the common buffer getting the
// data from the memory used by the DMA.
//--------------------------------------------------------------------------------------
int SoundResources::releaseBuffer ()
{
_canpost = true;
_bmutex.post ();
return 1;
}
//--------------------------------------------------------------------------------------
// Class: MicrophoneDeviceDriver
// Method: waitOnNewFrame
// Description: This call blocks until new data is available in the common buffer
//--------------------------------------------------------------------------------------
int SoundResources::waitOnNewFrame ()
{
_new_frame.wait ();
return 1;
}
void SoundResources::run()
{
MSG msg;
//----------------------------------------------------------------------
// Wait for a message sent by the audio driver
//----------------------------------------------------------------------
while ((GetMessage(&msg, 0, 0, 0) == 1) && isRunning())
{
switch (msg.message) {
case MM_WIM_DATA: //Buffer filled
/*********************************************************************************
* the msg.lParam contains a pointer to the WAVEHDR structure for the filled buffer. *
*********************************************************************************/
if (((WAVEHDR *)msg.lParam)->dwBytesRecorded) {
//----------------------------------------------------------------------
// Here write in the local buffer using the syncronization mutexes
//----------------------------------------------------------------------
if (_bmutex.check()) { // buffer acquired. Reading from the buffer
if (m_InRecord)
memcpy (_rawBuffer,
((WAVEHDR *)msg.lParam)->lpData,
((WAVEHDR *)msg.lParam)->dwBytesRecorded); // Note: is this right?
// The buffer could not be full...
if (_canpost) {
_canpost = false;
_new_frame.post();
}
_bmutex.post ();
}
else
{
//----------------------------------------------------------------------
// can't acquire, it means the buffer is still in use.
// silently ignores this condition.
//----------------------------------------------------------------------
//ACE_DEBUG ((LM_DEBUG, "lost a frame, acq thread\n"));
printf("lost a frame, acq thread\n");
}
}
//----------------------------------------------------------------------
// Requeue the used buffer
//----------------------------------------------------------------------
waveInAddBuffer(m_WaveInHandle,
(WAVEHDR *)msg.lParam,
sizeof(WAVEHDR));
break;
/* Our main thread is opening the WAVE device */
case MM_WIM_OPEN:
//printf( "ace_Debug: MicrophoneDeviceDriver: sound device opened\n");
break;
/* Our main thread is closing the WAVE device */
case MM_WIM_CLOSE:
break;
default:
//ACE_DEBUG ((LM_DEBUG, "yarpsounddriver: received an unknown message\n"));
break;
}
}
}
MicrophoneDeviceDriver::MicrophoneDeviceDriver()
{
dsp = -1;
system_resources = (void *) (new SoundResources);
}
MicrophoneDeviceDriver::~MicrophoneDeviceDriver()
{
if (system_resources != NULL)
delete (SoundResources *)system_resources;
system_resources = NULL;
close();
}
bool MicrophoneDeviceDriver::open(yarp::os::Searchable& config)
{
int ret=1;
SoundOpenParameters *res=new SoundOpenParameters();
SoundResources& d = RES(system_resources);
d.start(); //Start the thread first. The identifier is necesary in the lower level
/***************************************************************************
* The thread ID is necesary to run the waveIn call that uses it to assing *
* the callback message to this thread. Therefore, the Body part of the *
* thread will receive the messages (linked internally to hardware *
* interrupts) generated by the low level sound driver. *
***************************************************************************/
res->m_callbackthread_identifier = d.getKey();
ret = d._initialize (*(SoundOpenParameters *)res);
if (ret)
{
printf("returning true\n");
return true;
}
else
{
printf("returning false\n");
return false;
}
}
bool MicrophoneDeviceDriver::close(void)
{
SoundResources& d = RES(system_resources);
d.stop(); //This ends the thread. Will see if is really necessary in the sound driver
int ret = d._uninitialize ();
if(ret)
return true;
else
return false;
}
bool MicrophoneDeviceDriver::getSound(yarp::sig::Sound& sound)
{
SoundResources& d = RES(system_resources);
unsigned char *tmp;
d.waitOnNewFrame ();
d.acquireBuffer(&tmp);
short int *buffer = (short int*)tmp;
sound.resize(d.numSamples,d.channels);
sound.setFrequency(d.freqSample);
for (int a=0;a<d.numSamples; a++)
for(int c = 0; c < d.channels; c++)
sound.set(buffer[a*2+c],a,c);
d.releaseBuffer ();
return true;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?