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

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

[复制链接]
发表于 2011-5-7 21:31:51 | 显示全部楼层 |阅读模式
原文:http://sunerok.blog.163.com/blog/static/231096422010112815525949/1 Z; Z9 Y7 c# U0 [
. j& S2 v2 w, O8 m5 i2 u
参考了网上很多资料,也碰到了许多问题,终于解决了,很开心,把代码贴在这里分享一下:
9 D7 V: V# g1 x, Z: J! Z# C# ]- T* x# Z9 E" C
5 k9 e4 b' l5 \6 B+ ~
int DeviceManager::getAudioInputVolumn( const std::string &deviceName )6 K. Y7 V4 w8 b- I6 T
{: d  g' }# U  Y+ {3 s# |

. [  F# J# Q5 ^4 I
4 d' }4 d' I& K; }1 u& Q        MMRESULT          rc;     // 多媒体函数返回结果变量4 b7 i# t8 V' y5 e, w
        HMIXER            hMixer; // 混合器设备句柄- O3 r& _3 B8 k/ [, l( m
        MIXERLINE         mxl;    // 音频线路标准状态信息结构体, k2 f' j: M% Y
        MIXERLINECONTROLS mxlc;   // 音频线路控制器集合信息结构体
+ u/ K* D! [# {% [        MIXERCONTROL      mxc;    // 单个音频线路控制器信息结构体# U6 k# q( }: P1 `6 o; G
9 Z2 y: c! ~) L3 k0 z# v8 ]; i

8 ^" o6 a0 F3 r. h. H        //枚举所有声卡驱动,这个枚举很重要。很多代码调用mixOpen时只是用了第一个设备,即7 r9 G( u0 d+ w) D! F
        //mixerOpen(&hMixer, 0 , 0 ,0 ),但是我在这个设备下调用mixerGetLineInfo出问题了,: ~7 A, ]5 `0 G7 w: Y, }
       //可能还是跟声卡驱动有关。
( M; U' D" L* G        for( int deviceID =0 ; true ; deviceID++ ). f/ a* b! U7 ~* ~) J2 [
        {
- X, |1 A. j4 H4 ^" \7 ]                // 打开混合器设备, a4 E, C; y* M/ N9 `( N" n
                rc = mixerOpen(&hMixer, // 返回的设备句柄9 B* `$ X  ~2 ^/ }5 U5 |
                        deviceID,       // 单声卡的设备ID为零
- c7 o- J* d  x5 G* m                        0,       // 不使用回调机制
* _4 Z" A* c% r& D0 k  b                        0,       // 回调函数参数
4 d; N% I  A& Q9 b                        MIXER_OBJECTF_MIXER);      // MIXER_OBJECTF_MIXER宏的值,表示任选有效设备ID
2 ^$ e. m5 `5 W, B" M+ `' @                if( MMSYSERR_NOERROR!=rc )
2 f' R$ z$ F. U, x% m                {
! e5 a; t7 g. i% Q$ N9 \                        //跳出循环
; j- m0 j4 Z) I! i0 i  _                        break;/ M/ ]3 p1 P) S- S0 U0 E' Y" G
                }
; D" i$ @$ x$ u                // 打开混合器设备无错的话,则# {4 i$ S, t" Y  p
9 b' s! W7 p6 m
6 o% L' x7 `& G" G2 Z* ]
                // MIXERLINE 结构体变量清零( G8 h; }( v3 x* d2 U
                ZeroMemory(&mxl, sizeof(MIXERLINE));1 {1 D' J& L. U( I! e

/ X" K* ^; B& h0 H, C; u+ ?3 S9 ?) Q7 x# H* m9 j/ ]9 k
                mxl.cbStruct = sizeof(MIXERLINE); // 微软用此办法判断版本8 \- q+ G+ n+ [* G+ g
                // 指出需要获取的通道,声卡的音频输出用MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
' y# r' o- I3 c% X& ~                mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;- V8 M9 e/ z+ b# y, f: F. v

' o9 }: I4 ]; B8 w7 l& B2 [' Q/ C( O6 U' \" Y
                // 取得混合器设备的指定线路信息( [8 w5 N& A8 }5 K! {7 |7 Q
                rc = mixerGetLineInfo((HMIXEROBJ)hMixer,
$ J7 f, c/ D7 W) E2 w( f                        &mxl,- C3 d9 J* G- q  L* O' b
                        // 取得MIXERLINE::dwComponentType指定类型的第一个音频线路信息# d- h8 h5 |1 L4 H  v, G* ?
                        MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_COMPONENTTYPE);7 o& j7 F: o# u/ {3 D
                if( rc!=MMSYSERR_NOERROR )6 O: F2 o, V+ ?& \: g. U" Z
                {1 c0 U0 [% k) P) s" R
                        //无法获取声音输入线路,尝试其他声卡9 F, s4 \! j! m* [4 ]2 t; Y! j
                        continue;
$ _! l: N! U& t$ P                }# t# `1 M6 }$ W; }
1 Z! r8 X3 o4 X5 K' ]- I* V8 t) T5 E
  \  B, ~& t# R* z1 W! \% H
                // 取得混合器设备的指定线路信息成功的话,则
# Q4 I* ^" f; S( w* [- {6 i5 z- n4 J% Z
# w2 r+ a/ z3 a3 s
                // 将连接数保存 * U( R/ V3 c  Y$ F" y' }
                DWORD   dwConnections   =   mxl.cConnections; 0 U' Z0 s  H) G/ ?9 ^
                // 准备获取麦克风设备的ID 4 y$ B% U- l( Q/ s- O
                DWORD   dwLineID = -1; - q% t9 C9 A  G
                for( DWORD i=0 ; i<dwConnections; i++ )
" ?, {; Z, \: z. V, G4 k/ Y) f                { ( G9 r. `& w2 L5 r8 ?3 G5 ]6 V
                        // 枚举每一个设备,当Source的ID等于当前的迭代记数
( B9 ]' N4 w7 r5 y7 M0 u' g                        mxl.dwSource = i;
( A, Q3 n/ F% x8 G7 x' @                        // 根据SourceID获得连接的信息 : z# U, M" }+ ?- G
                        rc = mixerGetLineInfo(   (HMIXEROBJ)hMixer,   &mxl, % }' g! A' L. \9 Z( t8 v
                                MIXER_OBJECTF_HMIXER   |   MIXER_GETLINEINFOF_SOURCE   ); 6 F% a% b! Y1 _# d
                        // 判断函数执行错误
  R: p( }0 [9 }0 h                        if( MMSYSERR_NOERROR==rc )
, o( Z5 v' l& E7 q/ E0 Y8 S, r                        {
$ P! k0 @3 |  ^1 \% O* |+ ~3 b                                // 如果当前设备类型是麦克风,则跳出循环。
: _# k4 O+ _% u1 {$ _1 V! [; D                                if( mxl.dwComponentType==MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE )
0 U* l# Q8 m, H. A$ @! C8 o& I                                {
& E  _2 a. |- Q4 o, {, T( @                                        dwLineID = mxl.dwLineID;
3 b. L$ k7 ^; m) y, S                                        break; : n! o$ [# [( Q) O; G# |; L/ b
                                }
% t  _/ I0 Y, e                        }# C- {& P  U; Q/ }# Y
                }
3 J2 t2 G; g( e9 d' Y' x                // 如果没有找到,返回失败。 % Z0 g2 f$ @% B8 x7 Y* k: f
                if( dwLineID==-1 )
$ i+ m8 ^* B+ c                { . ~- p$ N1 l6 m2 x% D
                        //尝试其他声卡
* k) _- Z% @7 I2 [  W                        continue;3 Q' E! R% u. ]- p$ o* U
                }4 I6 a9 T1 G& N# E; o

# f1 C" V4 }+ g! C
. b, ^( @- ^1 `) S  H, M: X& [# ^                // MIXERCONTROL 结构体变量清零
, V* N2 w8 H/ ~" w0 u4 m                ZeroMemory(&mxc, sizeof(MIXERCONTROL));# N; ]7 o. Y6 S. A& ~  ?* X  y: `

9 W1 X+ @+ b* I3 {# J0 ?
$ F) V) K0 b" u& n; x( j3 R/ Z                mxc.cbStruct = sizeof(mxc); // 微软用此办法判断版本9 e: I9 S: M  l! ?9 z/ E, H
  V9 H  g' W* C& I, }

& H4 r* w( O, {! Y                // MIXERLINECONTROLS 结构体变量清零' g  m: x" @  t
                ZeroMemory(&mxlc, sizeof(MIXERLINECONTROLS));
& F0 \' v/ D6 ^& R! l& Y# g( O8 z9 K7 ?% [
( o! z2 t3 D( T! V
                mxlc.cbStruct = sizeof(mxlc); // 微软用此办法判断版本
1 o' P8 k1 N. Z* s0 m. U! |( w, R7 y- w3 |

$ G) q- c2 |3 Y5 ?2 H6 K                mxlc.dwLineID = dwLineID; // 上面取得的声卡音频输入线路标识- f6 G; P. H- i: ^0 K; p
                // 控制类型为控制音量
8 N2 J* B3 o/ r* B5 n                mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
0 E2 F7 \: e- l! i7 U/ {                mxlc.cControls = 1;          // 使用 MIXERCONTROL 结构体变量个数6 \5 N; a' a* I8 o8 ^7 V8 P! ~
                mxlc.pamxctrl = &mxc;        // MIXERCONTROL 结构体变量指针' F. y0 C) h" m2 M8 S( A: v2 y
                mxlc.cbmxctrl = sizeof(mxc); // MIXERCONTROL 结构体变量字节大小3 J5 K- X0 U7 [0 U2 z4 o1 w

7 o" y1 V# ?2 J4 g0 b$ g8 B
; R9 p3 X# ]. @" I                // 取得控制器信息
$ D7 s8 n% p7 M* |                rc = mixerGetLineControls((HMIXEROBJ)hMixer,
& P$ {+ J( d' I3 o! `; f% S5 A                        &mxlc,0 R) z; s$ m- _+ j  b3 v" P
                        MIXER_GETLINECONTROLSF_ONEBYTYPE);' r2 w3 Q; y3 a9 N$ P7 m- y
( j. Y/ C2 l5 ^! ^. }

+ p# n% {/ k+ O% X+ {                // 取得控制器信息成功的话,则0 m& X$ Y/ p) K. X" F, B
                if (MMSYSERR_NOERROR == rc)
0 l9 f# O1 {8 V' a2 M                {
: d1 \: T5 L( U6 d2 p                        // 获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum.
! V0 A6 h3 n7 D7 }1 H$ {0 r6 X                        MIXERCONTROLDETAILS        mxcd;      // 控制器的状态信息
2 J- G( f; M* j" [( T9 V4 |                        MIXERCONTROLDETAILS_SIGNED volStruct; // 音量结构体变量(就一个成员量)
+ S& A% C; _# ^* N( t) l8 H  c: s1 @! U0 T

$ u7 _: ?" Q) x( b& a9 o                        // MIXERCONTROLDETAILS 结构体变量清零' Q' T7 q6 R. @' K) z
                        ZeroMemory(&mxcd, sizeof(mxcd));
. g' o: X: f! [4 j8 U( o( j0 @8 D
8 g! v! K) L& U, G/ {
1 f+ D: d, i7 k+ f3 ]                        mxcd.cbStruct = sizeof(mxcd);       // 微软用此办法判断版本& k: C0 g! n8 w" z+ I) V# l( q% T
                        mxcd.dwControlID = mxc.dwControlID; // 上面取得的控制器标识8 h8 l4 u6 m1 F+ d3 B1 `3 I
                        mxcd.paDetails = &volStruct;        // 音量结构体变量指针& N) V7 A/ I. h7 J8 a8 Y* u: [3 N
                        mxcd.cbDetails = sizeof(volStruct); // 音量结构体变量字节大小
! H1 `" q6 i6 y# M                        mxcd.cChannels = 1;                 // 取得或设置全部通道
) q6 I4 z# h/ I- ^) L2 _4 n* Z' o- k0 p  f1 j; N7 f

4 c' ^0 D1 V# E" E                        //  获取控制器中的值的音量范围:mxc.Bounds.lMinimum到mxc.Bounds.lMaximum. ) W' @( g4 A$ e+ M
* B# t1 G* C4 K- v. B
7 W& m1 d, ?/ R# `( P# {
                        // 获得音量值
+ P5 a0 D3 k- q4 h                        rc = mixerGetControlDetails((HMIXEROBJ)hMixer,
- c0 ~7 p' F: h. u) e1 l  F4 j# K4 ]                                &mxcd,& z: Y8 i* V$ A
                                MIXER_GETCONTROLDETAILSF_VALUE);% i3 U9 {7 T5 B
% t) Y8 T2 p6 f& J0 w

; `2 Q+ z! V/ \/ S" H                        if (MMSYSERR_NOERROR == rc)( U5 Z  `4 q; t  @/ @1 ~
                        {  p- }* @& c( l4 V
                                long step = ( mxc.Bounds.lMaximum - mxc.Bounds.lMinimum ) /100;7 Z$ X, j9 D6 {: K! B6 D% M6 U' c

8 p. q  L$ D0 J# h1 w9 M2 A+ \: C' y  @% a! e$ L/ A# T4 Q
                                int index = ( volStruct.lValue - mxc.Bounds.lMinimum) /step ;
& @' K$ S! E, q+ U" {                                printf("音量:%X", volStruct.lValue);  l$ p& Q. B7 h0 s/ {- l1 I- U3 z
                                return index;
& I& _( k- e; a: k3 @* L: b                        }
, O- D9 C$ ^* {; f0 O0 W; R! r+ h                }
6 P4 c3 B- R' s: ]* b4 F        }
8 P$ R1 h7 Y' N4 Z/ \6 k8 z9 S6 S  h' m  T6 R
' ]/ I# j/ v% r. z; h: Q
        return -1;
% B$ N: y3 t: d% t# k}
9 Y& V8 I' L3 P8 T
  X6 k+ _9 W1 ^' B) P" D        相关网址:http://topic.csdn.net/t/20050606/10/4062001.html
" `0 L% P, V/ H9 h- w5 N& p% Z                        http://blog.csdn.net/tangaowen/archive/2010/07/28/5771149.aspx
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-11-14 23:42 , Processed in 0.019265 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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