-
Notifications
You must be signed in to change notification settings - Fork 7.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
I2S microphone stutter with IDF v5.0 (IDFGH-9764) #11098
Comments
I'm no expert with ESP-IDF but I have experience with data sampling... I could be way-off, but worth checking to at least rule-out my observations :
From these observations, the ESP 32 in 16-bit mode wasn't keeping up with the recording of data. Can you confirm the configured CPU speed of the ESP32? Also, from the docs, can you clarify if your app is going into light sleep, by checking the CONFIG_PM_ENABLE setting, according to your setup? https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/i2s.html Details
When the power management is enabled (i.e. CONFIG_PM_ENABLE is on), the system will adjust or stop the source clock of I2S before going into light sleep, thus potentially changing the I2S signals and leading to transmitting or receiving invalid data. |
Thanks cdluv! Those are some good points Since the board I am using doesn't have SD card reader, I have changed the example to write to PSRAM instead. After everything is written into PSRAM, I send the array over via socket to my computer so I can play the .wav file. Initially, I was streaming to socket right after CPU frequency: 160 MHz Should I increase the CPU speed? I looked at the settings and I see that
This shouldn't affect I2S, right? |
I also tried speeding up (240MHz) and slowing down (80MHz) the CPU but there was no difference |
Thanks for the info. If speeding up the CPU to 240MHz didn't help, then the choppiness is coming from elsewhere. Are you sending any information over UART while capturing the data? If so, try to not send output to the console, as this will cause an ISR to do work in the background when you least want it to. I'm not sure what the default setting for CONFIG_PM_ENABLE is, so you could try setting it to n, just in case the default value is y. CONFIG_PM_ENABLE=n Could you share your code which takes the I2S samples and copies to SPIRAM? One other thing that might be causing an issue is if Wi Fi is enabled (it shouldn't as it runs on a different core). Try disabling WiFi while you record the I2S data: (Note adc_power_off might be deprecated - I haven't checked, in which case comment out any annotated lines of code below:
Without looking at the code, I'm out of helpful ideas right this second. |
With these 3 I still see the stutter. I'll check again if I can turn wifi off. But I'm only turning wifi on after I copy to PSRAM. I have pasted my code here: https://gist.github.com/jayavanth/61938c8b52d1b5b3f24dc7e06ba7da89. Important parts are commented with Thank you for your help! 🙏 |
Thanks for sharing your code, and thanks for feeding back. I've learned something from you :-) I haven't compiled your code - just walked through it in my head and found a few things of slight concern - any combination of which could contribute to the overall choppiness you're encountering.
MOST IMPORTANTLY: To fix 1 and 3, may I suggest you create one large array for your sample output (if malloc allows it, of course), and copy your sample buffer to the next writable positions in the PSRAM buffer? If that's not possible, points 2, 3, and 4 remain relevant. Good luck! |
Hi @jayavanth , thanks for providing the codes! I've looked into your codes and the issue you described, there are some suggestion may help you to solve the issue: How The Issue OccursI found you allocated a static int16_t i2s_readraw_buff[SAMPLE_SIZE]; whose size is But when reading the data at line 122, you only read Then you copy the buffer to psram, however, you uses buffer index instead of For summary, the forth parameter How to SolveSolution 1As the issue is caused by the inappropriate buffer length, you can fixed it easily by give the whole size of the if (i2s_channel_read(rx_handle, (char *)i2s_readraw_buff, SAMPLE_SIZE * 2, &bytes_read, 100) == ESP_OK) { Solution 2Actually, you even don't need a temporary buffer int16_t* psram_array = (int16_t*)heap_caps_malloc(ROWS * COLS * sizeof(int16_t), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
if (i2s_channel_read(rx_handle, psram_array, ROWS * COLS * sizeof(int16_t), &bytes_read, 20 * 1000) == ESP_OK) {
// on read success
}
else {
// on read fail
} TipsNormally, only if data lost happened, you might need to consider whether CPU is too busy to read all the I2S data, but the stutter contains a complete data which can get rid of the possibility of data lost. If data lost happens, you can refer to How to prevent data lost section in programming guide. Really thanks for the great effort contribute by @cdluv ! Hope you all everything goes well! |
Thank you both. Ya I think that's definitely wrong. I think the .wav format is also wrong. Let me do all the experiments and I'll report back soon |
Great catch and nice work @L-KAYA ! A really clean and on-point answer. 👍 Good luck @jayavanth! |
An update:
I have updated my code here. Sorry for the commented lines and raw integer values for indexing: https://gist.github.com/jayavanth/7498ef6e75eed4eec975704c5d0dd292 So I have pretty much given up on PSRAM. I also found some posts to suggest that I2S and PSRAM don't work well together. But I'm not sure if those are still relevant and maybe those issues are fixed. My plan right now is to do the following:
Thank you both for the suggestions so far. I'll let you know how the above goes |
This is very odd, but I can see that the stutter will always occur between the times you have received a block of sound samples, and copying the recorded data to SPIRAM. The measures I suggested earlier should have had a positive effect. Here's a bullet-proof approach to prevent stutter:
Using the DMA buffer with conventional RAM means you'll have sufficient time to copy the sampled audio, without stuttering. Pretty sure that will work because the DMA controller will create an interrupt when the DMA buffer fills up, but also, audio capture will continue in the background. Note that a smaller buffer will create more interrupts, so having about 4K for a buffer will grant you more time to process the data which has arrived. Once again, good luck! If anything, we're learning loads. |
The SPI Flash didn't work either. It seems much worse. I don't see any stuttering, but the whole thing sounds robotic. Code here: https://gist.github.com/jayavanth/6226bc7b40f5b7c60cdb5837cc224b90. I was in disbelief when I heard the results from this. Really thought it would do better given the performance of SPI SD card readers Ok I'll take your advice and re-read and verify everything that you mentioned so far. Especially the last paragraph. Seems like PSRAM would give me the best chance here |
If you are worry about the data that recorded from I2S is not continuous, the tip is to register a However, I still suspect the data that be sent via WiFi might be incomplete, could you print all the data to the terminal, to check whether it looks correct before sending it. Also, you can try to move the print to each step (like before writing into flash) to trace where the data go wrong. |
You were right. I registered the callback and nothing was dropped. It's probably the wifi. Will investigate that |
All right. Found the bug! It was because I had set my socket to non-blocking! Will post the working code in a bit. Phew! |
Glad to hear that! BTW - I made a "faux pas" when I mentioned SPIRAM - I
didn't mean the on-chip flash memory. I actually meant PSRAM, and assumed
they could be used interchangeably. My bad - really sorry for the
confusion. Just to be clear:
Both PSRAM (Pseudo Static RAM) and SPIRAM (Serial Peripheral Interface RAM)
are types of Random Access Memory (RAM) used in the ESP32 microcontroller.
Here are some of the differences between them:
1. Interface: PSRAM is a parallel interface memory that requires a large
number of pins for data transfer, whereas SPIRAM uses a serial interface
with fewer pins.
2. Capacity: PSRAM is available in larger capacities than SPIRAM. PSRAM can
range from 16 MB to 64 MB, while SPIRAM is typically available in
capacities up to 4 MB.
3. Speed: PSRAM is faster than SPIRAM due to its parallel interface.
However, the difference in speed may not be noticeable in many applications.
4. Cost: PSRAM is more expensive than SPIRAM due to its larger capacity and
parallel interface.
5. Power Consumption: SPIRAM consumes less power than PSRAM due to its
serial interface, making it suitable for low-power applications.
6. Availability: SPIRAM is more widely available than PSRAM, making it
easier to find and purchase.
In summary, PSRAM and SPIRAM differ in terms of interface, capacity, speed,
cost, power consumption, and availability. The choice between the two
depends on the specific application requirements and the available budget.
The onboard flash chip should have been okay to use in combination with the recommended callback function implemented.
…On Fri, 7 Apr 2023 at 01:39, Jay ***@***.***> wrote:
All right. Found the bug! It was because I had set my socket to
non-blocking! Will post the working code in a bit. Phew!
—
Reply to this email directly, view it on GitHub
<#11098 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA534DWD462HGZVZZI2W7MDW75O3HANCNFSM6AAAAAAWPBLJWM>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Oh thank you! I thought they were the same |
Here's the final code for mono recording. Cached on PSRAM and then sent via TCP socket. Working on getting stereo working.. https://gist.github.com/jayavanth/98873070da289e2a4df2971563061665 Thank you @cdluv and @L-KAYA. Could not have done it without your help 🙏 |
Answers checklist.
IDF version.
v5.0
Operating System used.
macOS
How did you build your project?
Command line with idf.py
If you are using Windows, please specify command line type.
None
Development Kit.
Custom Board with ESP32-S3-WROOM-1-N16R8
Power Supply used.
USB
What is the expected behavior?
Clear sound from the mic
What is the actual behavior?
Steps to reproduce.
Mic: CMM-4030D-261-I2S-TR (Datasheet)
IDF version: 5.0
I used the
examples/i2s/i2s_recorder
and modified it for TDM instead of PDM.My
init_microphone()
functionAlthough this not a TDM, the best output I got was when I used this config. With STD configs, I got very noisy audio or just silence.
Sample for 8-bit audio: https://voca.ro/1lqOUedU4wOa (WARNING: VERY VERY LOUD)
Sample for 16-bit audio: https://voca.ro/11n2lNsQuS0r
This is what it looks on Audacity. There are some empty slots but they don't look like they all have the same size
![Screenshot 2023-03-31 at 12 19 50 PM](https://user-images.githubusercontent.com/584402/229210299-878b7358-03e5-4b29-82fc-0121791ea379.png)
Debug Logs.
No response
More Information.
No response
The text was updated successfully, but these errors were encountered: