📄 waveaudiosource.cxx
字号:
// WaveAudioSource.cpp: implementation of the WaveAudioSource class.
//
//////////////////////////////////////////////////////////////////////
#include "AudioSample.h"
#include "AudioSampleManager.h"
#include "WaveAudioSource.h"
using namespace std;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
WaveAudioSource::WaveAudioSource()
{
char subFacilityName[100];
sprintf(subFacilityName, "WaveAudioSource:%x", this);
tracer.SetSubFacilityName(subFacilityName);
SetTraceLevel();
tracer.tracef(EE, "Constructor begin\n");
numBuffers = WAVESOURCE_NUM_WAVEHDR;
bufferSize = WAVESOURCE_DEFAULT_WAVEHDR_SIZE;
InitializeCriticalSection(&waveInMutex);
InitializeCriticalSection(&bufferListMutex);
InitializeCriticalSection(&filterMutex);
dataEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
bEnableAddBuffer = false;
hWaveIn = NULL;
waveinDeviceID = WAVE_MAPPER;
buffersToAdd.clear();
bRunning = false;
needToSetVolume = false;
micVolume = 0;
// set default format
SetFormat(WaveFormat_PCM_16_8_1);
}
WaveAudioSource::~WaveAudioSource()
{
tracer.tracef(EE, "Destructor begin\n");
EnterCriticalSection(&filterMutex);
tracer.tracef(ARB, "WaveAudioSource~ : entered filterMutex\n");
LeaveCriticalSection(&filterMutex);
tracer.tracef(ARB, "WaveAudioSource~ : left filterMutex\n");
DeleteCriticalSection(&waveInMutex);
DeleteCriticalSection(&bufferListMutex);
DeleteCriticalSection(&filterMutex);
CloseHandle(dataEvent);
tracer.tracef(EE, "Destructor end\n");
}
int
WaveAudioSource::SetTraceLevel()
{
long SystemMask = 0;
if ((SystemMask = GetRegKeyLong(HKEY_CURRENT_USER, "Software\\Cisco Systems\\MTC\\Tracing", "AllComponents", 0x0)) == 0)
{
SystemMask = GetRegKeyLong(HKEY_CURRENT_USER, "Software\\Cisco Systems\\MTC\\Tracing", "WaveAudioSource", 0x100000);
}
tracer.SetSystemMask(SystemMask);
return 0;
}
int
WaveAudioSource::SetFormat(int waveFormatNumber)
{
tracer.tracef(EE, "SetFormat %d : bRunning = %d\n", waveFormatNumber, bRunning);
if (!bRunning)
{
format = WaveFormat::GetWaveFormat(waveFormatNumber);
}
tracer.tracef(EE, "~SetFormat\n");
return 0;
}
int
WaveAudioSource::SetVolume(unsigned long vvolume)
{
if (bRunning)
{
MMRESULT rc; // Return code.
HMIXER hMixer; // Mixer handle used in mixer API calls.
MIXERCONTROL mxc; // Holds the mixer control data.
MIXERLINE mxl; // Holds the mixer line data.
MIXERLINECONTROLS mxlc; // Obtains the mixer control.
bool volumeChanged = false;
// Open the mixer. This opens the mixer with a deviceID of 0. If you
// have a single sound card/mixer, then this will open it. If you have
// multiple sound cards/mixers, the deviceIDs will be 0, 1, 2, and
// so on.
rc = mixerOpen(&hMixer, (UINT)hWaveIn, 0, 0, MIXER_OBJECTF_HWAVEIN);
if (MMSYSERR_NOERROR == rc)
{
tracer.tracef(DET, "SetVolume : mixerOpen succeeded\n");
do
{
// Initialize MIXERLINE structure.
ZeroMemory(&mxl,sizeof(mxl));
mxl.cbStruct = sizeof(mxl);
// Specify the line you want to get. You are getting the input line
// here. If you want to get the output line, you need to use
// MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT.
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE) : %d\n", rc);
break;
}
// now find out the microphone input for that line (the ADC)
int numConnections = mxl.cConnections;
tracer.tracef(DET, "SetVolume : mixerGetLineInfo succeeded. numConnections = %d\n", numConnections);
DWORD destinationLineID = mxl.dwDestination;
for (int j=0; j<numConnections; j++)
{
mxl.cbStruct = sizeof(MIXERLINE);
mxl.dwDestination = destinationLineID;
mxl.dwSource = j;
rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl, MIXER_GETLINEINFOF_SOURCE);
if (rc == MMSYSERR_NOERROR)
{
tracer.tracef(DET, "SetVolume : mixerGetLineInfo succeeded. dwComponentType %d = 0x%x\n", j, mxl.dwComponentType);
if (mxl.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE ||
mxl.dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED)
{
// Get the control.
ZeroMemory(&mxlc, sizeof(mxlc));
mxlc.cbStruct = sizeof(mxlc);
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.cControls = 1;
mxlc.cbmxctrl = sizeof(mxc);
mxlc.pamxctrl = &mxc;
ZeroMemory(&mxc, sizeof(mxc));
mxc.cbStruct = sizeof(mxc);
rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE) : %d. Could not get MIXERCONTROL_CONTROLTYPE_VOLUME\n", rc);
break;
}
// After successfully getting the peakmeter control, the volume range
// will be specified by mxc.Bounds.lMinimum to mxc.Bounds.lMaximum.
MIXERCONTROLDETAILS mxcd; // Gets the control values.
MIXERCONTROLDETAILS_UNSIGNED volStruct; // Gets the control values.
MIXERCONTROLDETAILS_BOOLEAN muteStruct; // Get Mute Setting
long volume; // Holds the final volume value.
// Initialize the MIXERCONTROLDETAILS structure
ZeroMemory(&mxcd, sizeof(mxcd));
mxcd.cbStruct = sizeof(mxcd);
mxcd.cbDetails = sizeof(volStruct);
mxcd.dwControlID = mxc.dwControlID;
mxcd.paDetails = &volStruct;
mxcd.cChannels = 1;
// Get the current value of the volume control. Typically, you
// would set a timer in your program to query the volume every 10th
// of a second or so.
rc = mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd,
MIXER_GETCONTROLDETAILSF_VALUE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_GETCONTROLDETAILSF_VALUE) : %d\n", rc);
break;
}
volume = volStruct.dwValue;
volStruct.dwValue = (0xffff * vvolume) / 100;
rc = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_SETCONTROLDETAILSF_VALUE) : %d\n", rc);
break;
}
volumeChanged = true;
// Get the mute control.
ZeroMemory(&mxlc, sizeof(mxlc));
mxlc.cbStruct = sizeof(mxlc);
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
mxlc.cControls = 1;
mxlc.cbmxctrl = sizeof(mxc);
mxlc.pamxctrl = &mxc;
ZeroMemory(&mxc, sizeof(mxc));
mxc.cbStruct = sizeof(mxc);
rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE) : %d. Could not get MIXERCONTROL_CONTROLTYPE_VOLUME\n", rc);
if (mxl.dwComponentType != MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)
{
continue;
}
else
{
break;
}
}
ZeroMemory(&mxcd, sizeof(mxcd));
mxcd.cbStruct = sizeof(mxcd);
mxcd.cbDetails = sizeof(muteStruct);
mxcd.dwControlID = mxc.dwControlID;
mxcd.paDetails = &muteStruct;
mxcd.cChannels = 1;
// Get the current value of the mute control. Typically, you
// would set a timer in your program to query the volume every 10th
// of a second or so.
rc = mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd,
MIXER_GETCONTROLDETAILSF_VALUE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_GETCONTROLDETAILSF_VALUE) : %d\n", rc);
break;
}
muteStruct.fValue = vvolume == 0 ? 1 : 0;
rc = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_SETCONTROLDETAILSF_VALUE) : %d\n", rc);
break;
}
break;
}
}
}
} while (false);
if (volumeChanged == false)
{
do
{
// Initialize MIXERLINE structure.
ZeroMemory(&mxl,sizeof(mxl));
mxl.cbStruct = sizeof(mxl);
// Specify the line you want to get. You are getting the input line
// here. If you want to get the output line, you need to use
// MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT.
mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
MIXER_GETLINEINFOF_COMPONENTTYPE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl, MIXER_GETLINEINFOF_COMPONENTTYPE) : %d\n", rc);
break;
}
// now find out the microphone input for that line (the ADC)
int numConnections = mxl.cConnections;
tracer.tracef(DET, "SetVolume : mixerGetLineInfo succeeded. numConnections = %d\n", numConnections);
DWORD destinationLineID = mxl.dwDestination;
// Get the control.
ZeroMemory(&mxlc, sizeof(mxlc));
mxlc.cbStruct = sizeof(mxlc);
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mxlc.cControls = 1;
mxlc.cbmxctrl = sizeof(mxc);
mxlc.pamxctrl = &mxc;
ZeroMemory(&mxc, sizeof(mxc));
mxc.cbStruct = sizeof(mxc);
rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE) : %d. Could not get MIXERCONTROL_CONTROLTYPE_VOLUME\n", rc);
if (mxl.dwComponentType != MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)
{
continue;
}
else
{
break;
}
}
MIXERCONTROLDETAILS mxcd; // Gets the control values.
MIXERCONTROLDETAILS_UNSIGNED volStruct; // Gets the control values.
MIXERCONTROLDETAILS_BOOLEAN muteStruct; // Get Mute Setting
long volume; // Holds the final volume value.
// Initialize the MIXERCONTROLDETAILS structure
ZeroMemory(&mxcd, sizeof(mxcd));
mxcd.cbStruct = sizeof(mxcd);
mxcd.cbDetails = sizeof(volStruct);
mxcd.dwControlID = mxc.dwControlID;
mxcd.paDetails = &volStruct;
mxcd.cChannels = 1;
// Get the current value of the peakmeter control. Typically, you
// would set a timer in your program to query the volume every 10th
// of a second or so.
rc = mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd,
MIXER_GETCONTROLDETAILSF_VALUE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_GETCONTROLDETAILSF_VALUE) : %d\n", rc);
break;
}
volume = volStruct.dwValue;
volStruct.dwValue = (0xffff * vvolume) / 100;
rc = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_SETCONTROLDETAILSF_VALUE) : %d\n", rc);
break;
}
volumeChanged = true;
// Get the mute control.
ZeroMemory(&mxlc, sizeof(mxlc));
mxlc.cbStruct = sizeof(mxlc);
mxlc.dwLineID = mxl.dwLineID;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
mxlc.cControls = 1;
mxlc.cbmxctrl = sizeof(mxc);
mxlc.pamxctrl = &mxc;
ZeroMemory(&mxc, sizeof(mxc));
mxc.cbStruct = sizeof(mxc);
rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
MIXER_GETLINECONTROLSF_ONEBYTYPE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE) : %d. Could not get MIXERCONTROL_CONTROLTYPE_VOLUME\n", rc);
if (mxl.dwComponentType != MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE)
{
continue;
}
else
{
break;
}
}
ZeroMemory(&mxcd, sizeof(mxcd));
mxcd.cbStruct = sizeof(mxcd);
mxcd.cbDetails = sizeof(muteStruct);
mxcd.dwControlID = mxc.dwControlID;
mxcd.paDetails = &muteStruct;
mxcd.cChannels = 1;
// Get the current value of the mute control. Typically, you
// would set a timer in your program to query the volume every 10th
// of a second or so.
rc = mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd,
MIXER_GETCONTROLDETAILSF_VALUE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_GETCONTROLDETAILSF_VALUE) : %d\n", rc);
break;
}
muteStruct.fValue = vvolume == 0 ? 1 : 0;
rc = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd,
MIXER_SETCONTROLDETAILSF_VALUE);
if (MMSYSERR_NOERROR != rc)
{
tracer.tracef(ERR, "SetVolume : e-mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_SETCONTROLDETAILSF_VALUE) : %d\n", rc);
break;
}
break;
} while (false);
}
mixerClose(hMixer);
}
else
{
tracer.tracef(ERR, "SetVolume : e-mixerOpen : %d\n", rc);
}
}
else
{
needToSetVolume = true;
}
micVolume = vvolume;
return 0;
}
int
WaveAudioSource::SetDeviceID(unsigned int deviceID)
{
waveinDeviceID = deviceID;
return 0;
}
int
WaveAudioSource::SetBufferSize(int size)
{
tracer.tracef(EE, "SetBufferSize %d : bRunning = %d\n", size, bRunning);
if (!bRunning)
{
bufferSize = size;
}
tracer.tracef(EE, "~SetBufferSize\n");
return 0;
}
int
WaveAudioSource::SetNumBuffers(int num)
{
tracer.tracef(EE, "SetNumBuffers %d : bRunning = %d\n", num, bRunning);
if (!bRunning)
{
numBuffers = num;
}
tracer.tracef(EE, "~SetNumBuffers\n");
return 0;
}
int
WaveAudioSource::BeginAudioCapture()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -