昨日今日とWASAPIの初期化コードを書いていた。排他モードで音を鳴らそうと思ったのだけれど、IsFormatSupportedでエラー:AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWEDとなってしまう。共有モードでは問題ない。
void makeWaveFormat(WAVEFORMATEXTENSIBLE& format,
int sample_rate = 44100,int channels = 2,int bits_per_sample = 16,int valid_bits_per_sample = 16,
uint32_t type = WAVE_FORMAT_EXTENSIBLE,
const GUID& sub_type = KSDATAFORMAT_SUBTYPE_PCM)
{
ZeroMemory(&format,sizeof(WAVEFORMATEXTENSIBLE));
format.Format.wFormatTag = type;
format.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
format.SubFormat = sub_type;
format.Format.nSamplesPerSec = sample_rate;
format.Format.nChannels = channels;
format.Format.wBitsPerSample = bits_per_sample;
format.Format.nBlockAlign = (format.Format.wBitsPerSample / 8) * format.Format.nChannels;
format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec * format.Format.nBlockAlign;
format.Samples.wValidBitsPerSample = valid_bits_per_sample;
format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
}
SoundDriver::SoundDriver()
{
String^ deviceID = MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default);
ActivateAudioInterface(deviceID->Data(),__uuidof(IAudioClient2),&audioClient_);
WAVEFORMATEXTENSIBLE format;
makeWaveFormat(format);
sf::co_task_memory<WAVEFORMATEX> alt_format;
HRESULT hr = audioClient_->IsFormatSupported(
AUDCLNT_SHAREMODE_EXCLUSIVE,
reinterpret_cast<WAVEFORMATEX*>(&format),
reinterpret_cast<WAVEFORMATEX**>(&alt_format));
REFERENCE_TIME latency_;
audioClient_->GetStreamLatency(&latency_);
REFERENCE_TIME defaultDevicePeriod,minDevicePriod;
audioClient_->GetDevicePeriod(&defaultDevicePeriod,&minDevicePriod);
DX::ThrowIfFailed(
audioClient_->Initialize(
AUDCLNT_SHAREMODE_EXCLUSIVE,
AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
minDevicePriod,minDevicePriod,
reinterpret_cast<WAVEFORMATEX*>(&format),NULL));
DX::ThrowIfFailed(audioClient_->GetService(__uuidof(IAudioRenderClient),&audioRenderClient_));
}
なんとなくMetro Styleでは排他モードのサポートはないのではないかなとググってみると下記を発見。
IAudioClient does not support Exclusive mode in Metro Apps?.
サポートしてないんだろうな。おそらく。
共有モードだとサンプルレートとかビット数がアプリ側で固定できないんだよね。設定値に応じて変換コードを入れるか、エラーでユーザーに変更を促すか、どちらかの対応が必要だ。