audio-resampler icon indicating copy to clipboard operation
audio-resampler copied to clipboard

Please clarify use as ASRC

Open timsurber opened this issue 1 year ago • 3 comments

Hey,

thank you for your work!

Could you please explain how to use your library as ASRC (asynchronous sample rate converter) .

Imagine I have two threads, one is pushing new samples in, the other receives them at non synchronous clocks.

Your library would be in the middle.

Which functions would I call?

Which parameters would be static and which should be varied in the servo loop? I would imagine ratio, but what about numInputFrames and numOutputFrames?

Thank you!

timsurber avatar Jul 20 '23 01:07 timsurber

First, let me apologize for not having any function-level documentation on the resampler; I really must rectify that! Especially for implementing an ASRC, the demo application is not sufficient.

For an ASRC, the only parameter that would be controlled in the servo loop is the ratio, and the only function you would call (once you got started) would be resampleProcess() (or resampleProcessInterleaved() depending on your data layout).

The numInputFrames and numOutputFrames simply indicate to the function how many samples are available at input and how much writable space is available at output. In other words, the process function just continues to convert (at the given ratio) until either the available input or available output is exhausted (and both input samples used and output samples generated are returned). Of course, if you are operating directly on ring buffers then you might need multiple calls to account for wrapping, but the normal use would be to process as much data as possible, as long as there’s space for the result.

The crudest design I can imagine for an ASRC is where you have one large ring buffer that receives the resampled data (to head) and outputs to the destination (from tail). In that case the buffer level directly controls the ratio: as the buffer level drops the ratio is increased, which causes the resampled data to flow into the buffer faster. The buffer could also hold audio before it's resampled too, either way is pretty much equivalent.

Of course, this simple case is complicated by the fact that the data might be arriving (and leaving) in chunks, so unless the buffer is many times the size of the chunks (which means high latency) then it becomes more complex to gauge the “fullness” unless there is timestamp information along with the chunks. In other words, by knowing when the last chunks arrived and left, it's possible to create a much more accurate estimate for the actual fullness.

In the most exacting case where precise sample timestamping is available, then it is possible to make very small adjustments to the ratio and correct for the difference in a single small buffer (i.e., a “tight” servo). However, for this to work well it is desireable to get subsample position information from the resampler, and that’s what the resampleGetPosition() function is for. Let me know if you need more help with that (it’s not documented at all), although probably by the time a sample-accurate version is working without this, it will be obvious to you what you need.

I have found that ASRC applications can vary quite a lot with respect to their requirements and implementations, so it’s difficult to answer too specifically. But I hope this helps you get a feeling for how this library might be used. If something is not clear or you need more guidance, please feel free to ask.

dbry avatar Jul 21 '23 00:07 dbry

Thank you this helps really a lot!

timsurber avatar Jul 21 '23 19:07 timsurber

Great!

I have just added function-level documentation as promised.

dbry avatar Jul 22 '23 02:07 dbry