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

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

[复制链接]
发表于 2011-5-7 21:31:51 | 显示全部楼层 |阅读模式
原文:http://sunerok.blog.163.com/blog/static/231096422010112815525949/
) G8 }' Z: K5 j; q5 c/ n) t3 V0 @! v& n1 h8 |1 X9 @6 w: d
参考了网上很多资料,也碰到了许多问题,终于解决了,很开心,把代码贴在这里分享一下:% f) D8 O2 Y$ h
5 B) e7 O2 ]8 @
( f( x+ N6 @8 Y) P" E7 g" @
int DeviceManager::getAudioInputVolumn( const std::string &deviceName )' K/ W% _. Z# ]0 o
{
1 d; z: z1 T. c  Z& b- c
( O2 ~# C: g8 d, e" s: T4 t  u) X
; Q# c4 S( G/ d8 }0 H" A% v. w, c        MMRESULT          rc;     // 多媒体函数返回结果变量; v* S% `# N4 t% e3 M- B' n
        HMIXER            hMixer; // 混合器设备句柄' j( ?1 S5 q& C% _3 h, B0 J- y
        MIXERLINE         mxl;    // 音频线路标准状态信息结构体
  u- ~3 f! F5 v" ?/ \# f: I# H        MIXERLINECONTROLS mxlc;   // 音频线路控制器集合信息结构体
4 g  Y% L6 E* u% m- M: y        MIXERCONTROL      mxc;    // 单个音频线路控制器信息结构体
& I) s: h% k4 n" c4 Q; s
; @/ M$ F3 s# x, f  H( @' m9 i3 w) P" i
        //枚举所有声卡驱动,这个枚举很重要。很多代码调用mixOpen时只是用了第一个设备,即
1 z$ @. d) B/ ~( ]* N        //mixerOpen(&hMixer, 0 , 0 ,0 ),但是我在这个设备下调用mixerGetLineInfo出问题了,5 k9 z* ]; b3 \& v7 p4 F# i0 L! A
       //可能还是跟声卡驱动有关。! [# l6 x1 O! d5 {
        for( int deviceID =0 ; true ; deviceID++ )
: s2 i) [4 |' E( U( `9 x        {, g0 I1 n  \% W
                // 打开混合器设备% [; Q8 j6 G4 j
                rc = mixerOpen(&hMixer, // 返回的设备句柄  O6 b5 Q+ x( z$ l7 B, Q
                        deviceID,       // 单声卡的设备ID为零- ~$ U' f9 r. _
                        0,       // 不使用回调机制
; F% Q$ B) _- q4 C+ C7 d* g                        0,       // 回调函数参数
- e5 ^. Z6 t7 `9 d' v                        MIXER_OBJECTF_MIXER);      // MIXER_OBJECTF_MIXER宏的值,表示任选有效设备ID
+ V* J; n/ k/ m4 z; j8 C, r5 m                if( MMSYSERR_NOERROR!=rc )
9 u! T& s, r% Y) M, B' G                {" a" A. B$ p# P) R  E6 a$ `
                        //跳出循环
1 s9 n$ p2 {' H$ G8 D9 i                        break;
% c1 R( a- c+ ]* Q                }' W3 G; s# l  ^  y3 f" s
                // 打开混合器设备无错的话,则
  n) W, s! Y" V$ ?& H7 t) w, M' o/ K' u  D5 \9 m! t* I

% e& j, H% J3 \% Z                // MIXERLINE 结构体变量清零
6 C8 l. {+ S$ D0 _4 ^9 ]: f                ZeroMemory(&mxl, sizeof(MIXERLINE));5 r% A4 [+ d- _5 \' x6 d- T2 ?2 r

/ [' i8 Q, _8 v* u7 l% t7 E% u  R' I& ^, ?
                mxl.cbStruct = sizeof(MIXERLINE); // 微软用此办法判断版本- p  Y2 }6 m) y
                // 指出需要获取的通道,声卡的音频输出用MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
! u! O8 Q& u: U                mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;! z" X* u/ E; A& E
3 L6 x: f5 m7 n7 Q5 J1 m) G# a

5 b( G. ]1 \! M% u( B+ S: F2 h                // 取得混合器设备的指定线路信息
* h$ n3 M$ c/ @                rc = mixerGetLineInfo((HMIXEROBJ)hMixer,' U' o% H0 ~& e5 R9 P" ^' a
                        &mxl,
' S: A6 N9 y( J+ {; Z                        // 取得MIXERLINE::dwComponentType指定类型的第一个音频线路信息
3 a% D, L, y9 R5 U                        MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_COMPONENTTYPE);
8 O# p9 h1 I  e! d9 r' G( K" I                if( rc!=MMSYSERR_NOERROR )
4 N! X: O- _' ?; Y                {
5 Z# d) H% D$ j                        //无法获取声音输入线路,尝试其他声卡
" y/ I8 r! N5 M4 {! _2 P  t                        continue;
4 ?$ l/ t2 y; f5 j3 [                }! J" i; c2 M9 p. B( {4 g0 U/ b2 G

# j' w: R5 `0 }& _! D, i" Y& {. M$ `, K  i" O( q
                // 取得混合器设备的指定线路信息成功的话,则
+ }6 L6 P0 P% R$ h+ E$ r, X- c$ z8 B3 {  [4 U
! e3 a$ `7 z% Z  c8 C& G
                // 将连接数保存 1 A8 g  [: J; ?
                DWORD   dwConnections   =   mxl.cConnections; 5 }- l+ h  D2 _* }, e& O0 j
                // 准备获取麦克风设备的ID
& ?, ]5 s4 S1 G' @! s' N                DWORD   dwLineID = -1;
& b6 K" J; j9 e  c7 u9 E                for( DWORD i=0 ; i<dwConnections; i++ )2 ^0 [* n* c& h! x2 g  A
                {
1 P. b( ^' t* Q* k  B& N  [                        // 枚举每一个设备,当Source的ID等于当前的迭代记数
: f8 M, a5 U: B8 ?- x/ j                        mxl.dwSource = i;+ R2 L- e  b& _1 e# h
                        // 根据SourceID获得连接的信息 ) p: w' ^+ W  h  }
                        rc = mixerGetLineInfo(   (HMIXEROBJ)hMixer,   &mxl,
+ g- z' B7 b: B: J! N                                MIXER_OBJECTF_HMIXER   |   MIXER_GETLINEINFOF_SOURCE   ); 7 Q* L1 ^9 B: \  ~
                        // 判断函数执行错误
/ w0 r* X" o" p( W% K3 i6 U6 e                        if( MMSYSERR_NOERROR==rc )9 E# _! f! e, h8 I( B4 {- n
                        { ! E/ n5 B" P2 W5 g0 Q8 y2 F) x0 e) H4 s
                                // 如果当前设备类型是麦克风,则跳出循环。 + t3 {+ C! {2 W/ L, r$ S7 W
                                if( mxl.dwComponentType==MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE )! K+ f2 w8 |9 e/ j2 ~3 G' Y
                                {
; y$ {& p  S. }/ x                                        dwLineID = mxl.dwLineID; & k: U3 g" a' k3 q8 H+ l- Q
                                        break; 3 r' H% b% s9 |5 F" S
                                }
1 ^; k1 e' H2 s% v" y                        }/ R/ h( ~( }# ?" Q
                }
- [$ H4 W5 E5 Y& q5 E3 `; h8 b. o& R9 b                // 如果没有找到,返回失败。
5 C3 T* Z# P: u$ z                if( dwLineID==-1 )
, G* x* w: o% d4 o' f                {
4 W. E) r* I. b  u3 V8 v                        //尝试其他声卡
  N4 {  i: _* M( t                        continue;
% a  P/ ~5 Z3 r' ]+ |% N6 J7 Y                }
3 H- B! h$ W, I& B6 n
6 n1 O+ _! f; q, ~. s) O1 F4 [! B' [$ ?# r* x
                // MIXERCONTROL 结构体变量清零4 B  N& S& w" Y
                ZeroMemory(&mxc, sizeof(MIXERCONTROL));) F. c' G1 V& I2 @$ [
6 M$ \- ]/ |4 G3 i& n+ ^

8 I! P5 I+ [9 O% }1 n3 f                mxc.cbStruct = sizeof(mxc); // 微软用此办法判断版本
0 s; B4 P* _, [. l
$ Z4 }6 l5 ^1 E$ f6 X' W/ s8 a* N( L' ~7 Z
                // MIXERLINECONTROLS 结构体变量清零
) i8 Q  s! h8 D2 S1 c  u  M                ZeroMemory(&mxlc, sizeof(MIXERLINECONTROLS));
3 _" x2 }8 Q# {, _+ m% |$ x6 }
0 Y+ y" h) x6 J* b- Q9 i% b% S6 i
                mxlc.cbStruct = sizeof(mxlc); // 微软用此办法判断版本
' R8 z) `. }. n: i9 V) s, e8 g! c& C/ |3 P. [/ v( e

3 [  S1 c2 e. D% }3 H                mxlc.dwLineID = dwLineID; // 上面取得的声卡音频输入线路标识
, V' |( _. f9 D" g, m( O9 `                // 控制类型为控制音量
% r3 y; ~% ^3 W$ ~! j, A                mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
# O3 w, V6 G# k6 p2 ]                mxlc.cControls = 1;          // 使用 MIXERCONTROL 结构体变量个数
/ ^# `# R& S* y5 ]( Y" z  z                mxlc.pamxctrl = &mxc;        // MIXERCONTROL 结构体变量指针0 I- d# k* l% Y% Z! `7 h9 q" B
                mxlc.cbmxctrl = sizeof(mxc); // MIXERCONTROL 结构体变量字节大小0 x5 Y2 B  J# y* n$ ], k
# V3 C9 T" L4 c0 L  A# j

6 B, W* M. D, N* R# P3 V% Y                // 取得控制器信息
7 X0 G! c  X! ?- W. B                rc = mixerGetLineControls((HMIXEROBJ)hMixer,' @6 k$ t" }4 Q" I
                        &mxlc,% B, K! I, _& O$ U0 f" `, n3 I
                        MIXER_GETLINECONTROLSF_ONEBYTYPE);
1 r. ^4 O7 r5 x0 Y; L/ D! G# _' K! M+ z$ P# d8 \+ K% R
2 \* ^: y' c" K
                // 取得控制器信息成功的话,则
2 a$ b# C/ F; }3 N& ]9 r                if (MMSYSERR_NOERROR == rc)
( L; I( W, [5 c' R, \                {" y6 p5 v3 @# i" h
                        // 获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum., D1 p- j; r' d6 a
                        MIXERCONTROLDETAILS        mxcd;      // 控制器的状态信息
4 [2 H$ [3 \# e) `; A" I# l                        MIXERCONTROLDETAILS_SIGNED volStruct; // 音量结构体变量(就一个成员量)
) c! i% F/ I  }3 o4 z' F+ w. K* j) l5 e3 ?

- @0 E$ a+ [% M                        // MIXERCONTROLDETAILS 结构体变量清零  Y& D: g6 a3 z( m
                        ZeroMemory(&mxcd, sizeof(mxcd));* D7 }% X' [/ \) V6 b' e
3 u9 k' \1 N/ m: O# E4 X

& C; @" p4 g) H" W                        mxcd.cbStruct = sizeof(mxcd);       // 微软用此办法判断版本
; }& J$ z5 S* l7 Y7 j                        mxcd.dwControlID = mxc.dwControlID; // 上面取得的控制器标识2 m4 \3 w2 X; s) @5 Z
                        mxcd.paDetails = &volStruct;        // 音量结构体变量指针0 A3 m: G" f. Q) D  k
                        mxcd.cbDetails = sizeof(volStruct); // 音量结构体变量字节大小: u, V, q* ^7 `: c4 u
                        mxcd.cChannels = 1;                 // 取得或设置全部通道
# B. ?9 E( \$ [- e2 d! F6 B( z* w' o

3 Z: k+ l. f+ K9 D: z- Q* C5 z                        //  获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
; F  l( C8 o$ j* Y! r0 y( z- a+ f7 ?9 A9 M! d6 G& k
5 Z, O' i" U7 e  l! z5 e% p6 d
                        // 获得音量值- c0 E: E* x) G7 H4 B0 d
                        rc = mixerGetControlDetails((HMIXEROBJ)hMixer,
' H+ `, ]! ]3 \$ u( _0 |" o9 r                                &mxcd,
" s# E" u/ I- s0 M) ^+ `  H  K                                MIXER_GETCONTROLDETAILSF_VALUE);: W% r  F% N8 K  O, p& u
2 M0 f8 x* z( V2 h* c0 K! S

/ e4 z/ E; j' V) _  z                        if (MMSYSERR_NOERROR == rc)4 F, x/ w  C- ^& k" y" ], j1 ]$ l
                        {
) @  p4 n, F9 v% X$ }                                long step = ( mxc.Bounds.lMaximum - mxc.Bounds.lMinimum ) /100;
, I6 p( [1 I0 B
* r* h) T8 u! d& G4 J8 u, ?* {. i
8 o8 L2 m. U  Z' x9 L, }) }& h                                int index = ( volStruct.lValue - mxc.Bounds.lMinimum) /step ;
) J2 p/ R+ E; K; J9 h8 S* l' [                                printf("音量:%X", volStruct.lValue);
+ v$ L2 W* ?, q' Q) q6 A9 I                                return index;/ l9 j0 b% _. J0 B! Q1 Z9 @. I
                        }
" P% ^' @+ w; F6 D% J5 \2 P                }1 T1 Q+ w5 P( ^% E& _/ K7 X. a
        }
; A% `* _1 j. T1 Y& V2 j$ @6 Q3 Y1 i  ^1 i
1 X2 @, ~0 o2 |: G2 s
        return -1;
# u" x6 N) W; D- I4 W}
& d2 r7 B1 A& C$ P# b
4 a" l4 Q. b) Y! Q        相关网址:http://topic.csdn.net/t/20050606/10/4062001.html
9 u- j7 \$ d( \; V% N                        http://blog.csdn.net/tangaowen/archive/2010/07/28/5771149.aspx
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-2 08:59 , Processed in 0.016677 second(s), 14 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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