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

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

[复制链接]
发表于 2011-5-7 21:31:51 | 显示全部楼层 |阅读模式
原文:http://sunerok.blog.163.com/blog/static/231096422010112815525949/
) |& \  B- j6 ?# V" W
9 ], v% _3 U" S" P8 X$ O参考了网上很多资料,也碰到了许多问题,终于解决了,很开心,把代码贴在这里分享一下:
2 d0 w5 }. a* j( T2 Y4 j9 l' W0 G; K9 u& Z: R
: [/ a0 n  c' g1 ^6 N$ S
int DeviceManager::getAudioInputVolumn( const std::string &deviceName )1 T3 T  F5 }6 L% ]5 r. \+ G* a
{- G+ V! _# N; [
4 c5 [- `; V6 I+ @9 h6 O
% L% k+ w; D1 a/ }5 [
        MMRESULT          rc;     // 多媒体函数返回结果变量
9 Z/ H6 N6 }" T- @3 H6 U3 `5 \( ]        HMIXER            hMixer; // 混合器设备句柄* L7 `1 L3 A0 _- b, S' R8 F% {
        MIXERLINE         mxl;    // 音频线路标准状态信息结构体
' r' v1 t  ?5 `! `* X" y# t        MIXERLINECONTROLS mxlc;   // 音频线路控制器集合信息结构体
* n0 f4 i# R6 s" N" m* Q$ n        MIXERCONTROL      mxc;    // 单个音频线路控制器信息结构体+ N6 u' G/ F5 T: H! S

+ ]4 S- d! B/ ]% X: q' m# u4 p% C8 M! W6 `% \6 x  L6 S+ c
        //枚举所有声卡驱动,这个枚举很重要。很多代码调用mixOpen时只是用了第一个设备,即: A" Z1 G) q% ~' v0 A7 X" {
        //mixerOpen(&hMixer, 0 , 0 ,0 ),但是我在这个设备下调用mixerGetLineInfo出问题了,* K; a: Y$ O- N) g, x7 X
       //可能还是跟声卡驱动有关。6 r9 ]8 Y) t5 n& i1 W9 {
        for( int deviceID =0 ; true ; deviceID++ )8 i# i0 [: y( I: |
        {% [5 O' v7 \: {$ c
                // 打开混合器设备
) r1 Y# u7 ~. `. }3 g" z                rc = mixerOpen(&hMixer, // 返回的设备句柄
' }# }2 `6 y5 M, Q2 {( g                        deviceID,       // 单声卡的设备ID为零
8 s3 a' v7 q7 H, t! e                        0,       // 不使用回调机制
, l+ v  T8 @9 F' }                        0,       // 回调函数参数
8 g3 G, B& ]) g9 r8 I9 ^. Z# E) k. b                        MIXER_OBJECTF_MIXER);      // MIXER_OBJECTF_MIXER宏的值,表示任选有效设备ID* {( t; Z* N9 f6 E. `$ b& W
                if( MMSYSERR_NOERROR!=rc )
9 _8 u! P6 w3 k0 E                {
" z5 t3 Y) {9 A# f$ B0 I7 _+ E                        //跳出循环
% C3 i5 F: d8 z# l( L                        break;
- c8 |) f1 E( t& R% L( Z                }( t. P6 D; P( }, W: {2 E
                // 打开混合器设备无错的话,则
5 w3 o2 {- |- L- A' T
3 @+ e6 |, i  e/ }# X
$ W' e& Q$ I$ x0 C4 ^4 v                // MIXERLINE 结构体变量清零  P2 [, {8 L; D# \1 v/ i2 x
                ZeroMemory(&mxl, sizeof(MIXERLINE));! X! G$ y! \) e$ n5 l2 |; l3 I

# F' S7 t! P. F: a- A1 R
0 E  J+ @2 k- G0 z6 C                mxl.cbStruct = sizeof(MIXERLINE); // 微软用此办法判断版本: @- j+ F8 J& g
                // 指出需要获取的通道,声卡的音频输出用MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
5 k4 Z9 M6 C1 X                mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;5 \- [8 R9 @; D, U' @7 l% K( E3 Z
1 ?1 m- v& a2 n4 u) k! f
8 Y; \8 C( @5 c$ M. y! O
                // 取得混合器设备的指定线路信息. r' z8 ]$ _3 d; L/ M
                rc = mixerGetLineInfo((HMIXEROBJ)hMixer,
  T, W: H  ~8 U                        &mxl,# N, U% I5 k2 R; n$ @: ]
                        // 取得MIXERLINE::dwComponentType指定类型的第一个音频线路信息
# j5 H, m6 Q, ~) M& Y                        MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_COMPONENTTYPE);. Q! n) u  I: v; l, a
                if( rc!=MMSYSERR_NOERROR )" T: R1 ?# u& }1 X, V
                {
3 D2 U. W8 J$ X$ T$ r                        //无法获取声音输入线路,尝试其他声卡
# i: D9 i" {' V, E' I                        continue;
  r  o5 M  F- L2 m                }
6 I% I& K' Y* K- e
4 b9 e5 {/ z% D7 W
6 `( ?; u! W! l5 J                // 取得混合器设备的指定线路信息成功的话,则  f; \. H" D& V: C+ Q3 r

+ y6 d$ z* ]! [: S' N9 f2 Q8 S/ F7 o% C  D4 t
                // 将连接数保存
- b+ K& j6 [$ n7 S" h3 d                DWORD   dwConnections   =   mxl.cConnections; $ I9 n4 {; [+ L. n: G4 \
                // 准备获取麦克风设备的ID
8 _+ \0 F) [! k3 @                DWORD   dwLineID = -1;
. q  z# I! J8 v                for( DWORD i=0 ; i<dwConnections; i++ )4 m2 }, H. c7 M! f
                {
3 m+ g/ }% u4 l                        // 枚举每一个设备,当Source的ID等于当前的迭代记数
" c- t2 Y" C2 _2 v% o; F9 C                        mxl.dwSource = i;
; M  f; f1 E) r( S. v% b5 Y, |                        // 根据SourceID获得连接的信息 ( }+ |, L' v- B* w! J6 |, H+ K8 X8 a. \
                        rc = mixerGetLineInfo(   (HMIXEROBJ)hMixer,   &mxl, " d# O' u' A6 y  ~
                                MIXER_OBJECTF_HMIXER   |   MIXER_GETLINEINFOF_SOURCE   );
& u& s# }; P5 ~' t                        // 判断函数执行错误 * b/ u' S; v+ H
                        if( MMSYSERR_NOERROR==rc ), q6 m: f" v. r% ?0 P# w6 g4 ?$ `
                        { , c% {- A5 T( o
                                // 如果当前设备类型是麦克风,则跳出循环。
) i# v! Z7 k' e                                if( mxl.dwComponentType==MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE ). k7 r+ E4 t" g& M2 m7 ]2 z7 e
                                { 8 H4 _- a3 q4 N+ ?
                                        dwLineID = mxl.dwLineID; " b' ~. ?" b0 D, Y7 B# D  u* l- \
                                        break; 6 G5 p  G! m/ @8 j  Q0 A6 {
                                }2 ^2 [- [1 h3 R) P, I
                        }/ K9 M3 T1 @- W" I' n. V
                }1 h- J5 ]$ |0 L' L8 F  Z1 x$ t
                // 如果没有找到,返回失败。 6 b8 z7 _8 W& q
                if( dwLineID==-1 )
  G5 {" o0 y  ]$ k" J                { 8 Z6 b  \5 K$ Z8 @: S7 G$ ]- a
                        //尝试其他声卡
3 o1 h% ]4 W; v1 ]                        continue;, b; f9 K. A; U6 g0 f
                }
. b  V; f$ H% q6 N. S
2 v# f6 Y. m- e$ y2 O' y2 @( y& ]' P2 k' y& g1 j
                // MIXERCONTROL 结构体变量清零
% i5 m. \. x! I                ZeroMemory(&mxc, sizeof(MIXERCONTROL));  z/ ~: Y$ K2 e: J% v* ?
6 I1 s! L$ q4 U# ?
' k8 l: r5 l# D. Q9 L4 i: L' U
                mxc.cbStruct = sizeof(mxc); // 微软用此办法判断版本
6 ]* X* K3 C# W( C3 _: O/ H: X
8 g+ V, J+ ~9 w/ T$ E$ n* s1 O$ F3 `0 f, A2 e2 v( s
                // MIXERLINECONTROLS 结构体变量清零
& `1 }' L/ V4 v) y+ L/ D                ZeroMemory(&mxlc, sizeof(MIXERLINECONTROLS));
# z7 L, s# C4 p$ _
# v- Z5 e( _- o! s6 z" D# {+ `  a0 d
                mxlc.cbStruct = sizeof(mxlc); // 微软用此办法判断版本1 S$ Q4 d  k  b& E0 I' d4 _
+ F( t4 ]! K0 f/ s# B9 j9 {5 O
0 u3 v2 T$ E, X- V1 a
                mxlc.dwLineID = dwLineID; // 上面取得的声卡音频输入线路标识- S0 A; B/ F2 N1 ~! M  ]
                // 控制类型为控制音量
4 ^. R/ \6 L+ U                mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
5 m% Y3 |+ F. }8 {& Q% m; m/ ~, ]% `                mxlc.cControls = 1;          // 使用 MIXERCONTROL 结构体变量个数
1 X8 h" L, B4 v                mxlc.pamxctrl = &mxc;        // MIXERCONTROL 结构体变量指针
8 \5 p+ q* Y& W3 t* M1 E, ^                mxlc.cbmxctrl = sizeof(mxc); // MIXERCONTROL 结构体变量字节大小& j- K( \9 N) U' l  p+ Q
# E: I# [" {; d- [

) K$ b# v3 F5 r' O                // 取得控制器信息/ K  z) I& X1 @6 l/ y2 y) {
                rc = mixerGetLineControls((HMIXEROBJ)hMixer,
* a! R  M0 e. i8 |- l                        &mxlc,
* s- R' T& I* B3 R; `8 Z% e4 H                        MIXER_GETLINECONTROLSF_ONEBYTYPE);" b* H# J3 ^8 ?
/ G: C! U& ~% V7 o, }

5 a9 |2 X8 E* C! H                // 取得控制器信息成功的话,则' g& k* }# X$ Z4 Z0 D; P8 y
                if (MMSYSERR_NOERROR == rc)1 e( @9 J5 o( x! H( k9 ]- X
                {4 q: I  |; p# q3 Z0 J1 g
                        // 获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
# G+ t# d6 r9 U, x3 ?' [                        MIXERCONTROLDETAILS        mxcd;      // 控制器的状态信息
. S/ B. [: K3 A                        MIXERCONTROLDETAILS_SIGNED volStruct; // 音量结构体变量(就一个成员量)! V$ R! @2 g3 T( f

- F8 {9 y5 F4 [4 f1 C4 E# k/ K4 d, l& m1 j" P& C% e
                        // MIXERCONTROLDETAILS 结构体变量清零2 s+ x  K( k8 O# O1 U) N+ G
                        ZeroMemory(&mxcd, sizeof(mxcd));' h, o# F. j0 X8 P! O$ X. l# l
! J$ _/ |! L: M8 x/ W9 E) B

: X( ~/ o+ `& Z                        mxcd.cbStruct = sizeof(mxcd);       // 微软用此办法判断版本0 O+ A+ k- Y) m
                        mxcd.dwControlID = mxc.dwControlID; // 上面取得的控制器标识
( U! j* s8 @- t: S/ G                        mxcd.paDetails = &volStruct;        // 音量结构体变量指针
$ Q% T8 _4 m' S5 j0 c* t                        mxcd.cbDetails = sizeof(volStruct); // 音量结构体变量字节大小
$ Z' }; q, J+ D. S4 T# y& B, T                        mxcd.cChannels = 1;                 // 取得或设置全部通道: }& f" H" @. w
% t1 y, T- {2 K. \# z
3 `- k* P9 r! i  k  R- o0 c
                        //  获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
' V2 C1 E( U* G, s* d. U8 b
4 A/ x8 o/ [/ {& a) x
, ]: ]4 o& |0 L# D  p% y1 x$ b+ z                        // 获得音量值- e- `8 j8 J  Y4 Q
                        rc = mixerGetControlDetails((HMIXEROBJ)hMixer,# N* P$ \9 E" a$ Z6 F1 @
                                &mxcd,# P* Z* M* l, S7 F2 t
                                MIXER_GETCONTROLDETAILSF_VALUE);
8 }' Z: C  d8 V0 }. Y7 b
8 ?3 P7 r& j1 I; _/ `& C7 B# H& k* Q0 _9 g; u
                        if (MMSYSERR_NOERROR == rc)
9 t6 w! q( s$ G  [                        {% L8 g3 H. ~% ?9 u# N" r
                                long step = ( mxc.Bounds.lMaximum - mxc.Bounds.lMinimum ) /100;; [0 t* a* Z9 @# p  u7 `" n8 b6 S% M
6 l2 t2 c7 l. u$ c
  \& u! L% B% q: z
                                int index = ( volStruct.lValue - mxc.Bounds.lMinimum) /step ;" |9 g: r# L8 b: t0 I+ g
                                printf("音量:%X", volStruct.lValue);; n6 N3 D" _+ p- e9 b/ R' ~
                                return index;
* o1 E) d. B% Q: Y' ~# ]4 ?                        }
; I; ~4 H7 f+ S3 E% Q                }
- d; r2 p- J  t        }
' w; {( y% m" R, o4 e7 n* Z5 g6 x. O7 N! @$ L
& ~% r* J( u* j5 a
        return -1;% B5 S! w7 f: O: Y
}
& P$ w, e( m7 o- n1 \, w
7 z; ~7 ?- [& x9 [        相关网址:http://topic.csdn.net/t/20050606/10/4062001.html1 d) K6 |7 \) E/ Q8 {( v! k# k' \% l
                        http://blog.csdn.net/tangaowen/archive/2010/07/28/5771149.aspx
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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