Skip to content

Commit 4cc2774

Browse files
committed
Add variant of BBD for multi-channel
1 parent 17c3048 commit 4cc2774

4 files changed

Lines changed: 89 additions & 65 deletions

File tree

sources/bbd/bbd_line.cpp

Lines changed: 75 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,119 +4,143 @@
44

55
static constexpr unsigned interp_size = 128;
66

7-
void BBD_Line::setup(double fs, unsigned ns, const BBD_Filter_Spec &fsin, const BBD_Filter_Spec &fsout)
7+
template <unsigned Channels>
8+
void BBD_Line<Channels>::setup(double fs, unsigned ns, const BBD_Filter_Spec &fsin, const BBD_Filter_Spec &fsout)
89
{
9-
mem_.reserve(8192);
10+
mem_.reserve(8192 * Channels);
1011

1112
const BBD_Filter_Coef &fin = BBD::compute_filter_cached(fs, interp_size, fsin);
1213
const BBD_Filter_Coef &fout = BBD::compute_filter_cached(fs, interp_size, fsout);
1314
fin_ = &fin;
1415
fout_ = &fout;
1516

16-
unsigned Min = fin.M;
17-
unsigned Mout = fout.M;
18-
Xin_.reset(new cdouble[Min]);
19-
Xout_.reset(new cdouble[Mout]);
20-
Xout_mem_.reset(new cdouble[Mout]);
21-
Gin_.reset(new cdouble[Min]);
22-
Gout_.reset(new cdouble[Mout]);
17+
assert(fin.M <= Mmax);
18+
assert(fout.M <= Mmax);
2319

2420
set_delay_size(ns);
2521
clear();
2622
}
2723

28-
void BBD_Line::set_delay_size(unsigned ns)
24+
template <unsigned Channels>
25+
void BBD_Line<Channels>::set_delay_size(unsigned ns)
2926
{
3027
mem_.clear();
31-
mem_.resize(ns);
28+
mem_.resize(ns * Channels);
3229
imem_ = 0;
3330
ns_ = ns;
3431
}
3532

36-
void BBD_Line::clear()
33+
template <unsigned Channels>
34+
void BBD_Line<Channels>::clear()
3735
{
3836
std::fill(mem_.begin(), mem_.end(), 0);
3937
imem_ = 0;
4038
pclk_ = 0;
4139
ptick_ = 0;
42-
ybbd_old_ = 0;
43-
unsigned Min = fin_->M;
44-
unsigned Mout = fout_->M;
45-
std::fill(&Xin_[0], &Xin_[Min], 0);
46-
std::fill(&Xout_[0], &Xout_[Mout], 0);
47-
std::fill(&Xout_mem_[0], &Xout_mem_[Mout], 0);
40+
ybbd1_.fill(0);
41+
for (unsigned c = 0; c < Channels; ++c) {
42+
Xin_[c].fill(0);
43+
Xout1_[c].fill(0);
44+
}
4845
}
4946

50-
void BBD_Line::process(unsigned n, const float *input, float *output, const float *clock)
47+
template <unsigned Channels>
48+
void BBD_Line<Channels>::process(unsigned n, const float *const inputs[Channels], float *const outputs[Channels], const float *clock)
5149
{
5250
unsigned ns = ns_;
5351
float *mem = mem_.data();
5452
unsigned imem = imem_;
5553
double pclk = pclk_;
5654
unsigned ptick = ptick_;
57-
double ybbd_old = ybbd_old_;
55+
std::array<double, Channels> ybbd1 = ybbd1_;
5856

59-
const BBD_Filter_Coef &fin = *fin_, &fout = *fout_;
60-
unsigned Min = fin.M, Mout = fout.M;
61-
cdouble *Xin = Xin_.get(), *Xout = Xout_.get();
62-
cdouble *Xout_mem = Xout_mem_.get();
63-
cdouble *Gin = Gin_.get(), *Gout = Gout_.get();
64-
const cdouble *Pin = fin.P.get(), *Pout = fout.P.get();
57+
const BBD_Filter_Coef &fin = *fin_;
58+
const BBD_Filter_Coef &fout = *fout_;
59+
unsigned Min = fin.M;
60+
unsigned Mout = fout.M;
61+
const cdouble *const Pin = fin.P.get();
62+
const cdouble *const Pout = fout.P.get();
6563

6664
for (unsigned i = 0; i < n; ++i) {
67-
double fclk = clock[i];
68-
69-
for (unsigned m = 0; m < Mout; ++m)
70-
Xout[m] = 0;
65+
std::array<cdouble, Mmax> Xout_[Channels] = {};
7166

67+
double fclk = clock[i];
7268
if (fclk > 0) {
7369
double pclk_old = pclk;
7470
pclk += fclk;
71+
7572
unsigned tick_count = (unsigned)pclk;
7673
pclk -= tick_count;
74+
7775
for (unsigned tick = 0; tick < tick_count; ++tick) {
7876
double d = (1 - pclk_old + tick) * (1 / fclk);
7977
d -= (unsigned)d;
78+
8079
if ((ptick & 1) == 0) {
80+
cdouble Gin[Mmax];
8181
fin.interpolate_G(d, Gin);
82-
cdouble s = 0;
83-
for (unsigned m = 0; m < Min; ++m)
84-
s += Gin[m] * Xin[m];
85-
mem[imem] = s.real();
82+
83+
for (unsigned c = 0; c < Channels; ++c) {
84+
const std::array<cdouble, Mmax> &Xin = Xin_[c];
85+
cdouble s = 0;
86+
for (unsigned m = 0; m < Min; ++m)
87+
s += Gin[m] * Xin[m];
88+
mem[imem * Channels + c] = s.real();
89+
}
90+
8691
imem = ((imem + 1) < ns) ? (imem + 1) : 0;
8792
}
8893
else {
94+
cdouble Gout[Mmax];
8995
fout.interpolate_G(d, Gout);
90-
double ybbd = mem[imem];
91-
double delta = ybbd - ybbd_old;
92-
ybbd_old = ybbd;
93-
for (unsigned m = 0; m < Mout; ++m)
94-
Xout[m] += Gout[m] * delta;
96+
97+
for (unsigned c = 0; c < Channels; ++c) {
98+
std::array<cdouble, Mmax> &Xout = Xout_[c];
99+
double ybbd = mem[imem * Channels + c];
100+
double delta = ybbd - ybbd1[c];
101+
ybbd1[c] = ybbd;
102+
for (unsigned m = 0; m < Mout; ++m)
103+
Xout[m] += Gout[m] * delta;
104+
}
95105
}
106+
96107
++ptick;
97108
}
98109
}
99110

100-
for (unsigned m = 0; m < Min; ++m)
101-
Xin[m] = Pin[m] * Xin[m] + cdouble(input[i]);
111+
for (unsigned c = 0; c < Channels; ++c) {
112+
const float *input = inputs[c];
113+
float *output = outputs[c];
102114

103-
cdouble y = fout.H * ybbd_old;
104-
for (unsigned m = 0; m < Mout; ++m) {
105-
cdouble xout = Pout[m] * Xout_mem[m] + Xout[m];
106-
Xout_mem[m] = xout;
107-
y += xout;
108-
}
115+
std::array<cdouble, Mmax> &Xin = Xin_[c];
116+
std::array<cdouble, Mmax> &Xout1 = Xout1_[c];
117+
const std::array<cdouble, Mmax> &Xout = Xout_[c];
109118

110-
output[i] = y.real();
119+
for (unsigned m = 0; m < Min; ++m)
120+
Xin[m] = Pin[m] * Xin[m] + cdouble(input[i]);
121+
122+
cdouble y = fout.H * ybbd1[c];
123+
for (unsigned m = 0; m < Mout; ++m) {
124+
cdouble xout = Pout[m] * Xout1[m] + Xout[m];
125+
Xout1[m] = xout;
126+
y += xout;
127+
}
128+
129+
output[i] = y.real();
130+
}
111131
}
112132

113133
imem_ = imem;
114134
pclk_ = pclk;
115135
ptick_ = ptick;
116-
ybbd_old_ = ybbd_old;
136+
ybbd1_ = ybbd1;
117137
}
118138

119-
void BBD_Line::process(unsigned n, float *inout, const float *clock)
139+
template <unsigned Channels>
140+
void BBD_Line<Channels>::process(unsigned n, float *const inouts[Channels], const float *clock)
120141
{
121-
process(n, inout, inout, clock);
142+
process(n, inouts, inouts, clock);
122143
}
144+
145+
template class BBD_Line<1>;
146+
template class BBD_Line<2>;

sources/bbd/bbd_line.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@
22
#include "bbd_filter.h"
33
#include <algorithm>
44
#include <vector>
5-
#include <memory>
5+
#include <array>
66
#include <complex>
77
typedef std::complex<double> cdouble;
88

9+
template <unsigned Channels = 1>
910
class BBD_Line {
1011
public:
1112
void setup(double fs, unsigned ns, const BBD_Filter_Spec &fsin, const BBD_Filter_Spec &fsout);
1213
void set_delay_size(unsigned ns);
1314
void clear();
14-
void process(unsigned n, const float *input, float *output, const float *clock);
15-
void process(unsigned n, float *inout, const float *clock);
15+
void process(unsigned n, const float *const inputs[Channels], float *const outputs[Channels], const float *clock);
16+
void process(unsigned n, float *const inouts[Channels], const float *clock);
1617

1718
const BBD_Filter_Coef &filter_in() const noexcept { return *fin_; }
1819
const BBD_Filter_Coef &filter_out() const noexcept { return *fout_; }
@@ -28,12 +29,11 @@ class BBD_Line {
2829
unsigned imem_; // delay memory index
2930
double pclk_; // clock phase
3031
unsigned ptick_; // clock tick counter
31-
double ybbd_old_;
3232
const BBD_Filter_Coef *fin_;
3333
const BBD_Filter_Coef *fout_;
34-
std::unique_ptr<cdouble[]> Xin_;
35-
std::unique_ptr<cdouble[]> Xout_;
36-
std::unique_ptr<cdouble[]> Xout_mem_; // sample memory of output filter
37-
std::unique_ptr<cdouble[]> Gin_;
38-
std::unique_ptr<cdouble[]> Gout_;
34+
std::array<double, Channels> ybbd1_;
35+
36+
enum { Mmax = 8 }; // the maximum filter order
37+
std::array<cdouble, Mmax> Xin_[Channels];
38+
std::array<cdouble, Mmax> Xout1_[Channels]; // sample memory of output filter
3939
};

sources/dsp/Delay3Phase.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,20 @@ void Delay3Phase::AnalogDelay::process(const float *input, const float *const mo
6666
///
6767
float avgDelay = 5e-3f;
6868
float varDelay = 1e-3f;
69-
float delayClockLo = BBD_Line::hz_rate_for_delay(avgDelay - varDelay, NumAnalogBBDStages) * sampleTime;
70-
float delayClockHi = BBD_Line::hz_rate_for_delay(avgDelay + varDelay, NumAnalogBBDStages) * sampleTime;
69+
float delayClockLo = BBD_Line<1>::hz_rate_for_delay(avgDelay - varDelay, NumAnalogBBDStages) * sampleTime;
70+
float delayClockHi = BBD_Line<1>::hz_rate_for_delay(avgDelay + varDelay, NumAnalogBBDStages) * sampleTime;
7171

7272
///
7373
for (unsigned l = 0; l < 3; ++l) {
74-
BBD_Line &line = fDelayLine[l];
74+
BBD_Line<1> &line = fDelayLine[l];
7575
float *lineOutput = lineOutputs[l];
7676
const float *mod = mods[l];
7777

7878
float clock[BufferLimit];
7979
for (unsigned i = 0; i < count; ++i)
8080
clock[i] = delayClockLo + (delayClockHi - delayClockLo) * 0.5f * (1.0f + mod[i]);
8181

82-
line.process(count, input, lineOutput, clock);
82+
line.process(count, &input, &lineOutput, clock);
8383
}
8484

8585
float *outputL = outputs[0];

sources/dsp/Delay3Phase.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Delay3Phase {
2323

2424
private:
2525
float fSampleTime = 0;
26-
BBD_Line fDelayLine[3];
26+
BBD_Line<1> fDelayLine[3];
2727
};
2828

2929
private:

0 commit comments

Comments
 (0)