找回密码
 注册
查看: 5095|回复: 0

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

[复制链接]
发表于 2011-5-7 21:31:51 | 显示全部楼层 |阅读模式
原文:http://sunerok.blog.163.com/blog/static/231096422010112815525949/
9 A% p" x1 L9 E5 ]1 B* s
. A0 p# q0 h% b) h# q* A: y1 Q参考了网上很多资料,也碰到了许多问题,终于解决了,很开心,把代码贴在这里分享一下:! x+ q3 c+ S% N/ j
+ k+ O5 K  T* J2 H' w2 J2 V5 f6 w
2 K) P- q( d5 B1 D% E+ w
int DeviceManager::getAudioInputVolumn( const std::string &deviceName )% t2 Q+ X. W" v6 L" r- l3 Z5 ~
{, ^5 u) @' o# }" r: X0 N3 `& a: }/ P

& n! E' J! n5 F2 S$ {# X$ W: @" B9 g' o8 d7 e# ]  W; p
        MMRESULT          rc;     // 多媒体函数返回结果变量& |, \* u# A0 F; f/ o% }
        HMIXER            hMixer; // 混合器设备句柄; u) _: u9 X2 e! K
        MIXERLINE         mxl;    // 音频线路标准状态信息结构体
1 h- X* H% T  ~* X' F+ y4 I* M        MIXERLINECONTROLS mxlc;   // 音频线路控制器集合信息结构体. V3 a! C0 Q/ M
        MIXERCONTROL      mxc;    // 单个音频线路控制器信息结构体
0 X& Z% [3 d7 H7 \4 s/ K% ?  \1 m. s$ ~% l4 N6 K# A! b
4 H; L8 Z  F% i, @# T
        //枚举所有声卡驱动,这个枚举很重要。很多代码调用mixOpen时只是用了第一个设备,即. ?& C) t* R% H: ^' i
        //mixerOpen(&hMixer, 0 , 0 ,0 ),但是我在这个设备下调用mixerGetLineInfo出问题了,
. G( `7 D5 X1 d2 H, ?# X; G& k; ?       //可能还是跟声卡驱动有关。; C- s& ?% e7 X9 V; Y& K
        for( int deviceID =0 ; true ; deviceID++ )
1 |% f' c0 U9 Y" j' u8 u        {
' F7 ]# P1 v7 L, ^% h) c' U% e                // 打开混合器设备
( E: T- u8 U, p1 a/ s1 V+ m                rc = mixerOpen(&hMixer, // 返回的设备句柄
# U8 [3 L* e+ m+ r* r7 ?2 A                        deviceID,       // 单声卡的设备ID为零
3 p& r; O. ~# x: Q                        0,       // 不使用回调机制
' `& c# x' H1 x& r1 @, `                        0,       // 回调函数参数9 [8 Y: b9 C8 o7 A1 Z6 N7 M' i
                        MIXER_OBJECTF_MIXER);      // MIXER_OBJECTF_MIXER宏的值,表示任选有效设备ID9 O$ Y) D: T* n
                if( MMSYSERR_NOERROR!=rc )
6 ~* o) Q+ z4 P2 @, b9 `! `" E                {" G; L( _( q' l7 _( h2 c7 R
                        //跳出循环
) D2 p" N0 j* q7 s; g                        break;
- a# H/ V4 d: N: R                }$ s" L, i, Q. f& G2 u
                // 打开混合器设备无错的话,则
6 k* L5 _9 c# a; m9 T2 I% Q2 N! E& x9 P

: i$ `) y8 _7 x7 ?$ G9 j$ T) c                // MIXERLINE 结构体变量清零$ W& c4 I& {+ J2 L* x4 @- Y
                ZeroMemory(&mxl, sizeof(MIXERLINE));0 Y  s" ?% ?" H  i1 r5 [3 r, H+ G
7 q# g& X8 N3 s- A

+ c* e3 H, Y, s& I0 m5 v. ]                mxl.cbStruct = sizeof(MIXERLINE); // 微软用此办法判断版本9 z3 G% l8 ^, u1 j9 X2 ?
                // 指出需要获取的通道,声卡的音频输出用MIXERLINE_COMPONENTTYPE_DST_SPEAKERS# T# _5 l, x0 ?) e7 v1 I
                mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
6 ]; L) M4 K% |2 ^
. |8 w; _6 b: D( C
4 Z5 r7 g+ ]4 M. x+ {0 z                // 取得混合器设备的指定线路信息
9 {: a+ e0 A- _' s8 D0 w                rc = mixerGetLineInfo((HMIXEROBJ)hMixer,6 L, |& F7 I. ~6 {0 h7 |+ @. e
                        &mxl,
; K; A; x7 C* a* ^" r$ C* {( V                        // 取得MIXERLINE::dwComponentType指定类型的第一个音频线路信息
4 O0 b) H0 n( `. _) l                        MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_COMPONENTTYPE);# d; v% v9 o4 a$ s8 o3 J
                if( rc!=MMSYSERR_NOERROR )
( [+ w& Q; k; b+ M6 F                {  _2 f5 P8 F2 ~
                        //无法获取声音输入线路,尝试其他声卡, ]  a! W0 X3 L% I3 N9 p
                        continue;
  X$ ]5 E, p' F0 R2 U& P: o                }! q* R5 _7 Y0 l$ c, ]4 Z$ r# P( E

/ q5 c$ w* j* j% s
' o: K! V) Y3 T7 H* x" O: R; S                // 取得混合器设备的指定线路信息成功的话,则
) e6 ?' R% I* a! ]
4 Y4 B2 e; a6 C7 B/ X7 t" O7 t) Z. V# j% Q1 l1 k2 @# w
                // 将连接数保存 8 K2 ], R4 U5 V: Z! v
                DWORD   dwConnections   =   mxl.cConnections;
* u1 z# b; s) p                // 准备获取麦克风设备的ID
! I& o. T0 v& @) y                DWORD   dwLineID = -1; 0 S  W# Z4 m/ n) a( x! ~! o
                for( DWORD i=0 ; i<dwConnections; i++ )( s6 V" h$ g8 d+ x" e4 s% \  p
                { ( e# i) Q! p  G# @. a, T; s) J
                        // 枚举每一个设备,当Source的ID等于当前的迭代记数 / D4 h; q9 h- b( {* ]2 V, b. S+ X
                        mxl.dwSource = i;
0 n6 u5 y. W+ N                        // 根据SourceID获得连接的信息
1 P/ S4 o& x/ o                        rc = mixerGetLineInfo(   (HMIXEROBJ)hMixer,   &mxl, 5 l0 G$ w: |3 q, b( J# X
                                MIXER_OBJECTF_HMIXER   |   MIXER_GETLINEINFOF_SOURCE   );
( X. ^4 M5 Z' m4 J6 B9 x4 {                        // 判断函数执行错误
$ R. l0 P+ [, E% [! T4 i# D5 @% H# ?                        if( MMSYSERR_NOERROR==rc ), f  O+ x1 g8 F7 K
                        {
: y1 d+ C/ d: \) i; {                                // 如果当前设备类型是麦克风,则跳出循环。
; j7 w/ @( J. i* V! q9 q8 |                                if( mxl.dwComponentType==MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE )
% r8 ~/ }+ v% c1 A1 F6 z  X                                {
% t. n; x  x- [4 \1 ~4 ?, H" f% d                                        dwLineID = mxl.dwLineID;
* ^" U! i. b1 i" p+ `                                        break;
1 T, `8 ^/ f6 p                                }
% x6 ^* M+ e& u. q9 |7 w- T" `                        }
9 l5 X( N# C( j                }! K. Q/ a! Z; F, u0 [
                // 如果没有找到,返回失败。 . Z3 \) o- U0 \
                if( dwLineID==-1 )
" {  M/ h. p, C) r- J5 ~, ~3 v7 |) Q                { 5 H( B/ i7 I1 e( w1 @" r
                        //尝试其他声卡& j$ p+ P3 E+ P7 ]- p
                        continue;
% S0 e* P3 X4 i                }1 A! B- B4 ^  |' T1 G, F

! l, U( X: D; D4 _2 `) Y. r3 l3 R6 T; k
                // MIXERCONTROL 结构体变量清零
4 w* y- G7 h& Z, \0 x                ZeroMemory(&mxc, sizeof(MIXERCONTROL));
, Y) X2 e5 @% U2 ]
: P' }4 z7 ?6 K3 i" A, Q; o( [/ D4 D; K8 H  i2 N/ P- C2 ^
                mxc.cbStruct = sizeof(mxc); // 微软用此办法判断版本3 q( m. q- c6 c5 E( ?0 V

8 A) T3 l2 E, `- D' X5 X& W
9 f, H/ n1 T: U% W                // MIXERLINECONTROLS 结构体变量清零
% t; A! ]/ G  l6 w                ZeroMemory(&mxlc, sizeof(MIXERLINECONTROLS));
. `5 r$ b7 W" Z' X! k- ^
& B. R7 k! ~% Z1 L! W7 Y2 j9 E4 l, o
                mxlc.cbStruct = sizeof(mxlc); // 微软用此办法判断版本
8 \* G& U# e4 P2 j* b& q
+ l3 J- q0 c7 U1 l' X( s/ `5 P2 M$ W1 u" j' Q  ?* x: B/ `
                mxlc.dwLineID = dwLineID; // 上面取得的声卡音频输入线路标识; z4 f0 ^- c+ O
                // 控制类型为控制音量
0 m/ T6 c* U3 v- [8 K2 @                mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
- H1 ?& n/ I# C$ \                mxlc.cControls = 1;          // 使用 MIXERCONTROL 结构体变量个数/ o# E4 G( l& A) I* \, l2 j
                mxlc.pamxctrl = &mxc;        // MIXERCONTROL 结构体变量指针
7 c: B' x# `, H+ X! |; E3 h                mxlc.cbmxctrl = sizeof(mxc); // MIXERCONTROL 结构体变量字节大小3 _! }( n- U* ]$ T  o; e
4 `9 L* j7 W' Q
5 C* n, s4 w! ~* g! z6 t. D
                // 取得控制器信息3 {; e. ^0 R8 e2 E" c% J
                rc = mixerGetLineControls((HMIXEROBJ)hMixer,3 M5 p# C7 E3 h9 K! ~& E3 O% P
                        &mxlc,8 X: G. K& S, r7 Z
                        MIXER_GETLINECONTROLSF_ONEBYTYPE);
. V/ U8 z6 ~( o; }; O, n3 n
/ n& |* G1 J- \9 j& ~, V" J( s# f+ |2 J. R' `3 W0 l
                // 取得控制器信息成功的话,则+ p3 m3 D! D* A* O* ^
                if (MMSYSERR_NOERROR == rc)
3 H0 [7 P2 n, @( ]4 {: U: D                {
- J$ A# Z  V1 }                        // 获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.% }+ ]$ c$ l* m4 ?- ~& Z5 D9 [
                        MIXERCONTROLDETAILS        mxcd;      // 控制器的状态信息
  u1 r) {, ]: D6 m: c2 W  @  k4 T1 s                        MIXERCONTROLDETAILS_SIGNED volStruct; // 音量结构体变量(就一个成员量)( l" N* c2 I8 C8 K( [

+ k7 h& O( n# ]2 y2 S  Q' `8 ~
$ a5 g4 y6 L* x* f/ e. s/ ^                        // MIXERCONTROLDETAILS 结构体变量清零
0 S8 m/ X0 Y* ^1 Q                        ZeroMemory(&mxcd, sizeof(mxcd));
, p, P7 z- D- i7 S
' z2 V, h+ L) _- V$ G+ ^& M' M" T9 v. I! j0 ^  L3 X7 `
                        mxcd.cbStruct = sizeof(mxcd);       // 微软用此办法判断版本- H0 M: [. F, d4 o) F
                        mxcd.dwControlID = mxc.dwControlID; // 上面取得的控制器标识  q- d' Y2 W0 ]( ^6 {
                        mxcd.paDetails = &volStruct;        // 音量结构体变量指针
9 f' Z' v' X3 i% Y( E/ S- k                        mxcd.cbDetails = sizeof(volStruct); // 音量结构体变量字节大小
2 }5 Z; d: ^' A, x- o                        mxcd.cChannels = 1;                 // 取得或设置全部通道
: M: Y5 i; l% _8 h% ]  p; }
0 T! E( r7 \. m9 }7 X! i# E
1 A) D5 R9 N  o$ n4 N# [                        //  获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
: E* U: ^! W; w2 F4 f% D9 w7 l/ h$ [9 d( Z
7 _; Q' y1 l) n( X. j0 R
                        // 获得音量值
& Z% [' S+ L# J( c3 ]. u4 r                        rc = mixerGetControlDetails((HMIXEROBJ)hMixer,
. m" G" u( D9 _# t" Q3 ?                                &mxcd,1 y5 W$ R# U6 z  t& K
                                MIXER_GETCONTROLDETAILSF_VALUE);
  s% z3 d" |" P
6 @6 M8 S4 u1 z0 x3 [% x; b8 g
# k6 R6 R( y2 C) k( L1 n7 I                        if (MMSYSERR_NOERROR == rc)
! `8 s6 [# d: s$ s                        {2 X, Y) K, l0 M5 }3 y
                                long step = ( mxc.Bounds.lMaximum - mxc.Bounds.lMinimum ) /100;
, C( m7 \0 x& P2 z+ v* i/ a& B8 t) k# R1 x% d# O) r
6 F$ u( A' P: y9 g  Z3 `6 X, r" q
                                int index = ( volStruct.lValue - mxc.Bounds.lMinimum) /step ;
8 ~5 J0 z# U/ R/ q                                printf("音量:%X", volStruct.lValue);
4 Z8 o% e& n8 W) b                                return index;, w% @2 v& h% e1 c' N
                        }+ K: k( `$ R: t; A
                }: s+ M1 Y/ i; T( P
        }$ r" B( I8 x% M* U- e7 C& i# j

8 _1 `# J. H  \. \, Z% \/ ^7 O! f: {; [( p) ?' D+ M6 k
        return -1;: K2 T! }; }8 C$ A) r
}
; J" r& m/ w: z, L* E9 o! `
& s& V; o/ [- x- b/ X6 }2 O: n/ ^0 \        相关网址:http://topic.csdn.net/t/20050606/10/4062001.html
% O$ X% L9 c  q. \" M: H& g                        http://blog.csdn.net/tangaowen/archive/2010/07/28/5771149.aspx
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-2 09:02 , Processed in 0.017628 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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