Skip to content

Commit 973b72b

Browse files
committed
Audio works on esp32-m5stack-atoms3r
Need to implement buffering
1 parent 4a2cd25 commit 973b72b

File tree

5 files changed

+185
-64
lines changed

5 files changed

+185
-64
lines changed
Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,21 @@
11
dependencies:
2-
idf:
3-
source:
4-
type: idf
5-
version: 5.4.1
6-
m5stack/m5gfx:
7-
component_hash: a44875eb6d6577bddcf1669ad5dec35e1afa425b7ca8e99af6b38505f37840e6
8-
dependencies: []
9-
source:
10-
registry_url: https://components.espressif.com
11-
type: service
12-
version: 0.2.9
13-
m5stack/m5unified:
14-
component_hash: 9851fefc25bc05f8cdeadd4c6118c3300cfefcebf7e8c748dc9ccc2811100de6
2+
espressif/esp_codec_dev:
3+
component_hash: c71e2d13dad6fc41561590dd88dbc45c79e3f4ef48d5ee3575c60e8b6c8e79d5
154
dependencies:
16-
- name: m5stack/m5gfx
17-
registry_url: https://components.espressif.com
5+
- name: idf
186
require: private
19-
version: ^0.2.6
7+
version: '>=4.0'
208
source:
219
registry_url: https://components.espressif.com/
2210
type: service
23-
version: 0.2.4
11+
version: 1.3.5
12+
idf:
13+
source:
14+
type: idf
15+
version: 5.4.1
2416
direct_dependencies:
17+
- espressif/esp_codec_dev
2518
- idf
26-
- m5stack/m5unified
27-
manifest_hash: 6c856b0c15014cd213a8417ee6353debbf5a3f71b049e54dff1b99b6268cff03
19+
manifest_hash: c74d03622862bf2a85301c12f34d445e0d5bfc643f05f1b14820503605dd0b55
2820
target: esp32s3
2921
version: 2.0.0
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
dependencies:
22
idf:
3-
version: ">=4.1.0"
4-
m5stack/m5unified: "^0.2.4"
3+
version: '>=4.1.0'
4+
espressif/esp_codec_dev: ^1.3.5

esp32-m5stack-atoms3r/src/main.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,6 @@ extern "C" void app_main(void) {
1616
}
1717
ESP_ERROR_CHECK(ret);
1818

19-
auto cfg = M5.config();
20-
cfg.external_speaker.atomic_echo = true;
21-
M5.begin(cfg);
22-
23-
M5.Display.setBrightness(70);
24-
M5.Display.setTextSize(1.5);
25-
M5.Display.fillScreen(BLACK);
26-
M5.Display.println("Pipecat ESP32 client initialized\n");
27-
2819
ESP_ERROR_CHECK(esp_event_loop_create_default());
2920
peer_init();
3021
pipecat_init_audio_capture();

esp32-m5stack-atoms3r/src/main.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
#include <peer.h>
22

3-
#ifndef LINUX_BUILD
4-
#include <M5Unified.h>
5-
#endif
6-
73
#define LOG_TAG "pipecat"
84
#define MAX_HTTP_OUTPUT_BUFFER 4096
95
#define HTTP_TIMEOUT_MS 10000

esp32-m5stack-atoms3r/src/media.cpp

Lines changed: 172 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@
1111
#include "esp_check.h"
1212
#include "esp_log.h"
1313
#include "esp_heap_caps.h"
14+
15+
#include <esp_codec_dev.h>
16+
#include <esp_codec_dev_defaults.h>
17+
#include <esp_log.h>
18+
19+
#include "driver/i2c_master.h"
20+
#include <driver/i2s_std.h>
21+
1422
#include "main.h"
1523

1624
#define SAMPLE_RATE (16000)
@@ -21,6 +29,168 @@
2129
#define OPUS_ENCODER_BITRATE 30000
2230
#define OPUS_ENCODER_COMPLEXITY 0
2331

32+
i2c_master_bus_handle_t i2c_bus;
33+
esp_codec_dev_handle_t audio_dev;
34+
35+
void configure_pi4ioe(void) {
36+
i2c_master_dev_handle_t i2c_device;
37+
i2c_device_config_t i2c_device_cfg = {
38+
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
39+
.device_address = 0x43, // PI4IOE Address
40+
.scl_speed_hz = 400 * 1000,
41+
.scl_wait_us = 0,
42+
.flags = {
43+
.disable_ack_check = 0,
44+
},
45+
};
46+
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus, &i2c_device_cfg, &i2c_device));
47+
48+
auto writeRegister = [=](uint8_t reg, uint8_t value) {
49+
uint8_t buffer[2] = {reg, value};
50+
ESP_ERROR_CHECK(i2c_master_transmit(i2c_device, buffer, 2, 100));
51+
};
52+
53+
writeRegister(0x07, 0x00); // Set to high-impedance
54+
writeRegister(0x0D, 0xFF); // Enable pull-up
55+
writeRegister(0x03, 0x6E); // Set input=0, output=1
56+
writeRegister(0x05, 0xFF); // Unmute speaker
57+
i2c_master_bus_rm_device(i2c_device);
58+
}
59+
60+
void configure_es8311(void) {
61+
i2s_chan_config_t chan_cfg = {
62+
.id = I2S_NUM_0,
63+
.role = I2S_ROLE_MASTER,
64+
.dma_desc_num = 6,
65+
.dma_frame_num = 240,
66+
.auto_clear_after_cb = true,
67+
.auto_clear_before_cb = false,
68+
.intr_priority = 0,
69+
};
70+
71+
i2s_chan_handle_t tx_handle = nullptr, rx_handle = nullptr;
72+
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle));
73+
74+
i2s_std_config_t std_cfg = {
75+
.clk_cfg = {
76+
.sample_rate_hz = SAMPLE_RATE,
77+
.clk_src = I2S_CLK_SRC_DEFAULT,
78+
.ext_clk_freq_hz = 0,
79+
.mclk_multiple = I2S_MCLK_MULTIPLE_256,
80+
},
81+
.slot_cfg = {
82+
.data_bit_width = I2S_DATA_BIT_WIDTH_16BIT,
83+
.slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO,
84+
.slot_mode = I2S_SLOT_MODE_STEREO,
85+
.slot_mask = I2S_STD_SLOT_BOTH,
86+
.ws_width = I2S_DATA_BIT_WIDTH_16BIT,
87+
.ws_pol = false,
88+
.bit_shift = true,
89+
.left_align = true,
90+
.big_endian = false,
91+
.bit_order_lsb = false
92+
},
93+
.gpio_cfg = {
94+
.mclk = GPIO_NUM_NC,
95+
.bclk = GPIO_NUM_8,
96+
.ws = GPIO_NUM_6,
97+
.dout = GPIO_NUM_5,
98+
.din = GPIO_NUM_7,
99+
.invert_flags = {
100+
.mclk_inv = false,
101+
.bclk_inv = false,
102+
.ws_inv = false
103+
}
104+
}
105+
};
106+
107+
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle, &std_cfg));
108+
ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle, &std_cfg));
109+
110+
audio_codec_i2s_cfg_t i2s_cfg = {
111+
.port = I2S_NUM_0,
112+
.rx_handle = rx_handle,
113+
.tx_handle = tx_handle,
114+
};
115+
audio_codec_i2c_cfg_t i2c_cfg = {
116+
.port = I2C_NUM_1,
117+
.addr = ES8311_CODEC_DEFAULT_ADDR,
118+
.bus_handle = i2c_bus,
119+
};
120+
es8311_codec_cfg_t es8311_cfg = {
121+
.ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg),
122+
.gpio_if = audio_codec_new_gpio(),
123+
.codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH,
124+
.pa_pin = GPIO_NUM_NC,
125+
.use_mclk = false,
126+
.hw_gain = {
127+
.pa_voltage = 5.0,
128+
.codec_dac_voltage = 3.3
129+
}
130+
};
131+
132+
esp_codec_dev_cfg_t dev_cfg = {
133+
.dev_type = ESP_CODEC_DEV_TYPE_IN_OUT,
134+
.codec_if = es8311_codec_new(&es8311_cfg),
135+
.data_if = audio_codec_new_i2s_data(&i2s_cfg),
136+
};
137+
audio_dev = esp_codec_dev_new(&dev_cfg);
138+
139+
esp_codec_dev_sample_info_t fs = {
140+
.bits_per_sample = 16,
141+
.channel = 1,
142+
.channel_mask = 0,
143+
.sample_rate = SAMPLE_RATE,
144+
.mclk_multiple = 0,
145+
};
146+
ESP_ERROR_CHECK(esp_codec_dev_open(audio_dev, &fs));
147+
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(audio_dev, 30.0));
148+
ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(audio_dev, 100));
149+
}
150+
151+
int Read(void* dest, int size) {
152+
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(audio_dev, (void*)dest, size));
153+
return size;
154+
}
155+
156+
int Write(const void* data, int size) {
157+
ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(audio_dev, (void*)data, size));
158+
return size;
159+
}
160+
161+
void pipecat_init_audio_capture() {
162+
i2c_master_bus_config_t i2c_bus_cfg = {
163+
.i2c_port = I2C_NUM_1,
164+
.sda_io_num = GPIO_NUM_38,
165+
.scl_io_num = GPIO_NUM_39,
166+
.clk_source = I2C_CLK_SRC_DEFAULT,
167+
.glitch_ignore_cnt = 7,
168+
.intr_priority = 0,
169+
.trans_queue_depth = 0,
170+
.flags = {
171+
.enable_internal_pullup = 1,
172+
},
173+
};
174+
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus));
175+
configure_pi4ioe();
176+
configure_es8311();
177+
}
178+
179+
opus_int16 *decoder_buffer = NULL;
180+
OpusDecoder *opus_decoder = NULL;
181+
182+
void pipecat_init_audio_decoder() {
183+
int decoder_error = 0;
184+
opus_decoder = opus_decoder_create(SAMPLE_RATE, 1, &decoder_error);
185+
if (decoder_error != OPUS_OK) {
186+
printf("Failed to create OPUS decoder");
187+
return;
188+
}
189+
190+
decoder_buffer = (opus_int16 *)malloc(PCM_BUFFER_SIZE);
191+
}
192+
193+
24194
std::atomic<bool> is_playing = false;
25195
unsigned int silence_count = 0;
26196

@@ -39,47 +209,19 @@ void set_is_playing(int16_t *in_buf, size_t in_samples) {
39209
}
40210

41211
if (silence_count >= 20 && is_playing) {
42-
M5.Speaker.end();
43-
M5.Mic.begin();
44212
is_playing = false;
45213
} else if (any_set && !is_playing) {
46-
M5.Mic.end();
47-
M5.Speaker.begin();
48214
is_playing = true;
49215
}
50216
}
51217

52-
void pipecat_init_audio_capture() {
53-
M5.Speaker.setVolume(255);
54-
}
55-
56-
opus_int16 *decoder_buffer = NULL;
57-
OpusDecoder *opus_decoder = NULL;
58-
59-
void pipecat_init_audio_decoder() {
60-
int decoder_error = 0;
61-
opus_decoder = opus_decoder_create(SAMPLE_RATE, 1, &decoder_error);
62-
if (decoder_error != OPUS_OK) {
63-
printf("Failed to create OPUS decoder");
64-
return;
65-
}
66-
67-
decoder_buffer = (opus_int16 *)malloc(PCM_BUFFER_SIZE);
68-
}
69218

70219
void pipecat_audio_decode(uint8_t *data, size_t size) {
71220
int decoded_size =
72221
opus_decode(opus_decoder, data, size, decoder_buffer, PCM_BUFFER_SIZE, 0);
73222

74223
if (decoded_size > 0) {
75-
set_is_playing(decoder_buffer, decoded_size);
76-
if (is_playing) {
77-
M5.Speaker.playRaw(decoder_buffer, decoded_size, SAMPLE_RATE);
78-
do {
79-
M5.delay(1);
80-
M5.update();
81-
} while (M5.Speaker.isPlaying());
82-
}
224+
Write(decoder_buffer, PCM_BUFFER_SIZE);
83225
}
84226
}
85227

@@ -115,7 +257,7 @@ void pipecat_send_audio(PeerConnection *peer_connection) {
115257
memset(read_buffer, 0, PCM_BUFFER_SIZE);
116258
vTaskDelay(pdMS_TO_TICKS(20));
117259
} else {
118-
// M5.Mic.record(read_buffer, PCM_BUFFER_SIZE / sizeof(uint16_t), SAMPLE_RATE);
260+
// Do record
119261
}
120262

121263
auto encoded_size = opus_encode(opus_encoder, (const opus_int16 *)read_buffer,

0 commit comments

Comments
 (0)