Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
Andrea Odetti
007bf2335a 1) make sure AW does not fill the DS buffer, as semantics are unclear
2) process audio sooner, rather than a frame later
3) only 1 SDL buffer control (its size)
4) DS: Lock-Unlock probably reset the write cursor (in Windows)
5) DS: AW does not like DS buffer to be empty (or full??) at the begin
2021-07-11 14:33:26 +01:00
Andrea Odetti
d8f5641e5b Small fixes to the audio settings.
Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
2021-07-10 15:43:49 +01:00
Andrea Odetti
9add1555a2 Expose some SDL audio controls.
Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
2021-07-10 12:20:08 +01:00
7 changed files with 52 additions and 22 deletions

View file

@ -569,8 +569,8 @@ static ULONG Spkr_SubmitWaveBuffer_FullSpeed(short* pSpeakerBuffer, ULONG nNumSa
UINT nBytesFree = g_dwDSSpkrBufferSize - nBytesRemaining; // Calc free buffer space UINT nBytesFree = g_dwDSSpkrBufferSize - nBytesRemaining; // Calc free buffer space
ULONG nNumSamplesToUse = nNumSamples + nNumPadSamples; ULONG nNumSamplesToUse = nNumSamples + nNumPadSamples;
if(nNumSamplesToUse * sizeof(short) > nBytesFree) if(nNumSamplesToUse * sizeof(short) >= nBytesFree)
nNumSamplesToUse = nBytesFree / sizeof(short); nNumSamplesToUse = nBytesFree / sizeof(short) - 1;
// //
@ -766,8 +766,8 @@ static ULONG Spkr_SubmitWaveBuffer(short* pSpeakerBuffer, ULONG nNumSamples)
UINT nBytesFree = g_dwDSSpkrBufferSize - nBytesRemaining; // Calc free buffer space UINT nBytesFree = g_dwDSSpkrBufferSize - nBytesRemaining; // Calc free buffer space
ULONG nNumSamplesToUse = nNumSamples; ULONG nNumSamplesToUse = nNumSamples;
if(nNumSamplesToUse * sizeof(short) > nBytesFree) if(nNumSamplesToUse * sizeof(short) >= nBytesFree)
nNumSamplesToUse = nBytesFree / sizeof(short); nNumSamplesToUse = nBytesFree / sizeof(short) - 1;
if(bBufferError) if(bBufferError)
pSpeakerBuffer = &pSpeakerBuffer[nNumSamples - nNumSamplesToUse]; pSpeakerBuffer = &pSpeakerBuffer[nNumSamples - nNumSamplesToUse];

View file

@ -500,14 +500,24 @@ namespace sa2
ImGui::Separator(); ImGui::Separator();
if (ImGui::BeginTable("Devices", 5, ImGuiTableFlags_RowBg)) int size;
getAudioBufferSize(size);
if (ImGui::SliderInt("Buffer size", &size, 0, 1000, "%d ms"))
{
setAudioBufferSize(size);
}
ImGui::Separator();
if (ImGui::BeginTable("Devices", 6, ImGuiTableFlags_RowBg))
{ {
myAudioInfo = getAudioInfo(); myAudioInfo = getAudioInfo();
ImGui::TableSetupColumn("Running"); ImGui::TableSetupColumn("Running");
ImGui::TableSetupColumn("Channels"); ImGui::TableSetupColumn("Channels");
ImGui::TableSetupColumn("Volume"); ImGui::TableSetupColumn("Volume");
ImGui::TableSetupColumn("Buffer"); ImGui::TableSetupColumn("Direct");
ImGui::TableSetupColumn("Queue"); ImGui::TableSetupColumn("SDL");
ImGui::TableSetupColumn("Total");
ImGui::TableHeadersRow(); ImGui::TableHeadersRow();
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); // this requires imgui_internal.h ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); // this requires imgui_internal.h
@ -523,6 +533,9 @@ namespace sa2
ImGui::SliderFloat("", &device.buffer, 0.0f, device.size, "%.3f"); ImGui::SliderFloat("", &device.buffer, 0.0f, device.size, "%.3f");
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::SliderFloat("", &device.queue, 0.0f, device.size, "%.3f"); ImGui::SliderFloat("", &device.queue, 0.0f, device.size, "%.3f");
ImGui::TableNextColumn();
float total = device.buffer + device.queue;
ImGui::SliderFloat("", &total, 0.0f, 2 * device.size, "%.3f");
} }
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, false); ImGui::PushItemFlag(ImGuiItemFlags_Disabled, false);

View file

@ -140,13 +140,13 @@ void run_sdl(int argc, const char * argv [])
frameTimer.tic(); frameTimer.tic();
eventTimer.tic(); eventTimer.tic();
sa2::writeAudio();
processEventsUthernet2(5); processEventsUthernet2(5);
frame->ProcessEvents(quit); frame->ProcessEvents(quit);
eventTimer.toc(); eventTimer.toc();
cpuTimer.tic(); cpuTimer.tic();
frame->ExecuteOneFrame(oneFrame); frame->ExecuteOneFrame(oneFrame);
sa2::writeAudio();
cpuTimer.toc(); cpuTimer.toc();
if (!options.headless) if (!options.headless)

View file

@ -24,6 +24,8 @@ namespace
void printInfo() const; void printInfo() const;
sa2::SoundInfo getInfo() const; sa2::SoundInfo getInfo() const;
static int ourBufferSize;
private: private:
IDirectSoundBuffer * myBuffer; IDirectSoundBuffer * myBuffer;
@ -33,6 +35,7 @@ namespace
SDL_AudioSpec myAudioSpec; SDL_AudioSpec myAudioSpec;
int myBytesPerSecond; int myBytesPerSecond;
int myBytesPerUnit;
void close(); void close();
bool isRunning() const; bool isRunning() const;
@ -41,6 +44,7 @@ namespace
void mixBuffer(const void * ptr, const size_t size); void mixBuffer(const void * ptr, const size_t size);
}; };
int DirectSoundGenerator::ourBufferSize = 200;
std::unordered_map<IDirectSoundBuffer *, std::shared_ptr<DirectSoundGenerator>> activeSoundGenerators; std::unordered_map<IDirectSoundBuffer *, std::shared_ptr<DirectSoundGenerator>> activeSoundGenerators;
@ -48,6 +52,7 @@ namespace
: myBuffer(buffer) : myBuffer(buffer)
, myAudioDevice(0) , myAudioDevice(0)
, myBytesPerSecond(0) , myBytesPerSecond(0)
, myBytesPerUnit(0)
{ {
SDL_memset(&myAudioSpec, 0, sizeof(myAudioSpec)); SDL_memset(&myAudioSpec, 0, sizeof(myAudioSpec));
} }
@ -95,7 +100,8 @@ namespace
if (myAudioDevice) if (myAudioDevice)
{ {
const int bitsPerSample = myAudioSpec.format & SDL_AUDIO_MASK_BITSIZE; const int bitsPerSample = myAudioSpec.format & SDL_AUDIO_MASK_BITSIZE;
myBytesPerSecond = myAudioSpec.freq * myAudioSpec.channels * bitsPerSample / 8; myBytesPerUnit = myAudioSpec.channels * bitsPerSample / 8;
myBytesPerSecond = myAudioSpec.freq * myBytesPerUnit;
SDL_PauseAudioDevice(myAudioDevice, 0); SDL_PauseAudioDevice(myAudioDevice, 0);
return true; return true;
@ -133,7 +139,7 @@ namespace
const float coeff = 1.0 / myBytesPerSecond; const float coeff = 1.0 / myBytesPerSecond;
info.buffer = bytesInBuffer * coeff; info.buffer = bytesInBuffer * coeff;
info.queue = bytesInQueue * coeff; info.queue = bytesInQueue * coeff;
info.size = myBuffer->bufferSize * coeff; info.size = std::max(myBuffer->bufferSize * coeff, float(ourBufferSize / 1000.0));
} }
return info; return info;
@ -177,14 +183,17 @@ namespace
// otherwise AW starts generating a lot of samples // otherwise AW starts generating a lot of samples
// and we loose sync // and we loose sync
// assume SDL's buffer is the same size as AW's const int queued = SDL_GetQueuedAudioSize(myAudioDevice);
const int bytesFree = myBuffer->bufferSize - SDL_GetQueuedAudioSize(myAudioDevice); const int bufferSize = myBytesPerSecond * DirectSoundGenerator::ourBufferSize / 1000;
if (bytesFree > 0) if (queued < bufferSize) // trigger is already <= target
{ {
// make sure we only copy full frames
const int bytesToCopy = ((bufferSize - queued) / myBytesPerUnit) * myBytesPerUnit;
LPVOID lpvAudioPtr1, lpvAudioPtr2; LPVOID lpvAudioPtr1, lpvAudioPtr2;
DWORD dwAudioBytes1, dwAudioBytes2; DWORD dwAudioBytes1, dwAudioBytes2;
myBuffer->Read(bytesFree, &lpvAudioPtr1, &dwAudioBytes1, &lpvAudioPtr2, &dwAudioBytes2); myBuffer->Read(bytesToCopy, &lpvAudioPtr1, &dwAudioBytes1, &lpvAudioPtr2, &dwAudioBytes2);
if (lpvAudioPtr1 && dwAudioBytes1) if (lpvAudioPtr1 && dwAudioBytes1)
{ {
@ -260,4 +269,14 @@ namespace sa2
return info; return info;
} }
void getAudioBufferSize(int & size)
{
size = DirectSoundGenerator::ourBufferSize;
}
void setAudioBufferSize(const int size)
{
DirectSoundGenerator::ourBufferSize = size;
}
} }

View file

@ -22,4 +22,7 @@ namespace sa2
void writeAudio(); void writeAudio();
void printAudioInfo(); void printAudioInfo();
std::vector<SoundInfo> getAudioInfo(); std::vector<SoundInfo> getAudioInfo();
void getAudioBufferSize(int & size);
void setAudioBufferSize(const int size);
} }

View file

@ -55,11 +55,6 @@ HRESULT IDirectSoundBuffer::Stop()
return DS_OK; return DS_OK;
} }
HRESULT IDirectSoundBuffer::SetCurrentPosition( DWORD dwNewPosition )
{
return DS_OK;
}
HRESULT IDirectSoundBuffer::Play( DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags ) HRESULT IDirectSoundBuffer::Play( DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags )
{ {
this->myStatus |= DSBSTATUS_PLAYING; this->myStatus |= DSBSTATUS_PLAYING;
@ -102,6 +97,7 @@ HRESULT IDirectSoundBuffer::Lock( DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOI
} }
else else
{ {
myWritePosition = dwWriteCursor;
const DWORD availableInFirstPart = this->mySoundBuffer.size() - dwWriteCursor; const DWORD availableInFirstPart = this->mySoundBuffer.size() - dwWriteCursor;
*lplpvAudioPtr1 = this->mySoundBuffer.data() + dwWriteCursor; *lplpvAudioPtr1 = this->mySoundBuffer.data() + dwWriteCursor;

View file

@ -78,8 +78,8 @@ class IDirectSoundBuffer : public IUnknown
const std::unique_ptr<IDirectSoundNotify> mySoundNotify; const std::unique_ptr<IDirectSoundNotify> mySoundNotify;
std::vector<char> mySoundBuffer; std::vector<char> mySoundBuffer;
size_t myPlayPosition = 0; size_t myPlayPosition = 0x0000;
size_t myWritePosition = 0; size_t myWritePosition = 0x0100;
WORD myStatus = 0; WORD myStatus = 0;
LONG myVolume = DSBVOLUME_MAX; LONG myVolume = DSBVOLUME_MAX;
@ -95,7 +95,6 @@ class IDirectSoundBuffer : public IUnknown
HRESULT QueryInterface(int riid, void **ppvObject); HRESULT QueryInterface(int riid, void **ppvObject);
HRESULT SetCurrentPosition( DWORD dwNewPosition );
HRESULT GetCurrentPosition( LPDWORD lpdwCurrentPlayCursor, LPDWORD lpdwCurrentWriteCursor ); HRESULT GetCurrentPosition( LPDWORD lpdwCurrentPlayCursor, LPDWORD lpdwCurrentWriteCursor );
// Read is NOT part of Windows API // Read is NOT part of Windows API