60 lines
1.8 KiB
C++
60 lines
1.8 KiB
C++
#include "opus_decoder.h"
|
|
#include <esp_log.h>
|
|
|
|
#define TAG "OpusDecoderWrapper"
|
|
|
|
OpusDecoderWrapper::OpusDecoderWrapper(int sample_rate, int channels, int duration_ms)
|
|
: sample_rate_(sample_rate), channels_(channels), duration_ms_(duration_ms) {
|
|
int error;
|
|
audio_dec_ = opus_decoder_create(sample_rate, channels, &error);
|
|
if (audio_dec_ == nullptr) {
|
|
ESP_LOGE(TAG, "Failed to create audio decoder, error code: %d", error);
|
|
return;
|
|
}
|
|
|
|
// frame_size_ 表示每帧的样本数(单个通道)
|
|
frame_size_ = sample_rate / 1000 * duration_ms;
|
|
}
|
|
|
|
OpusDecoderWrapper::~OpusDecoderWrapper() {
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
if (audio_dec_ != nullptr) {
|
|
opus_decoder_destroy(audio_dec_);
|
|
}
|
|
}
|
|
|
|
bool OpusDecoderWrapper::Decode(std::vector<uint8_t>&& opus, std::vector<int16_t>& pcm) {
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
if (audio_dec_ == nullptr) {
|
|
ESP_LOGE(TAG, "Audio decoder is not configured");
|
|
return false;
|
|
}
|
|
|
|
// 计算每帧样本数,考虑通道数
|
|
int samples_per_channel = sample_rate_ * duration_ms_ / 1000;
|
|
int total_samples = samples_per_channel * channels_;
|
|
pcm.resize(total_samples);
|
|
|
|
auto ret = opus_decode(audio_dec_, opus.data(), opus.size(), pcm.data(), samples_per_channel, 0);
|
|
if (ret < 0) {
|
|
ESP_LOGE(TAG, "Failed to decode audio, error code: %d", ret);
|
|
return false;
|
|
}
|
|
|
|
// 调整pcm大小为实际解码的样本数
|
|
int actual_total_samples = ret * channels_;
|
|
if (actual_total_samples < total_samples) {
|
|
pcm.resize(actual_total_samples);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void OpusDecoderWrapper::ResetState() {
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
if (audio_dec_ != nullptr) {
|
|
opus_decoder_ctl(audio_dec_, OPUS_RESET_STATE);
|
|
}
|
|
}
|
|
|