diff --git a/CHANGELOG b/CHANGELOG index 8c1f13d5..6e5979ef 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +1.6.0-bacon15 + Finally solve "Audio randomly dies" issue + Various additions FX Command Box selector (#238) * In phrase and table views a selection box appears when editing FX commands diff --git a/sources/Adapters/SDL2/Audio/SDLAudioDriver.cpp b/sources/Adapters/SDL2/Audio/SDLAudioDriver.cpp index 5035fce8..5ec3002e 100644 --- a/sources/Adapters/SDL2/Audio/SDLAudioDriver.cpp +++ b/sources/Adapters/SDL2/Audio/SDLAudioDriver.cpp @@ -10,7 +10,8 @@ void sdl_callback(void *userdata, Uint8 *stream, int len) { }; SDLAudioDriverThread::SDLAudioDriverThread(SDLAudioDriver *driver) { - semaphore_ = SysSemaphore::Create(0, 4); + // Uncap the semaphore to prevent dropped requests during long OS stalls. + semaphore_=SysSemaphore::Create(0,1024); driver_ = driver; }; @@ -62,6 +63,9 @@ bool SDLAudioDriver::InitDriver() { input.samples = settings_.bufferSize_; input.userdata = this; + SDL_SetHint("APP_NAME", "LittleGPTracker"); + SDL_SetHint("AUDIO_DEVICE_APP_NAME", "LittleGPTracker"); + // On my machine this wasn't working. // SDL_AudioDeviceID deviceId = // SDL_OpenAudioDevice(NULL,0,&input,&returned,0); The above may return 0 @@ -83,8 +87,8 @@ bool SDLAudioDriver::InitDriver() { mainBuffer_ = (char *)((((int)unalignedMain_) + 1) & (0xFFFFFFFC)); #endif - Trace::Log("AUDIO", "%s successfully opened with %d samples", driverName, - fragSize_ / 4); + Trace::Log("AUDIO", "%s successfully opened with %d samples %d", driverName, + fragSize_ / 4, returned.freq); // Create mini blank buffer in case of underruns @@ -153,14 +157,17 @@ void SDLAudioDriver::OnChunkDone(Uint8 *stream, int len) { while (bufferSize_ - bufferPos_ < len) { // First move remaining bytes at the front - memcpy(mainBuffer_, mainBuffer_ + bufferPos_, bufferSize_ - bufferPos_); + memmove(mainBuffer_, mainBuffer_ + bufferPos_, + bufferSize_ - bufferPos_); // then get next queued buffer and copy data from it if (pool_[poolPlayPosition_].buffer_ == 0) { - SYS_MEMCPY(mainBuffer_ + bufferSize_ - bufferPos_, miniBlank_, len); - bufferSize_ = bufferSize_ - bufferPos_ + len; - + // Use fragSize_ instead of len! miniBlank_ is only allocated to + // fragSize_. Using len causes a buffer over-read if SDL requests a + // larger chunk. + SYS_MEMCPY(mainBuffer_+bufferSize_-bufferPos_, miniBlank_, fragSize_); + bufferSize_=bufferSize_-bufferPos_+fragSize_ ; bufferPos_ = 0; } else { @@ -168,7 +175,6 @@ void SDLAudioDriver::OnChunkDone(Uint8 *stream, int len) { pool_[poolPlayPosition_].buffer_, pool_[poolPlayPosition_].size_); - MidiService::GetInstance()->Flush(); // Adapt buffer variables bufferSize_ = @@ -181,6 +187,12 @@ void SDLAudioDriver::OnChunkDone(Uint8 *stream, int len) { poolPlayPosition_ = (poolPlayPosition_ + 1) % SOUND_BUFFER_COUNT; if (thread_) thread_->Notify(); + // Tick the engine and flush MIDI ONLY when a real logical block is + // processed! This keeps the sequencer perfectly in sync with the + // audio pool consumption, and prevents runaway MIDI generation on + // underruns which fills the ALSA buffer and freezes the thread. + onAudioBufferTick(); + MidiService::GetInstance()->Flush() ; } } // Now dump audio to the device diff --git a/sources/Application/Model/Project.h b/sources/Application/Model/Project.h index a3c14a3c..00bfe0f4 100644 --- a/sources/Application/Model/Project.h +++ b/sources/Application/Model/Project.h @@ -21,7 +21,7 @@ #define PROJECT_NUMBER "1" #define PROJECT_RELEASE "6" -#define BUILD_COUNT "0-bacon14" +#define BUILD_COUNT "0-bacon15" #define MAX_TAP 3