初期化処理にサンプルレート変換を組み込んでみた。
// WASAPIの初期化処理
// IMMDeviceEnumeratorの取得
THROW_IF_ERR(
CoCreateInstance(
__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&device_enumerator_)));
// デフォルトのオーディオデバイスを取得する
THROW_IF_ERR(
device_enumerator_
->GetDefaultAudioEndpoint(eRender,eMultimedia,&current_device_)
);
// オーディオクライアントを取得
THROW_IF_ERR(
current_device_
->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER,
NULL, reinterpret_cast<void **>(&audio_client_))
);
// 代替フォーマット定義
sf::co_task_memory<WAVEFORMATEX> alt_format;
// 読みこもうとしているWAVファイルのフォーマットをサポートしているか?
HRESULT hr = audio_client_->IsFormatSupported(
AUDCLNT_SHAREMODE_SHARED ,&wfx.Format,&alt_format);
bool sample_rate_convert = false;
float sample_rate_backup = 0.0f;
if(hr != S_OK) // S_FALSEならそのフォーマットをサポートしていないらしい..
{
// サンプルレートのコンバート
if(alt_format->nSamplesPerSec != wfx.Format.nSamplesPerSec)
{
// 本来のサンプルレートをバックアップする
sample_rate_backup = wfx.Format.nSamplesPerSec;
// 代替フォーマットのサンプルレートをセットする
wfx.Format.nSamplesPerSec = alt_format->nSamplesPerSec;
// 再計算する
wfx.Format.nAvgBytesPerSec = alt_format->nSamplesPerSec * wfx.Format.nBlockAlign;
// もう一回チェックする。
// サンプルレート以外でサポートしていない点があれば例外が発生する。
THROW_IF_ERR(audio_client_->IsFormatSupported(
AUDCLNT_SHAREMODE_SHARED ,&wfx.Format,&alt_format));
// フラグをセットする
sample_rate_convert = true;
} else {
// サンプルレート以外であれば例外を出す。
throw win32_error_exception(hr);
}
}
// 再生クライアントの初期化
REFERENCE_TIME buffer_period = latency_ms_ /* ms */ * 10000 ;
REFERENCE_TIME buffer_duration = buffer_period * periods_per_buffer_;
THROW_IF_ERR(audio_client_->Initialize(AUDCLNT_SHAREMODE_SHARED ,
AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_STREAMFLAGS_RATEADJUST,
buffer_duration,
buffer_period,
&(wfx.Format),
NULL));
// バッファサイズの取得
THROW_IF_ERR(audio_client_->GetBufferSize(&buffer_size_));
// 再生クライアントの取得
THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_render_client_)));
// サンプルレートコンバータ
if(sample_rate_convert)
{
THROW_IF_ERR(audio_client_->GetService(IID_PPV_ARGS(&audio_clock_adjustment_)));
// 本来のサンプルレートをセットする
audio_clock_adjustment_->SetSampleRate(sample_rate_backup);
}
audio clientをAUDCLNT_STREAMFLAGS_RATEADJUSTフラグをつけて初期化し、GetService()でIAudioClockAdjustmentインターフェースを取得し、SetSampleRate()で変換したいサンプルレートをセットするのである。これでサンプルレートを変換することができる。でも性能は良くないらしい。
コードは上記のように適当だ。モノラルのサポートなどはまだだったりする。