#pragma once #include #include #include #include #include struct ma_device; struct audio_compressor; struct attachment_send_req; class AudioRecorder : public QObject { Q_OBJECT public: explicit AudioRecorder(QObject* parent = nullptr); ~AudioRecorder() override; bool init(); void shutdown(); bool isInitialized() const { return m_initialized; } void setCaptureDeviceIndex(int index) { m_captureDeviceIndex = index; } int captureDeviceIndex() const { return m_captureDeviceIndex; } void startRecording(); void stopRecording(); bool isRecording() const { return m_recording; } float peakLevel() const; const int16_t* bufferData() const; size_t bufferSize() const; const std::vector& waveformLevels() const { return m_waveformLevels; } int durationMs() const; bool takeRecording(struct attachment_send_req* request); /* Передать остановленную запись без копии PCM. */ struct audio_compressor* compressor() const { return m_compressor; } void setCompressorEnabled(bool enabled); bool isCompressorEnabled() const { return m_compressorEnabled; } signals: void recordingStarted(); void recordingStopped(int durationMs); void durationChanged(int ms); private: ma_device* m_device = nullptr; bool m_initialized = false; bool m_recording = false; bool m_deviceStarted = false; int m_sampleRate = 48000; int m_channels = 1; int m_captureDeviceIndex = -1; std::vector m_pcmBuffer; mutable float m_peakLevel = 0.0f; std::vector m_recentRms = std::vector(5, 0.0f); int m_rmsIdx = 0; std::vector m_waveformLevels; QTimer m_durationTimer; int m_elapsedMs = 0; struct audio_compressor* m_compressor = nullptr; bool m_compressorEnabled = false; friend void audioCaptureCallback(ma_device* pDevice, void* pOutput, const void* pInput, unsigned int frameCount); };