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

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

[复制链接]
发表于 2011-5-7 21:31:51 | 显示全部楼层 |阅读模式
原文:http://sunerok.blog.163.com/blog/static/231096422010112815525949/
$ M- B! R$ S' H+ M5 s8 t% L
; |% s# W7 M( p参考了网上很多资料,也碰到了许多问题,终于解决了,很开心,把代码贴在这里分享一下:
: ~9 G" O9 l5 W- y  Z4 Q* ^
, b- K  m4 g8 n" X8 s; J* X" a( e, o# J
int DeviceManager::getAudioInputVolumn( const std::string &deviceName )) K" p2 K% B+ a) y  n4 `, a! X
{
; z( c, e- n! R8 f
$ l9 A, U( K; @0 u* y. [, ~' B& F* ]2 G  ?
        MMRESULT          rc;     // 多媒体函数返回结果变量
5 T9 j+ l, x* U        HMIXER            hMixer; // 混合器设备句柄% ]6 d+ ~' E/ p) X$ K/ D
        MIXERLINE         mxl;    // 音频线路标准状态信息结构体9 i6 J6 K' M- p* H/ a6 \) f. a' x
        MIXERLINECONTROLS mxlc;   // 音频线路控制器集合信息结构体4 [- S8 @7 l9 Q$ h2 V
        MIXERCONTROL      mxc;    // 单个音频线路控制器信息结构体
/ g0 U4 ~' L8 {% g% }% D$ |* X
4 O, m- R4 h1 W1 \, C
6 _7 [5 r. E9 S3 J9 j$ P        //枚举所有声卡驱动,这个枚举很重要。很多代码调用mixOpen时只是用了第一个设备,即
3 R. K* b6 X. B$ e! w3 Z        //mixerOpen(&hMixer, 0 , 0 ,0 ),但是我在这个设备下调用mixerGetLineInfo出问题了,4 l$ ?5 @* M4 @! z* q- H
       //可能还是跟声卡驱动有关。
6 Z4 T# I2 G2 H; O+ {+ c- r% B7 ?. ^        for( int deviceID =0 ; true ; deviceID++ )% p0 @0 ]! [1 h9 |- s/ O/ P! g
        {6 p' C7 [0 Z- |  j
                // 打开混合器设备
! M1 ^* k/ r+ c2 x  ?8 F3 M+ T                rc = mixerOpen(&hMixer, // 返回的设备句柄
( I6 p& ^: j& I* P% I# t                        deviceID,       // 单声卡的设备ID为零
! o+ ~0 Y& z* ~4 |( P$ M" Q% Q                        0,       // 不使用回调机制
; T/ `* ?: s* h                        0,       // 回调函数参数& Z$ o( W1 C, e8 a) w2 M
                        MIXER_OBJECTF_MIXER);      // MIXER_OBJECTF_MIXER宏的值,表示任选有效设备ID
2 G2 l5 S' s1 h$ d5 d                if( MMSYSERR_NOERROR!=rc )
- E+ E% q6 S. ^5 Q6 E                {. W2 [8 J$ R. ~$ I& A) L6 ^) d
                        //跳出循环6 d- x0 B' ^) l* C" F
                        break;$ z1 {' N- ?) u9 B3 q9 _
                }( N# e3 d3 t2 z5 E/ X' X
                // 打开混合器设备无错的话,则
+ L' T: m& Y8 s" f( Y  L  x( G) b. ^
& o! r/ V! G. J6 ^" V
4 p% C( F' `8 P1 t' Z8 S2 z% e                // MIXERLINE 结构体变量清零
5 x  e3 }- L8 K) `8 z                ZeroMemory(&mxl, sizeof(MIXERLINE));
! a* C$ y5 D% t+ f* x7 q; j" h! [7 Y1 |9 K, i

# g+ {1 R' X9 [5 Q5 V1 g2 B6 |                mxl.cbStruct = sizeof(MIXERLINE); // 微软用此办法判断版本, D& W; I4 I# r% e& v) f$ c
                // 指出需要获取的通道,声卡的音频输出用MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
0 @# U5 y( v3 ], Q                mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
+ x  p& n" z4 p$ T2 n6 c" _" h4 {  o; P; T( c/ u

  ?0 Y. ?1 ]  \; I' N9 P8 B                // 取得混合器设备的指定线路信息0 |* _4 O( R( O0 j
                rc = mixerGetLineInfo((HMIXEROBJ)hMixer,
5 Q5 z6 H( e7 C; l; \/ l                        &mxl,+ I; C, @7 s- I& a5 B  F
                        // 取得MIXERLINE::dwComponentType指定类型的第一个音频线路信息
5 t2 t2 A; l2 W% u' ^" {1 G                        MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_COMPONENTTYPE);+ U& R! h! l* c
                if( rc!=MMSYSERR_NOERROR )
1 d/ U7 f* B$ _+ x# N: F; O                {9 ?4 W7 d6 o  U! n  Q
                        //无法获取声音输入线路,尝试其他声卡# \: _9 N; [9 C% t5 K
                        continue;2 d5 ]% E3 N: }8 v/ ~
                }/ S# S9 i5 N/ A  t7 R' h0 n
' c% p, h2 S, ?* T9 C4 t7 Q! C
. E8 \  n+ @' k. I6 ^& n( t+ l  y
                // 取得混合器设备的指定线路信息成功的话,则
+ x2 ^/ W/ S# J7 h' ]
5 {$ ]: L5 b; ^: z9 C
7 L+ ]% r+ R, p: j2 V                // 将连接数保存 7 z( w4 P1 z" S. ]; }
                DWORD   dwConnections   =   mxl.cConnections; 0 e3 D4 K( `* M& `, P% s
                // 准备获取麦克风设备的ID 6 p  X( n7 `7 N! E  F
                DWORD   dwLineID = -1;
9 Y; u/ @* W0 v                for( DWORD i=0 ; i<dwConnections; i++ )
! L% X' d! X9 v: A8 D  V9 e                { 8 W7 q6 G0 O7 W( m7 T
                        // 枚举每一个设备,当Source的ID等于当前的迭代记数 - O( p7 d% D9 q/ G3 f
                        mxl.dwSource = i;" i9 M2 D$ I  L
                        // 根据SourceID获得连接的信息 & j% V* ^- o; m3 z2 J
                        rc = mixerGetLineInfo(   (HMIXEROBJ)hMixer,   &mxl,
* J1 q0 f2 A  B+ i. ?- J) q( K& \& {. c                                MIXER_OBJECTF_HMIXER   |   MIXER_GETLINEINFOF_SOURCE   );
; k3 }0 u4 I# m" o0 P3 C                        // 判断函数执行错误
7 c% T) v! U7 q4 J7 U  M: E- h8 Y                        if( MMSYSERR_NOERROR==rc )
" R0 i9 C# f- b  s                        { " W3 v" H% V8 H9 X0 v5 z
                                // 如果当前设备类型是麦克风,则跳出循环。 ; a& B  f8 ?3 M  \" F% _
                                if( mxl.dwComponentType==MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE )+ |/ c7 \) ~1 `0 P
                                {
" i% T: w- d, b# k8 s# M                                        dwLineID = mxl.dwLineID;
, D5 {! [0 r: N                                        break;
$ w0 c6 r$ Z8 C, ~                                }0 l7 j8 }; U% |
                        }1 V# a) w" n  I2 v7 Y2 U- r
                }
3 B7 E8 p. P3 e  M: B7 v                // 如果没有找到,返回失败。 . Q& D% r* \6 ^8 q
                if( dwLineID==-1 )
# @* m- L( a+ s! ?, j6 S  S& R4 W                { % [. a; b' E* M+ \/ S1 o
                        //尝试其他声卡
4 u6 e6 U, f; q                        continue;8 s& c2 R, F9 v6 `
                }- G& y  f+ q- M& M. M/ H# N4 B
, S) V+ ?$ g2 [6 M* w" X
2 D; E9 V% V! B2 Q9 e4 M% K, T
                // MIXERCONTROL 结构体变量清零
2 o% i8 w/ y* t, {1 M7 q                ZeroMemory(&mxc, sizeof(MIXERCONTROL));8 h1 ~  L( m# `: C: f* T1 E% @
/ V; J2 T( W/ }5 Y! v
& s9 b# N" w7 F* ~7 a8 h
                mxc.cbStruct = sizeof(mxc); // 微软用此办法判断版本* w! A; _( v, _; ]
1 k, Q6 G+ N- u9 Y5 }9 J' ^
9 l" z8 P+ B$ |( ^- @% z' F, _/ y
                // MIXERLINECONTROLS 结构体变量清零0 \# |; s& T: Y6 J  s) W
                ZeroMemory(&mxlc, sizeof(MIXERLINECONTROLS));% f. T! f+ J6 h, l. \( ]
& p  M0 Q# w: C5 u; N

% l; e: }1 L, e: o                mxlc.cbStruct = sizeof(mxlc); // 微软用此办法判断版本8 C/ ^) k9 V6 w
+ _* H; ?% b% J& e1 F1 x6 u& K+ K- T$ M
6 w+ i3 b/ x8 g
                mxlc.dwLineID = dwLineID; // 上面取得的声卡音频输入线路标识3 G% R( V3 [2 ]5 T( C
                // 控制类型为控制音量% j8 S! e$ G2 \! ^
                mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
9 w: ^9 s* B  P' O1 R                mxlc.cControls = 1;          // 使用 MIXERCONTROL 结构体变量个数2 A" o( _* }5 q8 ~8 x% V5 a. Y9 K4 d
                mxlc.pamxctrl = &mxc;        // MIXERCONTROL 结构体变量指针! V! q2 n4 G/ }0 l/ ~6 h: Z
                mxlc.cbmxctrl = sizeof(mxc); // MIXERCONTROL 结构体变量字节大小. F8 E! J* k' V8 ]0 D
# H) B. h* i- a* d

. c4 B  y9 b0 }& R. a                // 取得控制器信息/ @# K# s  v6 m- R$ |% v
                rc = mixerGetLineControls((HMIXEROBJ)hMixer,
- x$ c, a) k, E5 h                        &mxlc,# i" l  d; ?. ]9 @2 |
                        MIXER_GETLINECONTROLSF_ONEBYTYPE);+ |) K4 h- V( Q# I
' o5 Y1 x5 I1 K

* \& B$ ^6 Z' T% g                // 取得控制器信息成功的话,则
7 F- O0 c6 {( A5 \$ q# i, O                if (MMSYSERR_NOERROR == rc)
- k! B" P9 h/ [# e/ \, x                {
4 ?0 P7 H" U; {# p2 J                        // 获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
8 d( _' K) O5 B/ L* \4 x' s  x0 Q                        MIXERCONTROLDETAILS        mxcd;      // 控制器的状态信息
! u: G1 w1 K9 U, _5 l( u7 y                        MIXERCONTROLDETAILS_SIGNED volStruct; // 音量结构体变量(就一个成员量)
- S' K$ t* K9 K" I- o* O) g
: C2 X4 t2 m7 \' M. S0 V  z
. ?) ?) w% b" K                        // MIXERCONTROLDETAILS 结构体变量清零
- {+ c% D$ G9 z. i                        ZeroMemory(&mxcd, sizeof(mxcd));+ r* Y6 |. T6 Y8 G; L
5 R" m+ Q# g2 L

( I# h7 d0 c! A                        mxcd.cbStruct = sizeof(mxcd);       // 微软用此办法判断版本
5 v3 M3 M* m7 G# q- `( Q6 j                        mxcd.dwControlID = mxc.dwControlID; // 上面取得的控制器标识6 `* h9 v2 z$ f- K) b$ y; R
                        mxcd.paDetails = &volStruct;        // 音量结构体变量指针* l9 W+ S9 l: ^+ V0 o" o3 N  A0 U$ ]
                        mxcd.cbDetails = sizeof(volStruct); // 音量结构体变量字节大小
$ ^7 }# S8 l  }' W: o6 d# m                        mxcd.cChannels = 1;                 // 取得或设置全部通道
8 l+ {4 q  J  S9 e! [
6 y+ h9 y& u7 H  ?) ~
5 l! O6 p% Y- t" j$ n                        //  获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum. % I6 Q3 `2 L0 ]2 g6 V5 E1 z
$ [8 \9 N7 c$ o( L+ I
9 s* H' b" i5 P/ N
                        // 获得音量值
! S6 j+ E7 q/ |+ h& H( S                        rc = mixerGetControlDetails((HMIXEROBJ)hMixer," _; |0 n" c- C
                                &mxcd,
4 G8 o0 j; `2 Y( Y, {" L                                MIXER_GETCONTROLDETAILSF_VALUE);/ `5 f& _- v; W1 r! u

% ~! r) Q7 P  [1 o2 J- [
7 o# C8 t# p1 ?& x4 ^                        if (MMSYSERR_NOERROR == rc)9 n) u6 A- a/ J* `
                        {
% b7 p% e3 _  O! o( b                                long step = ( mxc.Bounds.lMaximum - mxc.Bounds.lMinimum ) /100;3 T2 z" X; i- M; v/ N: Y
, u2 c, x, B. z9 L$ ]0 j/ _+ }
) H1 I5 E7 G5 `$ p. x
                                int index = ( volStruct.lValue - mxc.Bounds.lMinimum) /step ;. ?; I1 N( x; v
                                printf("音量:%X", volStruct.lValue);5 F5 F, k! ^5 @: ^/ q3 o& e
                                return index;
8 ^7 P! V' Y) Y                        }
6 {4 x5 |1 C8 O                }
9 D( L* E, b. _9 v" \) X& O! \        }
2 ]3 y7 [0 }% g2 Z. n' Y1 P
8 u0 U' B2 b( G0 t- ~8 \" E; ~+ ?9 c  a
        return -1;& g: {2 o9 [' f5 k& Y9 e% e2 d
}
( b9 x' \7 d/ r4 ?% U. ~# z7 Z& s7 {8 O6 Y6 }3 w+ u5 {8 [, }
        相关网址:http://topic.csdn.net/t/20050606/10/4062001.html; N5 N% o  f" p- R% y
                        http://blog.csdn.net/tangaowen/archive/2010/07/28/5771149.aspx
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-12-30 04:23 , Processed in 0.018574 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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