On the STM32L4 Discovery kit for IoT node (B-L47E-IOT0A1
), there are two MP34DT01
microphones: one
with LR pulled to VDD and the second with LR pulled low. DFSDM1_CKOUT
and
DFSDM1_DATIN2
are connected for both. I have this board, with the system clock set at 80MHz, and DFSDM CH2
enabled In DMA
mode. Additionally I have the filter set in continuous mode with Fosr
set at 52, and Iosr
at 8. I can get values so I know that the microphones are working, but trying to play back the audio results in a bunch of static. I believe my sampling rate should be 48KHz because the interal SPI clock divider is set to 4. -- (80MHz/4)/(52 * 8) = 48KHz]
-- My setup is below:
// Audio.c
#define AUDIO_LEN 240
#define H_AUDIO_LEN 120
int32_t micRecBuf[AUDIO_LEN];
int32_t micAudioBuf[AUDIO_LEN];
volatile uint8_t audioFilterHalfCplt = 0;
volatile uint8_t audioFilterCplt = 0;
void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) {
audioFilterHalfCplt = 1;
}
void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) {
audioFilterCplt = 1;
}
void micInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) {
HAL_DFSDM_FilterRegularStart_DMA(hdfsdm_filter, micRecBuf, AUDIO_LEN);
}
while(true) {
// first half of DMA is filled, now process
if (audioFilterHalfCplt == 1) {
// fill the audio buffer
for (i = 0; i < H_AUDIO_LEN; i++) {
micAudioBuf[i] = micRecBuf[i] << 8; // remove meta data
}
// reset the flag
audioFilterHalfCplt = 0;
}
// second half is filled, finish process
if (audioFilterCplt == 1) {
// fill the audio buffer
for (i = H_AUDIO_LEN; i < AUDIO_LEN; i++) {
micAudioBuf[i] = micRecBuf[i] << 8; // remove meta data
}
}
I am able to retrieve the data and save it to a binary file using this shell command:
screen -S audio -L -Logfile audio.bin /dev/ttyACM1 9600, cs8
And I save the data as a wav file using this python script:
#!/usr/bin/env python3
import wave
with open("audio.bin", "rb") as input_file:
data = input_file.read()
with wave.open("output.wav", "wb") as output_file:
output_file.setnchannels(1) # Assuming mono
output_file.setsampwidth(4) # Assuming 16-bit samples (2 bytes)
output_file.setframerate(48077) # Set the sample rate
output_file.writeframesraw(data)
When I play back the audio file it is all static. Where am I going wrong in this process?
Caveat: Not a complete solution, but some things to try ...
Although, it may be an issue with the wiring or DMA setup, etc. there are some things to check first to ensure your capture and transfer process is correct.
From my top comment: You're outputting mono 16 bit which is 2 bytes but you specify 4? Also, bitrates are usually 44100 (pc audio) or 48000 (mp4 audio), so 48077 seems strange to me.
Can you verify that your PC captures the data correctly? That is, the baud rate, etc. are correct. Are both the PC and STM32 set correctly?
Have the STM32 output a fixed string of known bytes at the beginning. (e.g.) for (i = 0; i < 256; ++i) buf[i] = i;
That fixed [and verifiable] pattern should start the .bin
file. You can examine this with a hex editor.
If you set up your PC to output [through its speakers] a pure tone (e.g. sine wave) and record that, when you get the .bin
back file on your PC, you should be able to plot the raw data and see the sine wave.
Can you guarantee that when your DMA completes, that it completely fills the buffer? Is there a function you can call to get the number of bytes actually transferred by the DMA? (e.g.) Could you get a completion that has fewer bytes than you requested?
Could you have a race condition between the DMA and your code? Is your buffering scheme good enough to prevent the DMA from doing output to first and second halves, but go so fast that it tries to fill the first buffer [partially] again?
In other words, your base waits for a "DMA complete" flag (e.g. audioFilterHalfCplt
) and grabs the data. But, what prevents the DMA from writing the next chunk of data into that buffer while you are pulling it out in your loop?