Reading and playing back audio samples realtime
Posted: Sat Jan 21, 2023 8:39 pm
Dear fellow forummembers,
For a school project, I would like to get a bass-amplifier up-and-running with an ESP32. My idea for doing this is as follows:
I want to sample audio from AUX via I2S reading. Then I want to filter out the bass frequencies via a low-pass-filter. Next I will add a multiple of these frequency values to the original sample, and I will output them once again via I2S. I think I have the reading part down, however, I'm kind of stuck on writing with I2S. My code is as follows:
If anyone is able to help me that would be very much appreciated. If you have any questions for me, do not hesitate to ask, I'll be monitoring this post as much as I can .
Thanks in advance and kind regards,
Thom
For a school project, I would like to get a bass-amplifier up-and-running with an ESP32. My idea for doing this is as follows:
I want to sample audio from AUX via I2S reading. Then I want to filter out the bass frequencies via a low-pass-filter. Next I will add a multiple of these frequency values to the original sample, and I will output them once again via I2S. I think I have the reading part down, however, I'm kind of stuck on writing with I2S. My code is as follows:
- // Global defines
- #define SERIAL_BAUDRATE 9600
- // I2S variables
- #define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) // Set the array size for the samples
- #define ADC_INPUT_PIN ADC1_CHANNEL_4 // Pin we want to input from, this is pin 32
- #define ADC_OUTPUT_PIN ADC1_CHANNEL_5 // Pin we want to output to, this is pin 33
- const i2s_port_t I2S_PORT = I2S_NUM_0; // I2S port used (we use I2S_NUM_0 because this supports ADC and DAC)
- const double SAMPLING_FREQUENCY = 41000; // Sampling frequency
- const int SAMPLE_BLOCK = 512; // Amount of samples we want to store in one block
- const uint16_t OFFSET = (int)ADC_INPUT_PIN * 0x1000; // Offset for the input pin
- // Setup part
- I2SManager::I2SManager() {
- Serial.println("Configuring I2S...");
- esp_err_t err;
- // The I2S configuration
- const i2s_config_t i2s_config = {
- .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_ADC_BUILT_IN),
- .sample_rate = SAMPLING_FREQUENCY,
- .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
- .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
- .communication_format = I2S_COMM_FORMAT_I2S_MSB,
- .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
- .dma_buf_count = 4,
- .dma_buf_len = SAMPLE_BLOCK
- };
- // Set the driver for the I2S port
- err = i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
- if (err != ESP_OK) {
- Serial.printf("Failed installing driver: %d\n", err);
- while (true)
- ;
- }
- static const i2s_pin_config_t pin_config = {
- .bck_io_num = -1,
- .ws_io_num = -1,
- .data_out_num = ADC_OUTPUT_PIN,
- .data_in_num = ADC_INPUT_PIN
- };
- // Set pin config
- i2s_set_pin(I2S_PORT, &pin_config);
- // Enable DAC mode
- i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
- // Set input pin to ADC mode
- err = i2s_set_adc_mode(ADC_UNIT_1, ADC_INPUT_PIN);
- if (err != ESP_OK) {
- Serial.printf("Failed setting up adc mode: %d\n", err);
- while (true)
- ;
- }
- Serial.println("I2S driver installed.");
- }
- // Loop part
- void I2SManager::getSamples() {
- // Read samples from I2S buffer
- size_t bytesRead = 0;
- i2s_read(I2S_PORT, (void*)samples, sizeof(samples), &bytesRead, portMAX_DELAY);
- // Check if all samples are filled
- if (bytesRead != sizeof(samples)) {
- Serial.printf("Could only read %u bytes of %u in FillBufferI2S()\n", bytesRead, sizeof(samples));
- return;
- }
- // This prints some data, I don't know if its correct because I can't check it yet
- for (uint16_t i = 0; i < ARRAYSIZE(samples); i++) {
- Serial.printf("%7d\n", samples[i]);
- }
- int bytesWritten;
- i2s_write(I2S_PORT, (void*)samples, sizeof(samples), (size_t*)&bytesWritten, portMAX_DELAY);
- }
Thanks in advance and kind regards,
Thom