UAC2.0 Microphone: Audio artifacts with STM32L432 DMA > tud_audio_write() - Need guidance on proper buffering #3202
-
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 1 reply
This comment was marked as off-topic.
This comment was marked as off-topic.
-
Beta Was this translation helpful? Give feedback.
-
I'm in vacation without my PC so can't help you a lot.
It's fine to write data to USB directly from DMA interrupt, no need to count 48 samples for each write, audio class has flow control to correct clock drift. |
Beta Was this translation helpful? Give feedback.
-
@HiFiPhile Thank you for your pointers! I appreciate you taking some time to respond. We have done some more rigorous tests and are still getting regular 288-sample jump cuts in the audio when recording in Audacity. The audio is actually good for about #define ADC_BUFFER_SIZE 96
static uint16_t adc_buffer[ADC_BUFFER_SIZE];
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
if (hadc->Instance == ADC_INSTANCE) {
const uint32_t half = ADC_BUFFER_SIZE / 2;
uint16_t *raw = &adc_buffer[0];
// flip sign-bit in place
for (uint32_t i = 0; i < half; i++) {
raw[i] ^= 0x8000;
}
tud_audio_write((uint8_t*)raw, half * sizeof(uint16_t));
}
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if (hadc->Instance == ADC_INSTANCE) {
const uint32_t half = ADC_BUFFER_SIZE / 2;
uint16_t *raw = &adc_buffer[half];
// flip sign-bit in place
for (uint32_t i = 0; i < half; i++) {
raw[i] ^= 0x8000;
}
tud_audio_write((uint8_t*)raw, half * sizeof(uint16_t));
}
} We're feeding a 1kHz sine wave through the analog front-end. Audacity recording: ![]() ![]() ![]() The weird thing is that when I store 4096 of these samples to RAM in the DMA callbacks and dump them over CDC and plot them I see no cuts at all and everything looks fine: ![]() This leads me to believe our PCB design and ADC/DMA/oversampling configurations are working fine. I have pretty much tried everything I can think of these last few weeks, but granted I'm new to this library and USB audio in general. As I'm reading the Could this be a bug? Maybe the flow control? fsdev driver? Any gotchas or configurations I'm missing? Any help is very welcome! Would of course be open to send you any more data or share a test repository if you like. Thanks again for the response! Also, enjoy your vacation! EDIT: I just noticed that if I increase the buffer size to something much larger like: #define CFG_TUD_AUDIO_FUNC_1_EP_IN_SW_BUF_SZ 256 * CFG_TUD_AUDIO_EP_SZ_IN Then the audio stays perfectly fine for about 412ms (19,813 samples), then starts having problems. If I keep it small like |
Beta Was this translation helpful? Give feedback.
-
I think the greatest possibility is clock deviation, didn't notice you are using HSI clock. A clock of at least 0.1% precision should be used, 1% difference is pretty high, even noticable as a tone change. Taking full speed 48khz as example, in theory flow control can tolerate 2% deviation by sending 47/49 samples short/long packet. But in real Windows doesn't like device sending consecutive short/long packet so the regulation only happens each 10 packets, in result the maximum allowed deviation become 0.2%. You can log the fifo level like uac2_speaker_fb example with tud_audio_get_ep_in_ff() and tu_fifo_count(). |
Beta Was this translation helpful? Give feedback.
-
You were absolutely right about the clock deviation! I found the root cause: my STM32L432's HSI16 trim register was somehow set to 0 instead of the factory default of 16, causing approximately 3-5% frequency error. This was way beyond your 0.2% tolerance requirement. Adding Your explanation about Windows not tolerating consecutive short/long packets and the 10-packet regulation window leading to the 0.2% maximum deviation was incredibly helpful for understanding why the flow control was dropping samples. It confirms the need to redesign the next prototype with a proper HSE crystal oscillator, but this HSI16 trim fix proves the theory and makes it somewhat usable for now. Thank you for pointing me in the right direction! EDIT: |
Beta Was this translation helpful? Give feedback.
I think the greatest possibility is clock deviation, didn't notice you are using HSI clock.
A clock of at least 0.1% precision should be used, 1% difference is pretty high, even noticable as a tone change.
Taking full speed 48khz as example, in theory flow control can tolerate 2% deviation by sending 47/49 samples short/long packet. But in real Windows doesn't like device sending consecutive short/long packet so the regulation only happens each 10 packets, in result the maximum allowed deviation become 0.2%.
You can log the fifo level like uac2_speaker_fb example with tud_audio_get_ep_in_ff() and tu_fifo_count().