Audio recording fixed

This commit is contained in:
Niellune
2026-03-24 16:42:27 +02:00
parent 93c10a9f72
commit 6001a0eb96
5 changed files with 53 additions and 20 deletions
+2 -2
View File
@@ -24,9 +24,9 @@ void Logger::setLevel(int level)
return; return;
} }
if (level > static_cast<int>(Level::Verbose)) if (level > static_cast<int>(Level::Protocol))
{ {
_level = Level::Verbose; _level = Level::Protocol;
return; return;
} }
+49 -16
View File
@@ -3,6 +3,7 @@
#include "protocol/protocol_const.h" #include "protocol/protocol_const.h"
#include "settings.h" #include "settings.h"
#include "common/logger.h" #include "common/logger.h"
#include <time.h>
// Add sample size (buffer size in samples) to ChannelConfig // Add sample size (buffer size in samples) to ChannelConfig
ChannelConfig PcmAudio::_configTable[] = { ChannelConfig PcmAudio::_configTable[] = {
@@ -24,6 +25,7 @@ PcmAudio::PcmAudio(const char *name) : _name("default"),
{ {
if (name && strlen(name) > 0) if (name && strlen(name) > 0)
_name = name; _name = name;
log_v("Created %s", _name.c_str());
} }
PcmAudio::~PcmAudio() PcmAudio::~PcmAudio()
@@ -31,12 +33,14 @@ PcmAudio::~PcmAudio()
stop(); stop();
if (_thread.joinable()) if (_thread.joinable())
_thread.join(); _thread.join();
log_v("Destroyed %s", _name.c_str());
} }
void PcmAudio::start(AtomicQueue<Message> *data, PcmAudio *fader) void PcmAudio::start(AtomicQueue<Message> *data, PcmAudio *fader)
{ {
if (_active) if (_active)
stop(); stop();
log_v("Starting %s", _name.c_str());
_fader = fader; _fader = fader;
_data = data; _data = data;
_active = true; _active = true;
@@ -47,6 +51,7 @@ void PcmAudio::stop()
{ {
if (!_active) if (!_active)
return; return;
log_v("Stopping %s", _name.c_str());
_active = false; _active = false;
_data->notify(); _data->notify();
} }
@@ -69,13 +74,11 @@ bool PcmAudio::isZero(const Message *msg)
{ {
const uint64_t *p = (const uint64_t *)msg->data(); const uint64_t *p = (const uint64_t *)msg->data();
int n = msg->length() / 8; int n = msg->length() / 8;
for (int i = 0; i < n; ++i) for (int i = 0; i < n; ++i)
{ {
if (p[i] != 0) if (p[i] != 0)
return false; return false;
} }
return true; return true;
} }
@@ -83,9 +86,7 @@ void PcmAudio::fade(bool enable)
{ {
_fade.store(enable); _fade.store(enable);
if (!_playing) if (!_playing)
{
_volume = enable ? Settings::audioFade : 1.0; _volume = enable ? Settings::audioFade : 1.0;
}
} }
void PcmAudio::fade(uint8_t *data, int32_t length) void PcmAudio::fade(uint8_t *data, int32_t length)
@@ -95,7 +96,7 @@ void PcmAudio::fade(uint8_t *data, int32_t length)
return; return;
int16_t *buf = reinterpret_cast<int16_t *>(data); int16_t *buf = reinterpret_cast<int16_t *>(data);
for (size_t i = 0; i < length / 2; i++) for (int i = 0; i < length / 2; i++)
{ {
if (fade) if (fade)
{ {
@@ -116,15 +117,29 @@ void PcmAudio::play(SDL_AudioDeviceID device, ChannelConfig config, int32_t segm
{ {
uint8_t zeroSegments = 0; uint8_t zeroSegments = 0;
bool nonZero = false; bool nonZero = false;
int prefill = config.channels == 1 ? Settings::audioDelayCall : Settings::audioDelay; int prefill = config.channels == 1 ? Settings::audioDelayCall : Settings::audioDelay;
int segmentTimeMs = 1000.0 * segmentSize / (config.rate * config.channels * 2.0); int segmentTimeMs = 1000.0 * segmentSize / (config.rate * config.channels * 2.0);
int waitTimeMs = (prefill + 1) * segmentTimeMs;
log_i("Prepare to play %s %dkHz %s chunk %d ~%dms prefill %d ~%dms", _name.c_str(),
config.rate,
(config.channels == 2 ? "stereo" : "mono"),
segmentSize,
segmentTimeMs,
prefill,
waitTimeMs);
log_i("Prepare to play %s %dkHz %s prefill %d ~%dms chunk %d", _name.c_str(), config.rate, (config.channels == 2 ? "stereo" : "mono"), prefill, segmentTimeMs, segmentSize); if (!_data->waitFor(_active, AUDIO_RESET_SECONDS * 1000, prefill))
if (!_data->waitFor(_active, segmentTimeMs * (prefill + 1) * 3, prefill))
{ {
_data->clear(); _data->clear();
log_w("Not enough data to play %s %dkHz %s prefill %d ~%dms chunk %d", _name.c_str(), config.rate, (config.channels == 2 ? "stereo" : "mono"), prefill, segmentTimeMs, segmentSize); log_w("Not enough data to play %s %dkHz %s chunk %d ~%dms prefill %d ~%dms",
_name.c_str(),
config.rate,
(config.channels == 2 ? "stereo" : "mono"),
segmentSize,
segmentTimeMs,
prefill,
waitTimeMs);
return; return;
} }
@@ -142,11 +157,15 @@ void PcmAudio::play(SDL_AudioDeviceID device, ChannelConfig config, int32_t segm
return; return;
fade(segment->data(), segment->length()); fade(segment->data(), segment->length());
SDL_QueueAudio(device, segment->data(), segment->length()); SDL_QueueAudio(device, segment->data(), segment->length());
if (!_playing) if (!_playing && prefill-- <= 0)
{ {
log_d("Start playing %s %dkHz %s", _name.c_str(), config.rate, (config.channels == 2 ? "stereo" : "mono")); log_d("Start playing %s %dkHz %s",
_name.c_str(),
config.rate,
(config.channels == 2 ? "stereo" : "mono"));
SDL_PauseAudioDevice(device, 0); SDL_PauseAudioDevice(device, 0);
_playing = true; _playing = true;
} }
@@ -169,7 +188,7 @@ void PcmAudio::play(SDL_AudioDeviceID device, ChannelConfig config, int32_t segm
} }
} }
if (!_data->waitFor(_active, segmentTimeMs * 3)) if (!_data->waitFor(_active, waitTimeMs))
return; return;
} }
} }
@@ -179,11 +198,12 @@ void PcmAudio::loop()
std::string threadName = "audio-" + _name; std::string threadName = "audio-" + _name;
setThreadName(threadName.c_str()); setThreadName(threadName.c_str());
log_d("Audio %s thread started", _name.c_str()); log_d("Started thread %s", _name.c_str());
SDL_AudioDeviceID device = 0; SDL_AudioDeviceID device = 0;
SDL_AudioSpec spec; SDL_AudioSpec spec;
time_t playEnd = time(NULL);
while (_data->wait(_active)) while (_data->wait(_active))
{ {
const Message *segment = _data->peek(); const Message *segment = _data->peek();
@@ -213,13 +233,20 @@ void PcmAudio::loop()
device = SDL_OpenAudioDevice(nullptr, 0, &spec, nullptr, 0); device = SDL_OpenAudioDevice(nullptr, 0, &spec, nullptr, 0);
if (device == 0) if (device == 0)
{ {
log_w("Failed to open audio %s > %s", _name.c_str(), SDL_GetError()); log_w("Failed to open audio %s %dkHz %s samples %d > %s",
_name.c_str(),
config.rate,
(config.channels == 2 ? "stereo" : "mono"),
Settings::audioBuffer * config.scale, SDL_GetError());
SDL_Delay(100); SDL_Delay(100);
continue; continue;
} }
_config = config; _config = config;
} }
if (difftime(time(NULL), playEnd) > AUDIO_RESET_SECONDS)
SDL_ClearQueuedAudio(device);
if (_fader) if (_fader)
_fader->fade(true); _fader->fade(true);
play(device, config, segment->length()); play(device, config, segment->length());
@@ -227,13 +254,19 @@ void PcmAudio::loop()
if (_fader) if (_fader)
_fader->fade(false); _fader->fade(false);
SDL_PauseAudioDevice(device, 1); SDL_PauseAudioDevice(device, 1);
log_i("Stop playing %s", _name.c_str()); playEnd = time(NULL);
log_d("Stop playing %s %dkHz %s",
_name.c_str(),
config.rate,
(config.channels == 2 ? "stereo" : "mono"));
} }
if (device) if (device != 0)
{ {
SDL_PauseAudioDevice(device, 1); SDL_PauseAudioDevice(device, 1);
SDL_ClearQueuedAudio(device); SDL_ClearQueuedAudio(device);
SDL_CloseAudioDevice(device); SDL_CloseAudioDevice(device);
} }
log_v("Stopped thread %s", _name.c_str());
} }
+1
View File
@@ -13,6 +13,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 FADE_ZERO_SEGMENTS 10 #define FADE_ZERO_SEGMENTS 10
#define AUDIO_RESET_SECONDS 5
struct ChannelConfig struct ChannelConfig
{ {
+1
View File
@@ -183,6 +183,7 @@ void Connection::writeLoop(libusb_device_handle *handler, uint8_t ep)
int transferred; int transferred;
libusb_bulk_transfer(handler, ep, message->header(), message->headerSize(), &transferred, 0); libusb_bulk_transfer(handler, ep, message->header(), message->headerSize(), &transferred, 0);
message->setOffset(0);
if (message->length() > 0) if (message->length() > 0)
libusb_bulk_transfer(handler, ep, message->data(), message->length(), &transferred, 0); libusb_bulk_transfer(handler, ep, message->data(), message->length(), &transferred, 0);
} }
-2
View File
@@ -25,8 +25,6 @@ ConnectionReader::ConnectionReader()
ConnectionReader::~ConnectionReader() ConnectionReader::~ConnectionReader()
{ {
log_v("Destroying");
stop(); stop();
for (Context &context : _transfers) for (Context &context : _transfers)