Use Transposed Direct Form II for the BS2B filters

This commit is contained in:
Chris Robinson 2019-07-29 19:40:03 -07:00
parent 4c9e18c5a0
commit 06e5454eb9
2 changed files with 37 additions and 43 deletions

View File

@ -23,9 +23,9 @@
#include "config.h"
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iterator>
#include "bs2b.h"
#include "math_defs.h"
@ -35,7 +35,7 @@
static void init(struct bs2b *bs2b)
{
float Fc_lo, Fc_hi;
float G_lo, G_hi;
float G_lo, G_hi;
float x, g;
switch(bs2b->level)
@ -127,60 +127,55 @@ int bs2b_get_srate(struct bs2b *bs2b)
void bs2b_clear(struct bs2b *bs2b)
{
std::fill(std::begin(bs2b->last_sample), std::end(bs2b->last_sample), bs2b::t_last_sample{});
std::fill(std::begin(bs2b->history), std::end(bs2b->history), bs2b::t_last_sample{});
} /* bs2b_clear */
void bs2b_cross_feed(struct bs2b *bs2b, float *RESTRICT Left, float *RESTRICT Right, int SamplesToDo)
void bs2b_cross_feed(struct bs2b *bs2b, float *Left, float *Right, int SamplesToDo)
{
const float a0_lo{bs2b->a0_lo};
const float b1_lo{bs2b->b1_lo};
const float a0_hi{bs2b->a0_hi};
const float a1_hi{bs2b->a1_hi};
const float b1_hi{bs2b->b1_hi};
float lsamples[128][2];
float rsamples[128][2];
int base;
for(base = 0;base < SamplesToDo;)
for(int base{0};base < SamplesToDo;)
{
int todo = std::min(128, SamplesToDo-base);
int i;
const int todo{std::min(128, SamplesToDo-base)};
/* Process left input */
lsamples[0][0] = bs2b->a0_lo*Left[0] +
bs2b->b1_lo*bs2b->last_sample[0].lo;
lsamples[0][1] = bs2b->a0_hi*Left[0] +
bs2b->a1_hi*bs2b->last_sample[0].asis +
bs2b->b1_hi*bs2b->last_sample[0].hi;
for(i = 1;i < todo;i++)
float z_lo{bs2b->history[0].lo};
float z_hi{bs2b->history[0].hi};
for(int i{0};i < todo;i++)
{
lsamples[i][0] = bs2b->a0_lo*Left[i] +
bs2b->b1_lo*lsamples[i-1][0];
lsamples[i][1] = bs2b->a0_hi*Left[i] +
bs2b->a1_hi*Left[i-1] +
bs2b->b1_hi*lsamples[i-1][1];
lsamples[i][0] = a0_lo*Left[i] + z_lo;
z_lo = b1_lo*lsamples[i][0];
lsamples[i][1] = a0_hi*Left[i] + z_hi;
z_hi = a1_hi*Left[i] + b1_hi*lsamples[i][1];
}
bs2b->last_sample[0].asis = Left[i-1];
bs2b->last_sample[0].lo = lsamples[i-1][0];
bs2b->last_sample[0].hi = lsamples[i-1][1];
bs2b->history[0].lo = z_lo;
bs2b->history[0].hi = z_hi;
/* Process right input */
rsamples[0][0] = bs2b->a0_lo*Right[0] +
bs2b->b1_lo*bs2b->last_sample[1].lo;
rsamples[0][1] = bs2b->a0_hi*Right[0] +
bs2b->a1_hi*bs2b->last_sample[1].asis +
bs2b->b1_hi*bs2b->last_sample[1].hi;
for(i = 1;i < todo;i++)
z_lo = bs2b->history[1].lo;
z_hi = bs2b->history[1].hi;
for(int i{0};i < todo;i++)
{
rsamples[i][0] = bs2b->a0_lo*Right[i] +
bs2b->b1_lo*rsamples[i-1][0];
rsamples[i][1] = bs2b->a0_hi*Right[i] +
bs2b->a1_hi*Right[i-1] +
bs2b->b1_hi*rsamples[i-1][1];
rsamples[i][0] = a0_lo*Right[i] + z_lo;
z_lo = b1_lo*rsamples[i][0];
rsamples[i][1] = a0_hi*Right[i] + z_hi;
z_hi = a1_hi*Right[i] + b1_hi*rsamples[i][1];
}
bs2b->last_sample[1].asis = Right[i-1];
bs2b->last_sample[1].lo = rsamples[i-1][0];
bs2b->last_sample[1].hi = rsamples[i-1][1];
bs2b->history[1].lo = z_lo;
bs2b->history[1].hi = z_hi;
/* Crossfeed */
for(i = 0;i < todo;i++)
for(int i{0};i < todo;i++)
*(Left++) = lsamples[i][1] + rsamples[i][0];
for(i = 0;i < todo;i++)
for(int i{0};i < todo;i++)
*(Right++) = rsamples[i][1] + lsamples[i][0];
base += todo;

View File

@ -57,14 +57,13 @@ struct bs2b {
float a1_hi;
float b1_hi;
/* Buffer of last filtered sample.
/* Buffer of filter history
* [0] - first channel, [1] - second channel
*/
struct t_last_sample {
float asis;
float lo;
float hi;
} last_sample[2];
} history[2];
DEF_NEWDEL(bs2b)
};
@ -85,6 +84,6 @@ int bs2b_get_srate(bs2b *bs2b);
/* Clear buffer */
void bs2b_clear(bs2b *bs2b);
void bs2b_cross_feed(bs2b *bs2b, float *RESTRICT Left, float *RESTRICT Right, int SamplesToDo);
void bs2b_cross_feed(bs2b *bs2b, float *Left, float *Right, int SamplesToDo);
#endif /* BS2B_H */