Drive desktop call clock from rendered PCM and capture timing

This commit is contained in:
evgeny committed 2026-10-14 19:28:38 +02:00
1 parent 7bac999d93
commit 39bfedca86
3 files changed
+23 -11

No files matched your search

+18 -8
View File
@@ -122,7 +122,7 @@ void VoiceAudioIo::reference(const float* pcm, unsigned frames, int64_t firstTim
}
/* Выход всегда обслуживается независимо от capture/VAD. Уже потреблённый PCM становится референсом у владельца микшера. */
void VoiceAudioIo::mix(float* stereo, unsigned frames, int64_t firstTimeUs) {
void VoiceAudioIo::mix(float* stereo, unsigned frames, int64_t firstTimeUs, bool measured) {
uint64_t epoch = m_playEpoch.load();
if (!firstTimeUs) firstTimeUs = voice_time_us();
unsigned consumed = 0;
@@ -140,9 +140,9 @@ void VoiceAudioIo::mix(float* stereo, unsigned frames, int64_t firstTimeUs) {
++m_playPosition;
++consumed;
}
if (m_kind == Kind::Radio && consumed) {
if (consumed) {
PlaybackProgress progress{epoch, m_playCurrent.position + m_playPosition,
firstTimeUs + (int64_t)consumed * 1000000 / 48000};
firstTimeUs + (int64_t)consumed * 1000000 / 48000, measured};
if (!m_playProgress.push(progress)) m_progressDropped.fetch_add(1, std::memory_order_relaxed);
}
m_wake.notify_all();
@@ -151,11 +151,18 @@ void VoiceAudioIo::mix(float* stereo, unsigned frames, int64_t firstTimeUs) {
void VoiceAudioIo::playbackLoop() {
uint64_t epoch = m_playEpoch.load();
uint64_t position = 0;
call_clock_snapshot clock{};
if (m_kind == Kind::Call && call_audio_get_clock(m_session, voice_time_us(), &clock) != 0)
DEBUG_WARN(DEBUG_CATEGORY_CALL, "voice-io: call clock unavailable session=%llu", (unsigned long long)m_session);
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);
if (m_kind == Kind::Call) {
call_audio_reset_io(m_session, 1);
if (call_audio_get_clock(m_session, voice_time_us(), &clock) != 0)
DEBUG_WARN(DEBUG_CATEGORY_CALL, "voice-io: reset call clock unavailable session=%llu", (unsigned long long)m_session);
}
else radio_audio_reset_playback(m_session);
position = 0;
epoch = requested;
@@ -163,11 +170,13 @@ void VoiceAudioIo::playbackLoop() {
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);
int64_t now = voice_time_us(), remaining = progress.endTimeUs - now;
if (m_kind == Kind::Call)
call_audio_playback_progress(m_session, clock.epoch, progress.position, progress.endTimeUs, now, progress.measured);
else 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",
if (lost) DEBUG_WARN(DEBUG_CATEGORY_CALL, "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; block.position = position;
@@ -282,7 +291,7 @@ void VoiceAudioIo::captureLoop() {
if (mark < markerCount) applyMarker(markers[mark].kind, markers[mark].value);
begin = end;
}
if (m_kind == Kind::Call && frames == 960) call_audio_feed_prepared_pcm(m_session, cleaned, muteMask);
if (m_kind == Kind::Call && frames == 960) call_audio_feed_prepared_pcm(m_session, cleaned, muteMask, frameTime);
filled = 0; markerCount = 0;
};
// Отчёт работает и при отсутствии PCM, иначе длительный провал захвата невидим.
@@ -350,6 +359,7 @@ void VoiceAudioIo::captureLoop() {
filled = 0; markerCount = 0;
if (aec) speex_aec_reset(aec);
if (m_kind == Kind::Radio) radio_audio_capture_discontinuity(m_session);
else call_audio_reset_io(m_session, 0);
}
expectedSequence = event.sequence + event.frames;
captureRoute = event.route;
+2 -2
View File
@@ -27,7 +27,7 @@ public:
/* firstTimeUs — монотонное время первого физического PCM-фрейма (backend либо оценка). */
void capture(const int16_t* pcm, unsigned frames, int64_t firstTimeUs, uint64_t route = 0, bool missing = false);
void reference(const float* pcm, unsigned frames, int64_t firstTimeUs);
void mix(float* stereo, unsigned frames, int64_t firstTimeUs = 0);
void mix(float* stereo, unsigned frames, int64_t firstTimeUs = 0, bool measured = false);
private:
enum class EventKind { Pcm, Ptt, Mute, Aec, Stop };
struct Event {
@@ -41,7 +41,7 @@ private:
int16_t pcm[1920]{};
};
struct Playback { uint64_t epoch = 0, position = 0; int16_t pcm[1920]{}; };
struct PlaybackProgress { uint64_t epoch = 0, position = 0; int64_t endTimeUs = 0; };
struct PlaybackProgress { uint64_t epoch = 0, position = 0; int64_t endTimeUs = 0; bool measured = false; };
AudioEventQueue<Event, 32> m_captureEvents, m_references;
AudioEventQueue<Playback, 12> m_playback;
AudioEventQueue<PlaybackProgress, 32> m_playProgress;