Setup:
I'm trying to record USB audio waveforms and I've noticed that periodically several samples are dropped (or zero samples are inserted - depending on which PC I use for recoding). I noticed the following comment in Arduino15/packages/teensy/hardware/avr/1.59.0/cores/teensy4/usb_audio.cpp:
I was able to add some debugging to usb_audio.cpp and it confirms that overrun is occurring (see the attached modified usb_audio.cpp and I2S_Audio.ino). The serial output while recording is:
In the corresponding recording from Audacity you can see the "ticks" that the correspond to the overruns (I've attached the corresponding wave file overrun.wav.zip where you can hear the "ticks").
I'm wondering if there is a simple fix?
Note: I am trying to record from I2S - but #if def'ed it out, replacing with the AudioSynthWaveformSine to avoid the use of any HW other than the Teensy 4.1. The issue is present when using I2S as well.
- Arduino 2.3.3 - CLI version 1.0.4
- Intel MacBook Pro running MacOS 15.0.1
- Teensy 4.1
- Teensy library 1.59
I'm trying to record USB audio waveforms and I've noticed that periodically several samples are dropped (or zero samples are inserted - depending on which PC I use for recoding). I noticed the following comment in Arduino15/packages/teensy/hardware/avr/1.59.0/cores/teensy4/usb_audio.cpp:
I think that the processor clock that is used to generate the samples does not match the USB frame rate - and there is a slight clock drift between the two when using the fixed schedule that averages to 44100 samples/s (the 9 frames of 44 samples and 1 frame of 45 samples with a USB frame rate 1000/s). The drift eventually results in either overrun or underrun of the buffers depending on whether the teensy clock is faster or slower than the USB frame rate. It appears that this is handled for USB playback, but not for USB record.unsigned int usb_audio_transmit_callback(void)
{
static uint32_t count=5;
uint32_t avail, num, target, offset, len=0;
audio_block_t *left, *right;
if (++count < 10) { // TODO: dynamic adjust to match USB rate
target = 44;
} else {
count = 0;
target = 45;
}
...
I was able to add some debugging to usb_audio.cpp and it confirms that overrun is occurring (see the attached modified usb_audio.cpp and I2S_Audio.ino). The serial output while recording is:
With an overrun ~ every 1s.18:04:45.713 -> usb_overrun: 3 usb_underrun: 1
18:04:46.817 -> usb_overrun: 6 usb_underrun: 1
18:04:47.923 -> usb_overrun: 7 usb_underrun: 1
18:04:49.032 -> usb_overrun: 8 usb_underrun: 1
18:04:50.137 -> usb_overrun: 9 usb_underrun: 1
18:04:52.319 -> usb_overrun: 10 usb_underrun: 1
18:04:53.426 -> usb_overrun: 11 usb_underrun: 1
18:04:54.533 -> usb_overrun: 12 usb_underrun: 1
18:04:55.639 -> usb_overrun: 13 usb_underrun: 1
18:04:58.925 -> usb_overrun: 14 usb_underrun: 1
In the corresponding recording from Audacity you can see the "ticks" that the correspond to the overruns (I've attached the corresponding wave file overrun.wav.zip where you can hear the "ticks").
I'm wondering if there is a simple fix?
Note: I am trying to record from I2S - but #if def'ed it out, replacing with the AudioSynthWaveformSine to avoid the use of any HW other than the Teensy 4.1. The issue is present when using I2S as well.