static int XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture) { HRESULT result = S_OK; WAVEFORMATEX waveformat; int valid_format = 0; SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); IXAudio2 *ixa2 = NULL; IXAudio2SourceVoice *source = NULL; UINT32 devId = 0; /* 0 == system default device. */ static IXAudio2VoiceCallbackVtbl callbacks_vtable = { VoiceCBOnVoiceProcessPassStart, VoiceCBOnVoiceProcessPassEnd, VoiceCBOnStreamEnd, VoiceCBOnBufferStart, VoiceCBOnBufferEnd, VoiceCBOnLoopEnd, VoiceCBOnVoiceError }; static IXAudio2VoiceCallback callbacks = { &callbacks_vtable }; // add WIN_CoInitialize() and WIN_CoUninitialize here; // to avoid XAudio2Create return hr 0x800401f0 ипн╢╣Всц CoInitialize; if (iscapture) { SDL_SetError("XAudio2: capture devices unsupported."); return 0; } else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) { SDL_SetError("XAudio2: XAudio2Create() failed."); return 0; } if (devname != NULL) { UINT32 devcount = 0; UINT32 i = 0; if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) { IXAudio2_Release(ixa2); SDL_SetError("XAudio2: IXAudio2_GetDeviceCount() failed."); return 0; } for (i = 0; i < devcount; i++) { XAUDIO2_DEVICE_DETAILS details; if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) { char *str = utf16_to_utf8(details.DisplayName); if (str != NULL) { const int match = (SDL_strcmp(str, devname) == 0); SDL_free(str); if (match) { devId = i; break; } } } } if (i == devcount) { IXAudio2_Release(ixa2); SDL_SetError("XAudio2: Requested device not found."); return 0; } } /* Initialize all variables that we clean on shutdown */ this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc((sizeof *this->hidden)); if (this->hidden == NULL) { IXAudio2_Release(ixa2); SDL_OutOfMemory(); return 0; } SDL_memset(this->hidden, 0, (sizeof *this->hidden)); this->hidden->ixa2 = ixa2; this->hidden->semaphore = CreateSemaphore(NULL, 1, 2, NULL); if (this->hidden->semaphore == NULL) { XAUDIO2_CloseDevice(this); SDL_SetError("XAudio2: CreateSemaphore() failed!"); return 0; } while ((!valid_format) && (test_format)) { switch (test_format) { case AUDIO_U8: case AUDIO_S16: case AUDIO_S32: case AUDIO_F32: this->spec.format = test_format; valid_format = 1; break; } test_format = SDL_NextAudioFormat(); } if (!valid_format) { XAUDIO2_CloseDevice(this); SDL_SetError("XAudio2: Unsupported audio format"); return 0; } /* Update the fragment size as size in bytes */ SDL_CalculateAudioSpec(&this->spec); /* We feed a Source, it feeds the Mastering, which feeds the device. */ this->hidden->mixlen = this->spec.size; this->hidden->mixbuf = (Uint8 *) SDL_malloc(2 * this->hidden->mixlen); if (this->hidden->mixbuf == NULL) { XAUDIO2_CloseDevice(this); SDL_OutOfMemory(); return 0; } this->hidden->nextbuf = this->hidden->mixbuf; SDL_memset(this->hidden->mixbuf, 0, 2 * this->hidden->mixlen); /* We use XAUDIO2_DEFAULT_CHANNELS instead of this->spec.channels. On Xbox360, this means 5.1 output, but on Windows, it means "figure out what the system has." It might be preferable to let XAudio2 blast stereo output to appropriate surround sound configurations instead of clamping to 2 channels, even though we'll configure the Source Voice for whatever number of channels you supply. */ result = IXAudio2_CreateMasteringVoice(ixa2, &this->hidden->mastering, XAUDIO2_DEFAULT_CHANNELS, this->spec.freq, 0, devId, NULL); if (result != S_OK) { XAUDIO2_CloseDevice(this); SDL_SetError("XAudio2: Couldn't create mastering voice"); return 0; } SDL_zero(waveformat); if (SDL_AUDIO_ISFLOAT(this->spec.format)) { waveformat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; } else { waveformat.wFormatTag = WAVE_FORMAT_PCM; } waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format); waveformat.nChannels = this->spec.channels; waveformat.nSamplesPerSec = this->spec.freq; waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8); waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; result = IXAudio2_CreateSourceVoice(ixa2, &source, &waveformat, XAUDIO2_VOICE_NOSRC | XAUDIO2_VOICE_NOPITCH, 1.0f, &callbacks, NULL, NULL); if (result != S_OK) { XAUDIO2_CloseDevice(this); SDL_SetError("XAudio2: Couldn't create source voice"); return 0; } this->hidden->source = source; /* Start everything playing! */ result = IXAudio2_StartEngine(ixa2); if (result != S_OK) { XAUDIO2_CloseDevice(this); SDL_SetError("XAudio2: Couldn't start engine"); return 0; } result = IXAudio2SourceVoice_Start(source, 0, XAUDIO2_COMMIT_NOW); if (result != S_OK) { XAUDIO2_CloseDevice(this); SDL_SetError("XAudio2: Couldn't start source voice"); return 0; } return 1; /* good to go. */ }
static int XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { HRESULT result = S_OK; WAVEFORMATEX waveformat; int valid_format = 0; SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); IXAudio2 *ixa2 = NULL; IXAudio2SourceVoice *source = NULL; #if defined(SDL_XAUDIO2_WIN8) LPCWSTR devId = NULL; #else UINT32 devId = 0; /* 0 == system default device. */ #endif static IXAudio2VoiceCallbackVtbl callbacks_vtable = { VoiceCBOnVoiceProcessPassStart, VoiceCBOnVoiceProcessPassEnd, VoiceCBOnStreamEnd, VoiceCBOnBufferStart, VoiceCBOnBufferEnd, VoiceCBOnLoopEnd, VoiceCBOnVoiceError }; static IXAudio2VoiceCallback callbacks = { &callbacks_vtable }; #if defined(SDL_XAUDIO2_WIN8) /* !!! FIXME: hook up hotplugging. */ #else if (handle != NULL) { /* specific device requested? */ /* -1 because we increment the original value to avoid NULL. */ const size_t val = ((size_t) handle) - 1; devId = (UINT32) val; } #endif if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) { return SDL_SetError("XAudio2: XAudio2Create() failed at open."); } /* XAUDIO2_DEBUG_CONFIGURATION debugConfig; debugConfig.TraceMask = XAUDIO2_LOG_ERRORS; //XAUDIO2_LOG_WARNINGS | XAUDIO2_LOG_DETAIL | XAUDIO2_LOG_FUNC_CALLS | XAUDIO2_LOG_TIMING | XAUDIO2_LOG_LOCKS | XAUDIO2_LOG_MEMORY | XAUDIO2_LOG_STREAMING; debugConfig.BreakMask = XAUDIO2_LOG_ERRORS; //XAUDIO2_LOG_WARNINGS; debugConfig.LogThreadID = TRUE; debugConfig.LogFileline = TRUE; debugConfig.LogFunctionName = TRUE; debugConfig.LogTiming = TRUE; ixa2->SetDebugConfiguration(&debugConfig); */ /* Initialize all variables that we clean on shutdown */ this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc((sizeof *this->hidden)); if (this->hidden == NULL) { IXAudio2_Release(ixa2); return SDL_OutOfMemory(); } SDL_memset(this->hidden, 0, (sizeof *this->hidden)); this->hidden->ixa2 = ixa2; this->hidden->semaphore = SDL_CreateSemaphore(1); if (this->hidden->semaphore == NULL) { XAUDIO2_CloseDevice(this); return SDL_SetError("XAudio2: CreateSemaphore() failed!"); } while ((!valid_format) && (test_format)) { switch (test_format) { case AUDIO_U8: case AUDIO_S16: case AUDIO_S32: case AUDIO_F32: this->spec.format = test_format; valid_format = 1; break; } test_format = SDL_NextAudioFormat(); } if (!valid_format) { XAUDIO2_CloseDevice(this); return SDL_SetError("XAudio2: Unsupported audio format"); } /* Update the fragment size as size in bytes */ SDL_CalculateAudioSpec(&this->spec); /* We feed a Source, it feeds the Mastering, which feeds the device. */ this->hidden->mixlen = this->spec.size; this->hidden->mixbuf = (Uint8 *) SDL_malloc(2 * this->hidden->mixlen); if (this->hidden->mixbuf == NULL) { XAUDIO2_CloseDevice(this); return SDL_OutOfMemory(); } this->hidden->nextbuf = this->hidden->mixbuf; SDL_memset(this->hidden->mixbuf, 0, 2 * this->hidden->mixlen); /* We use XAUDIO2_DEFAULT_CHANNELS instead of this->spec.channels. On Xbox360, this means 5.1 output, but on Windows, it means "figure out what the system has." It might be preferable to let XAudio2 blast stereo output to appropriate surround sound configurations instead of clamping to 2 channels, even though we'll configure the Source Voice for whatever number of channels you supply. */ #if SDL_XAUDIO2_WIN8 result = IXAudio2_CreateMasteringVoice(ixa2, &this->hidden->mastering, XAUDIO2_DEFAULT_CHANNELS, this->spec.freq, 0, devId, NULL, AudioCategory_GameEffects); #else result = IXAudio2_CreateMasteringVoice(ixa2, &this->hidden->mastering, XAUDIO2_DEFAULT_CHANNELS, this->spec.freq, 0, devId, NULL); #endif if (result != S_OK) { XAUDIO2_CloseDevice(this); return SDL_SetError("XAudio2: Couldn't create mastering voice"); } SDL_zero(waveformat); if (SDL_AUDIO_ISFLOAT(this->spec.format)) { waveformat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; } else { waveformat.wFormatTag = WAVE_FORMAT_PCM; } waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format); waveformat.nChannels = this->spec.channels; waveformat.nSamplesPerSec = this->spec.freq; waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8); waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; waveformat.cbSize = sizeof(waveformat); #ifdef __WINRT__ // DLudwig: for now, make XAudio2 do sample rate conversion, just to // get the loopwave test to work. // // TODO, WinRT: consider removing WinRT-specific source-voice creation code from SDL_xaudio2.c result = IXAudio2_CreateSourceVoice(ixa2, &source, &waveformat, 0, 1.0f, &callbacks, NULL, NULL); #else result = IXAudio2_CreateSourceVoice(ixa2, &source, &waveformat, XAUDIO2_VOICE_NOSRC | XAUDIO2_VOICE_NOPITCH, 1.0f, &callbacks, NULL, NULL); #endif if (result != S_OK) { XAUDIO2_CloseDevice(this); return SDL_SetError("XAudio2: Couldn't create source voice"); } this->hidden->source = source; /* Start everything playing! */ result = IXAudio2_StartEngine(ixa2); if (result != S_OK) { XAUDIO2_CloseDevice(this); return SDL_SetError("XAudio2: Couldn't start engine"); } result = IXAudio2SourceVoice_Start(source, 0, XAUDIO2_COMMIT_NOW); if (result != S_OK) { XAUDIO2_CloseDevice(this); return SDL_SetError("XAudio2: Couldn't start source voice"); } return 0; /* good to go. */ }
static int XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture) { HRESULT result = S_OK; WAVEFORMATEX waveformat; int valid_format = 0; SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format); IXAudio2 *ixa2 = NULL; IXAudio2SourceVoice *source = NULL; UINT32 devId = 0; /* 0 == system default device. */ if (iscapture) { return SDL_SetError("XAudio2: capture devices unsupported."); } else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) { return SDL_SetError("XAudio2: XAudio2Create() failed at open."); } if (devname != NULL) { UINT32 devcount = 0; UINT32 i = 0; if (i == devcount) { ixa2->Release(); return SDL_SetError("XAudio2: Requested device not found."); } } /* Initialize all variables that we clean on shutdown */ _this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc((sizeof *_this->hidden)); if (_this->hidden == NULL) { return SDL_OutOfMemory(); } SDL_memset(_this->hidden, 0, (sizeof *_this->hidden)); _this->hidden->ixa2 = ixa2; _this->hidden->semaphore = CreateSemaphoreEx(NULL, 1, 2, NULL, 0, 0); if (_this->hidden->semaphore == NULL) { XAUDIO2_CloseDevice(_this); return SDL_SetError("XAudio2: CreateSemaphore() failed!"); } while ((!valid_format) && (test_format)) { switch (test_format) { case AUDIO_U8: case AUDIO_S16: case AUDIO_S32: case AUDIO_F32: _this->spec.format = test_format; valid_format = 1; break; } test_format = SDL_NextAudioFormat(); } if (!valid_format) { XAUDIO2_CloseDevice(_this); return SDL_SetError("XAudio2: Unsupported audio format"); } /* Update the fragment size as size in bytes */ SDL_CalculateAudioSpec(&_this->spec); /* We feed a Source, it feeds the Mastering, which feeds the device. */ _this->hidden->mixlen = _this->spec.size; _this->hidden->mixbuf = (Uint8 *) SDL_malloc(2 * _this->hidden->mixlen); if (_this->hidden->mixbuf == NULL) { XAUDIO2_CloseDevice(_this); return SDL_OutOfMemory(); } _this->hidden->nextbuf = _this->hidden->mixbuf; SDL_memset(_this->hidden->mixbuf, 0, 2 * _this->hidden->mixlen); /* We use XAUDIO2_DEFAULT_CHANNELS instead of _this->spec.channels. On Xbox360, _this means 5.1 output, but on Windows, it means "figure out what the system has." It might be preferable to let XAudio2 blast stereo output to appropriate surround sound configurations instead of clamping to 2 channels, even though we'll configure the Source Voice for whatever number of channels you supply. */ result = ixa2->CreateMasteringVoice(&_this->hidden->mastering, XAUDIO2_DEFAULT_CHANNELS, _this->spec.freq, 0, nullptr, nullptr, AudioCategory_GameMedia); // XAUDIO2_DEFAULT_CHANNELS, // _this->spec.freq, 0, devId, NULL); if (result != S_OK) { XAUDIO2_CloseDevice(_this); return SDL_SetError("XAudio2: Couldn't create mastering voice"); } SDL_zero(waveformat); if (SDL_AUDIO_ISFLOAT(_this->spec.format)) { waveformat.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; } else { waveformat.wFormatTag = WAVE_FORMAT_PCM; } waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(_this->spec.format); waveformat.nChannels = _this->spec.channels; waveformat.nSamplesPerSec = _this->spec.freq; waveformat.nBlockAlign = waveformat.nChannels * (waveformat.wBitsPerSample / 8); waveformat.nAvgBytesPerSec = waveformat.nSamplesPerSec * waveformat.nBlockAlign; static VoiceCallback callbacks; XAUDIO2_SEND_DESCRIPTOR descriptors[1]; descriptors[0].pOutputVoice = _this->hidden->mastering; descriptors[0].Flags = 0; XAUDIO2_VOICE_SENDS sends = {0}; sends.SendCount = 1; sends.pSends = descriptors; result = ixa2->CreateSourceVoice(&source, &waveformat, 0, 1.0f, &callbacks, &sends, nullptr); if (result != S_OK) { XAUDIO2_CloseDevice(_this); return SDL_SetError("XAudio2: Couldn't create source voice"); } _this->hidden->source = source; /* Start everything playing! */ result = ixa2->StartEngine(); if (result != S_OK) { XAUDIO2_CloseDevice(_this); return SDL_SetError("XAudio2: Couldn't start engine"); } result = source->Start(0, XAUDIO2_COMMIT_NOW); if (result != S_OK) { XAUDIO2_CloseDevice(_this); return SDL_SetError("XAudio2: Couldn't start source voice"); } return 0; /* good to go. */ }