I2S microphone (RX)
-
- Posts: 263
- Joined: Sun Jun 19, 2016 12:00 am
Re: I2S microphone (RX)
I like things small and digital, so its not for me. I can see the appeal though - good luck!
Re: I2S microphone (RX)
you are right - perhabs i will try - - hope for the digi tiny ICS boards asap ))BuddyCasino wrote:I like things small and digital, so its not for me. I can see the appeal though - good luck!
best wishes
rudi
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪
-
- Posts: 263
- Joined: Sun Jun 19, 2016 12:00 am
Re: I2S microphone (RX)
Already packaged, will send them out tomorrow!hope for the digi tiny ICS boards asap
Re: I2S microphone (RX)
BuddyCasino wrote:Already packaged, will send them out tomorrow!hope for the digi tiny ICS boards asap
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪
Re: I2S microphone (RX)
I finally made some progress after updating to 2.1 of the SDK
I was able to use core elements of the code from BuddyCasino successfully to grab audio data from my i2s microphone ( SPH0645 )
I was able to successfully record audio, however the audio is quiet and easily peaks out.
I noticed when working on calculating the voltage of the audio signal that the min max of the signal is very high.
For example, in a quiet room the min reading ( converted to 16bit ) is: 63830, and the max is: 63865.
I'm expecting these numbers to be much much lower. Is there something i'm missing here?
i'm using the value for 'val' to determine the min / max thresholds...
is it just me with this issue? Any suggestions for how to solve this? Any help would be appreciated.
I was able to use core elements of the code from BuddyCasino successfully to grab audio data from my i2s microphone ( SPH0645 )
I was able to successfully record audio, however the audio is quiet and easily peaks out.
I noticed when working on calculating the voltage of the audio signal that the min max of the signal is very high.
For example, in a quiet room the min reading ( converted to 16bit ) is: 63830, and the max is: 63865.
I'm expecting these numbers to be much much lower. Is there something i'm missing here?
i'm using the value for 'val' to determine the min / max thresholds...
Code: Select all
#define NUM_CHANNELS 2
#define BIT_SIZE I2S_BITS_PER_SAMPLE_32BIT
...
for (int i = 0; i < samples_read; i ++){
uint16_t val = (rbuf[3] << 8 ) + rbuf[2];
...
rbuf += NUM_CHANNELS * (BIT_SIZE / 8);
Re: I2S microphone (RX)
Wow.... super thanks @BuddyCasinoBuddyCasino wrote:Here is a complete example, I verified it works:Code: Select all
/* * app_main.c * * Created on: 30.03.2017 * Author: michaelboeckling */ #include <stdlib.h> #include <stddef.h> #include <inttypes.h> #include <string.h> #include <stdio.h> #include <stdbool.h> #include <sys/time.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/event_groups.h" #include "esp_system.h" #include "esp_log.h" #include "driver/i2s.h" #define TAG "main" static void init_i2s() { const int sample_rate = 44100; /* TX: I2S_NUM_0 */ i2s_config_t i2s_config_tx = { .mode = I2S_MODE_MASTER | I2S_MODE_TX, .sample_rate = sample_rate, .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels .communication_format = I2S_COMM_FORMAT_I2S_MSB, .dma_buf_count = 32, // number of buffers, 128 max. .dma_buf_len = 32 * 2, // size of each buffer .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1 }; i2s_pin_config_t pin_config_tx = { .bck_io_num = GPIO_NUM_26, .ws_io_num = GPIO_NUM_25, .data_out_num = GPIO_NUM_22, .data_in_num = GPIO_NUM_23 }; i2s_driver_install(I2S_NUM_0, &i2s_config_tx, 0, NULL); i2s_set_pin(I2S_NUM_0, &pin_config_tx); /* RX: I2S_NUM_1 */ i2s_config_t i2s_config_rx = { .mode = I2S_MODE_MASTER | I2S_MODE_RX, // Only TX .sample_rate = sample_rate, .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT, // Only 8-bit DAC support .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels .communication_format = I2S_COMM_FORMAT_I2S_MSB, .dma_buf_count = 32, // number of buffers, 128 max. .dma_buf_len = 32 * 2, // size of each buffer .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 // Interrupt level 1 }; i2s_pin_config_t pin_config_rx = { .bck_io_num = GPIO_NUM_17, .ws_io_num = GPIO_NUM_18, .data_out_num = I2S_PIN_NO_CHANGE, .data_in_num = GPIO_NUM_5 }; i2s_driver_install(I2S_NUM_1, &i2s_config_rx, 0, NULL); i2s_set_pin(I2S_NUM_1, &pin_config_rx); } void task_megaphone(void *pvParams) { uint16_t buf_len = 1024; char *buf = calloc(buf_len, sizeof(char)); struct timeval tv = {0}; struct timezone *tz = {0}; gettimeofday(&tv, &tz); uint64_t micros = tv.tv_usec + tv.tv_sec * 1000000; uint64_t micros_prev = micros; uint64_t delta = 0; init_i2s(); int cnt = 0; int bytes_written = 0; while(1) { char *buf_ptr_read = buf; char *buf_ptr_write = buf; // read whole block of samples int bytes_read = 0; while(bytes_read == 0) { bytes_read = i2s_read_bytes(I2S_NUM_1, buf, buf_len, 0); } uint32_t samples_read = bytes_read / 2 / (I2S_BITS_PER_SAMPLE_32BIT / 8); // convert 2x 32 bit stereo -> 1 x 16 bit mono for(int i = 0; i < samples_read; i++) { // const char samp32[4] = {ptr_l[0], ptr_l[1], ptr_r[0], ptr_r[1]}; // left buf_ptr_write[0] = buf_ptr_read[2]; // mid buf_ptr_write[1] = buf_ptr_read[3]; // high // right buf_ptr_write[2] = buf_ptr_write[0]; // mid buf_ptr_write[3] = buf_ptr_write[1]; // high buf_ptr_write += 2 * (I2S_BITS_PER_SAMPLE_16BIT / 8); buf_ptr_read += 2 * (I2S_BITS_PER_SAMPLE_32BIT / 8); } // local echo bytes_written = samples_read * 2 * (I2S_BITS_PER_SAMPLE_16BIT / 8); i2s_write_bytes(I2S_NUM_0, buf, bytes_written, portMAX_DELAY); cnt += samples_read; if(cnt >= 44100) { gettimeofday(&tv, &tz); micros = tv.tv_usec + tv.tv_sec * 1000000; delta = micros - micros_prev; micros_prev = micros; printf("%d samples in %" PRIu64 " usecs\n", cnt, delta); cnt = 0; } } } /** * entry point */ void app_main() { printf("starting app_main()\n"); xTaskCreatePinnedToCore(&task_megaphone, "task_megaphone", 16384, NULL, 20, NULL, 0); }
I verify it works flawlessly!
I can also make it work if I use "bits_per_sample : I2S_BITS_PER_SAMPLE_32BIT" as I2S TX config, by changing the code a bit:
Code: Select all
int bytes_read = 0;
while(bytes_read == 0) {
bytes_read = i2s_read_bytes(I2S_NUM_1, buf, sizeof(buf), portMAX_DELAY);
}
uint32_t samples_read = bytes_read / (I2S_BITS_PER_SAMPLE_32BIT / 8);
for (int i = 0; i < samples_read; i++)
{
buf_ptr_write[0] = buf_ptr_read[2]; // mid
buf_ptr_write[1] = buf_ptr_read[3]; // high
}
int bytes_written = samples_read * (I2S_BITS_PER_SAMPLE_32BIT / 8);
i2s_write_bytes(I2S_NUM_0, (const char*)buf, bytes_written, portMAX_DELAY);
Re: I2S microphone (RX)
I was able to confirm the code presented here works.
I have one problem though, when attempting to calculate the voltage of the audio signal, the min / max values coming in from i2s is really high. For example, in a silent room i'm getting a min max threshold of about min:62300, max: 62345
I am able to record audio. It's comes in quiet. But it maxes out really easy. All I have to do is whistle in the mic and the sound starts to break apart. Is this something you think may be specific to my i2s mic ( SPH0645 ). Any insight would be appreciated.
thank you,
I have one problem though, when attempting to calculate the voltage of the audio signal, the min / max values coming in from i2s is really high. For example, in a silent room i'm getting a min max threshold of about min:62300, max: 62345
I am able to record audio. It's comes in quiet. But it maxes out really easy. All I have to do is whistle in the mic and the sound starts to break apart. Is this something you think may be specific to my i2s mic ( SPH0645 ). Any insight would be appreciated.
thank you,
-
- Posts: 263
- Joined: Sun Jun 19, 2016 12:00 am
Re: I2S microphone (RX)
Yeah its confusing. I'm not even sure about about the in-memory data representation. The I2S protocol is MSB first (big-endian) two's complement (signed) integer. I think the DMA controller / I2S peripheral take care of the MSB/LSB issue, and that the words are layed out big-endian in ESP32 memory, but its all guesswork and experimentation on my side.
So, make sure your bits are what you expect them to be. I'm very interested in your findings!
So, make sure your bits are what you expect them to be. I'm very interested in your findings!
Re: I2S microphone (RX)
from my tests, i have found that using "I2S_COMM_FORMAT_RAW_I2S" gave better precision and quality than using "I2S_COMM_FORMAT_I2S_MSB" for the i2s_config_t.communication_format.
To give an example: with "I2S_COMM_FORMAT_RAW_I2S" the min max values in a semi quiet room are:
min:~62130 to max:~62190
However with "I2S_COMM_FORMAT_I2S_MSB", the results are:
min:~63810 to max:~63740
65535-63740 = 1795 ( precision depth )
65535 - 62190 = 3345 ( precision depth )
almost twice as much room using RAW_I2S.
I tested the audio quality with the two modes and as expected RAW_I2S generates better audio quality.
To handle the peaking out I just replace all values that are less than 30000 with the last accepted sample that came in ( it seems to work, at least for my purpose but still... if we can do better i'd like to try )
I created a github repo with the code I used for conducting my tests: https://github.com/meetri/esp32-i2s-audio-test
I have a few questions.
1. i'd like to try this with a different i2s mems microhone. ( any suggestions, i'm using adafruit's SPH0645 )
2. any idea's why setting the communication_format to I2S_COMM_FORMAT_RAW_I2S would have this benefit and is there a way to tweak this further ?
---debug notes---
This is just notes from my testing. It may or may not mean anything. Just posting my observations.
my github code grabs the 4 bytes from the sample, and keeps track of the min and max and peak 2 peak values for each byte per sample page.
In general this is what i've found
byte X | P2P : MIN : MAX
byte 0 | 0 : 0 : 0
----------
this never changes no matter the configuration settings...
byte 1 | 128 : 0 : 128
----------
this also never changes ....
byte 2 | XX : YY : ZZ
----------
this is the only byte that has active variability.
However, blowing very slightly on this mic causes this byte to max out. ( i feel it maxes out much sooner than it should like soon as P2P gets to around 120 it just jumps to 255... )
byte 3 | 0 : 242 : 243
----------
This stays pretty much constant. byte 2 maxes out, the P2P begins climbing from a rested MIN:MAX of 242 (...
blowing slightly on the mic raises the peak to peak to to about 16 at max then it jumps to 255.
These are my observations. Looking at the data using my saleae logic analyzer, doesn't show any clear peaking.
Note. I am a super beginner in this world. I hope that these notes point to something I can do to get better audio quality from this.
To give an example: with "I2S_COMM_FORMAT_RAW_I2S" the min max values in a semi quiet room are:
min:~62130 to max:~62190
However with "I2S_COMM_FORMAT_I2S_MSB", the results are:
min:~63810 to max:~63740
65535-63740 = 1795 ( precision depth )
65535 - 62190 = 3345 ( precision depth )
almost twice as much room using RAW_I2S.
I tested the audio quality with the two modes and as expected RAW_I2S generates better audio quality.
To handle the peaking out I just replace all values that are less than 30000 with the last accepted sample that came in ( it seems to work, at least for my purpose but still... if we can do better i'd like to try )
I created a github repo with the code I used for conducting my tests: https://github.com/meetri/esp32-i2s-audio-test
I have a few questions.
1. i'd like to try this with a different i2s mems microhone. ( any suggestions, i'm using adafruit's SPH0645 )
2. any idea's why setting the communication_format to I2S_COMM_FORMAT_RAW_I2S would have this benefit and is there a way to tweak this further ?
---debug notes---
This is just notes from my testing. It may or may not mean anything. Just posting my observations.
my github code grabs the 4 bytes from the sample, and keeps track of the min and max and peak 2 peak values for each byte per sample page.
In general this is what i've found
byte X | P2P : MIN : MAX
byte 0 | 0 : 0 : 0
----------
this never changes no matter the configuration settings...
byte 1 | 128 : 0 : 128
----------
this also never changes ....
byte 2 | XX : YY : ZZ
----------
this is the only byte that has active variability.
However, blowing very slightly on this mic causes this byte to max out. ( i feel it maxes out much sooner than it should like soon as P2P gets to around 120 it just jumps to 255... )
byte 3 | 0 : 242 : 243
----------
This stays pretty much constant. byte 2 maxes out, the P2P begins climbing from a rested MIN:MAX of 242 (...
blowing slightly on the mic raises the peak to peak to to about 16 at max then it jumps to 255.
These are my observations. Looking at the data using my saleae logic analyzer, doesn't show any clear peaking.
Note. I am a super beginner in this world. I hope that these notes point to something I can do to get better audio quality from this.
-
- Posts: 263
- Joined: Sun Jun 19, 2016 12:00 am
Re: I2S microphone (RX)
I've got some ICS-43434 breakout boards that I bought from here:1. i'd like to try this with a different i2s mems microhone. ( any suggestions, i'm using adafruit's SPH0645 )
https://www.tindie.com/products/onehors ... icrophone/
It says ICS-43432 only on the store page but you can say that you want the ICS-43434 variety instead. I'll test them as soon as I can find the time.
Where do you get I2S_COMM_FORMAT_RAW_I2S from? I have the latest IDF and all I have are these:2. any idea's why setting the communication_format to I2S_COMM_FORMAT_RAW_I2S would have this benefit and is there a way to tweak this further ?
Code: Select all
typedef enum {
I2S_COMM_FORMAT_I2S = 0x01, /*!< I2S communication format I2S*/
I2S_COMM_FORMAT_I2S_MSB = 0x02, /*!< I2S format MSB*/
I2S_COMM_FORMAT_I2S_LSB = 0x04, /*!< I2S format LSB*/
I2S_COMM_FORMAT_PCM = 0x08, /*!< I2S communication format PCM*/
I2S_COMM_FORMAT_PCM_SHORT = 0x10, /*!< PCM Short*/
I2S_COMM_FORMAT_PCM_LONG = 0x20, /*!< PCM Long*/
} i2s_comm_format_t;
Who is online
Users browsing this forum: atx823 and 70 guests