forked from xiaozhi/xiaozhi-esp32
esp cert bundle
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
|
||||
Application::Application() {
|
||||
event_group_ = xEventGroupCreate();
|
||||
audio_encode_queue_ = xQueueCreate(100, sizeof(AudioEncoderData));
|
||||
audio_encode_queue_ = xQueueCreate(100, sizeof(iovec));
|
||||
audio_decode_queue_ = xQueueCreate(100, sizeof(AudioPacket*));
|
||||
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
@@ -74,16 +74,17 @@ void Application::Start() {
|
||||
});
|
||||
|
||||
// OPUS encoder / decoder use a lot of stack memory
|
||||
audio_encode_task_stack_ = (StackType_t*)malloc(4096 * 8);
|
||||
const size_t opus_stack_size = 4096 * 8;
|
||||
audio_encode_task_stack_ = (StackType_t*)malloc(opus_stack_size);
|
||||
xTaskCreateStatic([](void* arg) {
|
||||
Application* app = (Application*)arg;
|
||||
app->AudioEncodeTask();
|
||||
}, "opus_encode", 4096 * 8, this, 1, audio_encode_task_stack_, &audio_encode_task_buffer_);
|
||||
audio_decode_task_stack_ = (StackType_t*)malloc(4096 * 8);
|
||||
}, "opus_encode", opus_stack_size, this, 1, audio_encode_task_stack_, &audio_encode_task_buffer_);
|
||||
audio_decode_task_stack_ = (StackType_t*)malloc(opus_stack_size);
|
||||
xTaskCreateStatic([](void* arg) {
|
||||
Application* app = (Application*)arg;
|
||||
app->AudioDecodeTask();
|
||||
}, "opus_decode", 4096 * 8, this, 1, audio_decode_task_stack_, &audio_decode_task_buffer_);
|
||||
}, "opus_decode", opus_stack_size, this, 1, audio_decode_task_stack_, &audio_decode_task_buffer_);
|
||||
|
||||
wifi_station_.Start();
|
||||
|
||||
@@ -305,10 +306,11 @@ void Application::AudioCommunicationTask() {
|
||||
|
||||
if (chat_state_ == kChatStateListening) {
|
||||
// Send audio data to server
|
||||
AudioEncoderData data;
|
||||
data.size = res->data_size;
|
||||
data.data = malloc(data.size);
|
||||
memcpy((void*)data.data, res->data, data.size);
|
||||
iovec data = {
|
||||
.iov_base = malloc(res->data_size),
|
||||
.iov_len = (size_t)res->data_size
|
||||
};
|
||||
memcpy(data.iov_base, res->data, res->data_size);
|
||||
xQueueSend(audio_encode_queue_, &data, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
@@ -317,17 +319,18 @@ void Application::AudioCommunicationTask() {
|
||||
void Application::AudioEncodeTask() {
|
||||
ESP_LOGI(TAG, "Audio encode task started");
|
||||
while (true) {
|
||||
AudioEncoderData data;
|
||||
xQueueReceive(audio_encode_queue_, &data, portMAX_DELAY);
|
||||
iovec pcm;
|
||||
xQueueReceive(audio_encode_queue_, &pcm, portMAX_DELAY);
|
||||
|
||||
// Encode audio data
|
||||
opus_encoder_.Encode(data.data, data.size, [this](const void* data, size_t size) {
|
||||
opus_encoder_.Encode(pcm, [this](const iovec opus) {
|
||||
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
||||
if (ws_client_ && ws_client_->IsConnected()) {
|
||||
ws_client_->Send((const char*)data, size, true);
|
||||
ws_client_->Send(opus.iov_base, opus.iov_len, true);
|
||||
}
|
||||
});
|
||||
free((void*)data.data);
|
||||
|
||||
free(pcm.iov_base);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +345,7 @@ void Application::AudioDecodeTask() {
|
||||
int ret = opus_decode(opus_decoder_, packet->opus.data(), packet->opus.size(), packet->pcm.data(), frame_size, 0);
|
||||
if (ret < 0) {
|
||||
ESP_LOGE(TAG, "Failed to decode audio, error code: %d", ret);
|
||||
free(packet);
|
||||
delete packet;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
#define DETECTION_RUNNING 1
|
||||
#define COMMUNICATION_RUNNING 2
|
||||
|
||||
struct AudioEncoderData {
|
||||
const void* data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
enum ChatState {
|
||||
kChatStateIdle,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <cstring>
|
||||
|
||||
#define TAG "AudioDevice"
|
||||
#define SPEAKING BIT0
|
||||
|
||||
AudioDevice::AudioDevice() {
|
||||
audio_play_queue_ = xQueueCreate(100, sizeof(AudioPacket*));
|
||||
@@ -214,6 +213,7 @@ void AudioDevice::AudioPlayTask() {
|
||||
delete p;
|
||||
}
|
||||
breaked_ = false;
|
||||
playing_ = false;
|
||||
}
|
||||
break;
|
||||
case kAudioPacketTypeData:
|
||||
|
||||
@@ -83,7 +83,7 @@ void BuiltinLed::Blink(int times, int interval_ms) {
|
||||
delete args;
|
||||
this_->blink_task_ = nullptr;
|
||||
vTaskDelete(NULL);
|
||||
}, "blink", 4096, args, tskIDLE_PRIORITY, &blink_task_);
|
||||
}, "blink", 1024, args, tskIDLE_PRIORITY, &blink_task_);
|
||||
|
||||
xSemaphoreGive(mutex_);
|
||||
}
|
||||
|
||||
@@ -8,10 +8,6 @@ OpusEncoder::OpusEncoder() {
|
||||
}
|
||||
|
||||
OpusEncoder::~OpusEncoder() {
|
||||
if (out_buffer_ != nullptr) {
|
||||
free(out_buffer_);
|
||||
}
|
||||
|
||||
if (audio_enc_ != nullptr) {
|
||||
opus_encoder_destroy(audio_enc_);
|
||||
}
|
||||
@@ -22,10 +18,6 @@ void OpusEncoder::Configure(int sample_rate, int channels, int duration_ms) {
|
||||
opus_encoder_destroy(audio_enc_);
|
||||
audio_enc_ = nullptr;
|
||||
}
|
||||
if (out_buffer_ != nullptr) {
|
||||
free(out_buffer_);
|
||||
out_buffer_ = nullptr;
|
||||
}
|
||||
|
||||
int error;
|
||||
audio_enc_ = opus_encoder_create(sample_rate, channels, OPUS_APPLICATION_VOIP, &error);
|
||||
@@ -40,30 +32,29 @@ void OpusEncoder::Configure(int sample_rate, int channels, int duration_ms) {
|
||||
opus_encoder_ctl(audio_enc_, OPUS_SET_COMPLEXITY(5));
|
||||
|
||||
frame_size_ = sample_rate / 1000 * duration_ms;
|
||||
out_size_ = sample_rate * channels * sizeof(int16_t);
|
||||
out_buffer_ = (uint8_t*)malloc(out_size_);
|
||||
assert(out_buffer_ != nullptr);
|
||||
out_buffer_.resize(sample_rate * channels * sizeof(int16_t));
|
||||
}
|
||||
|
||||
void OpusEncoder::Encode(const void* pcm, size_t pcm_len, std::function<void(const void*, size_t)> handler) {
|
||||
void OpusEncoder::Encode(const iovec pcm, std::function<void(const iovec opus)> handler) {
|
||||
if (audio_enc_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Audio encoder is not configured");
|
||||
return;
|
||||
}
|
||||
|
||||
in_buffer_.append((const char*)pcm, pcm_len);
|
||||
auto pcm_data = (int16_t*)pcm.iov_base;
|
||||
in_buffer_.insert(in_buffer_.end(), pcm_data, pcm_data + pcm.iov_len / sizeof(int16_t));
|
||||
|
||||
while (in_buffer_.size() >= frame_size_ * sizeof(int16_t)) {
|
||||
auto ret = opus_encode(audio_enc_, (const opus_int16*)in_buffer_.data(), frame_size_, out_buffer_, out_size_);
|
||||
while (in_buffer_.size() >= frame_size_) {
|
||||
auto ret = opus_encode(audio_enc_, in_buffer_.data(), frame_size_, out_buffer_.data(), out_buffer_.size());
|
||||
if (ret < 0) {
|
||||
ESP_LOGE(TAG, "Failed to encode audio, error code: %ld", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (handler != nullptr) {
|
||||
handler(out_buffer_, ret);
|
||||
handler(iovec { out_buffer_.data(), (size_t)ret });
|
||||
}
|
||||
|
||||
in_buffer_.erase(0, frame_size_ * sizeof(int16_t));
|
||||
in_buffer_.erase(in_buffer_.begin(), in_buffer_.begin() + frame_size_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,23 +3,27 @@
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "lwip/sockets.h"
|
||||
#include "opus.h"
|
||||
|
||||
|
||||
class OpusEncoder {
|
||||
public:
|
||||
OpusEncoder();
|
||||
~OpusEncoder();
|
||||
|
||||
void Configure(int sample_rate, int channels, int duration_ms = 60);
|
||||
void Encode(const void* pcm, size_t pcm_len, std::function<void(const void*, size_t)> handler);
|
||||
void Encode(const iovec pcm, std::function<void(const iovec opus)> handler);
|
||||
bool IsBufferEmpty() const { return in_buffer_.empty(); }
|
||||
|
||||
private:
|
||||
struct OpusEncoder* audio_enc_ = nullptr;
|
||||
int frame_size_;
|
||||
int out_size_;
|
||||
uint8_t* out_buffer_ = nullptr;
|
||||
std::string in_buffer_;
|
||||
std::vector<uint8_t> out_buffer_;
|
||||
std::vector<int16_t> in_buffer_;
|
||||
};
|
||||
|
||||
#endif // _OPUS_ENCODER_H_
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <cstring>
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_crt_bundle.h"
|
||||
|
||||
|
||||
#define TAG "WebSocket"
|
||||
@@ -13,6 +14,7 @@ WebSocketClient::WebSocketClient(bool auto_reconnect) {
|
||||
esp_websocket_client_config_t config = {};
|
||||
config.task_prio = 1;
|
||||
config.disable_auto_reconnect = !auto_reconnect;
|
||||
config.crt_bundle_attach = esp_crt_bundle_attach;
|
||||
client_ = esp_websocket_client_init(&config);
|
||||
assert(client_ != NULL);
|
||||
|
||||
@@ -93,11 +95,11 @@ bool WebSocketClient::Connect(const char* uri) {
|
||||
return bits & WEBSOCKET_CONNECTED_BIT;
|
||||
}
|
||||
|
||||
void WebSocketClient::Send(const char* data, size_t len, bool binary) {
|
||||
void WebSocketClient::Send(const void* data, size_t len, bool binary) {
|
||||
if (binary) {
|
||||
esp_websocket_client_send_bin(client_, data, len, portMAX_DELAY);
|
||||
esp_websocket_client_send_bin(client_, (const char*)data, len, portMAX_DELAY);
|
||||
} else {
|
||||
esp_websocket_client_send_text(client_, data, len, portMAX_DELAY);
|
||||
esp_websocket_client_send_text(client_, (const char*)data, len, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
bool IsConnected() const;
|
||||
bool Connect(const char* uri);
|
||||
void Send(const std::string& data);
|
||||
void Send(const char* data, size_t len, bool binary = false);
|
||||
void Send(const void* data, size_t len, bool binary = false);
|
||||
|
||||
void OnConnected(std::function<void()> callback);
|
||||
void OnDisconnected(std::function<void()> callback);
|
||||
|
||||
Reference in New Issue
Block a user