2011年02月08日

WAVE再生時の音量調節



WAVE再生時の音量調節については、WAVE出力関数waveOutSetVolume関数がありますが、この関数を使うとシステム全体のボリューム調節をすることにもなり、ウィンドウズビスタ以降OSとも相性が良くないようです。そこで今回は読み込んだ音源データを直接加工して音量調節する方法を解説します。




CWaveOut::ReadSampleData関数において、CWaveOut::StreamIn関数で派生クラスから音源データを取得した後、DoVolume関数を呼び出して音量を調節します。

//音量調節
//pBuffer:音源データが格納されているバッファ
//nBufSize:バッファのバイト数
//pwfx:音源データの演奏形式を格納したWAVEFORMATEX構造体

BOOL CWaveOut::DoVolume(LPVOID pBuffer,UINT nBufSize,WAVEFORMATEX* pwfx)
{
ASSERT(::AfxIsValidAddress(pBuffer,nBufSize));
ASSERT(!::IsBadReadPtr(pwfx,sizeof(WAVEFORMATEX)));

//音量が左右とも最大なら、何もせずに終了します。
if (m_dwVolume==0xFFFFFFFF) return TRUE;

//左音量を取得します。
DWORD dwVolL=LOWORD(m_dwVolume);
//右音量を取得します。
DWORD dwVolR=HIWORD(m_dwVolume);
//サンプル数を算出します。
int nSamples=nBufSize/pwfx->nBlockAlign;

//演奏するサンプルあたりのバイト数で個別処理します。
switch(pwfx->nBlockAlign){
case 1://1バイト(8ビット音源)の場合。
//音量が最大ではない場合。

if (dwVolL<0xFFFF) {
//音源バッファへのポインタを取得します。
PBYTE src=(PBYTE)pBuffer;
PBYTE dst=src;
for(int i=0;i<nSamples;i++){
BYTE b=*src++;
//音量を掛けて出力音源を算出します。
*dst++=(BYTE)(b*dwVolL/0xFFFF);
}
}
break;

case 2://2バイトの場合。
//16ビットモノラルの場合。

if (pwfx->nChannels==1){
//音量が最大ではない場合。
if (dwVolL<0xFFFF){
//音源バッファへのポインタを取得します。
WORD* src=(WORD*)pBuffer;
WORD* dst=src;
for(int i=0;i<nSamples;i++){
DWORD dw=(DWORD)*src++;
//音量を掛けて出力音源を算出します。
if (dw&0x8000) { //負数の場合
dw|=0xFFFF0000;
dw=0-abs((LONG)dw)*dwVolL/0xFFFF;
}
else dw=dw*dwVolL/0xFFFF;
*dst++=(WORD)dw;
}
}
}
//8ビットステレオの場合
else{
//音源バッファへのポインタを取得します。
PBYTE src=(PBYTE)pBuffer;
PBYTE dst=src;
for(int i=0;i<nSamples;i++){
//左音量が最大ではない場合。
if (dwVolL<0xFFFF) {
BYTE b=*src++;
//左音量を掛けて左出力音源を算出します。
*dst++=(BYTE)(b*dwVolL/0xFFFF);
}
//左音量が最大の場合は、何もせずにポインタだけ進めます。
else {
src++;
dst++;
}
//右音量が最大ではない場合。
if (dwVolR<0xFFFF) {
BYTE b=*src++;
//右音量を掛けて右出力音源を算出します。
*dst++=(BYTE)(b*dwVolR)/0xFFFF;
}
//右音量が最大の場合は、何もせずにポインタだけ進めます。
else {
src++;
dst++;
}
}
}
break;

case 4: //4バイトの場合。
//音源バッファへのポインタを取得します。

WORD* src=(WORD*)pBuffer;
WORD* dst=src;
for(int i=0;i<nSamples;i++){
//左音量が最大ではない場合。
if (dwVolL<0xFFFF) {
DWORD dw=(DWORD)*src++;
//左音量を掛けて左出力音源を算出します。
if (dw&0x8000) { //負数の場合
dw|=0xFFFF0000;
dw=0-abs((LONG)dw)*dwVolL/0xFFFF;
}
else dw=dw*dwVolL/0xFFFF;
*dst++=(WORD)dw;
}
//左音量が最大の場合は、何もせずにポインタだけ進めます。
else{
src++;
dst++;
}
//右音量が最大ではない場合。
if (dwVolR<0xFFFF) {
DWORD dw=(DWORD)*src++;
//右音量を掛けて右出力音源を算出します。
if (dw&0x8000) { //負数の場合
dw|=0xFFFF0000;
dw=0-abs((LONG)dw)*dwVolR/0xFFFF;
}
else dw=dw*dwVolR/0xFFFF;
*dst++=(WORD)dw;
}
//右音量が最大の場合は、何もせずにポインタだけ進めます。
else{
src++;
dst++;
}
}
break;
}
return TRUE;
}






posted by ひろし at 13:15| Comment(0) | WAVEファイルフォーマット | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。