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 + -
显示快捷键?