📄 windowsaudioinputdevice_mixer.cpp
字号:
: hMixer(NULL), dwRecLineID(0), numPorts(0), ports(NULL) {}Mixer::~Mixer() { delete[] ports;}void Mixer::open(unsigned numChannels, unsigned samplingFrequency, unsigned granularityInMS) { HMIXER newHMixer = NULL; do { MIXERCAPS mc; if (mixerGetDevCaps(index, &mc, sizeof mc) != MMSYSERR_NOERROR) break; // Copy the mixer name: strncpy(name, mc.szPname, MAXPNAMELEN); // Find the correct line for this mixer: unsigned i, uWavIn; unsigned nWavIn = waveInGetNumDevs(); for (i = 0; i < nWavIn; ++i) { WAVEINCAPS wic; if (waveInGetDevCaps(i, &wic, sizeof wic) != MMSYSERR_NOERROR) continue; MIXERLINE ml; ml.cbStruct = sizeof ml; ml.Target.dwType = MIXERLINE_TARGETTYPE_WAVEIN; strncpy(ml.Target.szPname, wic.szPname, MAXPNAMELEN); ml.Target.vDriverVersion = wic.vDriverVersion; ml.Target.wMid = wic.wMid; ml.Target.wPid = wic.wPid; if (mixerGetLineInfo((HMIXEROBJ)index, &ml, MIXER_GETLINEINFOF_TARGETTYPE/*|MIXER_OBJECTF_MIXER*/) == MMSYSERR_NOERROR) { // this is the right line uWavIn = i; dwRecLineID = ml.dwLineID; break; } } if (i >= nWavIn) break; // error: we couldn't find the right line if (mixerOpen(&newHMixer, index, (unsigned long)NULL, (unsigned long)NULL, MIXER_OBJECTF_MIXER) != MMSYSERR_NOERROR) break; if (newHMixer == NULL) break; // Sanity check: re-call "mixerGetDevCaps()" using the mixer device handle: if (mixerGetDevCaps((UINT)newHMixer, &mc, sizeof mc) != MMSYSERR_NOERROR) break; if (mc.cDestinations < 1) break; // error: this mixer has no destinations if (!WindowsAudioInputDevice_common::openWavInPort(uWavIn, numChannels, samplingFrequency, granularityInMS)) break; hMixer = newHMixer; return; } while (0); // An error occurred: close(); } void Mixer::open() { open(1, 8000, 20);}void Mixer::getPortsInfo() { MIXERCAPS mc; mixerGetDevCaps((UINT)hMixer, &mc, sizeof mc); MIXERLINE mlt; unsigned i; for (i = 0; i < mc.cDestinations; ++i) { memset(&mlt, 0, sizeof mlt); mlt.cbStruct = sizeof mlt; mlt.dwDestination = i; if (mixerGetLineInfo((HMIXEROBJ)hMixer, &mlt, MIXER_GETLINEINFOF_DESTINATION) != MMSYSERR_NOERROR) continue; if (mlt.dwLineID == dwRecLineID) break; // this is the destination we're interested in } ports = new AudioInputPort[mlt.cConnections]; numPorts = mlt.cConnections; for (i = 0; i < numPorts; ++i) { MIXERLINE mlc; memcpy(&mlc, &mlt, sizeof mlc); mlc.dwSource = i; mixerGetLineInfo((HMIXEROBJ)hMixer, &mlc, MIXER_GETLINEINFOF_SOURCE/*|MIXER_OBJECTF_HMIXER*/); ports[i].tag = mlc.dwLineID; ports[i].dwComponentType = mlc.dwComponentType; strncpy(ports[i].name, mlc.szName, MIXER_LONG_NAME_CHARS); } // Make the microphone the first port in the list: for (i = 1; i < numPorts; ++i) {#ifdef OLD_MICROPHONE_TESTING_CODE if (_strnicmp("mic", ports[i].name, 3) == 0 || _strnicmp("mik", ports[i].name, 3) == 0) {#else if (ports[i].dwComponentType == MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE) {#endif AudioInputPort tmp = ports[0]; ports[0] = ports[i]; ports[i] = tmp; } }}Boolean Mixer::enableInputPort(unsigned portIndex, char const*& errReason, MMRESULT& errCode) { errReason = NULL; // unless there's an error AudioInputPort& port = ports[portIndex]; MIXERCONTROL mc; mc.cMultipleItems = 1; // in case it doesn't get set below MIXERLINECONTROLS mlc;#if 0 // the following doesn't seem to be needed, and can fail: mlc.cbStruct = sizeof mlc; mlc.pamxctrl = &mc; mlc.cbmxctrl = sizeof (MIXERCONTROL); mlc.dwLineID = port.tag; mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; if ((errCode = mixerGetLineControls((HMIXEROBJ)hMixer, &mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE/*|MIXER_OBJECTF_HMIXER*/)) != MMSYSERR_NOERROR) { errReason = "mixerGetLineControls()"; return False; }#endif MIXERLINE ml; memset(&ml, 0, sizeof (MIXERLINE)); ml.cbStruct = sizeof (MIXERLINE); ml.dwLineID = port.tag; if ((errCode = mixerGetLineInfo((HMIXEROBJ)hMixer, &ml, MIXER_GETLINEINFOF_LINEID)) != MMSYSERR_NOERROR) { errReason = "mixerGetLineInfo()1"; return False; } char portname[MIXER_LONG_NAME_CHARS+1]; strncpy(portname, ml.szName, MIXER_LONG_NAME_CHARS); memset(&ml, 0, sizeof (MIXERLINE)); ml.cbStruct = sizeof (MIXERLINE); ml.dwLineID = dwRecLineID; if ((errCode = mixerGetLineInfo((HMIXEROBJ)hMixer, &ml, MIXER_GETLINEINFOF_LINEID/*|MIXER_OBJECTF_HMIXER*/)) != MMSYSERR_NOERROR) { errReason = "mixerGetLineInfo()2"; return False; } // Get Mixer/MUX control information (need control id to set and get control details) mlc.cbStruct = sizeof mlc; mlc.dwLineID = ml.dwLineID; mlc.cControls = 1; mc.cbStruct = sizeof mc; // Needed???##### mc.dwControlID = 0xDEADBEEF; // For testing ##### mlc.pamxctrl = &mc; mlc.cbmxctrl = sizeof mc; mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_MUX; // Single Select if ((errCode = mixerGetLineControls((HMIXEROBJ)hMixer, &mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE/*|MIXER_OBJECTF_HMIXER*/)) != MMSYSERR_NOERROR) { mlc.dwControlType = MIXERCONTROL_CONTROLTYPE_MIXER; // Multiple Select mixerGetLineControls((HMIXEROBJ)hMixer, &mlc, MIXER_GETLINECONTROLSF_ONEBYTYPE/*|MIXER_OBJECTF_HMIXER*/); } unsigned matchLine = 0; if (mc.cMultipleItems > 1) { // Before getting control, we need to know which line to grab. // We figure this out by listing the lines, and comparing names: MIXERCONTROLDETAILS mcd; mcd.cbStruct = sizeof mcd; mcd.cChannels = ml.cChannels; mcd.cMultipleItems = mc.cMultipleItems; MIXERCONTROLDETAILS_LISTTEXT* mcdlText = new MIXERCONTROLDETAILS_LISTTEXT[mc.cMultipleItems]; mcd.cbDetails = sizeof (MIXERCONTROLDETAILS_LISTTEXT); mcd.paDetails = mcdlText; if (mc.dwControlID != 0xDEADBEEF) { // we know the control id for real mcd.dwControlID = mc.dwControlID; if ((errCode = mixerGetControlDetails((HMIXEROBJ)hMixer, &mcd, MIXER_GETCONTROLDETAILSF_LISTTEXT/*|MIXER_OBJECTF_HMIXER*/)) != MMSYSERR_NOERROR) { delete[] mcdlText; errReason = "mixerGetControlDetails()1"; return False; } } else { // Hack: We couldn't find a MUX or MIXER control, so try to guess the control id: for (mc.dwControlID = 0; mc.dwControlID < 32; ++mc.dwControlID) { mcd.dwControlID = mc.dwControlID; if ((errCode = mixerGetControlDetails((HMIXEROBJ)hMixer, &mcd, MIXER_GETCONTROLDETAILSF_LISTTEXT/*|MIXER_OBJECTF_HMIXER*/)) == MMSYSERR_NOERROR) break; } if (mc.dwControlID == 32) { // unable to guess mux/mixer control id delete[] mcdlText; errReason = "mixerGetControlDetails()2"; return False; } } for (unsigned i = 0; i < mcd.cMultipleItems; ++i) { if (strcmp(mcdlText[i].szName, portname) == 0) { matchLine = i; break; } } delete[] mcdlText; } // Now get control itself: MIXERCONTROLDETAILS mcd; mcd.cbStruct = sizeof mcd; mcd.dwControlID = mc.dwControlID; mcd.cChannels = ml.cChannels; mcd.cMultipleItems = mc.cMultipleItems; MIXERCONTROLDETAILS_BOOLEAN* mcdbState = new MIXERCONTROLDETAILS_BOOLEAN[mc.cMultipleItems]; mcd.paDetails = mcdbState; mcd.cbDetails = sizeof (MIXERCONTROLDETAILS_BOOLEAN); if ((errCode = mixerGetControlDetails((HMIXEROBJ)hMixer, &mcd, MIXER_GETCONTROLDETAILSF_VALUE/*|MIXER_OBJECTF_HMIXER*/)) != MMSYSERR_NOERROR) { delete[] mcdbState; errReason = "mixerGetControlDetails()3"; return False; } for (unsigned j = 0; j < mcd.cMultipleItems; ++j) { mcdbState[j].fValue = (j == matchLine); } if ((errCode = mixerSetControlDetails((HMIXEROBJ)hMixer, &mcd, MIXER_OBJECTF_HMIXER)) != MMSYSERR_NOERROR) { delete[] mcdbState; errReason = "mixerSetControlDetails()"; return False; } delete[] mcdbState; return True;}void Mixer::close() { WindowsAudioInputDevice_common::waveIn_close(); if (hMixer != NULL) mixerClose(hMixer); hMixer = NULL; dwRecLineID = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -