Hi Christoph and Group,
I believe I have already solved this. At least in my setups I do not hear cracks anymore for over a week now. I am running at 48khz and with smaller buffers. Sorry that I have not posted details or code yet, but I am seeing some differences in how Windows handles lower values of bInterval and am still making some changes to accommodate that before committing code.
The line below is necessary. It is what provides frequency feedback to the PC so that the PC can adjust its rate. It is the heart of USB audio in asynchronous mode. You shouldn't comment it out.
//feedback_accumulator += diff * 1; <=========== commented out!
The feedback_accumulator value is used to generate the 16.10 fixed point standard USB feedback value for the PC. This feedback value is what the USB gadget thinks its frequency is relative to the PC host. For example, take the initial value assigned to this register, 739875226. The actual feedback value that the PC sees is 739875225/(2**24) = 44.1000. The commented out code line above slowly adjusts this frequency over time as intended by the USB standard to synchronize the PC with the USB gadget. The Teensy code cleverly uses this mechanism to both synchronize clocks and keep 1.5XAUDIO_BLOCK_SIZE of data buffered. You are lucky that your Teensy 4.0 clock and PC clock are quite close in frequency so that you only hear a click every ~8 minutes. This will not be the case for everyone. This feedback is required to properly synchronize clocks and avoid any clicks.
The other line you comment out is not technically necessary, but I believe the intent is to "bump" the frequency a bit so that the device does not enter a scenario with too little data buffered so that jitter causes frequent underruns.
//if (f) feedback_accumulator += 3500; <=========== commented out!
There is a bug with the above line at least for the Teensy 4.0 platforms using USB2.0 that I have played with. For some reason that I don't understand yet, the PC will send the USB gadget audio packets of length 24 bytes every ms for the first second of operation. This causes multiple calls of the above line and results in the feedback_accumulator value being severely overcorrected. After a short initial time, the PC then starts sending packets of length 172 to 180 bytes every 1ms as expected for 44.1kHz. But the feedback_accumulator is so far out of alignment that it will take up to ten minutes for frequencies to resynchronize. To avoid this bug, change the line
AudioInputUSB::receive_flag = 1;
in usb_audio.cpp to
if (len > 100) AudioInputUSB::receive_flag = 1;
I think you can uncomment the code you commented out and make this one change and all your clicks should go away. I'm interested in learning if that really is the case for you.
73,
Steve
kf7o