├── LICENSE.txt ├── README.md ├── doc ├── DSC_0074.JPG ├── wiring.png └── wiring_MAX9814.jpg └── esp32_I2S_recorder ├── I2S.cpp ├── I2S.h ├── Wav.cpp ├── Wav.h └── esp32_I2S_recorder.ino /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Mhage 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # esp32_SoundRecorder 2 | ![board](doc/DSC_0074.JPG) 3 | 4 | ## Prepare 5 | - [ESP32-DevKitC](https://www.espressif.com/en/products/hardware/esp32-devkitc/overview) : espressif 6 | - [AE-ADMP441_K](http://akizukidenshi.com/catalog/g/gK-06864/) : Akizuki Denshi (or similar product using ADMP441) 7 | - [AE-MICRO-SD-DIP](http://akizukidenshi.com/catalog/g/gK-05488/) : Akizuki Denshi (or similar product for micro SD slot) 8 | - resistor 10kΩ x 4, 100kΩ x 1, capacitor 22pF x 1 9 | 10 | ## Wiring microphone with I2S interface 11 | ![wiring1](doc/wiring.png) 12 | 13 | ### Wiring MAX9814 (without I2S interface) by [ligantx](https://github.com/ligantx) 14 | ![WiringMax9814](doc/wiring_MAX9814.jpg) 15 | The SD card wiring is the same as above (for my sd card adapter, pullup resistors weren't necessary) 16 | 17 | MAX9814 Wiring: 18 | MAX9814 | ESP32 19 | GND - GND 20 | Vdd - 3V3 21 | Out - VP (GPIO36) 22 | AR - dont connect 23 | Gain - if it's not connected is 60dB Gain, if its connected to Gnd it's 50dB, and if it's connected to Vdd it's 40dB 24 | 25 | Note: if you want to change the Esp32 VP pin to another, use [this image](https://lastminuteengineers.com/wp-content/uploads/arduino/ESP32-Development-Board-Pinout.png) and change `ADC1_CHANNEL_0` in I2S.cpp file accordingly. 26 | 27 | i used information from [this example](https://github.com/espressif/esp-idf/blob/master/examples/peripherals/i2s_adc_dac/main/app_main.c) 28 | 29 | ## Development Environment 30 | - [Arduino IDE](https://www.arduino.cc/en/main/software) 31 | - [arduino-esp32](https://github.com/espressif/arduino-esp32) 32 | 33 | ## How to use 34 | Set SD card. Turn on the power. And it starts recording sound and saves as wav file (16bit, monoral, 44.1kHz) in SD card. 35 | -------------------------------------------------------------------------------- /doc/DSC_0074.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MhageGH/esp32_SoundRecorder/17a0b0020746ef2d7350bde928ed718f5e2b75aa/doc/DSC_0074.JPG -------------------------------------------------------------------------------- /doc/wiring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MhageGH/esp32_SoundRecorder/17a0b0020746ef2d7350bde928ed718f5e2b75aa/doc/wiring.png -------------------------------------------------------------------------------- /doc/wiring_MAX9814.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MhageGH/esp32_SoundRecorder/17a0b0020746ef2d7350bde928ed718f5e2b75aa/doc/wiring_MAX9814.jpg -------------------------------------------------------------------------------- /esp32_I2S_recorder/I2S.cpp: -------------------------------------------------------------------------------- 1 | #include "I2S.h" 2 | 3 | void I2S_Init(i2s_mode_t MODE, i2s_bits_per_sample_t BPS) 4 | { 5 | i2s_config_t i2s_config = { 6 | .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN), 7 | .sample_rate = SAMPLE_RATE, 8 | .bits_per_sample = BPS, 9 | .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, 10 | .communication_format = (i2s_comm_format_t)(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), 11 | .intr_alloc_flags = 0, 12 | .dma_buf_count = 16, 13 | .dma_buf_len = 60 14 | }; 15 | if (MODE == I2S_MODE_RX || MODE == I2S_MODE_TX) { 16 | Serial.println("using I2S_MODE"); 17 | i2s_pin_config_t pin_config; 18 | pin_config.bck_io_num = PIN_I2S_BCLK; 19 | pin_config.ws_io_num = PIN_I2S_LRC; 20 | if (MODE == I2S_MODE_RX) { 21 | pin_config.data_out_num = I2S_PIN_NO_CHANGE; 22 | pin_config.data_in_num = PIN_I2S_DIN; 23 | } 24 | else if (MODE == I2S_MODE_TX) { 25 | pin_config.data_out_num = PIN_I2S_DOUT; 26 | pin_config.data_in_num = I2S_PIN_NO_CHANGE; 27 | } 28 | 29 | i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); 30 | i2s_set_pin(I2S_NUM_0, &pin_config); 31 | i2s_set_clk(I2S_NUM_0, SAMPLE_RATE, BPS, I2S_CHANNEL_STEREO); 32 | } 33 | else if (MODE == I2S_MODE_DAC_BUILT_IN || MODE == I2S_MODE_ADC_BUILT_IN) { 34 | Serial.println("using ADC_builtin"); 35 | i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); 36 | // GPIO36, VP 37 | i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_0); 38 | } 39 | } 40 | 41 | int I2S_Read(char *data, int numData) 42 | { 43 | return i2s_read_bytes(I2S_NUM_0, (char *)data, numData, portMAX_DELAY); 44 | } 45 | 46 | void I2S_Write(char *data, int numData) 47 | { 48 | i2s_write_bytes(I2S_NUM_0, (const char *)data, numData, portMAX_DELAY); 49 | } 50 | -------------------------------------------------------------------------------- /esp32_I2S_recorder/I2S.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "freertos/FreeRTOS.h" 3 | #include "freertos/task.h" 4 | #include "driver/i2s.h" 5 | #include "esp_system.h" 6 | #define SAMPLE_RATE (44100) 7 | #define PIN_I2S_BCLK 26 8 | #define PIN_I2S_LRC 22 9 | #define PIN_I2S_DIN 34 10 | #define PIN_I2S_DOUT 25 11 | 12 | // This I2S specification : 13 | // - LRC high is channel 2 (right). 14 | // - LRC signal transitions once each word. 15 | // - DATA is valid on the CLOCK rising edge. 16 | // - Data bits are MSB first. 17 | // - DATA bits are left-aligned with respect to LRC edge. 18 | // - DATA bits are right-shifted by one with respect to LRC edges. 19 | // It's valid for ADMP441 (microphone) and MAX98357A (speaker). 20 | // It's not valid for SPH0645LM4H(microphone) and WM8960(microphon/speaker). 21 | // 22 | // - 44100Hz 23 | // - stereo 24 | 25 | /// @parameter MODE : I2S_MODE_RX or I2S_MODE_TX 26 | /// @parameter BPS : I2S_BITS_PER_SAMPLE_16BIT or I2S_BITS_PER_SAMPLE_32BIT 27 | void I2S_Init(i2s_mode_t MODE, i2s_bits_per_sample_t BPS); 28 | 29 | /// I2S_Read() for I2S_MODE_RX 30 | /// @parameter data: pointer to buffer 31 | /// @parameter numData: buffer size 32 | /// @return Number of bytes read 33 | int I2S_Read(char* data, int numData); 34 | 35 | /// I2S_Write() for I2S_MODE_TX 36 | /// @param data: pointer to buffer 37 | /// @param numData: buffer size 38 | void I2S_Write(char* data, int numData); 39 | -------------------------------------------------------------------------------- /esp32_I2S_recorder/Wav.cpp: -------------------------------------------------------------------------------- 1 | #include "Wav.h" 2 | 3 | void CreateWavHeader(byte* header, int waveDataSize){ 4 | header[0] = 'R'; 5 | header[1] = 'I'; 6 | header[2] = 'F'; 7 | header[3] = 'F'; 8 | unsigned int fileSizeMinus8 = waveDataSize + 44 - 8; 9 | header[4] = (byte)(fileSizeMinus8 & 0xFF); 10 | header[5] = (byte)((fileSizeMinus8 >> 8) & 0xFF); 11 | header[6] = (byte)((fileSizeMinus8 >> 16) & 0xFF); 12 | header[7] = (byte)((fileSizeMinus8 >> 24) & 0xFF); 13 | header[8] = 'W'; 14 | header[9] = 'A'; 15 | header[10] = 'V'; 16 | header[11] = 'E'; 17 | header[12] = 'f'; 18 | header[13] = 'm'; 19 | header[14] = 't'; 20 | header[15] = ' '; 21 | header[16] = 0x10; // linear PCM 22 | header[17] = 0x00; 23 | header[18] = 0x00; 24 | header[19] = 0x00; 25 | header[20] = 0x01; // linear PCM 26 | header[21] = 0x00; 27 | header[22] = 0x01; // monoral 28 | header[23] = 0x00; 29 | header[24] = 0x44; // sampling rate 44100 30 | header[25] = 0xAC; 31 | header[26] = 0x00; 32 | header[27] = 0x00; 33 | header[28] = 0x88; // Byte/sec = 44100x2x1 = 88200 34 | header[29] = 0x58; 35 | header[30] = 0x01; 36 | header[31] = 0x00; 37 | header[32] = 0x02; // 16bit monoral 38 | header[33] = 0x00; 39 | header[34] = 0x10; // 16bit 40 | header[35] = 0x00; 41 | header[36] = 'd'; 42 | header[37] = 'a'; 43 | header[38] = 't'; 44 | header[39] = 'a'; 45 | header[40] = (byte)(waveDataSize & 0xFF); 46 | header[41] = (byte)((waveDataSize >> 8) & 0xFF); 47 | header[42] = (byte)((waveDataSize >> 16) & 0xFF); 48 | header[43] = (byte)((waveDataSize >> 24) & 0xFF); 49 | } 50 | 51 | -------------------------------------------------------------------------------- /esp32_I2S_recorder/Wav.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // 16bit, monoral, 44100Hz, linear PCM 4 | void CreateWavHeader(byte* header, int waveDataSize); // size of header is 44 5 | -------------------------------------------------------------------------------- /esp32_I2S_recorder/esp32_I2S_recorder.ino: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | #include 3 | #include "Wav.h" 4 | #include "I2S.h" 5 | #include 6 | 7 | 8 | //comment the first line and uncomment the second if you use MAX9814 9 | //#define I2S_MODE I2S_MODE_RX 10 | #define I2S_MODE I2S_MODE_ADC_BUILT_IN 11 | 12 | const int record_time = 10; // second 13 | const char filename[] = "/sound.wav"; 14 | 15 | const int headerSize = 44; 16 | const int waveDataSize = record_time * 88000; 17 | const int numCommunicationData = 8000; 18 | const int numPartWavData = numCommunicationData/4; 19 | byte header[headerSize]; 20 | char communicationData[numCommunicationData]; 21 | char partWavData[numPartWavData]; 22 | File file; 23 | 24 | void setup() { 25 | Serial.begin(115200); 26 | if (!SD.begin()) Serial.println("SD begin failed"); 27 | while(!SD.begin()){ 28 | Serial.print("."); 29 | delay(500); 30 | } 31 | CreateWavHeader(header, waveDataSize); 32 | SD.remove(filename); 33 | file = SD.open(filename, FILE_WRITE); 34 | if (!file) return; 35 | file.write(header, headerSize); 36 | I2S_Init(I2S_MODE, I2S_BITS_PER_SAMPLE_32BIT); 37 | for (int j = 0; j < waveDataSize/numPartWavData; ++j) { 38 | I2S_Read(communicationData, numCommunicationData); 39 | for (int i = 0; i < numCommunicationData/8; ++i) { 40 | partWavData[2*i] = communicationData[8*i + 2]; 41 | partWavData[2*i + 1] = communicationData[8*i + 3]; 42 | } 43 | file.write((const byte*)partWavData, numPartWavData); 44 | } 45 | file.close(); 46 | Serial.println("finish"); 47 | } 48 | 49 | void loop() { 50 | } 51 | --------------------------------------------------------------------------------