I'm working on a multi-channel audio device, and most recently I've been testing to verify that the audio is bit-perfect. This means zero errors between USB device and host, so with that comes the requirement of no (i.e. never) overflows or underflows as the feedrate is adjusted by the feedback endpoint. Has anyone ever verified that the current mechanism implemented in the SDK can achieve this?
Hi @Alexis_A ,
So I've been doing a lot of testing to determine if I have a bit-perfect audio path;
particularly on the microphone side (HOST INPUT) of things.
Short answer: I don't.
First note, that my setup is using SAI interface to the Codec in interrupt mode rather
than DMA. I need to do this because my board is doing echo cancellation, so I need to
intercept all incoming microphone signal and push it into the AEC processor prior to
sending the data up to the host.
Ignoring the AEC portion, the SAI interrupt handler pulls all PCM off the codec through
the SAI FIFO. My code has to push that PCM to queues that are drained by the function
USB_AudioRecorderGetBuffer(). I had to modify that function (from the SDK example) to
pull the audio out of my queues.
The function is called with a buffer pointer and a number of bytes. If I just attempted
to retrieve the number of bytes requested, it didn't take long for there to be buffer
underflow errors (i.e. host asks for more data than I have). Eventually I realized that
I could modify the incoming length request to avoid buffer errors, and then feed up a
different amount of data to the host than the call to USB_AudioRecorderGetBuffer()
actually requested. This fixed 99% of the flow control problemms; however, I still
have an occasional error, and I assume that's where Endpoint Feedback comes in to the
As a result I had to try to understand the ENDPOINT Feedback stuff, and implement it for
the INPUT (microphone) direction. I thought with that in place flow control would be
solved, but it doesn't seem to help. I only see one incoming ENDPOINT feedback message
from the host (in USB_DeviceAudioIsoIN()) when I start up arecord on the Linux host that I
have my device plugged into. After that (sometimes it takes an hour) I still see occasional
bit errors on the audio/microphone feed.
Looking closer at the Feedback code, I see that the SPEAKER feedback request comes in quite
often, so I'm wondering if I really have the Feedback implemented properly on the INPUT side.
If anyone has any thoughts on this, I'd sure appreciate a replay...
I'm getting closer...
I can say with a high level of confidence that I now have bit-perfect audio in the IN direction (mic-array in my case). Referring to my previous post where I stated that I had it -almost- working based on a change made to USB_AudioRecorderGetBuffer() which allows my code to determine how much data to send to the host (rather than using the suggested length)...
That fixed it 100%. I found a snippet of my code that needed to be critical-section protected and that was causing occasional errors to be sent to the host. So, at this point, I can claim that at least the USB portion of the IN direction does give me bit-perfect audio. In the nutshell that means I can send "fake" data from the target up to the host for hours without seeing an error (the receiver knows what to expect, so it makes sure that's what it receives). The final open issue here is to understand why I still have occasional incoming SAI-FIFO errors (which obviously will cause errors regardless of how perfect the USB path is).
Just to clarify... after reading through the USB docs (yet again); I've come to realize that the feedback endpoint only applies to the OUT direction (speaker in my case). The IN direction is adaptive on the host side based on the amount of data it receives from the device. Since this is USB, and since I am by no means a USB expert; if someone knows better (i.e. I am wrong); please reply to this thread.
Unfortunately, since this application is custom I can't give an accurate opinion but a look at section 22.214.171.124 in the audio standard, there's a parameter in the descriptor to set the frequency the feedback endpoint provide new synchronization. Maybe tunning this parameter could help the little errors that are still present.
Thanks for responding, I will keep you posted on my results (testing in progress). As I see it there are two potential points of error (note that I am assuming the connection between USB-host/device is error free)...
For #1 to be error free, the feedback endpoint has to be smoothly adjusting for slight differences in clock timing between host and device.
For #2 to be error free, the codec driver must be properly emptying (or filling) the SAI FIFOs to keep pace with the codec itself.
Does this make sense to you?