Reputation: 638
I am totally new to the vdsp framework and I am trying to learn by building. My goal is for the signal to be processed in the following way:
From what I could understand from Apple's documentation the function vDSP_desamp() is what I am looking for (it can do both steps at the same time, right?)
How would I use this correctly?
Here are my thoughts:
Given an AudioBufferList *audio
and an array of filter coefficients filterCoeffs
with length [101]:
vDSP_desamp((float*)audio->mBuffers[0].mData, 2, &filterCoeffs, (float*)audio->mBuffers[0].mData, frames, 101);
would this be a correct use of the method? Do I need to implement a circular buffer for this process? Any guidance /direction /pointer to something to read would be very welcome. thanks
Upvotes: 3
Views: 1304
Reputation: 9159
Reading the documentation, vDSP_desamp()
is indeed a compound decimation and FIR operation. Doing both together is a good idea as it reduces memory access and there is scope for eliminating a lot of computation.
The assumption here is FIR filter has been recast with (P-1)/2
group delay. The consequence of this is that to calculate C(n)
the function needs access to A(n*I+p)
Where (using the terminology of the documentation):
`A[0..x-1]`: input sample array
`C[0..n-1]`: output sample array
`P`: number of filter coefficients
`I`: Decimation factor
Clearly if you pass a CoreAudio buffer to this, it'll run off the end of the buffer by 200 input samples. At best, yielding 100 garbage samples, and at worst a SIGSEGV
.
So, the simple answer is NO. You cannot use vDSP_desamp()
alone.
Your options are:
Assemble the samples needed into a buffer and then call vDSP_desamp()
for N
output samples. This involves copying samples from two CoreAudio buffers. If you're worried about latency, you recast the FIR to use 100 previous samples, alternatively, they could come from the next buffer.
Use vDSP_desamp()
for what you can, and calculate the more complex case when the filter wraps over the two buffers.
Two calls to vDSP_desamp()
- one with the easy case, and another with an assembled input buffer where samples wrap adjacent CoreAudio buffers
I don't see how you can use circular buffer to solve this problem: You still have the case where the buffer wraps to deal with, and still need to copy all samples into it.
Which is faster rather depends on the size of the audio buffers presented by CoreAudio. My hunch is that for small buffers, and a small filter length, vDSP_desamp()
possibly isn't worth it, but you're going to need to measure to be sure.
When I've implemented this kind of thing in the past on iOS, I've found a hand-rolled decimation and filter operation to be fairly insignificant in the grand scheme of things, and didn't bother optimizing further.
Upvotes: 1