This is called once a device is activated, possibly asynchronously. */
| 492 | |
| 493 | /* This is called once a device is activated, possibly asynchronously. */ |
| 494 | int |
| 495 | WASAPI_PrepDevice(_THIS, const SDL_bool updatestream) |
| 496 | { |
| 497 | /* !!! FIXME: we could request an exclusive mode stream, which is lower latency; |
| 498 | !!! it will write into the kernel's audio buffer directly instead of |
| 499 | !!! shared memory that a user-mode mixer then writes to the kernel with |
| 500 | !!! everything else. Doing this means any other sound using this device will |
| 501 | !!! stop playing, including the user's MP3 player and system notification |
| 502 | !!! sounds. You'd probably need to release the device when the app isn't in |
| 503 | !!! the foreground, to be a good citizen of the system. It's doable, but it's |
| 504 | !!! more work and causes some annoyances, and I don't know what the latency |
| 505 | !!! wins actually look like. Maybe add a hint to force exclusive mode at |
| 506 | !!! some point. To be sure, defaulting to shared mode is the right thing to |
| 507 | !!! do in any case. */ |
| 508 | const SDL_AudioSpec oldspec = this->spec; |
| 509 | const AUDCLNT_SHAREMODE sharemode = AUDCLNT_SHAREMODE_SHARED; |
| 510 | UINT32 bufsize = 0; /* this is in sample frames, not samples, not bytes. */ |
| 511 | REFERENCE_TIME duration = 0; |
| 512 | IAudioClient *client = this->hidden->client; |
| 513 | IAudioRenderClient *render = NULL; |
| 514 | IAudioCaptureClient *capture = NULL; |
| 515 | WAVEFORMATEX *waveformat = NULL; |
| 516 | SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); |
| 517 | SDL_AudioFormat wasapi_format = 0; |
| 518 | SDL_bool valid_format = SDL_FALSE; |
| 519 | HRESULT ret = S_OK; |
| 520 | DWORD streamflags = 0; |
| 521 | |
| 522 | SDL_assert(client != NULL); |
| 523 | |
| 524 | #ifdef __WINRT__ /* CreateEventEx() arrived in Vista, so we need an #ifdef for XP. */ |
| 525 | this->hidden->event = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS); |
| 526 | #else |
| 527 | this->hidden->event = CreateEventW(NULL, 0, 0, NULL); |
| 528 | #endif |
| 529 | |
| 530 | if (this->hidden->event == NULL) { |
| 531 | return WIN_SetError("WASAPI can't create an event handle"); |
| 532 | } |
| 533 | |
| 534 | ret = IAudioClient_GetMixFormat(client, &waveformat); |
| 535 | if (FAILED(ret)) { |
| 536 | return WIN_SetErrorFromHRESULT("WASAPI can't determine mix format", ret); |
| 537 | } |
| 538 | |
| 539 | SDL_assert(waveformat != NULL); |
| 540 | this->hidden->waveformat = waveformat; |
| 541 | |
| 542 | this->spec.channels = (Uint8) waveformat->nChannels; |
| 543 | |
| 544 | /* Make sure we have a valid format that we can convert to whatever WASAPI wants. */ |
| 545 | if ((waveformat->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) && (waveformat->wBitsPerSample == 32)) { |
| 546 | wasapi_format = AUDIO_F32SYS; |
| 547 | } else if ((waveformat->wFormatTag == WAVE_FORMAT_PCM) && (waveformat->wBitsPerSample == 16)) { |
| 548 | wasapi_format = AUDIO_S16SYS; |
| 549 | } else if ((waveformat->wFormatTag == WAVE_FORMAT_PCM) && (waveformat->wBitsPerSample == 32)) { |
| 550 | wasapi_format = AUDIO_S32SYS; |
| 551 | } else if (waveformat->wFormatTag == WAVE_FORMAT_EXTENSIBLE) { |
no test coverage detected