FC2ブログ

ホーム > WAVEファイルフォーマット > WAVE再生時の音量調節

WAVE再生時の音量調節



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




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

//音源データを入力ストリームから読み込む
BOOL CWaveOut::ReadSampleData(PWAVEHDR pWaveHdr)
{
ASSERT(AfxIsValidAddress(pWaveHdr,sizeof(WAVEHDR)));

LPVOID pBuffer=pWaveHdr->lpData;
DWORD dwBufferLength=pWaveHdr->dwBufferLength;
//出力バッファをゼロクリアします。
::ZeroMemory(pBuffer,dwBufferLength);
//入力ストリーム(オーバーライド関数)から音源データを入力します。
UINT nLength=StreamIn(pBuffer,dwBufferLength);
if (!nLength) return FALSE;
DoVolume(pBuffer,nLength,&m_wfx);
return TRUE;
}


入力された音源データの音量調節をします。

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

BOOL CWaveOut::DoVolume(LPVOID pBuffer,UINT nBufSize,WAVEFORMATEX* pwfx)
{
if (!AfxIsValidAddress(pBuffer,nBufSize)) return FALSE;
if (!AfxIsValidAddress(pwfx,sizeof(WAVEFORMATEX),0)) return FALSE;

//音量が左右とも最大なら、何もせずに終了します。
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;
}



<<WAVEファイルの再生ページの先頭モノラル音源の擬似ステレオ再生>>


スポンサーサイト



コメント: 0

この記事へのコメント
ブログ著者にのみ知らせます。

Trackback+Pingback: 0

TrackBack URL for this entry
http://hiroshi0945.blog75.fc2.com/tb.php/46-8735aca0
Listed below are links to weblogs that reference
WAVE再生時の音量調節 from マルチメディアファイルフォーマット

Home > WAVEファイルフォーマット > WAVE再生時の音量調節

タグクラウド
ブロとも申請フォーム

この人とブロともになる

ブロとも一覧

このページの先頭へ戻る