The ESP32 has a built-in 8-bit DAC. Digital to the analogue signal converter or analogue-digital converter or DAC is a device to convert digital signals with binary data into current or analogue voltage signals. For better sound quality, we can use an external I2S codec and amp. Adafruit I2S amp uses a MAX98357A IC. The MAX98357 is a low-cost, digital pulse-code modulation (PCM) input amplifier. The digital audio interface eliminates the need for I2C programming. This is an example :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include "driver/i2s.h" #include "freertos/queue.h" #include <pgmspace.h> #include "soundsample.h" //i2s configuration int i2s_num = 0; // i2s port number i2s_config_t i2s_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_RIGHT_LEFT, .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // high interrupt priority .dma_buf_count = 8, .dma_buf_len = 64 //Interrupt level 1 }; i2s_pin_config_t pin_config = { .bck_io_num = 26, //this is BCK pin .ws_io_num = 25, // this is LRCK pin .data_out_num = 22, // this is DATA output pin .data_in_num = -1 //Not used }; int i2s_write_sample_nb(uint32_t sample) { return i2s_write_bytes((i2s_port_t)i2s_num, (const char *)&sample, sizeof(uint32_t), 100); } //Main function to play samples from PROGMEM void playPROGMEMsample(const uint32_t* audioSample) { uint32_t sampleSize = sizeof(audioSample) * 4; uint32_t counter = 0; //initialize i2s with configurations above i2s_driver_install((i2s_port_t)i2s_num, &i2s_config, 0, NULL); i2s_set_pin((i2s_port_t)i2s_num, &pin_config); //set sample rates of i2s to sample rate of wav file i2s_set_sample_rates((i2s_port_t)i2s_num, 16000); uint32_t readData; while (audioSample) { readData = pgm_read_dword(&audioSample[counter++]); if (readData == NULL) break; i2s_write_sample_nb(readData); } i2s_driver_uninstall((i2s_port_t)i2s_num); //stop & destroy i2s driver } void setup() { Serial.begin(115200); Serial.println("Serial connection OK"); playPROGMEMsample(sample1); } void loop() {} |
This is the soundsample.h
file :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const uint32_t sample1[] PROGMEM = { 0xd8040600, 0x37113f27, 0x0b2f343c, 0xfa3efe46, 0xfe3d9531, 0xa8236a05, 0x81f78beb, 0x97e852e6, 0x03e154e6, 0x8adc57e3, 0x87f29b05, 0xc508e208, 0xa30aae0f, 0xca06e2fb, 0x7becbcdb, 0xb9e1f5d9, 0x92deb3e7, 0x94f15803, 0x130b58fb, 0x1afe6d03, 0x8f0fa404, 0x73f379f8, 0x82f080eb, 0xbae1e9e9, 0x5a015e0d, 0xbd07b411, 0x60224c35, 0x9f30ba39, 0x8b4a2a4e, 0x05508851, 0xae39c831, 0x8e2c6520, 0xc6164910, 0x4d17061c, 0x2c18c514, 0xcb13090d, 0x011cf128, 0xe22c9825, 0x420b76eb, 0xc4e4fbdf, 0x77d9e6c7, 0x01c9ffd3, 0x7cddbcea, 0xf0f45bfe, 0x31fb1af3, 0x58f358fa, 0x6ffed901, 0x0b040bfe, 0xe1fbf3ea, 0xbfe080d9, 0x30dcbde0, 0x85d99cd2, 0x3ac608c7, 0x6fd58ef4, 0x9606e90d, 0xd611a61b, 0xdb30643c, 0x9745a946, 0x1445754d, 0x0149c244, 0x283c823b, 0x1e416b33, 0x942b5220, 0x2117a611, // yadayadayada //yadayadayada... }; |
There are audio libraries which supports parsing and decoding MOD, WAV, MP3, FLAC, MIDI, AAC, and RTTL files and playing them on an I2S DAC :
---
1 | https://github.com/earlephilhower/ESP8266Audio |
The documentation of it is enough good resource. Another related good resource is TinySoundFont :
1 | https://github.com/schellingb/TinySoundFont |
Another slightly related good “out of the box” idea of interfacing with composite audio/video is :
1 | https://bitluni.net/esp32-composite-audio |