Hello. I'll get right to the point of this post. For 2 months, I've been trying to create a speaker system that allows me to hear my voice as I talk into the mic, in real time, through a speaker. I'm not trying to record anything and I'm not trying to send it over a server to do it. The audio is processed through one microcontroller locally.
Here are the components that I am working with.
1x INMP441 mic
1x ESP32 WROOM 32 board that has 38 pins
1x MAX98357A Amplifier
1x 4 Ohm 3 Watt Speaker.
Here are the connections between the components. I have these connected through a breadboard.
For the INMP441 Mic:
VDD to 3.3V Positive Rail
GND to GND Negative Rail
SD to GPIO 33
SCK to GPIO 32
WS to GPIO 25
For the MAX98357A:
VIN to 3.3V
GND to GND
DIN to GPIO 16
BCLK to GPIO 17
LRC to GPIO 18
I am not a programmer and I have searched through the internet for any tutorials on how this can be made. I even tried to combine the sketches through tutorials on Youtube, but I have not been successful. I have downloaded some sketches that allowed me to see the waveform in the Serial Plotter. I have downloaded some sketches that allowed me to make a sine wave generator, bluetooth speaker, etc.
In effort to make a sketch, I have been using ChatGPT in an effort to help me out. However, despite its usefulness, you can only use it for so long before it reaches its limit and you have to wait. However, I was able to have one sketch created in order to try and get the effect needed, but the serial monitor keeps saying:
E (7) esp_clock_output: esp_clock_output_start(207): Selected io is already mapped by another signal
E (8) i2s(legacy): i2s_check_set_mclk(1878): mclk configure failed
E (14) i2s(legacy): i2s_set_pin(1947): mclk config failed
I tried changing the bit rate to fix the clock frequency ( I did do some reading on the subject, but I am not a programmer) but it keeps messing up.
Here's is the code that I am currently using.
#include <driver/i2s.h>
// === Mic (INMP441) Pins ===
#define I2S_MIC_WS 25 // LRCL / WS
#define I2S_MIC_SD 33 // Data Out
#define I2S_MIC_SCK 32 // BCLK
// === Speaker (MAX98357A) Pins ===
#define I2S_SPK_DOUT 16 // DIN
#define I2S_SPK_BCLK 17 // BCLK
#define I2S_SPK_LRC 18 // LRC / WS
#define I2S_PORT_MIC I2S_NUM_0
#define I2S_PORT_SPK I2S_NUM_1
// === Buffer size ===
#define BUFFER_LEN 512
int16_t buffer[BUFFER_LEN];
void setup() {
Serial.begin(115200);
Serial.println("Starting real-time mic-to-speaker passthrough...");
// === Setup MIC (RX) ===
const i2s_config_t mic_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = 16000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
const i2s_pin_config_t mic_pins = {
.bck_io_num = I2S_MIC_SCK,
.ws_io_num = I2S_MIC_WS,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = I2S_MIC_SD
};
i2s_driver_install(I2S_PORT_MIC, &mic_config, 0, NULL);
i2s_set_pin(I2S_PORT_MIC, &mic_pins);
i2s_start(I2S_PORT_MIC);
// === Setup SPEAKER (TX) ===
const i2s_config_t spk_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = 16000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false,
.tx_desc_auto_clear = true,
.fixed_mclk = 0
};
const i2s_pin_config_t spk_pins = {
.bck_io_num = I2S_SPK_BCLK,
.ws_io_num = I2S_SPK_LRC,
.data_out_num = I2S_SPK_DOUT,
.data_in_num = I2S_PIN_NO_CHANGE
};
i2s_driver_install(I2S_PORT_SPK, &spk_config, 0, NULL);
i2s_set_pin(I2S_PORT_SPK, &spk_pins);
i2s_start(I2S_PORT_SPK);
}
void loop() {
size_t bytes_read, bytes_written;
// Read audio from mic
esp_err_t read_err = i2s_read(I2S_PORT_MIC, (void*)buffer, sizeof(buffer), &bytes_read, portMAX_DELAY);
if (read_err == ESP_OK && bytes_read > 0) {
// Write audio to speaker
i2s_write(I2S_PORT_SPK, (const void*)buffer, bytes_read, &bytes_written, portMAX_DELAY);
}
}
I don't know if I'm missing any I2S drivers to pull this off or maybe it's just not possible on one board. I would like to get this fixed if any one knows where I went wrong.
If this is not the right area for this topic, please move it at your best convenience.
Edit: I tried using the feature before posting this and it didn't show up correctly. Sorry in advance.

