-
Notifications
You must be signed in to change notification settings - Fork 30
/
OversamplePatch.hpp
87 lines (82 loc) · 2.6 KB
/
OversamplePatch.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/*
This patch does not do anything, only upsamples and downsamples the input signal. Used for computational cost measurements.
*/
#ifndef __OversamplePatch_hpp__
#define __OversamplePatch_hpp__
// #include "Oversample.hpp"
#include "StompBox.h"
#include "BiquadFilter.h"
/**
Implements 4x oversampling
*/
class Oversampler {
private:
BiquadFilter upfilter;
BiquadFilter downfilter;
float* oversampled;
public:
Oversampler(int blocksize) : upfilter(2), downfilter(2) {
/* [b,a] = ellip(2, 2, 70, 19200/(48000*4/2)) */
// static float coeffs[] = { 5.14483600142e-02, 1.01958385114e-01, 5.14483600142e-02, -1.35468949025e+00, 6.12586787851e-01 };
/* Convert series second-order sections to direct form
* output_precision(6)
* [b,a] = ellip(4, 2, 70, 19200/(48000*4/2))
* [sos,g] = tf2sos(b,a)
* b0 b1 b2 a0 a1 a2
* 1.0000000 1.4157500 1.0000000 1.0000000 -1.5499654 0.8890431 first biquad
* 1.0000000 0.0467135 1.0000000 1.0000000 -1.6359692 0.7189533 second biquad
*/
static float coeffs[] = {
/* [b,a] = ellip(4, 3, 40, 19200/(48000*4/2)); [sos,g] = tf2sos(b,a) */
1.00000000000e+00, -5.19191279323e-02, 1.00000000000e+00, -1.58391500480e+00, 9.32046186768e-01,
1.00000000000e+00, -1.29724486402e+00, 1.00000000000e+00, -1.65074162038e+00, 7.48880762740e-01
};
upfilter.setCoefficents(coeffs);
// two filters: same coefficients, different state variables
downfilter.setCoefficents(coeffs);
oversampled = (float*)malloc(blocksize*4*sizeof(float));
}
~Oversampler(){
free(oversampled);
}
float* upsample(float* buf, int sz){
float* p = oversampled;
for(int i=0; i<sz; ++i){
*p++ = buf[i];
*p++ = 0;
*p++ = 0;
*p++ = 0;
}
upfilter.process(oversampled, sz<<2);
return oversampled;
}
float* downsample(float* buf, int sz){
downfilter.process(oversampled, sz<<2);
float* p = oversampled;
for(int i=0; i<sz; ++i){
buf[i] = *p;
p += 4;
}
return buf;
}
};
class OversamplePatch : public Patch {
private:
Oversampler os;
public:
OversamplePatch() : os(getBlockSize()) {
}
void processAudio(AudioBuffer &buffer){
int size = buffer.getSize();
float* buf = buffer.getSamples(0);
float* upsampled = os.upsample(buf, size);
for(int i = 0; i < size*4; i++) {
upsampled[i] = oversampledFunction(upsampled[i]);
}
os.downsample(buf, size);
}
float oversampledFunction(float x){
return x * ( 27 + x*x ) / ( 27 + 9*x*x );
}
};
#endif // __OversamplePatch_hpp__