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

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

[复制链接]
发表于 2011-5-7 21:31:51 | 显示全部楼层 |阅读模式
原文:http://sunerok.blog.163.com/blog/static/231096422010112815525949/" ]3 @0 {2 C# b# p' @

$ W: n- ?1 j4 X0 m' V8 j! {9 |参考了网上很多资料,也碰到了许多问题,终于解决了,很开心,把代码贴在这里分享一下:
: d# \( b5 E# O* O# W* P) Q: s
) e  h& ?' c; X$ k3 ?* V" j, P+ A1 Y% F7 A; e- Z( U$ e; N' t: [/ t
int DeviceManager::getAudioInputVolumn( const std::string &deviceName )
7 F! d: B& o5 f0 s7 n! h- D{" u( B9 R8 w0 c; E9 Z. \
1 g: D3 j5 O4 P7 |: i4 n' ]

4 i$ u& E) U2 B: ^$ j$ w9 d        MMRESULT          rc;     // 多媒体函数返回结果变量
' h) o6 `; i* D1 o        HMIXER            hMixer; // 混合器设备句柄  F( ^; p2 T9 o1 r; e4 J
        MIXERLINE         mxl;    // 音频线路标准状态信息结构体: j  m) u5 x3 G8 c2 x6 b) B. E# U) ]
        MIXERLINECONTROLS mxlc;   // 音频线路控制器集合信息结构体7 g. F0 S2 }  M0 c* J6 q/ D
        MIXERCONTROL      mxc;    // 单个音频线路控制器信息结构体+ v4 J. `- E) `( k. h' F
6 N0 k* a* c  |, u% r- Z

( _& J- Y, r' e* Q        //枚举所有声卡驱动,这个枚举很重要。很多代码调用mixOpen时只是用了第一个设备,即
  }' [- s1 s- h. S( p        //mixerOpen(&hMixer, 0 , 0 ,0 ),但是我在这个设备下调用mixerGetLineInfo出问题了,
) j7 u# s# I7 }! L       //可能还是跟声卡驱动有关。
; Y' \2 B7 ]3 O9 K1 [$ G+ r! e+ s        for( int deviceID =0 ; true ; deviceID++ )
8 ]: X( x5 H( g        {# Q* W- w5 p( W( b4 `9 y
                // 打开混合器设备
0 A: o  f* r7 ?                rc = mixerOpen(&hMixer, // 返回的设备句柄9 |2 K+ S1 l* x; f. @- z
                        deviceID,       // 单声卡的设备ID为零
7 L  z' ~" u( x! P! ~1 p- t                        0,       // 不使用回调机制: J0 b8 w4 H1 U- w7 T
                        0,       // 回调函数参数- |& w4 s0 G$ X" |6 C3 I
                        MIXER_OBJECTF_MIXER);      // MIXER_OBJECTF_MIXER宏的值,表示任选有效设备ID
; i: e. q) Q- t9 h                if( MMSYSERR_NOERROR!=rc )
7 }) ?# J$ q& p6 a8 O                {
: w3 H0 |1 |7 m" p                        //跳出循环* x# v7 w$ U3 k$ g
                        break;9 `8 A7 Q  L/ }6 c
                }
' R3 F6 ]% o; W( i7 k0 M                // 打开混合器设备无错的话,则
% D7 E& @0 c% c* R! y( K/ [" Y$ \0 @6 X
' r3 }  C- W. P$ z' n6 T
                // MIXERLINE 结构体变量清零# s% D: j) [- Y2 Y
                ZeroMemory(&mxl, sizeof(MIXERLINE));% `2 G2 a8 t8 v; P
% g: E: j( U1 O4 W0 L
' F7 }+ Y  ?" v& I( c6 B. R
                mxl.cbStruct = sizeof(MIXERLINE); // 微软用此办法判断版本5 H8 w5 P$ A5 x, }( Y
                // 指出需要获取的通道,声卡的音频输出用MIXERLINE_COMPONENTTYPE_DST_SPEAKERS4 n7 z- U  Z& c% Y
                mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;( y5 F4 Q# e) U( x# _$ L7 c$ @

/ c" X) c- A+ {7 l% ~
/ i8 B( z& v# l8 O                // 取得混合器设备的指定线路信息
% t/ g5 Y- z3 [: o* p. G# c                rc = mixerGetLineInfo((HMIXEROBJ)hMixer,( \) Z: U8 j  g1 G, N& z
                        &mxl,
6 t2 p# q+ B  N( B8 c* v                        // 取得MIXERLINE::dwComponentType指定类型的第一个音频线路信息0 q% Q, v0 l# O$ m$ A2 ?* O
                        MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_COMPONENTTYPE);
3 v/ n- B; \8 S4 f+ T                if( rc!=MMSYSERR_NOERROR )
! L- |: @2 ^+ v% n& J  F                {
8 l% V- t: _+ J( r                        //无法获取声音输入线路,尝试其他声卡
" y9 P0 ?) D/ @1 t3 J                        continue;
6 [) F6 ~/ d0 U3 T4 {! i                }
- a6 M" `& I3 `. I% M
# e' e+ M" [; ]
% o2 Q' ?! o5 ^                // 取得混合器设备的指定线路信息成功的话,则6 r8 X# F% c: t
3 k0 N5 S2 d+ A+ i' q( z) _
+ h& i; d" [( Y8 E
                // 将连接数保存 ) ]) A" z: h6 O7 x  u
                DWORD   dwConnections   =   mxl.cConnections; 9 c$ g" R% _! [2 _; v$ v: V! t9 N3 v& ]
                // 准备获取麦克风设备的ID ' q* p% _. |& n# ^* N7 J
                DWORD   dwLineID = -1; $ e7 D- V; w# U- s  i3 q
                for( DWORD i=0 ; i<dwConnections; i++ )
3 L8 T  i0 T  {% k5 W) \3 O8 X                {
  i3 ^% ]) o  e8 o                        // 枚举每一个设备,当Source的ID等于当前的迭代记数
1 ^# ~8 ?) R' O" U8 T                        mxl.dwSource = i;
6 W8 V% C$ X* v                        // 根据SourceID获得连接的信息
/ C$ C# d, M5 }5 h) ?2 f$ X& R                        rc = mixerGetLineInfo(   (HMIXEROBJ)hMixer,   &mxl,
& m# z0 ]: J. s; s* z2 a) `                                MIXER_OBJECTF_HMIXER   |   MIXER_GETLINEINFOF_SOURCE   ); . G4 y+ B0 q4 B0 a% f
                        // 判断函数执行错误
- q2 |. q/ f( C" D                        if( MMSYSERR_NOERROR==rc )
- X5 t# J4 W) N) W& U# w                        {
$ R1 f  W, X0 L; h0 O1 [                                // 如果当前设备类型是麦克风,则跳出循环。
9 g0 Y* `5 I5 j& b& E9 `                                if( mxl.dwComponentType==MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE )
8 X: B* O2 a# m4 D9 I$ n                                {
! ]; b5 F; V: ]1 F                                        dwLineID = mxl.dwLineID; # R# e! I/ D& r, I9 @7 T5 M
                                        break; / A9 c- a2 a9 x" d* [2 |" Q
                                }/ H* T$ a& R9 s8 `6 @
                        }
9 t1 c' s& D3 h2 [# c                }( R2 T* ~1 `! O: o
                // 如果没有找到,返回失败。
; @3 A! J+ Q. }( S3 w                if( dwLineID==-1 )* u7 f4 h- {, I# E2 t
                { ' A, [7 J# `5 _8 L
                        //尝试其他声卡
, F: i7 y$ l; M                        continue;0 g9 ~1 m5 r6 o: ]4 Q/ C! {2 l9 o
                }
4 |$ J6 S' i2 N" h4 Q8 j6 r
% F3 |2 W7 C+ b: H9 S9 F' z) W0 T) i
                // MIXERCONTROL 结构体变量清零
4 d% f: I: ~: r8 i                ZeroMemory(&mxc, sizeof(MIXERCONTROL));
" s" |+ b' Y, ]3 V  b7 F3 f$ k. y3 R( K" I% d. n
2 Q/ }6 v% j7 {) i- i: l, \/ ^4 F4 `
                mxc.cbStruct = sizeof(mxc); // 微软用此办法判断版本
7 T6 n, S# y  N' }
7 b, N- ]% t9 w- O  ]
8 L, _$ V+ C$ s) ~                // MIXERLINECONTROLS 结构体变量清零/ x7 {6 ?4 d( ?& d: J  x  c
                ZeroMemory(&mxlc, sizeof(MIXERLINECONTROLS));
3 Q. d+ h8 z5 C* F$ k3 I) r% U$ D4 I: k4 k: ^

) B- N+ p0 d/ x( t6 m  ]) q4 S. `2 s                mxlc.cbStruct = sizeof(mxlc); // 微软用此办法判断版本0 U( O; @/ Q  W7 G% P

% [  H0 c* @+ U8 |7 [0 j/ m3 w- r! o/ n$ G
                mxlc.dwLineID = dwLineID; // 上面取得的声卡音频输入线路标识
% U/ \; s6 ^% Q0 q                // 控制类型为控制音量; P& s1 g: |4 _0 S
                mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
: {6 r3 a6 \" ^                mxlc.cControls = 1;          // 使用 MIXERCONTROL 结构体变量个数3 r* K1 q5 h4 e: f; ]: s4 t+ P* o! \
                mxlc.pamxctrl = &mxc;        // MIXERCONTROL 结构体变量指针/ s1 R8 I$ L4 V7 h! W
                mxlc.cbmxctrl = sizeof(mxc); // MIXERCONTROL 结构体变量字节大小; @3 F6 {5 M! ]' X

% l4 X: N- y: I/ {4 Z' S0 C) A
( h; v4 B% i% \: ]* E1 o+ n! g                // 取得控制器信息
7 ?9 p1 F% r9 k                rc = mixerGetLineControls((HMIXEROBJ)hMixer,$ Z2 i" l7 G: X9 S" l$ `
                        &mxlc,
+ ]: G5 r8 W6 p# m                        MIXER_GETLINECONTROLSF_ONEBYTYPE);
3 Q! C& N8 }" K1 f* ~# m5 ?; ]; ?
' T  d- S" z+ G$ }8 k( {2 @3 c  B# U; v% U8 f% k( h/ d
                // 取得控制器信息成功的话,则- r% C; I8 T3 ]: E5 _: b! m# i# g
                if (MMSYSERR_NOERROR == rc)
, E0 q- L, e1 O* y                {
: h$ P2 a( o1 W1 T: b! h: K                        // 获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
  A- Y( [- [, e- |                        MIXERCONTROLDETAILS        mxcd;      // 控制器的状态信息
: O5 j/ T% x/ s7 g! n- t                        MIXERCONTROLDETAILS_SIGNED volStruct; // 音量结构体变量(就一个成员量)
9 u5 C* D# M6 v# i1 j2 h; n  ?% g# b  C' _% K3 u

1 g+ x, [: a* F- Y7 m2 `0 i# C                        // MIXERCONTROLDETAILS 结构体变量清零
2 Z4 V4 _7 I+ J6 D. F                        ZeroMemory(&mxcd, sizeof(mxcd));; \  }% r' e/ `5 C8 X
0 Q6 u2 b& i( s$ s+ [7 h

2 I, z0 ^2 l  w9 f                        mxcd.cbStruct = sizeof(mxcd);       // 微软用此办法判断版本
+ U) [% O. o* X' {                        mxcd.dwControlID = mxc.dwControlID; // 上面取得的控制器标识
4 W9 ]& t  i  z                        mxcd.paDetails = &volStruct;        // 音量结构体变量指针& Y' v/ r! E! o4 B& r
                        mxcd.cbDetails = sizeof(volStruct); // 音量结构体变量字节大小: e4 v, [" t5 Y0 ]+ W
                        mxcd.cChannels = 1;                 // 取得或设置全部通道& E4 q" Z6 D& f( ~6 w9 c; t
* V0 }, [: b. \" _

: [# `# I* G5 A  r1 {                        //  获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
: E. b3 @% Q% F7 P5 r+ {+ _# m" x8 ~4 V/ W
6 ~; E. `2 k2 e- l/ A
                        // 获得音量值
; S% Y% a. T! _/ Y9 }                        rc = mixerGetControlDetails((HMIXEROBJ)hMixer,, ?0 y; V( E; u9 ~! q# N) v
                                &mxcd,' K' g  x! b4 t- Z7 f
                                MIXER_GETCONTROLDETAILSF_VALUE);
7 h6 `; c6 T! G0 |, s0 d- C, O2 ?/ ?) a+ |  B2 D% I
: T# Y9 E3 u9 i4 {/ s4 g
                        if (MMSYSERR_NOERROR == rc)
+ z) A4 V9 v  b$ Y$ e/ B6 B9 ~3 s- C                        {
9 v9 M/ ~: Y- J' D/ q                                long step = ( mxc.Bounds.lMaximum - mxc.Bounds.lMinimum ) /100;
2 N, G$ I! v1 E& j( w# t  ^  C# d) d. |7 C% ]# ?4 s
; x* F( K+ p; V! S! @
                                int index = ( volStruct.lValue - mxc.Bounds.lMinimum) /step ;
5 {5 I' s1 `7 l2 S                                printf("音量:%X", volStruct.lValue);( {! M' O; z, G- A- O8 g  f
                                return index;! V' Q! j' J* `3 ^. F1 ^* g2 f
                        }# ^1 S0 J3 X8 K/ n
                }
. T' P; r* X* ^7 S9 l        }& ]8 G4 i6 e; Z- W

% A2 g) T: f8 Y; u( [  |; M. j4 K
. t3 @1 u+ p( E. C9 x8 w" T        return -1;* Q& h( u! Z0 ^1 b: t
}
2 t# }# i5 P- N" r3 ~, O5 p3 O1 }" ], A( d  ^& g0 B3 L1 b
        相关网址:http://topic.csdn.net/t/20050606/10/4062001.html9 |3 [5 r: D* J+ g7 {+ R
                        http://blog.csdn.net/tangaowen/archive/2010/07/28/5771149.aspx
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-9-30 08:50 , Processed in 0.054655 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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