v1.8.0: Audio 代码重构与低功耗优化 (#943)

* Reconstruct Audio Code

* Remove old IoT implementation

* Add MQTT-UDP documentation

* OTA升级失败时,可以继续使用
This commit is contained in:
Xiaoxia
2025-07-19 22:45:22 +08:00
committed by GitHub
parent 0621578f55
commit 3c71558a5f
173 changed files with 2099 additions and 3265 deletions

View File

@@ -8,26 +8,21 @@
#include <string>
#include <mutex>
#include <list>
#include <deque>
#include <vector>
#include <condition_variable>
#include <memory>
#include <opus_encoder.h>
#include <opus_decoder.h>
#include <opus_resampler.h>
#include "protocol.h"
#include "ota.h"
#include "background_task.h"
#include "audio_processor.h"
#include "wake_word.h"
#include "audio_debugger.h"
#include "audio_service.h"
#include "device_state_event.h"
#define SCHEDULE_EVENT (1 << 0)
#define SEND_AUDIO_EVENT (1 << 1)
#define CHECK_NEW_VERSION_DONE_EVENT (1 << 2)
#define MAIN_EVENT_SCHEDULE (1 << 0)
#define MAIN_EVENT_SEND_AUDIO (1 << 1)
#define MAIN_EVENT_WAKE_WORD_DETECTED (1 << 2)
#define MAIN_EVENT_VAD_CHANGE (1 << 3)
#define MAIN_EVENT_ERROR (1 << 4)
#define MAIN_EVENT_CHECK_NEW_VERSION_DONE (1 << 5)
enum AecMode {
kAecOff,
@@ -35,10 +30,6 @@ enum AecMode {
kAecOnServerSide,
};
#define OPUS_FRAME_DURATION_MS 60
#define MAX_AUDIO_PACKETS_IN_QUEUE (2400 / OPUS_FRAME_DURATION_MS)
#define AUDIO_TESTING_MAX_DURATION_MS 10000
class Application {
public:
static Application& GetInstance() {
@@ -51,7 +42,7 @@ public:
void Start();
DeviceState GetDeviceState() const { return device_state_; }
bool IsVoiceDetected() const { return voice_detected_; }
bool IsVoiceDetected() const { return audio_service_.IsVoiceDetected(); }
void Schedule(std::function<void()> callback);
void SetDeviceState(DeviceState state);
void Alert(const char* status, const char* message, const char* emotion = "", const std::string_view& sound = "");
@@ -60,72 +51,41 @@ public:
void ToggleChatState();
void StartListening();
void StopListening();
void UpdateIotStates();
void Reboot();
void WakeWordInvoke(const std::string& wake_word);
void PlaySound(const std::string_view& sound);
bool CanEnterSleepMode();
void SendMcpMessage(const std::string& payload);
void SetAecMode(AecMode mode);
bool ReadAudio(std::vector<int16_t>& data, int sample_rate, int samples);
AecMode GetAecMode() const { return aec_mode_; }
BackgroundTask* GetBackgroundTask() const { return background_task_; }
void PlaySound(const std::string_view& sound);
AudioService& GetAudioService() { return audio_service_; }
private:
Application();
~Application();
std::unique_ptr<WakeWord> wake_word_;
std::unique_ptr<AudioProcessor> audio_processor_;
std::unique_ptr<AudioDebugger> audio_debugger_;
std::mutex mutex_;
std::list<std::function<void()>> main_tasks_;
std::deque<std::function<void()>> main_tasks_;
std::unique_ptr<Protocol> protocol_;
EventGroupHandle_t event_group_ = nullptr;
esp_timer_handle_t clock_timer_handle_ = nullptr;
volatile DeviceState device_state_ = kDeviceStateUnknown;
ListeningMode listening_mode_ = kListeningModeAutoStop;
AecMode aec_mode_ = kAecOff;
std::string last_error_message_;
AudioService audio_service_;
bool has_server_time_ = false;
bool aborted_ = false;
bool voice_detected_ = false;
bool busy_decoding_audio_ = false;
int clock_ticks_ = 0;
TaskHandle_t check_new_version_task_handle_ = nullptr;
// Audio encode / decode
TaskHandle_t audio_loop_task_handle_ = nullptr;
BackgroundTask* background_task_ = nullptr;
std::chrono::steady_clock::time_point last_output_time_;
std::list<AudioStreamPacket> audio_send_queue_;
std::list<AudioStreamPacket> audio_decode_queue_;
std::condition_variable audio_decode_cv_;
std::list<AudioStreamPacket> audio_testing_queue_;
// 新增用于维护音频包的timestamp队列
std::list<uint32_t> timestamp_queue_;
std::mutex timestamp_mutex_;
std::unique_ptr<OpusEncoderWrapper> opus_encoder_;
std::unique_ptr<OpusDecoderWrapper> opus_decoder_;
OpusResampler input_resampler_;
OpusResampler reference_resampler_;
OpusResampler output_resampler_;
void MainEventLoop();
void OnAudioInput();
void OnAudioOutput();
void ResetDecoder();
void SetDecodeSampleRate(int sample_rate, int frame_duration);
void OnWakeWordDetected();
void CheckNewVersion(Ota& ota);
void ShowActivationCode(const std::string& code, const std::string& message);
void OnClockTimer();
void SetListeningMode(ListeningMode mode);
void AudioLoop();
void EnterAudioTestingMode();
void ExitAudioTestingMode();
};
#endif // _APPLICATION_H_