vDSP_biquadm

63 views
Skip to first unread message

Jean-Baptiste Rolland

unread,
Jul 29, 2016, 10:11:59 AM7/29/16
to perfoptimi...@lists.apple.com
Dear All,

In the context of a C++ project with iOS 9.3 (tested on iPad Pro), we would need a little bit more informations about the Accelerate framework concerning multi-channel biquadratic IIR filtering.

We would like to update the coefficients of a filter during the filtering process.
Thus, we use the function vDSP_biquadm_setCoefficientsDouble and this implementation for one section:


#include <stdio.h>
#include <Accelerate/Accelerate.h>
#include <iomanip>

int main()
{
double coefficient[5];
coefficient[0] = 0.638945525159022;
coefficient[1] = 1.277891050318045;
coefficient[2] = 0.638945525159022;
coefficient[3] = 1.142980502539901;
coefficient[4] = 0.412801598096189;

vDSP_biquadm_Setup mySetup = vDSP_biquadm_CreateSetup(coefficient, 1,1);

float signal1[16] = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ,13 ,14, 15, 16];
float signal1Out[16];
float signal2[16] = [ 15, 37, 59, 81, 103, 125, 147, 169, 191, 213, 235, 257, 279, 301, 323, 345];
float signal2Out[16];

vDSP_biquadm(mySetup, &signal1, 1, &signal1Out, 1, 16);

// Coefficients change
coefficient[0] = 1.;
coefficient[1] = 2.;
coefficient[2] = 1.;
coefficient[3] = 0.897657940036644;
coefficient[4] = 0.527186904631596;

vDSP_biquadm_SetCoefficientsDouble(mySetup, coefficient, 0, 0, 1, 1);     //<——————— Use of setCoefficientDouble

vDSP_biquadm(mySetup, &signal2, 1, &signal2Out, 1, 16);

return 0
}

We obtained good results for the filtering of the signal1, but the results obtained for the second signal after updating the coefficients are:
signal2Out[0]=40.057090759277344;
signal2Out[1]=38.728538513183594;
signal2Out[2]=92.117446899414062;
signal2Out[3]=132.89286804199219;
signal2Out[4]=156.14456176757812;
signal2Out[5]=201.77621459960938;
signal2Out[6]=236.55659484863281;
signal2Out[7]=269.27932739257812;
signal2Out[8]=309.56973266601562;
signal2Out[9]=344.1517333984375;
signal2Out[10]=379.86834716796875;
signal2Out[11]=417.57586669921875;
signal2Out[12]=452.89813232421875;
signal2Out[13]=489.3118896484375;
signal2Out[14]=526.00335693359375;
signal2Out[15]=561.87005615234375;

But we would expect to obtain those ones :
signal2Out[0]=20.908199852169549;
signal2Out[1]=51.944713092210286;
signal2Out[2]=90.348886631351817;
signal2Out[3]=127.513031537668510;
signal2Out[4]=161.906163765033682;
signal2Out[5]=199.440444388422065;
signal2Out[6]=235.615889909845521;
signal2Out[7]=271.355132157128480;
signal2Out[8]=308.202295838932002;
signal2Out[9]=344.284885723306786;
signal2Out[10]=380.469719640719177;
signal2Out[11]=416.965846704155410;
signal2Out[12]=453.128637288337472;
signal2Out[13]=489.426540328725821;
signal2Out[14]=525.778889236458781;
signal2Out[15]=562.011134858551259;


However if we use the function setTargetsDouble such as :

#include <stdio.h>
#include <Accelerate/Accelerate.h>
#include <iomanip>

int main()
{
double coefficient[5];
coefficient[0] = 0.638945525159022;
coefficient[1] = 1.277891050318045;
coefficient[2] = 0.638945525159022;
coefficient[3] = 1.142980502539901;
coefficient[4] = 0.412801598096189;

vDSP_biquadm_Setup mySetup = vDSP_biquadm_CreateSetup(coefficient, 1,1);

float signal1[16] = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ,13 ,14, 15, 16];
float signal1Out[16];
float signal2[16] = [ 15, 37, 59, 81, 103, 125, 147, 169, 191, 213, 235, 257, 279, 301, 323, 345];
float signal2Out[16];

vDSP_biquadm(mySetup, &signal1, 1, &signal1Out, 1, 16);

// Coefficients change
coefficient[0] = 1.;
coefficient[1] = 2.;
coefficient[2] = 1.;
coefficient[3] = 0.897657940036644;
coefficient[4] = 0.527186904631596;

vDSP_biquadm_setTargetsDouble(mySetup, coefficient, 0.5, 2, 0, 0, 1, 1); //<——————— Use of setTargetDouble

vDSP_biquadm(mySetup, &signal2, 1, &signal2Out, 1, 16);

return 0
}

Then we obtain the good results.


Could you please explain us why in our case the vDSP_biquadm_setCoefficientsDouble does not return the right results, and why the choice of the rate and the threshold in the function vDSP_biquadm_setTargetsDouble allow us to compute the good ones ?


Many thanks in advance for your help!

Best Regards,

Jean-Baptiste Guillaume Rolland - Research Software Developer -
------------------------------------------------------------------
Steinberg Media Technologies GmbH
Frankenstrasse 18 b
20097 Hamburg
Phone: +49 40 21035 - 186
E-mail: jb.ro...@steinberg.de
www germany : www.steinberg.de
www international: www.steinberg.net



- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Steinberg Media Technologies GmbH, Frankenstrasse 18b, D-20097 Hamburg, Germany

Phone: +49 (40) 21035-0 | Fax: +49 (40) 21035-300 | www.steinberg.net

President: Andreas Stelling | Managing Director: Thomas Schöpe, Hirofumi Osawa

Registration Court: Hamburg HRB 86534

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Eric Postpischil

unread,
Jul 29, 2016, 2:28:16 PM7/29/16
to Jean-Baptiste Rolland, perfoptimi...@lists.apple.com
On Jul 29, 2016, at 10:11, Jean-Baptiste Rolland <JB.Ro...@steinberg.de> wrote:

Could you please explain us why in our case the vDSP_biquadm_setCoefficientsDouble does not return the right results, and why the choice of the rate and the threshold in the function vDSP_biquadm_setTargetsDouble allow us to compute the good ones ?

vDSP_biquadm_SetCoefficientsDouble says to immediately change the coefficients in use. At and around the point where you called it:

The most recent two inputs (at the end of signal1) were 15 and 16.
The most recent two outputs (at the end of signal1Out) were 14.77 and 15.7703.
The next input (at the start of signal2) is 15.

Then, computing with the new coefficients (1, 2, 1, .89766, and .527187), the next output is:

1 * 15 + 2 * 16 + 1 * 15 - .89766 * 15.7703 - .527187 * 14.77 = 40.0571.

This is as you observed.

In contrast, vDSP_biquadm_SetTargetsDouble says to “gradually” change the coefficients toward target values. In the intended use, what would happen here is that the next value would be computed with the old coefficients and would yield the same values as above, and then the coefficients would be changed slightly, and then the next value would be computed with the changed coefficients, and this would continue as the coefficients approached their target values.

However, you called vDSP_biquadm_SetTargetsDouble with 2 for the threshold value. This value says “when the changing coefficients are within this threshold of the target value, call it close enough and jump them the rest of the way.” A problem here is that the old and new coefficients already differ by less than 2 (e.g., 1-.6389 = .3611). vDSP_biquadm was not implemented with this in mind (and it could probably be considered a bug); it expects changing the coefficients to take several iterations at least. What resulted was a code path where vDSP_biquadm immediately used the new coefficients but used them with partially calculated sums already in progress. Thus, it used an unintended mix of old and new coefficients.

I am not sure why the resulting values look like something you expected. They are not intended to have those values by design of vDSP_biquadm.

—edp (Eric Postpischil)
Reply all
Reply to author
Forward
0 new messages