
音量设定
最近一段时间在更改音量需求差异的之后,让我对在WINCE下对诸多音量的设定有了一定的理解,现在将我的理解提到blog上,让各位指教。
首先我们来看下,这些声音设定都在注册表:HKEY_CURRENT_USER\ControlPanel\Volume下,里面的几个键值都是控制声音的。先解释如下:
Volume: 系统的主音量,范围是0x0 ~ 0xFFFFFFFF.
Screen: 屏幕敲击声. 当数值为0(或65536)无声,1为柔和,65538为清亮
Key: 键盘敲打声,数值的含义和Screen相同.
Mute: 控制其它静音的选项. 置0x04位为1时允许事件声音,0x02允许应用程序声音,0x01允许警告声.需要留意的是,如果不禁止应用程序声音,则告诫声位也将被忽视.
知道各个键值的含义后,我从最主要的平台的主音量Volume说起。
一、对平台主音量Volume的操作
首先我们来看一段最简单的改变音量的代码:
DWORDdwVolume=0xAAAAAAAA;
waveOutSetVolume(0,dwVolume);
waveOutSetVolume()的第一个参数是设施ID,因为还要修改的是整个平台音量,所以在这里直接取0值就能;第二个参数是还要设定的亮度数值,范围是从 0x0 ~ 0xFFFFFFFF。
通过waveOutSetVolume()这个API,我们可以很容易的修改平台设备的音量,但这个之后,如果你去查看注册表的Volume的字段是没有变化的,因为它只更改了设备的音量,变化还没有这么快到达注册表。但你可以到“控制面板”中的“音量与声音”打开一下,注册表的值也随之改变。(反之,通过对注册表的单独操作对详细音量是起不到作用的)
所以,我对音量的操作,首先对注册表中的Volume进行操作,在用waveOutSetVolume()这个API具体改变音量,这样可以超过一致。具体操作代码如下:
DWORD dwVolume = 0;
CReg* pVolumeReg = NULL;
pVolumeReg = new CReg( HKEY_CURRENT_USER, TEXT("ControlPanel\\Volume") );
dwVolume = pVolumeReg->ValueDW(TEXT("Volume"));
。。。。。。。。。。。。。。对音量的具体设置
if( waveOutSetVolume(NULL, dwVolume) != MMSYSERR_NOERROR ) 音量设定是否成功
{
DBGMSG(ZONE_1, (TEXT("waveOutSetVolume failed, [MainLayere.cpp, SetVolume]")));
}
pVolumeReg->SetDW(TEXT("Volume"),dwVolume);设置注册表
delete pVolumeReg;
pVolumeReg = NULL;
上面用到的CReg是一个对注册表操作的类,是我们小组用的一个基类(Walzer注:在WINCE500目录下搜索CReg可以找到, 其实微软的人也很懒)。这样我们对主音量设定就很完善了。
二、对软件按钮声音(KEY键值)的设定
尽管waveOutSetVolume()这个API对主亮度设定很好用,但这个变量的用途却也有比较有限的,也就是说,它没法取消平台的主亮度;如果想更改软件按钮声音或键盘敲打声,则就无能为力.
有些比较细致的朋友可能会从"控制面板"的"声音"入手,发现每次在控制面板调节声音,相应的"ControlPanel\Volume"下的键值数值就会更改.但如若是直接修其下的改注册表,却是无论如何都达不到相应的用途的----因为没有通知平台,注册表已经被更改.
如果应该告知系统,注册表已经设置,并请平台依据修改的数值来取消音量,则还要读取微软一个未公开的API:AudioUpdateFromRegistry().
这个API在文档中是没法搜索到,如果还要读取这个变量,可以有两种办法.
一是直接包括"pwinuser.h"文件,然后直接读取.
二是读入coredll.dll库,引出该变量并使用.
第一种方法比较不稳定,因为有一些人的sdk中没有这个pwinuser.h文件,所以程序找不到。我还是推荐用第二种方法,直接调用该API(就象我们组长说的暴力调用API,这个方式真的还是不错的。)
其具体代码如下:

typedefvoid(WINAPI*DLL_AUDIOUPDATEFROMREGISTRY)();定义一个新类别指针,指向WINAPI
DLL_AUDIOUPDATEFROMREGISTRYDll_AudioUpdateFromRegistry=NULL;
HINSTANCEhCoreDll=LoadLibrary(TEXT("coredll.dll"));
if(hCoreDll)
{
Dll_AudioUpdateFromRegistry=(DLL_AUDIOUPDATEFROMREGISTRY)GetProcAddress(hCll,_T("AudioUpdateFromRegistry"));调用该API
if(Dll_AudioUpdateFromRegistry)
{
(Dll_AudioUpdateFromRegistry)();
}
else
{
returnFALSE;
}
FreeLibrary(hCoreDll);
}
else
{
returnFALSE;
}
returnTRUE;
这样借助设置注册表Key键值wince6.0 音乐播放器,然后通过读取该办法能够实现对按钮声音的设定。
对Screen和Mute的设定也可以用该办法,至此,对WINCE各种音量的设定就基本掌握了。三、MP3音量设置
Volume : -1000…….0 Balance : -1000……..1000
IBasicAudio *m_pBA;
BOOL CItsMp3Play::SetVolume(LONG lVolume, LONG lBalance) //mp3音量设置,非系统音量
if(m_pBA == NULL)
return FALSE;
if(lVolume<MIN_VOLUME&&lVolume>MAX_VOLUME&&lBalance<MIN_BALANCE&&lBalance>MAX_BALANCE)
{
return FALSE;
}
m_pBA->put_Volume(lVolume);
m_pBA->put_Balance(lBalance);
return TRUE;
四.解决wince420不能设置左右声道音量的弊端
在wince420中不能使用WaveOutSetVolume分别设定左右声道音量,这是因为在wince底层的wav解码上面只使用了参数的低16位,并没有将高低位分开来设定左右声道增益。因此我追踪调试进入底层,找出设定系统音量的变量!
还有一点是还要表明的,在好多应用中使用的声音芯片都是低成本的,一般不支持左右声道噪音调节功能,因此我们只有在wav播放中设定左右声道数据的增益,从而超过左右声道音量分别控制的效果。
默认系统是一个双声道系统。
首先看一下PLATFORM\SMDK2410\DRIVERS\WAVEDEV\Output.cpp文件:
WaveStreamContext::Render之后的数据就是直接发送到内部声音芯片的数据,他依据参数以及标志位选择OutputStreamContextXXX::Render2,XXX表示双声道S单声道M,bit位是8位还是16位。
以双声道OutputStreamContextS16::Render2为例,我的BSP里面的代码如下:
PBYTE OutputStreamContextS16::Render2(PBYTE pBuffer, PBYTE pBufferEnd, PBYTE pBufferLast)
LONG CurrT = m_CurrT;
LONG DeltaT = m_DeltaT;
LONG CurrSamp0 = m_CurrSamp[0];
LONG CurrSamp1 = m_CurrSamp[1];
LONG PrevSamp0 = m_PrevSamp[0];
LONG PrevSamp1 = m_PrevSamp[1];
PBYTE pCurrData = m_lpCurrData;
PBYTE pCurrDataEnd = m_lpCurrDataEnd;
LONG fxpGain = m_fxpGain;//修改之后,表示两个声道,原文件中只有一个
LONG fxpGain1 = m_fxpGain1;
LONG OutSamp0;
LONG OutSamp1;
while (pBuffer < pBufferEnd)
{
while (CurrT >= 0x10000)
{
if (pCurrData>=pCurrDataEnd)
{
goto Exit;
}
CurrT -= 0x10000;
PrevSamp0 = CurrSamp0;
PrevSamp1 = CurrSamp1;
PPCM_SAMPLE pSampleSrc = (PPCM_SAMPLE)pCurrData;
CurrSamp0 = (LONG)pSampleSrc->s16.sample_left;
CurrSamp1 = (LONG)pSampleSrc->s16.sample_right;
pCurrData+=4;
}
//在这个地方将左右声道数据增益分别设定,这样输出的数据音量增益就会不同,当然我们嘴巴听的声响大小就不一样了
OutSamp0 = PrevSamp0 + (((CurrSamp0 - PrevSamp0) * CurrT) >> 16);
OutSamp0 = (OutSamp0 * fxpGain) >> VOLSHIFT;

OutSamp1 = PrevSamp1 + (((CurrSamp1 - PrevSamp1) * CurrT) >> 16);
OutSamp1 = (OutSamp1 * fxpGain1) >> VOLSHIFT;
CurrT += DeltaT;
if (pBuffer < pBufferLast)
{
OutSamp0 += ((HWSAMPLE *)pBuffer)[0];
OutSamp1 += ((HWSAMPLE *)pBuffer)[1];
#if USE_MIX_SATURATE
// Handle saturation
if (OutSamp0>AUDIO_SAMPLE_MAX)
{
OutSamp0=AUDIO_SAMPLE_MAX;
}
else if (OutSamp0<AUDIO_SAMPLE_MIN)
{
OutSamp0=AUDIO_SAMPLE_MIN;
}
if (OutSamp1>AUDIO_SAMPLE_MAX)
{
OutSamp1=AUDIO_SAMPLE_MAX;
}
else if (OutSamp1<AUDIO_SAMPLE_MIN)
{
OutSamp1=AUDIO_SAMPLE_MIN;
}
#endif
}
((HWSAMPLE *)pBuffer)[0] = (HWSAMPLE)OutSamp0;
((HWSAMPLE *)pBuffer)[1] = (HWSAMPLE)OutSamp1;
pBuffer += 2*sizeof(HWSAMPLE);
}
Exit:
m_dwByteCount += (pCurrData - m_lpCurrData);
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/bofangqi/article-120036-1.html
减少人员及财产损失
他家的女人对公众开放了