microphonedevicedriver.cpp

来自「一个语言识别引擎」· C++ 代码 · 共 636 行 · 第 1/2 页

CPP
636
字号
// -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-

/*
 * Copyright (C) 2006 Julio Gomes, Alexandre Bernardino
 * CopyPolicy: Released under the terms of the GNU GPL v2.0.
 *
 */

/***********************************************************************

  YARP2 MicrophoneDeviceDriver

  Windows Native Implementation for sound acquisition

  Adapted from YARP1 - YarpSoundDeviceDriver, YarpSoundCardUtils

  Author of YARP1 (original) Code: Carlos Beltran, Lira-Lab, DIST, UNIGE

  Authors of YARP2 (adapted) Code: Julio Gomes, Alexandre Bernardino, VisLab, ISR-IST

  Contact: jgomes(a)isr.ist.utl.pt, alex(a)isr.ist.utl.pt

************************************************************************/

#include <yarp/MicrophoneDeviceDriver.h>
#include <yarp/os/all.h>
#include <ace/Sched_Params.h>

#undef main
#include <windows.h>
#include <mmsystem.h>

using namespace yarp::os;
using namespace yarp::dev;


/*
  SoundOpenParameters contains initialization parameters.
  It is inherited from YARP1 and is now obsolete.
  Future: use Searchable class instead.
*/
struct SoundOpenParameters
{
	SoundOpenParameters()
	{
		m_callbackthread_identifier = 0;
		m_Channels      = 0;
		m_SamplesPerSec = 0;
		m_BitsPerSample = 0;
		m_BufferLength  = 0;
	}

	int m_callbackthread_identifier;  //This is the thread identifier for the callback
	int m_Channels;
	int m_SamplesPerSec;
	int m_BitsPerSample;
	int m_BufferLength;
};

/*
  SoundResources: 
  Encapsulates windows native stuff for sound acquisition.
*/

class SoundResources : public yarp::os::Semaphore, public yarp::os::Thread
{
public:
	//----------------------------------------------------------------------
	//  Constructor/Destructor
	//----------------------------------------------------------------------
	SoundResources (void) : _bmutex(1),
							_new_frame(0),
							_canpost(true),
							numSamples(2048),
							microDistance(0.14)
	{
		//----------------------------------------------------------------------
		// Initialize variables
		// Default: 16-bit, 44KHz, stereo
		//----------------------------------------------------------------------
		m_InRecord     = false;
		dwBufferLength = 8192;
		freqSample     = 44100;
		nBitsSample    = 16;
		channels       = 2;
	}

	~SoundResources () { _uninitialize (); }

	//----------------------------------------------------------------------
	// Variables  
	//----------------------------------------------------------------------
	yarp::os::Semaphore _bmutex;
	yarp::os::Semaphore _new_frame;
	bool          _canpost;

	//Declare usefull variables
    HWAVEIN       m_WaveInHandle;    // Handle to the WAVE In Device
    HMIXER        m_MixerHandle;     // Handle to Mixer for WAVE In Device
    WAVEHDR       m_WaveHeader[3];   // We use two WAVEHDR's for recording (ie, double-buffering) in this example
    bool          m_InRecord;        // Variable used to indicate whether we are in record
    unsigned char m_DoneAll;         // Variable used by recording thread to indicate whether we are in record

    MMRESULT      m_err;
    WAVEFORMATEX  m_waveFormat;
    MIXERLINE     m_mixerLine;
    HANDLE        m_waveInThread;
    unsigned long m_n;
    unsigned long m_numSrc;
	
	// Control structures 
	MIXERCONTROL      m_mixerControlArray;
	MIXERLINECONTROLS m_mixerLineControls;

	//Local lockable buffer
	unsigned char *_rawBuffer;

	//----------------------------------------------------------------------
	//  Parameters
	//----------------------------------------------------------------------
	DWORD        dwBufferLength;
	const DWORD  numSamples;       //dwBufferLength/4
	DWORD        freqSample;
	const double microDistance;    // babybot
	WORD         nBitsSample;
	WORD         channels;

	//----------------------------------------------------------------------
	// Public Method definitions 
	//----------------------------------------------------------------------
	int _initialize (const SoundOpenParameters& params);
	int _uninitialize (void);
	int _select_line(unsigned int type);
	int _select_control(unsigned int control);
	int acquireBuffer (void *buffer);
	int releaseBuffer (void);
	int waitOnNewFrame(void);
	void run(void);
	

protected:
	
	//----------------------------------------------------------------------
	//  Protected method definitions
	//----------------------------------------------------------------------
	int _init (const SoundOpenParameters& params);
	void _prepareBuffers (void);
	void _print_dst_lines();
	void _print_src_lines();
};

//--------------------------------------------------------------------------------------
//       Class:  SoundResources
//      Method:  _print_src_lines
// Description:  This function prints in the screen the source lines present
//--------------------------------------------------------------------------------------
void
SoundResources::_print_src_lines()
{
	for (int i = 0; i < m_numSrc; i++)
        {
            m_mixerLine.cbStruct = sizeof(MIXERLINE);
            m_mixerLine.dwSource = i;

            if (!(m_err = mixerGetLineInfo((HMIXEROBJ)m_MixerHandle, &m_mixerLine, MIXER_GETLINEINFOF_SOURCE)))
                {
                    if (m_mixerLine.dwComponentType != MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER)
                        printf("\t\t#%lu: %s\n", i, m_mixerLine.szName);
                }
        }
}

//--------------------------------------------------------------------------------------
//       Class:  SoundResources
//      Method:  (public)_select_control
// Description:  This methos allows to select the type of control in the selected line
//--------------------------------------------------------------------------------------
int
SoundResources::_select_control(unsigned int control_type)
{
	//----------------------------------------------------------------------
	//  Fill the mixerLineControls structure
	//----------------------------------------------------------------------
	m_mixerLineControls.cbStruct      = sizeof(MIXERLINECONTROLS);
	m_mixerLineControls.dwLineID      = m_mixerLine.dwLineID;
	m_mixerLineControls.cControls     = 1;
	m_mixerLineControls.dwControlType = control_type;
	m_mixerLineControls.pamxctrl      = &m_mixerControlArray;
	m_mixerLineControls.cbmxctrl      = sizeof(MIXERCONTROL);

	m_err = mixerGetLineControls((HMIXEROBJ)m_MixerHandle, 
								 &m_mixerLineControls, 
								 MIXER_GETLINECONTROLSF_ONEBYTYPE);
	
	if (m_err != MMSYSERR_NOERROR) 
		printf("yarpsounddriver: %s has no %s control!\n", 
			   m_mixerLine.szName, 
			   m_mixerLineControls.pamxctrl->szName);
	
	return 1;
}

int SoundResources::_select_line(unsigned int type)
{

    for(int i = 0; i < m_numSrc; i++) {
		m_mixerLine.cbStruct = sizeof(MIXERLINE);	
		m_mixerLine.dwSource = i;

		m_err = mixerGetLineInfo((HMIXEROBJ)m_MixerHandle,
								 &m_mixerLine,
								 MIXER_GETLINEINFOF_SOURCE);
		
		if (m_err != MMSYSERR_NOERROR) continue;
		
		if (m_mixerLine.dwComponentType == type)
            {
                printf("yarpsounddriver: source line found\n");
                return 1;
            }	
	}
	printf("yarpsounddriver: -warning- source line not found\n");
	return -1;

}

void SoundResources::_prepareBuffers(void) {

	//----------------------------------------------------------------------
	//  Preparing all memory buffer allocation
	//----------------------------------------------------------------------
	m_WaveHeader[2].dwBufferLength = 
        m_WaveHeader[1].dwBufferLength = 
        m_WaveHeader[0].dwBufferLength = dwBufferLength;

	m_WaveHeader[0].lpData = (char *)VirtualAlloc(0, 
												  m_WaveHeader[0].dwBufferLength, 
												  MEM_COMMIT, 
												  PAGE_READWRITE);
	m_WaveHeader[1].lpData = (char *)VirtualAlloc(0, 
												  m_WaveHeader[1].dwBufferLength, 
												  MEM_COMMIT, 
												  PAGE_READWRITE);
	m_WaveHeader[2].lpData = (char *)VirtualAlloc(0, 
												  m_WaveHeader[2].dwBufferLength, 
												  MEM_COMMIT, 
												  PAGE_READWRITE);
	
	//----------------------------------------------------------------------
	// Initialize dwFlags and dwLoops to 0. This seems to be necesary according to the
	// Microsoft Windows documentation 
	//----------------------------------------------------------------------
	m_WaveHeader[0].dwFlags = m_WaveHeader[1].dwFlags = m_WaveHeader[2].dwFlags = 0L;
	m_WaveHeader[0].dwLoops = m_WaveHeader[1].dwLoops = m_WaveHeader[2].dwFlags = 0L; 

	//----------------------------------------------------------------------
	// Initialize the headers
	//----------------------------------------------------------------------
	if ((m_err = waveInPrepareHeader(m_WaveInHandle, &m_WaveHeader[0], sizeof(WAVEHDR)))) 
		printf("yarpsounddriver: Error preparing WAVEHDR -- %08X\n", m_err);
	if ((m_err = waveInPrepareHeader(m_WaveInHandle, &m_WaveHeader[1], sizeof(WAVEHDR)))) 
		printf("yarpsounddriver: Error preparing WAVEHDR -- %08X\n", m_err);
	if ((m_err = waveInPrepareHeader(m_WaveInHandle, &m_WaveHeader[2], sizeof(WAVEHDR)))) 
		printf("yarpsounddriver: Error preparing WAVEHDR -- %08X\n", m_err);

	//----------------------------------------------------------------------
	//  It is necessary to queue the two buffers.  
	//----------------------------------------------------------------------
	if ((m_err = waveInAddBuffer(m_WaveInHandle, &m_WaveHeader[0], sizeof(WAVEHDR))))
		printf("yarpsounddriver: Error queueing WAVEHDR 1! -- %08X\n", m_err);
	if ((m_err = waveInAddBuffer(m_WaveInHandle, &m_WaveHeader[1], sizeof(WAVEHDR))))
		printf("yarpsounddriver: Error queueing WAVEHDR 2! -- %08X\n", m_err);
	if ((m_err = waveInAddBuffer(m_WaveInHandle, &m_WaveHeader[2], sizeof(WAVEHDR))))
		printf("yarpsounddriver: Error queueing WAVEHDR 2! -- %08X\n", m_err);

	return;
}


void SoundResources::_print_dst_lines() {

	MIXERCAPS mixerCaps;

	mixerGetDevCaps(0,&mixerCaps, sizeof(mixerCaps));

	for (int i = 0; i < mixerCaps.cDestinations; i++)
        {
            m_mixerLine.cbStruct      = sizeof(MIXERLINE);
            m_mixerLine.dwSource      = 0;
            m_mixerLine.dwDestination = i;

            if (!(m_err = mixerGetLineInfo((HMIXEROBJ)m_MixerHandle, &m_mixerLine, MIXER_GETLINEINFOF_DESTINATION))) {
				printf("\t#%lu: %s\n", i, m_mixerLine.szName);
            }
            m_numSrc = m_mixerLine.cConnections;
            _print_src_lines();
        }

	return;
}



int SoundResources::_initialize (const SoundOpenParameters& params)
{
	_init (params);
	_prepareBuffers ();
	
	//start continuous acquisition
	if ((m_err = waveInStart(m_WaveInHandle))) {
		printf("MicrophoneDeviceDriver: Error starting record! -- %08X\n", m_err);
	}
	m_InRecord = true;

	return 1;
}

//--------------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?