S.F. Page

Programming,Music,etc...

Metro Apps はWASAPI排他モードをサポートしないようだ

昨日今日と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?.

サポートしてないんだろうな。おそらく。

共有モードだとサンプルレートとかビット数がアプリ側で固定できないんだよね。設定値に応じて変換コードを入れるか、エラーでユーザーに変更を促すか、どちらかの対応が必要だ。