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. */ }
ga_DeviceImpl_XAudio2* gaX_device_open_xaudio2(gc_int32 in_numBuffers, gc_int32 in_numSamples, ga_Format* in_format) { ga_DeviceImpl_XAudio2* ret = gcX_ops->allocFunc(sizeof(ga_DeviceImpl_XAudio2)); HRESULT result; WAVEFORMATEX fmt; gc_int32 i; ret->devType = GA_DEVICE_TYPE_XAUDIO2; ret->numBuffers = in_numBuffers; ret->numSamples = in_numSamples; memcpy(&ret->format, in_format, sizeof(ga_Format)); ret->sampleSize = ga_format_sampleSize(in_format); ret->nextBuffer = 0; ret->xa = 0; ret->master = 0; CoInitializeEx(NULL, COINIT_MULTITHREADED); result = XAudio2Create(&ret->xa, 0, XAUDIO2_DEFAULT_PROCESSOR); if(FAILED(result)) goto cleanup; result = IXAudio2_CreateMasteringVoice(ret->xa, &ret->master, 2, 44100, 0, 0, 0); if(FAILED(result)) goto cleanup; fmt.cbSize = sizeof(WAVEFORMATEX); ZeroMemory(&fmt, sizeof(WAVEFORMATEX)); fmt.cbSize = sizeof(WAVEFORMATEX); fmt.wFormatTag = WAVE_FORMAT_PCM; fmt.nChannels = 2; fmt.wBitsPerSample = 16; fmt.nSamplesPerSec = 44100; fmt.nBlockAlign = fmt.nChannels * (fmt.wBitsPerSample / 8); fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; result = IXAudio2_CreateSourceVoice(ret->xa, &ret->source, &fmt, XAUDIO2_VOICE_NOPITCH, XAUDIO2_DEFAULT_FREQ_RATIO, 0, 0, 0); if(FAILED(result)) goto cleanup; result =IXAudio2_StartEngine(ret->xa); if(FAILED(result)) goto cleanup; result = IXAudio2SourceVoice_Start(ret->source, 0, XAUDIO2_COMMIT_NOW); if(FAILED(result)) goto cleanup; ret->buffers = gcX_ops->allocFunc(ret->numBuffers * sizeof(void*)); for(i = 0; i < ret->numBuffers; ++i) ret->buffers[i] = gcX_ops->allocFunc(ret->numSamples * ret->sampleSize); return ret; cleanup: if(ret->source) { IXAudio2SourceVoice_Stop(ret->source, 0, XAUDIO2_COMMIT_NOW); IXAudio2SourceVoice_FlushSourceBuffers(ret->source); IXAudio2SourceVoice_DestroyVoice(ret->source); } if(ret->xa) IXAudio2_StopEngine(ret->xa); if(ret->master) IXAudio2MasteringVoice_DestroyVoice(ret->master); if(ret->xa) IXAudio2_Release(ret->xa); CoUninitialize(); gcX_ops->freeFunc(ret); return 0; }
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. */ }
BYTE snd_start(void) { int psamples; if (!cfg->apu.channel[APU_MASTER]) { return (EXIT_OK); } // come prima cosa blocco eventuali riproduzioni snd_stop(); memset(&snd, 0x00, sizeof(_snd)); memset(&xaudio2, 0x00, sizeof(xaudio2)); memset(&cbd, 0x00, sizeof(_callback_data)); snd.cache = &cbd; audio_channels(cfg->channels_mode); switch (cfg->samplerate) { case S48000: snd.samplerate = 48000; break; case S44100: snd.samplerate = 44100; break; case S22050: snd.samplerate = 22050; break; case S11025: snd.samplerate = 11025; break; } if (XAudio2Create(&xaudio2.engine, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) { MessageBox(NULL, "ATTENTION: Unable to create XAudio2 object. Probably you\n" "have an incomplete installation of DirectX 10." , "Error!", MB_ICONEXCLAMATION | MB_OK); return (EXIT_ERROR); } if (IXAudio2_CreateMasteringVoice(xaudio2.engine, &xaudio2.master, snd.channels, snd.samplerate, 0, 0, NULL) != S_OK) { MessageBox(NULL, "ATTENTION: Unable to create XAudio2 master voice.", "Error!", MB_ICONEXCLAMATION | MB_OK); return (EXIT_ERROR); } { WAVEFORMATEX wfm; memset(&wfm, 0, sizeof(wfm)); wfm.wFormatTag = WAVE_FORMAT_PCM; wfm.nChannels = snd.channels; wfm.wBitsPerSample = 16; wfm.nSamplesPerSec = snd.samplerate; wfm.nBlockAlign = (wfm.nChannels * wfm.wBitsPerSample) / 8; wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign; wfm.cbSize = sizeof(wfm); if (IXAudio2_CreateSourceVoice(xaudio2.engine, &xaudio2.source, &wfm, XAUDIO2_VOICE_NOSRC | XAUDIO2_VOICE_NOPITCH, XAUDIO2_DEFAULT_FREQ_RATIO, &callbacks, NULL, NULL) != S_OK) { MessageBox(NULL, "ATTENTION: Unable to create XAudio2 source voice.\n", "Error!", MB_ICONEXCLAMATION | MB_OK); return (EXIT_ERROR); } } { double factor = (1.0f / 48000.0f) * (double) snd.samplerate; psamples = ((1024 * factor) + ((512 * factor) * cfg->audio_buffer_factor)); } snd.samples = psamples * 2; snd.frequency = machine.cpu_hz / (double) snd.samplerate; xaudio2.opened = TRUE; #if !defined (RELEASE) xaudio2.tick = gui_get_ms(); #endif { // dimensione in bytes del buffer snd.buffer.size = (psamples * snd.channels * sizeof(*cbd.write)) * 5; snd.buffer.limit.low = (snd.buffer.size / 100) * 25; snd.buffer.limit.high = (snd.buffer.size / 100) * 55; #if !defined (RELEASE) printf("softw bsize : %-6d - %-6d\n", snd.buffer.size, snd.samples); printf("softw limit : %-6d - %-6d\n", snd.buffer.limit.low, snd.buffer.limit.high); #endif // alloco il buffer in memoria if (!(cbd.start = (SWORD *) malloc(snd.buffer.size))) { MessageBox(NULL, "ATTENTION: Unable to allocate audio buffers.\n", "Error!", MB_ICONEXCLAMATION | MB_OK); return (EXIT_ERROR); } if (!(cbd.silence = (SWORD *) malloc(snd.buffer.size))) { MessageBox(NULL, "ATTENTION: Unable to allocate silence buffer.\n", "Error!", MB_ICONEXCLAMATION | MB_OK); return (EXIT_ERROR); } // inizializzo il frame di scrittura cbd.write = cbd.start; // inizializzo il frame di lettura cbd.read = (SBYTE *) cbd.start; // punto alla fine del buffer cbd.end = cbd.read + snd.buffer.size; // creo il lock if ((xaudio2.semaphore = CreateSemaphore(NULL, 1, 2, NULL)) == NULL) { MessageBox(NULL, "ATTENTION: Unable to create XAudio2 semaphore.\n", "Error!", MB_ICONEXCLAMATION | MB_OK); return (EXIT_ERROR); } // azzero completamente i buffers memset(cbd.start, 0x00, snd.buffer.size); // azzero completamente il buffer del silenzio memset(cbd.silence, 0x00, snd.buffer.size); // azzero completamente la struttura XAUDIO2_BUFFER memset(&xaudio2.buffer, 0x00, sizeof(xaudio2.buffer)); xaudio2.buffer.AudioBytes = psamples * sizeof(*cbd.write) * snd.channels; //xaudio2.buffer.pAudioData = (const BYTE *) cbd.read; xaudio2.buffer.pAudioData = (const BYTE *) cbd.silence; xaudio2.buffer.PlayBegin = 0; xaudio2.buffer.PlayLength = psamples; xaudio2.buffer.LoopBegin = 0; xaudio2.buffer.LoopLength = 0; xaudio2.buffer.LoopCount = 0; xaudio2.buffer.pContext = snd.cache; cbd.xa2buffer = &xaudio2.buffer; cbd.xa2source = xaudio2.source; cbd.lock = xaudio2.semaphore; if (IXAudio2SourceVoice_SubmitSourceBuffer(xaudio2.source, (const XAUDIO2_BUFFER *) cbd.xa2buffer, NULL) != S_OK) { MessageBox(NULL, "ATTENTION: Unable to set sound engine.\n", "Error!", MB_ICONEXCLAMATION | MB_OK); return (EXIT_ERROR); } } if (extcl_snd_start) { extcl_snd_start((WORD) snd.samplerate); } audio_channels_init_mode(); audio_quality(cfg->audio_quality); if(IXAudio2_StartEngine(xaudio2.engine) != S_OK) { MessageBox(NULL, "ATTENTION: Unable to start sound engine.\n", "Error!", MB_ICONEXCLAMATION | MB_OK); return (EXIT_ERROR); } if(IXAudio2SourceVoice_Start(xaudio2.source, 0, XAUDIO2_COMMIT_NOW) != S_OK) { MessageBox(NULL, "ATTENTION: Unable to start source voice.\n", "Error!", MB_ICONEXCLAMATION | MB_OK); return (EXIT_ERROR); } return (EXIT_OK); }