Drive desktop call clock from rendered PCM and capture timing
This commit is contained in:
1 parent
7bac999d93
commit
39bfedca86
3 files changed
+23
-11
No files matched your search
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user