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
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мс) */ |
|
};
|
|
|