chatgui: report radio output progress with device timing
This commit is contained in:
1 parent
fe7aabb44a
commit
06c35839ef
3 files changed
+31
-6
No files matched your search
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user