chatgui: report radio output progress with device timing

This commit is contained in:
evgeny committed 2026-10-08 14:27:05 +02:00
1 parent fe7aabb44a
commit 06c35839ef
3 files changed
+31 -6

No files matched your search

+25 -3
View File
@@ -21,7 +21,8 @@ VoiceAudioIo::~VoiceAudioIo() { stop(); }
bool VoiceAudioIo::start(Kind kind, uint64_t session) {
stop();
m_kind = kind; m_session = session;
m_captureEvents.reset(); m_references.reset(); m_playback.reset();
m_captureEvents.reset(); m_references.reset(); m_playback.reset(); m_playProgress.reset();
m_progressDropped = 0;
m_playPosition = 960; m_playEpoch = 1;
m_captureDropped = m_referenceDropped = m_playbackUnderruns = 0;
m_running = true;
@@ -121,8 +122,10 @@ void VoiceAudioIo::reference(const float* pcm, unsigned frames, int64_t firstTim
}
/* Выход всегда обслуживается независимо от capture/VAD. Уже потреблённый PCM становится референсом у владельца микшера. */
void VoiceAudioIo::mix(float* stereo, unsigned frames) {
void VoiceAudioIo::mix(float* stereo, unsigned frames, int64_t firstTimeUs) {
uint64_t epoch = m_playEpoch.load();
if (!firstTimeUs) firstTimeUs = voice_time_us();
unsigned consumed = 0;
for (unsigned i = 0; i < frames; ++i) {
if (m_playCurrent.epoch != epoch) m_playPosition = 960;
if (m_playPosition == 960) {
@@ -135,26 +138,45 @@ void VoiceAudioIo::mix(float* stereo, unsigned frames) {
stereo[2*i] += m_playCurrent.pcm[2*m_playPosition] / 32768.0f;
stereo[2*i+1] += m_playCurrent.pcm[2*m_playPosition+1] / 32768.0f;
++m_playPosition;
++consumed;
}
if (m_kind == Kind::Radio && consumed) {
PlaybackProgress progress{epoch, m_playCurrent.position + m_playPosition,
firstTimeUs + (int64_t)consumed * 1000000 / 48000};
if (!m_playProgress.push(progress)) m_progressDropped.fetch_add(1, std::memory_order_relaxed);
}
m_wake.notify_all();
}
void VoiceAudioIo::playbackLoop() {
uint64_t epoch = m_playEpoch.load();
uint64_t position = 0;
if (m_kind == Kind::Radio) radio_audio_playback_progress(m_session, 0, 0);
while (m_running) {
uint64_t requested = m_playEpoch.load();
if (requested != epoch) {
if (m_kind == Kind::Call) call_audio_reset_io(m_session, 1);
else radio_audio_reset_playback(m_session);
position = 0;
epoch = requested;
}
PlaybackProgress progress{};
for (unsigned count = 0; count < 32 && m_playProgress.pop(progress); ++count) {
if (progress.epoch != epoch) continue;
int64_t remaining = progress.endTimeUs - voice_time_us();
radio_audio_playback_progress(m_session, progress.position, remaining > 0 ? (remaining + 99) / 100 : 0);
}
unsigned lost = m_progressDropped.exchange(0);
if (lost) DEBUG_WARN(DEBUG_CATEGORY_RADIO, "voice-io: playback progress overflow session=%llu dropped=%u",
(unsigned long long)m_session, lost);
if (m_playback.size() < 2) {
Playback block{}; block.epoch = epoch;
Playback block{}; block.epoch = epoch; block.position = position;
if (m_kind == Kind::Call) {
int16_t mono[960]{};
int count = std::clamp(call_audio_pull_pcm(m_session, mono, 960), 0, 960);
for (int i = 0; i < count; ++i) block.pcm[2*i] = block.pcm[2*i+1] = mono[i];
} else radio_audio_pull_pcm(m_session, block.pcm, 1920);
position += 960;
if (!m_playback.push(block)) DEBUG_WARN(DEBUG_CATEGORY_CALL, "voice-io: playback queue contention");
} else {
std::unique_lock lock(m_waitMutex);