Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions main/audio/audio_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ void AudioCodec::SetOutputVolume(int volume) {
settings.SetInt("output_volume", output_volume_);
}

void AudioCodec::SetInputGain(float gain) {
input_gain_ = gain;
ESP_LOGI(TAG, "Set input gain to %.1f", input_gain_);
}

void AudioCodec::EnableInput(bool enable) {
if (enable == input_enabled_) {
return;
Expand Down
4 changes: 3 additions & 1 deletion main/audio/audio_codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@

#define AUDIO_CODEC_DMA_DESC_NUM 6
#define AUDIO_CODEC_DMA_FRAME_NUM 240
#define AUDIO_CODEC_DEFAULT_MIC_GAIN 30.0

class AudioCodec {
public:
AudioCodec();
virtual ~AudioCodec();

virtual void SetOutputVolume(int volume);
virtual void SetInputGain(float gain);
virtual void EnableInput(bool enable);
virtual void EnableOutput(bool enable);

Expand All @@ -35,6 +35,7 @@ class AudioCodec {
inline int input_channels() const { return input_channels_; }
inline int output_channels() const { return output_channels_; }
inline int output_volume() const { return output_volume_; }
inline float input_gain() const { return input_gain_; }
inline bool input_enabled() const { return input_enabled_; }
inline bool output_enabled() const { return output_enabled_; }

Expand All @@ -51,6 +52,7 @@ class AudioCodec {
int input_channels_ = 1;
int output_channels_ = 1;
int output_volume_ = 70;
float input_gain_ = 0.0;

virtual int Read(int16_t* dest, int samples) = 0;
virtual int Write(const int16_t* data, int samples) = 0;
Expand Down
3 changes: 2 additions & 1 deletion main/audio/codecs/box_audio_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ BoxAudioCodec::BoxAudioCodec(void* i2c_master_handle, int input_sample_rate, int
input_channels_ = input_reference_ ? 2 : 1; // 输入通道数
input_sample_rate_ = input_sample_rate;
output_sample_rate_ = output_sample_rate;
input_gain_ = 30;

CreateDuplexChannels(mclk, bclk, ws, dout, din);

Expand Down Expand Up @@ -200,7 +201,7 @@ void BoxAudioCodec::EnableInput(bool enable) {
fs.channel_mask |= ESP_CODEC_DEV_MAKE_CHANNEL_MASK(1);
}
ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs));
ESP_ERROR_CHECK(esp_codec_dev_set_in_channel_gain(input_dev_, ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), AUDIO_CODEC_DEFAULT_MIC_GAIN));
ESP_ERROR_CHECK(esp_codec_dev_set_in_channel_gain(input_dev_, ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), input_gain_));
} else {
ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_));
}
Expand Down
3 changes: 2 additions & 1 deletion main/audio/codecs/es8311_audio_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Es8311AudioCodec::Es8311AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port,
output_sample_rate_ = output_sample_rate;
pa_pin_ = pa_pin;
pa_inverted_ = pa_inverted;
input_gain_ = 30;

assert(input_sample_rate_ == output_sample_rate_);
CreateDuplexChannels(mclk, bclk, ws, dout, din);
Expand Down Expand Up @@ -81,7 +82,7 @@ void Es8311AudioCodec::UpdateDeviceState() {
.mclk_multiple = 0,
};
ESP_ERROR_CHECK(esp_codec_dev_open(dev_, &fs));
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(dev_, AUDIO_CODEC_DEFAULT_MIC_GAIN));
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(dev_, input_gain_));
ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(dev_, output_volume_));
} else if (!input_enabled_ && !output_enabled_ && dev_ != nullptr) {
esp_codec_dev_close(dev_);
Expand Down
4 changes: 3 additions & 1 deletion main/audio/codecs/es8374_audio_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Es8374AudioCodec::Es8374AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port,
input_channels_ = 1; // 输入通道数
input_sample_rate_ = input_sample_rate;
output_sample_rate_ = output_sample_rate;
input_gain_ = 30;

pa_pin_ = pa_pin;
CreateDuplexChannels(mclk, bclk, ws, dout, din);

Expand Down Expand Up @@ -146,7 +148,7 @@ void Es8374AudioCodec::EnableInput(bool enable) {
.mclk_multiple = 0,
};
ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs));
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, AUDIO_CODEC_DEFAULT_MIC_GAIN));
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, input_gain_));
} else {
ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_));
}
Expand Down
4 changes: 3 additions & 1 deletion main/audio/codecs/es8388_audio_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Es8388AudioCodec::Es8388AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port,
input_channels_ = input_reference_ ? 2 : 1; // 输入通道数
input_sample_rate_ = input_sample_rate;
output_sample_rate_ = output_sample_rate;
input_gain_ = 24;

pa_pin_ = pa_pin;
CreateDuplexChannels(mclk, bclk, ws, dout, din);

Expand Down Expand Up @@ -158,7 +160,7 @@ void Es8388AudioCodec::EnableInput(bool enable) {
uint8_t gain = (11 << 4) + 0;
ctrl_if_->write_reg(ctrl_if_, 0x09, 1, &gain, 1);
}else{
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, 24.0));
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, input_gain_));
}
} else {
ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_));
Expand Down
3 changes: 2 additions & 1 deletion main/audio/codecs/es8389_audio_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Es8389AudioCodec::Es8389AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port,
input_channels_ = 1; // 输入通道数
input_sample_rate_ = input_sample_rate;
output_sample_rate_ = output_sample_rate;
input_gain_ = 40;
pa_pin_ = pa_pin;
CreateDuplexChannels(mclk, bclk, ws, dout, din);

Expand Down Expand Up @@ -153,7 +154,7 @@ void Es8389AudioCodec::EnableInput(bool enable) {
.mclk_multiple = 0,
};
ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs));
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, 40.0));
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, input_gain_));
} else {
ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_));
}
Expand Down
163 changes: 56 additions & 107 deletions main/audio/codecs/no_audio_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,53 @@ NoAudioCodecSimplex::NoAudioCodecSimplex(int input_sample_rate, int output_sampl
ESP_LOGI(TAG, "Simplex channels created");
}

NoAudioCodecSimplexPdm::NoAudioCodecSimplexPdm(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, i2s_std_slot_mask_t spk_slot_mask,gpio_num_t mic_sck, gpio_num_t mic_din) {
int NoAudioCodec::Write(const int16_t* data, int samples) {
std::lock_guard<std::mutex> lock(data_if_mutex_);
std::vector<int32_t> buffer(samples);

// output_volume_: 0-100
// volume_factor_: 0-65536
int32_t volume_factor = pow(double(output_volume_) / 100.0, 2) * 65536;
for (int i = 0; i < samples; i++) {
int64_t temp = int64_t(data[i]) * volume_factor; // 使用 int64_t 进行乘法运算
if (temp > INT32_MAX) {
buffer[i] = INT32_MAX;
} else if (temp < INT32_MIN) {
buffer[i] = INT32_MIN;
} else {
buffer[i] = static_cast<int32_t>(temp);
}
}

size_t bytes_written;
ESP_ERROR_CHECK(i2s_channel_write(tx_handle_, buffer.data(), samples * sizeof(int32_t), &bytes_written, portMAX_DELAY));
return bytes_written / sizeof(int32_t);
}

int NoAudioCodec::Read(int16_t* dest, int samples) {
size_t bytes_read;

std::vector<int32_t> bit32_buffer(samples);
if (i2s_channel_read(rx_handle_, bit32_buffer.data(), samples * sizeof(int32_t), &bytes_read, portMAX_DELAY) != ESP_OK) {
ESP_LOGE(TAG, "Read Failed!");
return 0;
}

samples = bytes_read / sizeof(int32_t);
for (int i = 0; i < samples; i++) {
int32_t value = bit32_buffer[i] >> 12;
dest[i] = (value > INT16_MAX) ? INT16_MAX : (value < -INT16_MAX) ? -INT16_MAX : (int16_t)value;
}
return samples;
}

// Delegating constructor: calls the main constructor with default slot mask
NoAudioCodecSimplexPdm::NoAudioCodecSimplexPdm(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, gpio_num_t mic_sck, gpio_num_t mic_din)
: NoAudioCodecSimplexPdm(input_sample_rate, output_sample_rate, spk_bclk, spk_ws, spk_dout, I2S_STD_SLOT_LEFT, mic_sck, mic_din) {
// All initialization is handled by the delegated constructor
}

NoAudioCodecSimplexPdm::NoAudioCodecSimplexPdm(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, i2s_std_slot_mask_t spk_slot_mask, gpio_num_t mic_sck, gpio_num_t mic_din) {
duplex_ = false;
input_sample_rate_ = input_sample_rate;
output_sample_rate_ = output_sample_rate;
Expand Down Expand Up @@ -292,110 +338,6 @@ NoAudioCodecSimplexPdm::NoAudioCodecSimplexPdm(int input_sample_rate, int output
ESP_LOGI(TAG, "Simplex channels created");
}

NoAudioCodecSimplexPdm::NoAudioCodecSimplexPdm(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, gpio_num_t mic_sck, gpio_num_t mic_din) {
duplex_ = false;
input_sample_rate_ = input_sample_rate;
output_sample_rate_ = output_sample_rate;

// Create a new channel for speaker
i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG((i2s_port_t)1, I2S_ROLE_MASTER);
tx_chan_cfg.dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM;
tx_chan_cfg.dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM;
tx_chan_cfg.auto_clear_after_cb = true;
tx_chan_cfg.auto_clear_before_cb = false;
tx_chan_cfg.intr_priority = 0;
ESP_ERROR_CHECK(i2s_new_channel(&tx_chan_cfg, &tx_handle_, NULL));


i2s_std_config_t tx_std_cfg = {
.clk_cfg = {
.sample_rate_hz = (uint32_t)output_sample_rate_,
.clk_src = I2S_CLK_SRC_DEFAULT,
.mclk_multiple = I2S_MCLK_MULTIPLE_256,
#ifdef I2S_HW_VERSION_2
.ext_clk_freq_hz = 0,
#endif

},
.slot_cfg = I2S_STD_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_MONO),
.gpio_cfg = {
.mclk = I2S_GPIO_UNUSED,
.bclk = spk_bclk,
.ws = spk_ws,
.dout = spk_dout,
.din = I2S_GPIO_UNUSED,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
},
},
};
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &tx_std_cfg));
#if SOC_I2S_SUPPORTS_PDM_RX
// Create a new channel for MIC in PDM mode
i2s_chan_config_t rx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG((i2s_port_t)0, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&rx_chan_cfg, NULL, &rx_handle_));
i2s_pdm_rx_config_t pdm_rx_cfg = {
.clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG((uint32_t)input_sample_rate_),
/* The data bit-width of PDM mode is fixed to 16 */
.slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO),
.gpio_cfg = {
.clk = mic_sck,
.din = mic_din,

.invert_flags = {
.clk_inv = false,
},
},
};
ESP_ERROR_CHECK(i2s_channel_init_pdm_rx_mode(rx_handle_, &pdm_rx_cfg));
#else
ESP_LOGE(TAG, "PDM is not supported");
#endif
ESP_LOGI(TAG, "Simplex channels created");
}

int NoAudioCodec::Write(const int16_t* data, int samples) {
std::lock_guard<std::mutex> lock(data_if_mutex_);
std::vector<int32_t> buffer(samples);

// output_volume_: 0-100
// volume_factor_: 0-65536
int32_t volume_factor = pow(double(output_volume_) / 100.0, 2) * 65536;
for (int i = 0; i < samples; i++) {
int64_t temp = int64_t(data[i]) * volume_factor; // 使用 int64_t 进行乘法运算
if (temp > INT32_MAX) {
buffer[i] = INT32_MAX;
} else if (temp < INT32_MIN) {
buffer[i] = INT32_MIN;
} else {
buffer[i] = static_cast<int32_t>(temp);
}
}

size_t bytes_written;
ESP_ERROR_CHECK(i2s_channel_write(tx_handle_, buffer.data(), samples * sizeof(int32_t), &bytes_written, portMAX_DELAY));
return bytes_written / sizeof(int32_t);
}

int NoAudioCodec::Read(int16_t* dest, int samples) {
size_t bytes_read;

std::vector<int32_t> bit32_buffer(samples);
if (i2s_channel_read(rx_handle_, bit32_buffer.data(), samples * sizeof(int32_t), &bytes_read, portMAX_DELAY) != ESP_OK) {
ESP_LOGE(TAG, "Read Failed!");
return 0;
}

samples = bytes_read / sizeof(int32_t);
for (int i = 0; i < samples; i++) {
int32_t value = bit32_buffer[i] >> 12;
dest[i] = (value > INT16_MAX) ? INT16_MAX : (value < -INT16_MAX) ? -INT16_MAX : (int16_t)value;
}
return samples;
}

int NoAudioCodecSimplexPdm::Read(int16_t* dest, int samples) {
size_t bytes_read;

Expand All @@ -405,6 +347,13 @@ int NoAudioCodecSimplexPdm::Read(int16_t* dest, int samples) {
return 0;
}

// 计算实际读取的样本数
return bytes_read / sizeof(int16_t);
samples = bytes_read / sizeof(int16_t);
if (input_gain_ > 0) {
int gain_factor = (int)input_gain_;
for (int i = 0; i < samples; i++) {
int32_t amplified = dest[i] * gain_factor;
dest[i] = (amplified > INT16_MAX) ? INT16_MAX : (amplified < -INT16_MAX) ? -INT16_MAX : (int16_t)amplified;
}
}
return samples;
}
3 changes: 2 additions & 1 deletion main/boards/m5stack-core-s3/cores3_audio_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ CoreS3AudioCodec::CoreS3AudioCodec(void* i2c_master_handle, int input_sample_rat
input_channels_ = input_reference_ ? 2 : 1; // 输入通道数
input_sample_rate_ = input_sample_rate;
output_sample_rate_ = output_sample_rate;
input_gain_ = 30;

CreateDuplexChannels(mclk, bclk, ws, dout, din);

Expand Down Expand Up @@ -200,7 +201,7 @@ void CoreS3AudioCodec::EnableInput(bool enable) {
fs.channel_mask |= ESP_CODEC_DEV_MAKE_CHANNEL_MASK(1);
}
ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs));
ESP_ERROR_CHECK(esp_codec_dev_set_in_channel_gain(input_dev_, ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), AUDIO_CODEC_DEFAULT_MIC_GAIN));
ESP_ERROR_CHECK(esp_codec_dev_set_in_channel_gain(input_dev_, ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), input_gain_));
} else {
ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_));
}
Expand Down
3 changes: 2 additions & 1 deletion main/boards/m5stack-tab5/tab5_audio_codec.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Tab5AudioCodec::Tab5AudioCodec(void* i2c_master_handle, int input_sample_rate, i
input_channels_ = input_reference_ ? 2 : 1; // 输入通道数
input_sample_rate_ = input_sample_rate;
output_sample_rate_ = output_sample_rate;
input_gain_ = 30;

CreateDuplexChannels(mclk, bclk, ws, dout, din);

Expand Down Expand Up @@ -199,7 +200,7 @@ void Tab5AudioCodec::EnableInput(bool enable) {
fs.channel_mask |= ESP_CODEC_DEV_MAKE_CHANNEL_MASK(1);
}
ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs));
ESP_ERROR_CHECK(esp_codec_dev_set_in_channel_gain(input_dev_, ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), AUDIO_CODEC_DEFAULT_MIC_GAIN));
ESP_ERROR_CHECK(esp_codec_dev_set_in_channel_gain(input_dev_, ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), input_gain_));
} else {
ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_));
}
Expand Down
Loading