mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-01-17 20:58:28 +01:00
cda10094da
byuu says: Added OV2's XAudio2 driver (it's better and faster than the DirectSound one) Fixed DirectInput keypad number codes Added launcher to make the profiles work Profiles now called: Accuracy, Compatibility, Performance (not debating names anymore) The launcher isn't going to work on OS X because of the .app folder bullshit (yes, yes, .sfc folders.) It also crashes on Windows XP for god only knows what reason. Works fine on Windows 7 and Linux. So XP users, rename the .dll files to .exe to test this release. I'll fix it on Monday. The color highlighting fucks up the radio boxes on the Windows classic theme, because Nokia can't afford a god damn QA team. Lastly, I forgot to add launcher to the make archive-all command, so the source for it will be in the next WIP.
201 lines
5.1 KiB
C++
Executable File
201 lines
5.1 KiB
C++
Executable File
/*
|
|
audio.xaudio2 (2010-08-14)
|
|
author: OV2
|
|
*/
|
|
|
|
#include "xaudio2.hpp"
|
|
#include <Windows.h>
|
|
|
|
namespace ruby {
|
|
|
|
class pAudioXAudio2: public IXAudio2VoiceCallback {
|
|
public:
|
|
IXAudio2 *pXAudio2;
|
|
IXAudio2MasteringVoice* pMasterVoice;
|
|
IXAudio2SourceVoice *pSourceVoice;
|
|
|
|
// inherited from IXAudio2VoiceCallback
|
|
STDMETHODIMP_(void) OnBufferStart(void *pBufferContext){}
|
|
STDMETHODIMP_(void) OnLoopEnd(void *pBufferContext){}
|
|
STDMETHODIMP_(void) OnStreamEnd() {}
|
|
STDMETHODIMP_(void) OnVoiceError(void *pBufferContext, HRESULT Error) {}
|
|
STDMETHODIMP_(void) OnVoiceProcessingPassEnd() {}
|
|
STDMETHODIMP_(void) OnVoiceProcessingPassStart(UINT32 BytesRequired) {}
|
|
|
|
struct {
|
|
unsigned buffers;
|
|
unsigned latency;
|
|
|
|
uint32_t *buffer;
|
|
unsigned bufferoffset;
|
|
|
|
volatile long submitbuffers;
|
|
unsigned writebuffer;
|
|
} device;
|
|
|
|
struct {
|
|
bool synchronize;
|
|
unsigned frequency;
|
|
unsigned latency;
|
|
} settings;
|
|
|
|
bool cap(const string& name) {
|
|
if(name == Audio::Synchronize) return true;
|
|
if(name == Audio::Frequency) return true;
|
|
if(name == Audio::Latency) return true;
|
|
return false;
|
|
}
|
|
|
|
any get(const string& name) {
|
|
if(name == Audio::Synchronize) return settings.synchronize;
|
|
if(name == Audio::Frequency) return settings.frequency;
|
|
if(name == Audio::Latency) return settings.latency;
|
|
return false;
|
|
}
|
|
|
|
bool set(const string& name, const any& value) {
|
|
if(name == Audio::Synchronize) {
|
|
settings.synchronize = any_cast<bool>(value);
|
|
if(pXAudio2) clear();
|
|
return true;
|
|
}
|
|
|
|
if(name == Audio::Frequency) {
|
|
settings.frequency = any_cast<unsigned>(value);
|
|
if(pXAudio2) init();
|
|
return true;
|
|
}
|
|
|
|
if(name == Audio::Latency) {
|
|
settings.latency = any_cast<unsigned>(value);
|
|
if(pXAudio2) init();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void pushbuffer(unsigned bytes,uint32_t *pAudioData) {
|
|
XAUDIO2_BUFFER xa2buffer={0};
|
|
xa2buffer.AudioBytes=bytes;
|
|
xa2buffer.pAudioData=reinterpret_cast<BYTE *>(pAudioData);
|
|
xa2buffer.pContext=0;
|
|
InterlockedIncrement(&device.submitbuffers);
|
|
pSourceVoice->SubmitSourceBuffer(&xa2buffer);
|
|
}
|
|
|
|
void sample(uint16_t left, uint16_t right) {
|
|
device.buffer[device.writebuffer * device.latency + device.bufferoffset++] = left + (right << 16);
|
|
if(device.bufferoffset < device.latency) return;
|
|
device.bufferoffset = 0;
|
|
|
|
if(device.submitbuffers == device.buffers - 1) {
|
|
if(settings.synchronize == true) {
|
|
//wait until there is at least one other free buffer for the next sample
|
|
while(device.submitbuffers == device.buffers - 1) {
|
|
//Sleep(0);
|
|
}
|
|
} else { //we need one free buffer for the next sample, so ignore the current contents
|
|
return;
|
|
}
|
|
}
|
|
|
|
pushbuffer(device.latency * 4,device.buffer + device.writebuffer * device.latency);
|
|
|
|
device.writebuffer = (device.writebuffer + 1) % device.buffers;
|
|
}
|
|
|
|
void clear() {
|
|
if(!pSourceVoice) return;
|
|
pSourceVoice->Stop(0);
|
|
pSourceVoice->FlushSourceBuffers(); //calls OnBufferEnd for all currently submitted buffers
|
|
|
|
device.writebuffer = 0;
|
|
|
|
device.bufferoffset = 0;
|
|
if(device.buffer) memset(device.buffer, 0, device.latency * device.buffers * 4);
|
|
|
|
pSourceVoice->Start(0);
|
|
}
|
|
|
|
bool init() {
|
|
term();
|
|
|
|
device.buffers = 8;
|
|
device.latency = settings.frequency * settings.latency / device.buffers / 1000.0 + 0.5;
|
|
device.buffer = new uint32_t[device.latency * device.buffers];
|
|
device.bufferoffset = 0;
|
|
device.submitbuffers = 0;
|
|
|
|
HRESULT hr;
|
|
if(FAILED(hr = XAudio2Create(&pXAudio2, 0 , XAUDIO2_DEFAULT_PROCESSOR))) {
|
|
return false;
|
|
}
|
|
|
|
if(FAILED(hr = pXAudio2->CreateMasteringVoice( &pMasterVoice, 2,
|
|
settings.frequency, 0, 0 , NULL))) {
|
|
return false;
|
|
}
|
|
|
|
WAVEFORMATEX wfx;
|
|
wfx.wFormatTag = WAVE_FORMAT_PCM;
|
|
wfx.nChannels = 2;
|
|
wfx.nSamplesPerSec = settings.frequency;
|
|
wfx.nBlockAlign = 4;
|
|
wfx.wBitsPerSample = 16;
|
|
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
|
wfx.cbSize = 0;
|
|
|
|
if(FAILED(hr = pXAudio2->CreateSourceVoice(&pSourceVoice, (WAVEFORMATEX*)&wfx,
|
|
XAUDIO2_VOICE_NOSRC , XAUDIO2_DEFAULT_FREQ_RATIO, this, NULL, NULL))) {
|
|
return false;
|
|
}
|
|
|
|
clear();
|
|
return true;
|
|
}
|
|
|
|
void term() {
|
|
if(pSourceVoice) {
|
|
pSourceVoice->Stop(0);
|
|
pSourceVoice->DestroyVoice();
|
|
pSourceVoice = 0;
|
|
}
|
|
if(pMasterVoice) {
|
|
pMasterVoice->DestroyVoice();
|
|
pMasterVoice = 0;
|
|
}
|
|
if(pXAudio2) {
|
|
pXAudio2->Release();
|
|
pXAudio2 = NULL;
|
|
}
|
|
if(device.buffer) {
|
|
delete[] device.buffer;
|
|
device.buffer = 0;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP_(void) OnBufferEnd(void *pBufferContext) {
|
|
InterlockedDecrement(&device.submitbuffers);
|
|
}
|
|
|
|
pAudioXAudio2() {
|
|
pXAudio2 = 0;
|
|
pMasterVoice = 0;
|
|
pSourceVoice = 0;
|
|
|
|
device.buffer = 0;
|
|
device.bufferoffset = 0;
|
|
device.submitbuffers = 0;
|
|
device.writebuffer = 0;
|
|
|
|
settings.synchronize = false;
|
|
settings.frequency = 22050;
|
|
settings.latency = 120;
|
|
}
|
|
};
|
|
|
|
DeclareAudio(XAudio2)
|
|
|
|
};
|