Mercurial > hg > beaglert
comparison examples/10-Instruments/airharp/Waveguide.cpp @ 468:85cf9c0da052 prerelease
merge
author | Giulio Moro <giuliomoro@yahoo.it> |
---|---|
date | Mon, 20 Jun 2016 17:08:02 +0100 |
parents | 8fcfbfb32aa0 |
children |
comparison
equal
deleted
inserted
replaced
467:03a2cd5f151b | 468:85cf9c0da052 |
---|---|
1 /* | |
2 * | |
3 * Simple 1-Dimensional Waveguide | |
4 * | |
5 */ | |
6 | |
7 #include "Waveguide.h" | |
8 #include "../include/Utilities.h" | |
9 #include <rtdk.h> | |
10 #include <cmath> | |
11 #include <stdio.h> | |
12 #include <cstdlib> | |
13 | |
14 #define DECAY 0.995//0.999 | |
15 #define DAMPING 0.01//0.05 | |
16 | |
17 // TODO: make damping and decay parametrisable | |
18 | |
19 Waveguide::Waveguide() { | |
20 | |
21 // initialize variables | |
22 a1_lp = 0; | |
23 a2_lp = 0; | |
24 b0_lp = 0; | |
25 b1_lp = 0; | |
26 b2_lp = 0; | |
27 _dt = 1.0/44100.0; | |
28 setFrequency(440); | |
29 updateFilterCoeffs(8000); | |
30 _filterReadPtr=0; | |
31 for(int i=0;i<FILTER_BUFFER_SIZE;i++) { | |
32 _filterBuffer_x[i] = 0; | |
33 _filterBuffer_y[i] = 0; | |
34 } | |
35 for(int i=0;i<WG_BUFFER_SIZE;i++) { | |
36 _buffer[i] = 0; | |
37 } | |
38 _lastX = 0; | |
39 _lastY = 0; | |
40 _readPtr = 0; | |
41 | |
42 } | |
43 | |
44 void Waveguide::setup() { | |
45 | |
46 } | |
47 | |
48 float Waveguide::update(float in) { | |
49 | |
50 // 1. advance delay buffer read pointer | |
51 | |
52 if(++_readPtr>=WG_BUFFER_SIZE) | |
53 _readPtr=0; | |
54 | |
55 // 2. write input into buffer | |
56 | |
57 _buffer[_readPtr] = in; | |
58 | |
59 // 3. read delayed sample from buffer | |
60 | |
61 float out = _buffer[(_readPtr-_periodInSamples+WG_BUFFER_SIZE)%WG_BUFFER_SIZE]; | |
62 | |
63 // 4. apply damping (low-pass) filter to output | |
64 | |
65 if(++_filterReadPtr>=FILTER_BUFFER_SIZE) | |
66 _filterReadPtr=0; | |
67 | |
68 out = b0_lp*out + | |
69 b1_lp*_filterBuffer_x[(_filterReadPtr-1+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE] + | |
70 b2_lp*_filterBuffer_x[(_filterReadPtr-2+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE] - | |
71 a1_lp*_filterBuffer_y[(_filterReadPtr-1+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE] - | |
72 a2_lp*_filterBuffer_y[(_filterReadPtr-2+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE]; | |
73 | |
74 // 5. Simple high-pass filter to block DC-offset | |
75 // y[n] = x[n] - x[n-1] + a * y[n-1] | |
76 float gain = 0.9999; | |
77 float temp = out; | |
78 out = out - _lastX + gain * _lastY; | |
79 _lastY = out; | |
80 _lastX = temp; | |
81 | |
82 // 6. Apply intensity damping | |
83 out *= DECAY; | |
84 | |
85 _filterBuffer_x[_filterReadPtr] = in; | |
86 _filterBuffer_y[_filterReadPtr] = out; | |
87 | |
88 return out; | |
89 | |
90 } | |
91 | |
92 void Waveguide::setFrequency(float frequency) { | |
93 | |
94 // NB: currently no interpolation, so may not be ideal for dynamically changing waveguide frequency | |
95 _periodInMilliseconds = 1000.0/frequency; | |
96 _periodInSamples = (int)(_periodInMilliseconds * 44.1); | |
97 | |
98 } | |
99 | |
100 void Waveguide::updateFilterCoeffs(float frequency) { | |
101 | |
102 // FIXME: Butterworth filter doesn't work very well, | |
103 // using simple FIR in the meantime | |
104 | |
105 a1_lp = 0; | |
106 a2_lp = 0; | |
107 b0_lp = 1.0 - DAMPING; | |
108 b1_lp = DAMPING; | |
109 b2_lp = 0; | |
110 | |
111 /* | |
112 // 'w' for sake of resembling lower-case 'omega' | |
113 float w = 2.0 * M_PI * frequency; | |
114 float t = _dt; | |
115 // The Q for a 2nd-order Butterworth is sqrt(2)/2 | |
116 float q = 0.707;//sqrt(2.0)/2.0; | |
117 | |
118 // low-pass filter coefficients | |
119 float a0_lp = w*w*t*t + 2*(w/q)*t + 4.0; | |
120 float k = 1.0/a0_lp; | |
121 a1_lp = (2.0*w*w*t*t - 8.0) * k; | |
122 a2_lp = (4.0 - (w/q)*2.0*t + w*w*t*t) * k; | |
123 b0_lp = (w*w*t*t) * k; | |
124 b1_lp = (2.0*w*w*t*t) * k; | |
125 b2_lp = (w*w*t*t) * k; | |
126 */ | |
127 | |
128 } |