feat: Use BOOT button to enter audio testing state when Wi-Fi configuring

This commit is contained in:
Terrence
2025-06-13 19:56:47 +08:00
parent dfad6a5b2c
commit bf125446b3
5 changed files with 62 additions and 1 deletions

View File

@@ -45,6 +45,7 @@ static const char* const STATE_STRINGS[] = {
"speaking",
"upgrading",
"activating",
"audio_testing",
"fatal_error",
"invalid_state"
};
@@ -290,10 +291,31 @@ void Application::PlaySound(const std::string_view& sound) {
}
}
void Application::EnterAudioTestingMode() {
ESP_LOGI(TAG, "Entering audio testing mode");
ResetDecoder();
SetDeviceState(kDeviceStateAudioTesting);
}
void Application::ExitAudioTestingMode() {
ESP_LOGI(TAG, "Exiting audio testing mode");
SetDeviceState(kDeviceStateWifiConfiguring);
// Copy audio_testing_queue_ to audio_decode_queue_
std::lock_guard<std::mutex> lock(mutex_);
audio_decode_queue_ = std::move(audio_testing_queue_);
audio_decode_cv_.notify_all();
}
void Application::ToggleChatState() {
if (device_state_ == kDeviceStateActivating) {
SetDeviceState(kDeviceStateIdle);
return;
} else if (device_state_ == kDeviceStateWifiConfiguring) {
EnterAudioTestingMode();
return;
} else if (device_state_ == kDeviceStateAudioTesting) {
ExitAudioTestingMode();
return;
}
if (!protocol_) {
@@ -327,6 +349,9 @@ void Application::StartListening() {
if (device_state_ == kDeviceStateActivating) {
SetDeviceState(kDeviceStateIdle);
return;
} else if (device_state_ == kDeviceStateWifiConfiguring) {
EnterAudioTestingMode();
return;
}
if (!protocol_) {
@@ -354,6 +379,11 @@ void Application::StartListening() {
}
void Application::StopListening() {
if (device_state_ == kDeviceStateAudioTesting) {
ExitAudioTestingMode();
return;
}
const std::array<int, 3> valid_states = {
kDeviceStateListening,
kDeviceStateSpeaking,
@@ -824,6 +854,28 @@ void Application::OnAudioOutput() {
}
void Application::OnAudioInput() {
if (device_state_ == kDeviceStateAudioTesting) {
if (audio_testing_queue_.size() >= AUDIO_TESTING_MAX_DURATION_MS / OPUS_FRAME_DURATION_MS) {
ExitAudioTestingMode();
return;
}
std::vector<int16_t> data;
int samples = OPUS_FRAME_DURATION_MS * 16000 / 1000;
if (ReadAudio(data, 16000, samples)) {
background_task_->Schedule([this, data = std::move(data)]() mutable {
opus_encoder_->Encode(std::move(data), [this](std::vector<uint8_t>&& opus) {
AudioStreamPacket packet;
packet.payload = std::move(opus);
packet.frame_duration = OPUS_FRAME_DURATION_MS;
packet.sample_rate = 16000;
std::lock_guard<std::mutex> lock(mutex_);
audio_testing_queue_.push_back(std::move(packet));
});
});
return;
}
}
if (wake_word_->IsDetectionRunning()) {
std::vector<int16_t> data;
int samples = wake_word_->GetFeedSize();
@@ -834,6 +886,7 @@ void Application::OnAudioInput() {
}
}
}
if (audio_processor_->IsRunning()) {
std::vector<int16_t> data;
int samples = audio_processor_->GetFeedSize();

View File

@@ -44,11 +44,13 @@ enum DeviceState {
kDeviceStateSpeaking,
kDeviceStateUpgrading,
kDeviceStateActivating,
kDeviceStateAudioTesting,
kDeviceStateFatalError
};
#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:
@@ -111,6 +113,7 @@ private:
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_;
@@ -134,6 +137,8 @@ private:
void OnClockTimer();
void SetListeningMode(ListeningMode mode);
void AudioLoop();
void EnterAudioTestingMode();
void ExitAudioTestingMode();
};
#endif // _APPLICATION_H_

View File

@@ -205,7 +205,8 @@ void CircularStrip::OnStateChanged() {
SetAllColor(color);
break;
}
case kDeviceStateListening: {
case kDeviceStateListening:
case kDeviceStateAudioTesting: {
StripColor color = { default_brightness_, low_brightness_, low_brightness_ };
SetAllColor(color);
break;

View File

@@ -220,6 +220,7 @@ void GpioLed::OnStateChanged() {
TurnOn();
break;
case kDeviceStateListening:
case kDeviceStateAudioTesting:
if (app.IsVoiceDetected()) {
SetBrightness(HIGH_BRIGHTNESS);
} else {

View File

@@ -136,6 +136,7 @@ void SingleLed::OnStateChanged() {
TurnOn();
break;
case kDeviceStateListening:
case kDeviceStateAudioTesting:
if (app.IsVoiceDetected()) {
SetColor(HIGH_BRIGHTNESS, 0, 0);
} else {