找回密码
 注册
搜索
查看: 4652|回复: 0

利用MIXER获取麦克风录音音量

[复制链接]
发表于 2011-5-7 21:31:51 | 显示全部楼层 |阅读模式
原文:http://sunerok.blog.163.com/blog/static/231096422010112815525949/
1 M5 e0 {9 s. W% L
3 _& `" F. _/ G% C/ g! M参考了网上很多资料,也碰到了许多问题,终于解决了,很开心,把代码贴在这里分享一下:
- B+ U4 Y% Q9 J0 D6 I8 d; F% V  l  I1 L. ?2 p

( b* X$ y  E+ @$ qint DeviceManager::getAudioInputVolumn( const std::string &deviceName )
+ z5 D) D+ `! l$ {0 o, Z7 ?{
, i+ f/ k' @  J' z- q! X/ f* T4 w# N4 X4 ]$ x* @& {
. ^; x6 p8 X3 e" r# u: }
        MMRESULT          rc;     // 多媒体函数返回结果变量
, t: m: ~1 \0 T5 S        HMIXER            hMixer; // 混合器设备句柄: _4 b8 H' b4 d  S4 T
        MIXERLINE         mxl;    // 音频线路标准状态信息结构体
' I3 g9 `) [6 @6 z        MIXERLINECONTROLS mxlc;   // 音频线路控制器集合信息结构体. z3 ~/ s  u6 M. Y7 m8 S0 l
        MIXERCONTROL      mxc;    // 单个音频线路控制器信息结构体
) P- w5 F/ ?2 j  |4 M. m0 x( q* K. N$ D- k8 U  e9 }

; }% M8 `. X! X8 \' S( U7 u        //枚举所有声卡驱动,这个枚举很重要。很多代码调用mixOpen时只是用了第一个设备,即
4 F( s9 P; N3 J* F. N        //mixerOpen(&hMixer, 0 , 0 ,0 ),但是我在这个设备下调用mixerGetLineInfo出问题了,
! S. W% J2 Y. Y! f6 l2 Q       //可能还是跟声卡驱动有关。# @. o# D: W- t3 y% _# V$ a
        for( int deviceID =0 ; true ; deviceID++ )3 \/ \, b3 `/ u8 R. a
        {
4 K' Q5 P% n7 ^/ X                // 打开混合器设备
( E6 Z4 L* V4 m; h1 R# G* i                rc = mixerOpen(&hMixer, // 返回的设备句柄6 w9 b( G1 d2 b9 w! R7 O* F( R
                        deviceID,       // 单声卡的设备ID为零
5 r6 s  h' d! y& }                        0,       // 不使用回调机制
9 y6 M2 k8 `& {                        0,       // 回调函数参数# G$ L& v7 B  y4 n' }
                        MIXER_OBJECTF_MIXER);      // MIXER_OBJECTF_MIXER宏的值,表示任选有效设备ID0 a" I# D* r9 |" b) ?
                if( MMSYSERR_NOERROR!=rc )7 x$ |  i4 j0 U1 J  Y: W
                {
8 f& g( w* E5 P                        //跳出循环
0 }( h9 _) I% e7 g4 f                        break;
8 e" n  ^9 E/ d4 Y0 G, y* X                }
  y. P; y( i- o8 G* f                // 打开混合器设备无错的话,则
/ g6 m; K- A6 ~) l9 p9 F8 N% ~4 t7 n3 e2 B
5 f0 g2 n; n$ ~9 M- b1 ^
                // MIXERLINE 结构体变量清零
- o( P0 N7 j0 u6 r; T2 B% m& Y* Y                ZeroMemory(&mxl, sizeof(MIXERLINE));
' X- e5 Y/ Z  A5 {' Q
4 C+ a) ?) i5 C! Y7 ?* h$ }  h% |8 P
                mxl.cbStruct = sizeof(MIXERLINE); // 微软用此办法判断版本' a  P& k9 @' u+ C
                // 指出需要获取的通道,声卡的音频输出用MIXERLINE_COMPONENTTYPE_DST_SPEAKERS7 y$ |: p6 \( @& P
                mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;( A2 X; H" W8 V5 V8 s$ l8 h
. R+ k3 P0 z' F6 T
1 M) W1 d0 R. f2 Q, r8 w9 C
                // 取得混合器设备的指定线路信息
% p6 q8 C/ T! W) L8 _7 o0 Z                rc = mixerGetLineInfo((HMIXEROBJ)hMixer,, X6 B8 H; b+ _) ~
                        &mxl,; D' Z) {/ F5 O9 o1 P4 ?! H
                        // 取得MIXERLINE::dwComponentType指定类型的第一个音频线路信息8 M* s+ l& U" v+ H$ {' {0 K6 H; _
                        MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_COMPONENTTYPE);
% d* p, X! y$ P7 k1 C4 k; C$ p                if( rc!=MMSYSERR_NOERROR )
# Q" u' [9 c  n8 N6 n9 Z# C                {  @, R+ Z5 l( p5 o
                        //无法获取声音输入线路,尝试其他声卡1 @: l5 I6 G4 J' z) x- h
                        continue;
/ T( J8 G7 R8 @7 q$ @                }6 a. K5 {0 n- a& t5 g
  O3 N$ H) H) F! b+ m; X! f# w9 j% s
/ ?* A* s7 @% r: }% `* h$ H
                // 取得混合器设备的指定线路信息成功的话,则
# `1 ], c8 t/ L# w0 d' @* o! I: P6 o- S

2 l6 ^- d4 I8 ~+ Y                // 将连接数保存 ( o; j' e; _- e) f
                DWORD   dwConnections   =   mxl.cConnections;
8 g9 q1 N2 B  y3 @3 u$ Q                // 准备获取麦克风设备的ID   K  M- E4 X6 `8 U' x2 D/ W/ H
                DWORD   dwLineID = -1;
7 ]# W- n& \( E* T6 ~+ E                for( DWORD i=0 ; i<dwConnections; i++ )- H! f: g. l1 ~7 F! w
                {
! h" i* t7 Q0 @+ e                        // 枚举每一个设备,当Source的ID等于当前的迭代记数 5 x' _: i! p6 R: }. g$ ~
                        mxl.dwSource = i;
, r. D. [% B9 S7 I7 D                        // 根据SourceID获得连接的信息 8 o5 W4 ]5 Y2 w' U
                        rc = mixerGetLineInfo(   (HMIXEROBJ)hMixer,   &mxl, " P- Z$ ?$ Q: w" l- a
                                MIXER_OBJECTF_HMIXER   |   MIXER_GETLINEINFOF_SOURCE   );
" Y) l/ k% b! M! c. X                        // 判断函数执行错误
7 _2 ~0 Q1 i- Q. p9 O# k$ W                        if( MMSYSERR_NOERROR==rc )& n6 N& w9 L8 L$ C
                        { 7 C1 V% v- c7 e% t) W/ D$ {
                                // 如果当前设备类型是麦克风,则跳出循环。 4 f  |$ I9 d# k; i% ^% u/ C8 F
                                if( mxl.dwComponentType==MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE )  G" V( A" ^- O4 X4 c0 T
                                {
6 P. L$ N5 M& T2 l7 x6 j# r' x* M                                        dwLineID = mxl.dwLineID; ) m: F% I0 _' Y) M, G" y0 F; U& k1 V
                                        break;
. e3 p& D$ B$ k                                }  y& Z. o. |" u. U, x
                        }
: r4 V$ Z" G6 V4 M3 W& @7 `                }+ `  {2 W* e0 z' m, x
                // 如果没有找到,返回失败。
0 v7 @, r  M% x5 U+ }& i                if( dwLineID==-1 )& j& O  }( l) j+ F
                { ! T% u+ v+ m5 x4 U
                        //尝试其他声卡4 ?8 h  \6 E4 e7 ?* X
                        continue;
+ w% n7 V& q* ~; y% c7 U! o* k                }
; B  Z& j. P/ K+ b/ ~  G
" L/ V1 D/ B% k1 @5 b
6 v6 U, ~5 q8 f/ c: Z, f5 Q                // MIXERCONTROL 结构体变量清零% G2 E0 L/ u0 F  W5 c( ~
                ZeroMemory(&mxc, sizeof(MIXERCONTROL));
0 N% V7 t* b7 x3 u8 E" {2 i3 _. p5 J+ b2 V; g( K; I
% m) p( c3 W1 ~' |* `
                mxc.cbStruct = sizeof(mxc); // 微软用此办法判断版本
8 @9 ]; X% y" J2 i  B9 ]$ T  A) ]! \
8 P  s* [" v4 ?; s3 ~2 u9 m
                // MIXERLINECONTROLS 结构体变量清零
) ~$ Y8 `, m0 ?4 U6 V                ZeroMemory(&mxlc, sizeof(MIXERLINECONTROLS));
1 }. u7 y2 b! A( o" A
1 B! b) v- M0 u
7 q& \0 B$ @2 b: {* b& c                mxlc.cbStruct = sizeof(mxlc); // 微软用此办法判断版本
1 K5 ]% @! j( ]( r+ n' o+ W
2 ^4 g: w9 P' E0 e& \' M6 F1 J$ X" z" s; X
                mxlc.dwLineID = dwLineID; // 上面取得的声卡音频输入线路标识1 Z# C; B! h4 g3 a+ k" B# |. Y
                // 控制类型为控制音量
/ w% D+ ?' P) }+ H1 w' c                mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;5 x4 R$ @; f7 _4 i
                mxlc.cControls = 1;          // 使用 MIXERCONTROL 结构体变量个数% d# L3 H; {  S! z& @
                mxlc.pamxctrl = &mxc;        // MIXERCONTROL 结构体变量指针
9 o+ @* N. p0 p& O! w                mxlc.cbmxctrl = sizeof(mxc); // MIXERCONTROL 结构体变量字节大小
6 ]' W1 G0 Y4 Y% `7 G
7 W5 x$ o7 W8 U( X: r: Q" ?% v9 |1 D6 N
                // 取得控制器信息, O8 W4 X9 Q) m5 D& W
                rc = mixerGetLineControls((HMIXEROBJ)hMixer,
: g# K3 A3 c2 p- t& @6 X                        &mxlc,; _0 H, O5 I% r! u; y
                        MIXER_GETLINECONTROLSF_ONEBYTYPE);
  B2 D  s; a5 w1 q8 s  z0 r2 V, e
% V% x8 ~; P4 u* A
% d/ E$ X: x5 p) z: g! B, d; _1 V, z                // 取得控制器信息成功的话,则- F* T  v% T2 n: s4 i
                if (MMSYSERR_NOERROR == rc)! t1 I/ ]* }( h
                {
& W" j1 F. `/ `                        // 获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.; a* Y* e& B/ W4 T2 a0 M1 V* |/ G
                        MIXERCONTROLDETAILS        mxcd;      // 控制器的状态信息% w  Z, l: b& E
                        MIXERCONTROLDETAILS_SIGNED volStruct; // 音量结构体变量(就一个成员量): Q( O! f& J, ^

- G4 H" G  O( M4 L' ?' P
7 y. U2 E* \, \" k, f% M1 q                        // MIXERCONTROLDETAILS 结构体变量清零
3 Z* }3 ^' e3 m5 T0 {  S+ Z8 g                        ZeroMemory(&mxcd, sizeof(mxcd));
5 U- c5 m4 A, F1 k0 X+ O1 ~+ \: a; p: A+ b

* O$ |& s5 s8 ]" w/ b+ n                        mxcd.cbStruct = sizeof(mxcd);       // 微软用此办法判断版本, W: n( X$ @0 U  d
                        mxcd.dwControlID = mxc.dwControlID; // 上面取得的控制器标识/ o( k* |) B5 x8 u0 N* C; V
                        mxcd.paDetails = &volStruct;        // 音量结构体变量指针, |/ M2 l0 f6 u& E; H7 S
                        mxcd.cbDetails = sizeof(volStruct); // 音量结构体变量字节大小
$ Z2 V* U: k' J/ u, `                        mxcd.cChannels = 1;                 // 取得或设置全部通道
4 _+ W: R6 u+ I6 F$ a2 J5 |. u# O, e4 r4 m2 Q+ u
  p; P# [* \& f
                        //  获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum. 7 o8 {& G. e8 A0 H7 U! a  ]6 l3 T) }6 R

: ~2 _- C; |2 j7 b9 }0 n0 B2 v# H& f7 ]& @# I" `
                        // 获得音量值
4 V4 Q9 m! Q6 n- L& p+ @+ {. X                        rc = mixerGetControlDetails((HMIXEROBJ)hMixer,! R) ]  o% e9 d# K( `9 G
                                &mxcd,
* c+ d) H$ g6 X                                MIXER_GETCONTROLDETAILSF_VALUE);% F4 l7 D) J6 G/ q  K: [

' \# K5 B# [, a. C2 A2 R
5 \1 r' c% t% T9 g6 l9 I                        if (MMSYSERR_NOERROR == rc)
5 V4 I9 T2 M# c" a5 w: @                        {8 W( G9 t2 T# K" e. s
                                long step = ( mxc.Bounds.lMaximum - mxc.Bounds.lMinimum ) /100;* z" ]% B/ b  c! z/ P
. C0 ~& ^8 k/ X, r4 i/ V

, ?$ x/ t% x; K1 t( O% }                                int index = ( volStruct.lValue - mxc.Bounds.lMinimum) /step ;* Q1 Q. x2 T3 x4 k& w
                                printf("音量:%X", volStruct.lValue);
8 C9 V& w$ j6 x                                return index;5 n, m  h1 ^. V' l0 g
                        }
* m8 p* F; p# L" a" J# G( h" B                }* D& {' l7 @1 c. J2 w
        }
6 C; X" n1 U6 w, V  }* \* P- f9 B' r: K1 q
2 m3 x/ v% ?- D1 t! R- E4 Y- z: d1 f, L! p
        return -1;5 X  \, c1 `3 |  u
}! ?7 J# |, @0 C! l9 {3 ~. s

' H9 \  D! A4 m4 ?8 Q        相关网址:http://topic.csdn.net/t/20050606/10/4062001.html  L" Q0 K9 S! o, s1 c" u3 u
                        http://blog.csdn.net/tangaowen/archive/2010/07/28/5771149.aspx
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2025-12-29 17:41 , Processed in 0.022937 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表