Fix audio buffering

This commit is contained in:
Niellune
2025-06-12 02:20:57 +03:00
parent 95a4e29501
commit b00de2c6ad
2 changed files with 42 additions and 29 deletions
+37 -27
View File
@@ -41,6 +41,12 @@ PcmAudio::~PcmAudio()
void PcmAudio::fadecpy(uint8_t *target, uint8_t *source, size_t len) void PcmAudio::fadecpy(uint8_t *target, uint8_t *source, size_t len)
{ {
if (!_fade && !_faded)
{
std::memcpy(target, source, len);
return;
}
int16_t *src = reinterpret_cast<int16_t *>(source); int16_t *src = reinterpret_cast<int16_t *>(source);
int16_t *dst = reinterpret_cast<int16_t *>(target); int16_t *dst = reinterpret_cast<int16_t *>(target);
_faded = true; _faded = true;
@@ -66,32 +72,41 @@ void PcmAudio::callback(void *userdata, Uint8 *stream, int len)
PcmAudio *self = static_cast<PcmAudio *>(userdata); PcmAudio *self = static_cast<PcmAudio *>(userdata);
const Message *segment = self->_data->peek(); const Message *segment = self->_data->peek();
if (segment && self->_offset == 0 && getConfig(segment->getInt(OFFSET_AUDIO_FORMAT)) != self->_config) if (segment && self->_offset == 0 && getConfig(segment->getInt(OFFSET_AUDIO_FORMAT)) != self->_config)
self->_reconfig = true;
bool underflow;
if (self->_data->has(self->_underflowSize))
{ {
underflow = false; self->_paused = true;
self->_underflowCount = 0; self->_cv.notify_one();
} }
else
if (self->_underflow)
{ {
underflow = true; int count = self->_data->count();
if (count > self->_prefill)
self->_underflow = false;
else if (count == self->_lastCount)
self->_underflowCount++;
else
self->_lastCount = count;
} }
while (len > 0) while (len > 0)
{ {
if (segment == nullptr || self->_reconfig || underflow) if(segment == nullptr && !self->_underflow)
{
if (self->_fader)
self->_fader->Fade(false);
self->_underflowCount = 0;
self->_underflow = true;
}
if (self->_underflow)
{ {
std::fill_n(stream, len, 0); std::fill_n(stream, len, 0);
self->_faded = self->_fade; self->_faded = self->_fade;
self->_volume = self->_faded ? Settings::audioFade : 1; self->_volume = self->_faded ? Settings::audioFade : 1;
if (underflow && self->_underflowCount++ < 20) if (self->_underflowCount < BUFFER_WAIT_COUNT)
{
self->_data->clear();
return; return;
} self->_data->clear();
self->_reconfig = true; self->_paused = true;
self->_cv.notify_one(); self->_cv.notify_one();
return; return;
} }
@@ -101,19 +116,12 @@ void PcmAudio::callback(void *userdata, Uint8 *stream, int len)
if (remain > len) if (remain > len)
{ {
if (self->_fade || self->_faded) self->fadecpy(stream, data, len);
self->fadecpy(stream, data, len);
else
std::memcpy(stream, data, len);
self->_offset = self->_offset + len; self->_offset = self->_offset + len;
return; return;
} }
if (self->_fade || self->_faded) self->fadecpy(stream, data, remain);
self->fadecpy(stream, data, remain);
else
std::memcpy(stream, data, remain);
len = len - remain; len = len - remain;
stream = stream + remain; stream = stream + remain;
self->_data->pop(); self->_data->pop();
@@ -121,7 +129,7 @@ void PcmAudio::callback(void *userdata, Uint8 *stream, int len)
segment = self->_data->peek(); segment = self->_data->peek();
if (segment && getConfig(segment->getInt(OFFSET_AUDIO_FORMAT)) != self->_config) if (segment && getConfig(segment->getInt(OFFSET_AUDIO_FORMAT)) != self->_config)
{ {
self->_reconfig = true; self->_paused = true;
self->_cv.notify_one(); self->_cv.notify_one();
} }
} }
@@ -201,9 +209,11 @@ void PcmAudio::runner()
} }
_offset = 0; _offset = 0;
_reconfig = false; _paused = false;
_underflow = true;
_underflowCount = 0; _underflowCount = 0;
_underflowSize = spec.channels == 1 ? Settings::audioDelayCall : Settings::audioDelay; _lastCount = 0;
_prefill = spec.channels == 1 ? Settings::audioDelayCall : Settings::audioDelay;
SDL_PauseAudioDevice(device, 0); SDL_PauseAudioDevice(device, 0);
std::cout << _name << " Start playing " << _config.rate << "kHz " << (_config.channels == 2 ? "stereo" : "mono") << std::endl; std::cout << _name << " Start playing " << _config.rate << "kHz " << (_config.channels == 2 ? "stereo" : "mono") << std::endl;
@@ -212,7 +222,7 @@ void PcmAudio::runner()
std::unique_lock<std::mutex> lock(_mtx); std::unique_lock<std::mutex> lock(_mtx);
_cv.wait(lock, [&] _cv.wait(lock, [&]
{ return _reconfig.load() || !_active.load(); }); { return _paused.load() || !_active.load(); });
SDL_PauseAudioDevice(device, 1); SDL_PauseAudioDevice(device, 1);
std::cout << _name << " Stop playing" << std::endl; std::cout << _name << " Stop playing" << std::endl;
+5 -2
View File
@@ -12,6 +12,7 @@
#define FADE_IN_SPEED 0.00001 #define FADE_IN_SPEED 0.00001
#define FADE_OUT_SPEED 0.0001 #define FADE_OUT_SPEED 0.0001
#define BUFFER_WAIT_COUNT 5
struct ChannelConfig struct ChannelConfig
{ {
@@ -58,13 +59,15 @@ private:
bool _faded; bool _faded;
float _volume; float _volume;
float _fadeVolume; float _fadeVolume;
bool _underflow;
int _underflowCount; int _underflowCount;
int _underflowSize; int _lastCount;
int _prefill;
std::thread _thread; std::thread _thread;
std::mutex _mtx; std::mutex _mtx;
std::condition_variable _cv; std::condition_variable _cv;
std::atomic<bool> _reconfig{false}; std::atomic<bool> _paused{false};
std::atomic<bool> _active{false}; std::atomic<bool> _active{false};
std::string _name; std::string _name;
}; };