DirectSound: Fixed latency issue that caused sound to cut off within the first second after loading a rom after starting the emulator
This commit is contained in:
parent
eacd07d010
commit
7b20300f6d
8 changed files with 57 additions and 29 deletions
|
@ -5,7 +5,7 @@ class BaseSoundManager : public IAudioDevice
|
|||
{
|
||||
public:
|
||||
void ProcessLatency(uint32_t readPosition, uint32_t writePosition);
|
||||
AudioStatistics GetStatistics();
|
||||
AudioStatistics GetStatistics() override;
|
||||
|
||||
protected:
|
||||
bool _isStereo;
|
||||
|
|
|
@ -17,6 +17,7 @@ class IAudioDevice
|
|||
virtual void Stop() = 0;
|
||||
virtual void Pause() = 0;
|
||||
virtual void ProcessEndOfFrame() = 0;
|
||||
virtual void UpdateSoundSettings() = 0;
|
||||
|
||||
virtual string GetAvailableDevices() = 0;
|
||||
virtual void SetAudioDevice(string deviceName) = 0;
|
||||
|
|
|
@ -92,7 +92,9 @@ void SoundMixer::Reset()
|
|||
|
||||
UpdateRates(true);
|
||||
UpdateEqualizers(true);
|
||||
|
||||
if(_audioDevice) {
|
||||
_audioDevice->UpdateSoundSettings();
|
||||
}
|
||||
_previousTargetRate = _sampleRate;
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,10 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
virtual void UpdateSoundSettings() override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ProcessEndOfFrame() override
|
||||
{
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ SdlSoundManager::SdlSoundManager(shared_ptr<Console> console)
|
|||
{
|
||||
_console = console;
|
||||
|
||||
if(InitializeAudio(44100, false)) {
|
||||
if(InitializeAudio(48000, true)) {
|
||||
_console->GetSoundMixer()->RegisterAudioDevice(this);
|
||||
}
|
||||
}
|
||||
|
@ -146,18 +146,25 @@ void SdlSoundManager::WriteToBuffer(uint8_t* input, uint32_t len)
|
|||
_writePosition = len - remainingBytes;
|
||||
}
|
||||
}
|
||||
|
||||
void SdlSoundManager::UpdateSoundSettings()
|
||||
{
|
||||
uint32_t sampleRate = _console->GetSettings()->GetSampleRate();
|
||||
uint32_t latency = _console->GetSettings()->GetAudioLatency();
|
||||
if(_sampleRate != sampleRate || _needReset || _previousLatency != latency) {
|
||||
Release();
|
||||
InitializeAudio(sampleRate, true);
|
||||
}
|
||||
}
|
||||
|
||||
void SdlSoundManager::PlayBuffer(int16_t *soundBuffer, uint32_t sampleCount, uint32_t sampleRate, bool isStereo)
|
||||
{
|
||||
uint32_t bytesPerSample = (SoundMixer::BitsPerSample / 8) * (isStereo ? 2 : 1);
|
||||
uint32_t latency = _console->GetSettings()->GetAudioLatency();
|
||||
if(_sampleRate != sampleRate || _isStereo != isStereo || _needReset || _previousLatency != latency) {
|
||||
Release();
|
||||
InitializeAudio(sampleRate, isStereo);
|
||||
}
|
||||
UpdateSoundSettings();
|
||||
|
||||
WriteToBuffer((uint8_t*)soundBuffer, sampleCount * bytesPerSample);
|
||||
|
||||
int32_t byteLatency = (int32_t)((float)(sampleRate * latency) / 1000.0f * bytesPerSample);
|
||||
int32_t byteLatency = (int32_t)((float)(sampleRate * _previousLatency) / 1000.0f * bytesPerSample);
|
||||
int32_t playWriteByteLatency = _writePosition - _readPosition;
|
||||
if(playWriteByteLatency < 0) {
|
||||
playWriteByteLatency = _bufferSize - _readPosition + _writePosition;
|
||||
|
|
|
@ -10,14 +10,15 @@ public:
|
|||
SdlSoundManager(shared_ptr<Console> console);
|
||||
~SdlSoundManager();
|
||||
|
||||
void PlayBuffer(int16_t *soundBuffer, uint32_t bufferSize, uint32_t sampleRate, bool isStereo);
|
||||
void Pause();
|
||||
void Stop();
|
||||
void PlayBuffer(int16_t *soundBuffer, uint32_t bufferSize, uint32_t sampleRate, bool isStereo) override;
|
||||
void Pause() override;
|
||||
void Stop() override;
|
||||
|
||||
void ProcessEndOfFrame();
|
||||
void ProcessEndOfFrame() override;
|
||||
void UpdateSoundSettings() override;
|
||||
|
||||
string GetAvailableDevices();
|
||||
void SetAudioDevice(string deviceName);
|
||||
string GetAvailableDevices() override;
|
||||
void SetAudioDevice(string deviceName) override;
|
||||
|
||||
private:
|
||||
vector<string> GetAvailableDeviceInfo();
|
||||
|
|
|
@ -14,7 +14,7 @@ SoundManager::SoundManager(shared_ptr<Console> console, HWND hwnd)
|
|||
|
||||
memset(&_audioDeviceID, 0, sizeof(_audioDeviceID));
|
||||
|
||||
if(InitializeDirectSound(44100, false)) {
|
||||
if(InitializeDirectSound(48000, true)) {
|
||||
_console->GetSoundMixer()->RegisterAudioDevice(this);
|
||||
} else {
|
||||
MessageManager::DisplayMessage("Error", "CouldNotInitializeAudioSystem");
|
||||
|
@ -279,16 +279,27 @@ void SoundManager::ProcessEndOfFrame()
|
|||
}
|
||||
}
|
||||
|
||||
void SoundManager::PlayBuffer(int16_t *soundBuffer, uint32_t sampleCount, uint32_t sampleRate, bool isStereo)
|
||||
void SoundManager::UpdateSoundSettings()
|
||||
{
|
||||
uint32_t bytesPerSample = (SoundMixer::BitsPerSample / 8) * (isStereo ? 2 : 1);
|
||||
uint32_t sampleRate = _console->GetSettings()->GetSampleRate();
|
||||
uint32_t latency = _console->GetSettings()->GetAudioLatency();
|
||||
if(_sampleRate != sampleRate || _isStereo != isStereo || _needReset || latency != _previousLatency) {
|
||||
if(_sampleRate != sampleRate || _needReset || latency != _previousLatency) {
|
||||
_previousLatency = latency;
|
||||
Release();
|
||||
InitializeDirectSound(sampleRate, isStereo);
|
||||
InitializeDirectSound(sampleRate, true);
|
||||
_secondaryBuffer->SetFrequency(sampleRate);
|
||||
|
||||
//Force DirectSound to initialize fully by starting and stopping playback
|
||||
//Otherwise the first play operation takes a little while longer and throws off the sound latency
|
||||
Play();
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::PlayBuffer(int16_t *soundBuffer, uint32_t sampleCount, uint32_t sampleRate, bool isStereo)
|
||||
{
|
||||
UpdateSoundSettings();
|
||||
uint32_t bytesPerSample = (SoundMixer::BitsPerSample / 8) * (isStereo ? 2 : 1);
|
||||
|
||||
DWORD currentPlayCursor, safeWriteCursor;
|
||||
_secondaryBuffer->GetCurrentPosition(¤tPlayCursor, &safeWriteCursor);
|
||||
|
@ -298,7 +309,7 @@ void SoundManager::PlayBuffer(int16_t *soundBuffer, uint32_t sampleCount, uint32
|
|||
CopyToSecondaryBuffer((uint8_t*)soundBuffer, soundBufferSize);
|
||||
|
||||
if(!_playing) {
|
||||
DWORD byteLatency = (int32_t)((float)(sampleRate * latency) / 1000.0f * bytesPerSample);
|
||||
DWORD byteLatency = (int32_t)((float)(sampleRate * _previousLatency) / 1000.0f * bytesPerSample);
|
||||
if(_lastWriteOffset >= byteLatency / 2) {
|
||||
Play();
|
||||
}
|
||||
|
|
|
@ -18,16 +18,18 @@ public:
|
|||
~SoundManager();
|
||||
|
||||
void Release();
|
||||
void ProcessEndOfFrame();
|
||||
void PlayBuffer(int16_t *soundBuffer, uint32_t bufferSize, uint32_t sampleRate, bool isStereo);
|
||||
void Play();
|
||||
void Pause();
|
||||
void Stop();
|
||||
void ProcessEndOfFrame() override;
|
||||
void UpdateSoundSettings() override;
|
||||
void PlayBuffer(int16_t *soundBuffer, uint32_t bufferSize, uint32_t sampleRate, bool isStereo) override;
|
||||
void Pause() override;
|
||||
void Stop() override;
|
||||
|
||||
string GetAvailableDevices();
|
||||
void SetAudioDevice(string deviceName);
|
||||
string GetAvailableDevices() override;
|
||||
void SetAudioDevice(string deviceName) override;
|
||||
|
||||
private:
|
||||
void Play();
|
||||
|
||||
vector<SoundDeviceInfo> GetAvailableDeviceInfo();
|
||||
static bool CALLBACK DirectSoundEnumProc(LPGUID lpGUID, LPCWSTR lpszDesc, LPCSTR lpszDrvName, LPVOID lpContext);
|
||||
bool InitializeDirectSound(uint32_t sampleRate, bool isStereo);
|
||||
|
|
Loading…
Add table
Reference in a new issue