📄 ac97mixer.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// -----------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// -----------------------------------------------------------------------------
#include "wavecommon.h"
#include "ac97regs.h"
#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
#define LOGICAL_VOLUME_MAX 0x10000
#define LOGICAL_VOLUME_MIN 0
// #define ZONE_MXDM 0
#ifdef DEBUG
// DEBUG-only support for displaying control type codes in readable form
typedef struct
{
DWORD val;
PWSTR str;
} MMSYSCODE;
#define MXCTYPE(typ) {typ, TEXT(#typ)}
MMSYSCODE ctype_table[] =
{
MXCTYPE(MIXERCONTROL_CONTROLTYPE_CUSTOM),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_BASS),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_EQUALIZER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_FADER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_TREBLE),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_VOLUME),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MIXER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MUX),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_SINGLESELECT),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_BOOLEANMETER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_PEAKMETER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_SIGNEDMETER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_DECIBELS),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_PERCENT),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_SIGNED),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_UNSIGNED),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_PAN),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_QSOUNDPAN),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_SLIDER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_BOOLEAN),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_BUTTON),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_LOUDNESS),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MONO),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MUTE),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_ONOFF),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_STEREOENH),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MICROTIME),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MILLITIME),
};
PWSTR
COMPTYPE(DWORD dwValue)
{ int i;
for (i = 0; i < NELEMS(ctype_table); i++) {
if (ctype_table[i].val == dwValue) {
return ctype_table[i].str;
}
}
return TEXT("<unknown>");
}
#else
#define COMPTYPE(n) TEXT("<>")
#endif
// destinations
enum {
LINE_OUT = 0x80,
PCM_IN,
CD,
LINE_IN,
MIC,
AUX,
PCM_OUT,
STEREO_MIX,
// unsupported lines - defined in AC97 spec, but not supported in this driver
VIDEO,
MONO_MIX,
PHONE,
NOLINE = 0xff // doesn't HAVE to be FF, but makes it easier to see
};
// mixer line ID are 16-bit values formed by concatenating the source and destination line indices
//
#define MXLINEID(dst,src) ((USHORT) ((USHORT)(dst) | (((USHORT) (src)) << 8)))
#define GET_MXLINE_SRC(lineid) ((lineid) >> 8)
#define GET_MXLINE_DST(lineid) ((lineid) & 0xff)
#define GET_MXCONTROL_ID(ctl) ((ctl)-g_controls)
const USHORT
g_dst_lines[] =
{
MXLINEID(LINE_OUT,NOLINE),
MXLINEID(PCM_IN,NOLINE)
};
const USHORT
g_LINE_OUT_sources[] =
{
MXLINEID(LINE_OUT,CD),
MXLINEID(LINE_OUT,LINE_IN),
MXLINEID(LINE_OUT,MIC),
MXLINEID(LINE_OUT,AUX),
MXLINEID(LINE_OUT,PCM_OUT)
};
const USHORT
g_PCM_IN_sources[] =
{
MXLINEID(PCM_IN,CD),
MXLINEID(PCM_IN,LINE_IN),
MXLINEID(PCM_IN,MIC),
MXLINEID(PCM_IN,AUX),
MXLINEID(PCM_IN,STEREO_MIX)
};
// MXLINEDESC corresponds to MIXERLINE, but is designed to conserve space
typedef struct tagMXLINEDESC const * PMXLINEDESC, MXLINEDESC;
typedef struct tagMXCONTROLDESC const * PMXCONTROLDESC, MXCONTROLDESC;
struct tagMXLINEDESC {
DWORD dwComponentType;
PCWSTR szShortName;
PCWSTR szName;
DWORD ucFlags;
USHORT const * pSources;
USHORT usLineID;
UINT8 ucChannels;
UINT8 ucConnections;
UINT8 ucControls;
DWORD dwTargetType;
UINT8 ucDstIndex;
UINT8 ucSrcIndex;
} ;
// Destinations:
// LINE_OUT - line out jack
// PCM_IN - input to ADC
// Sources:
// CD - CD_IN connector
// AUX - AUX_IN connector
// MIC - MIC jack
// LINE_IN - LINE_IN jack
// VIDEO - VIDEO_IN connctor
// PCM_OUT - output of DAC0+DAC1
// MIX_OUT - mix of (MIC, LINE_IN, PCM_OUT, VIDEO, CD, AUX)
// MXCONTROLDESC is driver shorthand for Volume and Mute MIXERCONTROL
struct tagMXCONTROLDESC
{
PWSTR szName;
DWORD dwType;
USHORT usLineID; // line that owns this control
USHORT usMask; // mask for valid range for this codec register
UCHAR ucCodecRegister; // address of AC97 register for this control
};
#define MXCE(dst,src,nme,type,mask,reg) {TEXT(nme),type,MXLINEID(dst,src),mask,reg}
#define MUTE_BIT 0x8000
const MXCONTROLDESC
g_controls[] = {
MXCE(LINE_OUT,NOLINE, "Master Volume", MIXERCONTROL_CONTROLTYPE_VOLUME, 0x000f, AC97_MASTER_VOLUME),
MXCE(LINE_OUT,NOLINE, "Master Mute", MIXERCONTROL_CONTROLTYPE_MUTE, 0x8000, AC97_MASTER_VOLUME),
MXCE(PCM_IN,NOLINE, "Record Select", MIXERCONTROL_CONTROLTYPE_MUX, 5, AC97_RECORD_SELECT),
// LINE_OUT source controls
MXCE(LINE_OUT,CD, "CD Volume", MIXERCONTROL_CONTROLTYPE_VOLUME, 0x001f, AC97_CD_VOLUME),
MXCE(LINE_OUT,CD, "CD Mute", MIXERCONTROL_CONTROLTYPE_MUTE, 0x8000, AC97_CD_VOLUME),
MXCE(LINE_OUT,LINE_IN, "Line In Volume", MIXERCONTROL_CONTROLTYPE_VOLUME, 0x001f, AC97_LINEIN_VOLUME),
MXCE(LINE_OUT,LINE_IN, "Line In Mute", MIXERCONTROL_CONTROLTYPE_MUTE, 0x8000, AC97_LINEIN_VOLUME),
MXCE(LINE_OUT,MIC, "Mic Volume", MIXERCONTROL_CONTROLTYPE_VOLUME, 0x001f, AC97_MIC_VOLUME),
MXCE(LINE_OUT,MIC, "Mic Mute", MIXERCONTROL_CONTROLTYPE_MUTE, 0x8000, AC97_MIC_VOLUME),
MXCE(LINE_OUT,MIC, "Mic Boost", MIXERCONTROL_CONTROLTYPE_ONOFF, 0x0004, AC97_MIC_VOLUME),
MXCE(LINE_OUT,AUX, "Aux Volume", MIXERCONTROL_CONTROLTYPE_VOLUME, 0x001f, AC97_AUX_VOLUME),
MXCE(LINE_OUT,AUX, "Aux Mute", MIXERCONTROL_CONTROLTYPE_MUTE, 0x8000, AC97_AUX_VOLUME),
MXCE(LINE_OUT,PCM_OUT, "Digital Volume", MIXERCONTROL_CONTROLTYPE_VOLUME, 0x001f, AC97_PCMOUT_VOLUME),
MXCE(LINE_OUT,PCM_OUT, "Digital Mute", MIXERCONTROL_CONTROLTYPE_MUTE, 0x8000, AC97_PCMOUT_VOLUME),
// PCM_IN source controls
// AC97 spec indicates that none of the inputs to the input MUX have Volume/Mute capabilities,
// but that the driver should create a "virtual" volume/mute control for each mux input
// When the application changes the MUX input line, the driver is responsible for
// adjusting the Record Gain register accordingly.
MXCE(PCM_IN,CD, "CD Volume", MIXERCONTROL_CONTROLTYPE_VOLUME, 0x000f, AC97_RECORD_GAIN),
MXCE(PCM_IN,LINE_IN, "Line In Volume", MIXERCONTROL_CONTROLTYPE_VOLUME, 0x000f, AC97_RECORD_GAIN),
MXCE(PCM_IN,STEREO_MIX, "Stereo Mix Volume",MIXERCONTROL_CONTROLTYPE_VOLUME, 0x000f, AC97_RECORD_GAIN),
MXCE(PCM_IN,MIC, "Mic Volume", MIXERCONTROL_CONTROLTYPE_VOLUME, 0x000f, AC97_RECORD_GAIN),
MXCE(PCM_IN,MIC, "Mic Boost", MIXERCONTROL_CONTROLTYPE_ONOFF, 0x0040, AC97_MIC_VOLUME),
MXCE(PCM_IN,AUX, "Aux Volume", MIXERCONTROL_CONTROLTYPE_VOLUME, 0x000f, AC97_RECORD_GAIN),
};
const int ncontrols = NELEMS(g_controls);
// MuxIndexToLine
// this table translates indices from the AC97_RECORD_SELECT (0x1A) register to line IDs
// note that not all entries in the table correspond to lines that are implemented
const USHORT MuxIndexToLine[] =
{
MXLINEID(PCM_IN,MIC),
MXLINEID(PCM_IN,CD),
MXLINEID(PCM_IN,VIDEO),
MXLINEID(PCM_IN,AUX),
MXLINEID(PCM_IN,LINE_IN),
MXLINEID(PCM_IN,STEREO_MIX),
MXLINEID(PCM_IN,MONO_MIX),
MXLINEID(PCM_IN,PHONE),
};
// mixerline ID
#define _MXLE(id,dst,src,flags,comptype,nch,ncnx,nctrl,sname,lname,target,sarray)\
{comptype,\
TEXT(sname),TEXT(lname),\
flags, \
sarray,\
id,\
nch,ncnx,nctrl,\
target,\
dst,src}
// declare a destination line
#define MXLED(id,dst,flags,comptype,nch,nctrl,sname,lname,target)\
_MXLE(MXLINEID(id,NOLINE),dst,NOLINE,flags,comptype,nch,NELEMS(g_##id##_sources),nctrl,sname,lname,target,g_##id##_sources)\
// declar a source line
#define MXSLE(id,dst,src,flags,comptype,nch,nctrl,sname,lname,target)\
_MXLE(id,dst,src,flags,comptype,nch,0,nctrl,sname,lname,target,NULL)\
const MXLINEDESC
g_mixerline[] =
{
// dst line 0 - speaker out
MXLED(LINE_OUT, 0,
MIXERLINE_LINEF_ACTIVE, // no flags
MIXERLINE_COMPONENTTYPE_DST_SPEAKERS,
2, // stereo
2, // controls
"Volume Control","Volume Control",
MIXERLINE_TARGETTYPE_WAVEOUT
),
// dst line 1 - PCM input
MXLED(PCM_IN, 1,
MIXERLINE_LINEF_ACTIVE, // flags
MIXERLINE_COMPONENTTYPE_DST_WAVEIN,
2, // stereo
1, // 1 control (MUX) - the AC97 record gain register is virtualized across all mux inputs
"Recording Contr","Recording Control",
MIXERLINE_TARGETTYPE_WAVEIN
),
// ----------------------
// LINE_OUT Sources Lines
// ----------------------
// src line 0 - CD
MXSLE(MXLINEID(LINE_OUT,CD), 0, 0,
MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE, // flags
MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC,
2,2,
"CD Audio","CD Audio",
MIXERLINE_TARGETTYPE_UNDEFINED
),
// src line 1 - LINE IN
MXSLE(MXLINEID(LINE_OUT,LINE_IN), 0, 1,
MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE, // flags
MIXERLINE_COMPONENTTYPE_SRC_LINE,
2,2,
"Line In","Line In",
MIXERLINE_TARGETTYPE_UNDEFINED
),
// src line 2 - Microphone
MXSLE(MXLINEID(LINE_OUT,MIC), 0, 2,
MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE, // flags
MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE,
1,3,
"Mic","Microphone",
MIXERLINE_TARGETTYPE_WAVEIN
),
// src line 3 - Aux
MXSLE(MXLINEID(LINE_OUT,AUX), 0, 3,
MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE, // flags
MIXERLINE_COMPONENTTYPE_SRC_ANALOG,
2,2,
"Aux","Aux Volume",
MIXERLINE_TARGETTYPE_UNDEFINED
),
// src line 4 - Aux
MXSLE(MXLINEID(LINE_OUT,PCM_OUT), 0, 4,
MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE, // flags
MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT,
2,2,
"Digital","Digital Volume",
MIXERLINE_TARGETTYPE_UNDEFINED
),
// ----------------------
// PCM_IN Sources Lines
// ----------------------
// src line 0 - CD
MXSLE(MXLINEID(PCM_IN, CD), 1, 0,
MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE, // flags
MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC,
2,1,
"CD Audio","CD Audio",
MIXERLINE_TARGETTYPE_UNDEFINED
),
// src line 1 - LINE IN
MXSLE(MXLINEID(PCM_IN, LINE_IN), 1, 1,
MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE, // flags
MIXERLINE_COMPONENTTYPE_SRC_LINE,
2,1,
"Line In","Line In",
MIXERLINE_TARGETTYPE_UNDEFINED
),
// src line 2 - Microphone
MXSLE(MXLINEID(PCM_IN, MIC), 1, 2,
MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE, // flags
MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE,
2,2,
"Microphone","Microphone",
MIXERLINE_TARGETTYPE_WAVEIN
),
// src line 3 - Aux
MXSLE(MXLINEID(PCM_IN, AUX), 1, 3,
MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE, // flags
MIXERLINE_COMPONENTTYPE_SRC_ANALOG,
2,1,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -