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

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

[复制链接]
发表于 2011-5-7 21:31:51 | 显示全部楼层 |阅读模式
原文:http://sunerok.blog.163.com/blog/static/231096422010112815525949/$ Q+ |0 L. c3 g/ V7 B. x! Y

" `( B/ t6 M; n, ^* b参考了网上很多资料,也碰到了许多问题,终于解决了,很开心,把代码贴在这里分享一下:- X! A4 J6 z' O/ D, R: G3 t

- h/ t- m5 h3 j1 k# U6 K2 r5 |9 v- N5 m6 d( K4 E# F
int DeviceManager::getAudioInputVolumn( const std::string &deviceName )
( H" m( K# k' W' X/ ~" j{
6 N2 G6 @" K2 H. ~) l- j0 `0 q# v* m9 Q7 |8 X1 D9 o5 u

% T7 u+ s5 i' u$ r/ ~7 @        MMRESULT          rc;     // 多媒体函数返回结果变量! I7 t# g: P/ B, G. y5 t6 r
        HMIXER            hMixer; // 混合器设备句柄
4 r6 t! N5 [8 }        MIXERLINE         mxl;    // 音频线路标准状态信息结构体
5 N/ `6 v8 }: m9 {! `        MIXERLINECONTROLS mxlc;   // 音频线路控制器集合信息结构体
1 M" b( u& f: l! r0 v        MIXERCONTROL      mxc;    // 单个音频线路控制器信息结构体: o- \$ P( M" @, H! U3 u) @/ \% K; ~4 p

4 g" [# `3 ~% l2 {. m
8 ?- b' G% s; v( g% B! r/ o# p        //枚举所有声卡驱动,这个枚举很重要。很多代码调用mixOpen时只是用了第一个设备,即
: K; r* H, k$ _' A        //mixerOpen(&hMixer, 0 , 0 ,0 ),但是我在这个设备下调用mixerGetLineInfo出问题了,4 j! `: h" n& \& K2 r
       //可能还是跟声卡驱动有关。+ R3 `( e( @! ~+ ^: t
        for( int deviceID =0 ; true ; deviceID++ )8 g: n- `' [3 f. B
        {0 m& i4 e, i6 p% B. Q; I; ]; C
                // 打开混合器设备
0 Q' H$ u( d. o- [1 g                rc = mixerOpen(&hMixer, // 返回的设备句柄
0 S- r6 O  B  ~) j( E                        deviceID,       // 单声卡的设备ID为零
( j1 i+ n( K/ O  r  s6 u% R& d                        0,       // 不使用回调机制
: u/ K7 b5 p8 I1 v9 e6 [3 F# D5 O                        0,       // 回调函数参数
+ s- B1 c' c. y9 _                        MIXER_OBJECTF_MIXER);      // MIXER_OBJECTF_MIXER宏的值,表示任选有效设备ID
  J. G) }0 Z; V0 o" D$ E                if( MMSYSERR_NOERROR!=rc )
# X0 A8 p" g6 m: h& B* c0 E                {2 ?' L) e/ }7 r5 Q
                        //跳出循环
4 R( U. q  A/ G% Q$ w* G( K' n                        break;
& z! j6 U9 C: l4 F                }
  R/ Y: p8 _" {                // 打开混合器设备无错的话,则0 }7 h: w1 J: u7 V
" G: b2 H& z% Y2 v. m: {5 R6 f
4 }  X! Z8 h2 P( v7 G- f5 {6 }
                // MIXERLINE 结构体变量清零& N4 N* ~5 @5 o" i0 c5 Y3 J
                ZeroMemory(&mxl, sizeof(MIXERLINE));
! n9 u3 N! A2 _1 _6 m9 g+ {" ?& L  `

; ~3 e; @# \- o                mxl.cbStruct = sizeof(MIXERLINE); // 微软用此办法判断版本3 F6 @, T# E( m3 u/ n
                // 指出需要获取的通道,声卡的音频输出用MIXERLINE_COMPONENTTYPE_DST_SPEAKERS! d8 J- }. e# [' d) B
                mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
( `0 Q! @! s3 B5 @- ?1 a  \2 l% X) M0 q& A4 n3 \

( _" m$ G+ Q5 q+ ]2 v: f/ A& k                // 取得混合器设备的指定线路信息
. t7 x- a/ {6 M                rc = mixerGetLineInfo((HMIXEROBJ)hMixer,
5 n# b5 {( m  ^. ]+ a/ k                        &mxl,
& o, e0 C7 ?# ]- Q8 W; c                        // 取得MIXERLINE::dwComponentType指定类型的第一个音频线路信息
/ `, S+ ^2 d" c( l; Q' A. b3 n4 q                        MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_COMPONENTTYPE);
3 v" S& G: r% A4 U- `7 T8 Z' ^                if( rc!=MMSYSERR_NOERROR )
: D. N* S5 R' e! w2 `/ Q0 |# `                {
4 X2 W" E- ]; P# P  P- @                        //无法获取声音输入线路,尝试其他声卡
3 T* h+ F2 b! d/ |" ]& S9 V2 X                        continue;
5 I6 _7 P+ T* ?                }
, P" u1 Y: B5 S$ q& e0 {, ~2 E8 _7 s) u+ `# Y3 o
- i. Q& M* C* ]: ^4 }6 R
                // 取得混合器设备的指定线路信息成功的话,则
% V7 B( u( [; i
9 _  V0 y/ b5 l4 Z$ p: a
6 Y8 }$ s/ v; b0 M6 ^5 q& r                // 将连接数保存 , ^- [$ }5 I$ t4 v+ i* t$ B
                DWORD   dwConnections   =   mxl.cConnections; 8 g, k6 U9 E% `4 n/ s
                // 准备获取麦克风设备的ID
2 P/ b  `( v  B                DWORD   dwLineID = -1; $ a, I0 g: f: P0 G+ `: ^
                for( DWORD i=0 ; i<dwConnections; i++ )- r, m+ o9 r5 U+ F* N
                {
; n8 p, r8 }  o7 p                        // 枚举每一个设备,当Source的ID等于当前的迭代记数
, p/ f# N+ M: ^4 o# N                        mxl.dwSource = i;2 X9 F. W" A& e! s8 T& U
                        // 根据SourceID获得连接的信息 8 K2 n* i# w' d- z4 C: w% H
                        rc = mixerGetLineInfo(   (HMIXEROBJ)hMixer,   &mxl,   ]" q: y  n! {# }1 E4 w
                                MIXER_OBJECTF_HMIXER   |   MIXER_GETLINEINFOF_SOURCE   ); * b" A' N. T  V" t
                        // 判断函数执行错误 1 y& ^, S! N' m" e" ?
                        if( MMSYSERR_NOERROR==rc )9 R) O; Y& ^( k# l( ^; F, q' I! {% V
                        {
, n& L, N5 Z! Q+ q& O. C/ S  F                                // 如果当前设备类型是麦克风,则跳出循环。 : {- Z: O1 l0 f% _# _
                                if( mxl.dwComponentType==MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE )
! a4 {: ^5 T9 `8 _$ X                                { ; A" S8 K: ^2 ?8 N- L, I5 z
                                        dwLineID = mxl.dwLineID;
3 I7 L- A9 J) }, G" K9 K                                        break;   G& c8 a( l9 T* t' T0 @- f
                                }' b3 i! g1 S$ q% i
                        }
6 K1 M% b- i! ~' y                }
. r6 ]& u/ l7 e# r7 A( a" b3 ^                // 如果没有找到,返回失败。 2 v' c( K% E) _- d2 R
                if( dwLineID==-1 )% v1 c8 f) W  Q3 u9 A
                {
5 t' H% [9 R. B) r                        //尝试其他声卡, K7 j: {; v5 C
                        continue;! G0 p2 Q* \# a* }
                }, ~0 d# d9 [$ Z4 E6 x. i
5 A4 L9 ?- V2 a! _0 T8 Z

. O6 E! \' I. @8 J                // MIXERCONTROL 结构体变量清零
+ Q) y* a- x& D$ ]                ZeroMemory(&mxc, sizeof(MIXERCONTROL));6 m# v' f/ Z* _5 p; J! e
4 f/ k+ i! U: \/ v" R! Q# m) W
: ]0 {1 a8 \3 Q7 [* e
                mxc.cbStruct = sizeof(mxc); // 微软用此办法判断版本; x# T& P0 z' W, e

: y) S7 @! ~+ v' a$ G5 k& P
: Z! q1 t5 M1 m) U                // MIXERLINECONTROLS 结构体变量清零8 v2 Q/ i4 ]/ F9 J
                ZeroMemory(&mxlc, sizeof(MIXERLINECONTROLS));
& E- k$ j8 ~" @3 X% c8 z: ]7 W& ~5 I3 V7 I8 B) b
# E7 g4 j3 E, f0 y8 [
                mxlc.cbStruct = sizeof(mxlc); // 微软用此办法判断版本
7 N! N/ b. E  X/ U
" d8 [0 k$ h1 a. D
6 x8 H1 H9 B; f( P5 H- {6 O3 T* p                mxlc.dwLineID = dwLineID; // 上面取得的声卡音频输入线路标识
1 j  @* f! i; J7 w/ [  @                // 控制类型为控制音量+ v7 O3 Z1 A0 }% m* {1 C4 C
                mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;0 v' u0 }' y. C4 m, C1 L" ~3 a
                mxlc.cControls = 1;          // 使用 MIXERCONTROL 结构体变量个数
) B% u& i$ m1 [                mxlc.pamxctrl = &mxc;        // MIXERCONTROL 结构体变量指针0 {" ?+ s/ l; O/ W* d+ f2 _
                mxlc.cbmxctrl = sizeof(mxc); // MIXERCONTROL 结构体变量字节大小+ h* m7 Q' V' ?* Y2 T+ r9 A; n
' L' A) n' T$ w* s# u0 W/ c7 W6 ]

: |: M- [& S& o8 Z                // 取得控制器信息
' o" b7 Q- p# l                rc = mixerGetLineControls((HMIXEROBJ)hMixer,
, @, x  M* }2 o+ U                        &mxlc,6 h2 G' I) Y8 N4 w& o
                        MIXER_GETLINECONTROLSF_ONEBYTYPE);5 ?- F6 K8 m- n0 p

1 y& d9 l' j( C9 K
/ h+ N6 |) E7 `5 \  ^2 c7 m8 C4 f% W                // 取得控制器信息成功的话,则
- o9 I' A  o& j) F2 n                if (MMSYSERR_NOERROR == rc)+ }9 ^, U! c/ J9 `) Y
                {7 ^( t2 I* _7 ?
                        // 获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
: H$ b. k$ A! Q9 p) t: R7 s                        MIXERCONTROLDETAILS        mxcd;      // 控制器的状态信息# ?" g  J, ^( s5 E* z
                        MIXERCONTROLDETAILS_SIGNED volStruct; // 音量结构体变量(就一个成员量)
7 z" \% H8 k, ]% }! w
+ y; w8 F" z6 s( C8 b
8 T% @' I2 n! g, h) \, V- ?9 A                        // MIXERCONTROLDETAILS 结构体变量清零
& U. c! h) f& \- f6 U                        ZeroMemory(&mxcd, sizeof(mxcd));+ _, i6 w/ S0 B0 V0 Y& [' [

* M& c( R: E8 E: _6 d
% G; r) ~* r9 a' g% D7 A                        mxcd.cbStruct = sizeof(mxcd);       // 微软用此办法判断版本
- }* t/ p1 I5 j  ?0 t) j                        mxcd.dwControlID = mxc.dwControlID; // 上面取得的控制器标识  M8 }1 G' ?! {+ M- \3 k% k2 m, Q$ P
                        mxcd.paDetails = &volStruct;        // 音量结构体变量指针
. u  @# y6 w9 W; m1 ?                        mxcd.cbDetails = sizeof(volStruct); // 音量结构体变量字节大小
! x2 g! ?9 L; K$ q0 J& z, P* F                        mxcd.cChannels = 1;                 // 取得或设置全部通道
5 c" u  s( H) \8 E4 f  w
) I/ {- L# u/ x& ~' q: P
: j# q- v% w* N: k, Z& j0 X                        //  获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
; ?; @2 q. M8 s0 l% D
( m( S$ h% J5 x' h1 |
* C; k8 ?/ k  M0 q( x                        // 获得音量值
) V/ G- R- I# d' @4 I                        rc = mixerGetControlDetails((HMIXEROBJ)hMixer,
/ n1 y1 z' r8 C  t8 M                                &mxcd,- Q* p( u  e0 _9 o
                                MIXER_GETCONTROLDETAILSF_VALUE);
$ a7 a# j& M: v% f$ m" J8 N& i  a
, T. M$ \& s6 D. J
" d0 Q9 @& T/ M7 N/ [' G2 @6 G                        if (MMSYSERR_NOERROR == rc)  C0 Y, x3 H6 u; |/ ]* T
                        {; S5 F7 [3 z& Q
                                long step = ( mxc.Bounds.lMaximum - mxc.Bounds.lMinimum ) /100;
% C. m: R& y4 G9 t+ a0 C) O$ r  y, a, g6 C

; m, u. s: v+ ^' Z3 M" X. S7 H) B                                int index = ( volStruct.lValue - mxc.Bounds.lMinimum) /step ;0 F2 o+ g4 t2 x& J1 X
                                printf("音量:%X", volStruct.lValue);6 ]2 E8 q" l( v' ~% E+ i7 }! P# C
                                return index;4 E3 U/ D1 G, d( B/ z* H
                        }6 ~  e! X" X. u+ S9 t: [( t& f
                }. u( f4 H) |' T( p0 B# ?
        }. B4 ^( a" J, q# V# E' m( n) z
: Z/ `& a+ P4 W3 w
' ~" z( E- f! _$ S3 p
        return -1;
0 i: {+ ]: ]+ L- L; w}
- @2 W% y4 U* J. N
, q- N+ ?5 ~- o- |, P1 ]& B2 s        相关网址:http://topic.csdn.net/t/20050606/10/4062001.html( B" H# Q% U; c9 i3 h4 @7 T
                        http://blog.csdn.net/tangaowen/archive/2010/07/28/5771149.aspx
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-13 22:33 , Processed in 0.017300 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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