mirror of
https://github.com/niellun/FastCarPlay.git
synced 2026-09-23 02:10:42 +02:00
Fix audio buffering
This commit is contained in:
+37
-27
@@ -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
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user