You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

73 lines
3.4 KiB

#pragma once
#include <QObject>
#include <atomic>
#include <cstdint>
#include <vector>
struct ma_device;
/* Аудио-контур рации (desktop): только miniaudio I/O + захват/воспроизведение.
* Весь аудиопроцессинг (Opus, per-source декодеры, микшер) — в сервисном слое
* src/radio/radio_audio.c; сюда приходит/отсюда уходит финальный PCM.
*
* Потоки:
* - аудио-поток (miniaudio callback): capture → radio_audio_feed_pcm,
* radio_audio_pull_pcm → playback;
* - GUI-поток: start()/stop() по включению/выключению рации канала. */
class RadioAudioEngine : public QObject {
Q_OBJECT
public:
static RadioAudioEngine* instance();
/* Включить прослушивание канала (после toggle рации). 0 = успех. */
int start(quint64 groupId);
/* Выключить прослушивание канала (toggle рации выключен). */
void stop();
/* PTT: зажата / отпущена (только когда радио канала включено). */
void talkBegin();
void talkEnd();
void setHotkeyTalking(bool pressed); // независимый владелец PTT — глобальная клавиатура
bool isTalking() const { return m_talking.load(); }
bool isActive() const { return m_active.load(); }
quint64 groupId() const { return m_groupId.load(); }
/* аудио-поток: miniaudio callbacks (захват и воспроизведение раздельно) */
void captureCallback(const void* in, unsigned int frames);
void playbackCallback(void* out, unsigned int frames);
signals:
void talkingChanged(bool talking); // GUI-поток, суммарное состояние кнопки и хоткея
private:
RadioAudioEngine() = default;
void updateTalking();
bool m_buttonTalking = false, m_hotkeyTalking = false; // GUI-поток
void teardownDevice();
int initDevice();
std::atomic<bool> m_active{false};
std::atomic<bool> m_talking{false};
std::atomic<bool> m_vadMode{false}; /* VAD авто-PTT: фидим PCM постоянно */
std::atomic<uint64_t> m_groupId{0};
ma_device* m_captureDevice = nullptr;
ma_device* m_playbackDevice = nullptr;
bool m_captureStarted = false;
bool m_playbackStarted = false;
std::vector<int16_t> m_captureBuf; /* FRAME_SAMPLES * m_captureChannels, аудио-поток */
int m_capturePos = 0;
int m_captureChannels = 1; /* 1=моно, 2=стерео — по настройке/возможности */
/* диагностика (DEBUG_CATEGORY_DEBUG): фактический cadence playback-коллбэка */
unsigned int m_dbgFrames = 0;
uint32_t m_dbgCbCount = 0;
uint64_t m_dbgLastTb = 0; /* момент предыдущего сброса статистики (для cb/s) */
uint64_t m_dbgPrevCbTb = 0; /* момент входа предыдущего коллбэка */
uint64_t m_dbgGapMax = 0; /* макс. gap между коллбэками за окно (tb 0.1мс) */
uint64_t m_dbgBodyMax = 0; /* макс. длительность тела коллбэка за окно (tb 0.1мс) */
};