Mercurial > hg > beaglert
comparison projects/d-box/FeedbackOscillator.cpp @ 0:8a575ba3ab52
Initial commit.
author | andrewm |
---|---|
date | Fri, 31 Oct 2014 19:10:17 +0100 |
parents | |
children | be427da6fb9c |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:8a575ba3ab52 |
---|---|
1 /* | |
2 * FeedbackOscillator.cpp | |
3 * | |
4 * Recursive phase-shift oscillator implemented | |
5 * on the matrix | |
6 * | |
7 * Andrew McPherson 2014 | |
8 */ | |
9 | |
10 #include "FeedbackOscillator.h" | |
11 #include <cstdlib> | |
12 #include <cmath> | |
13 | |
14 #define COEFF_B0 0 | |
15 #define COEFF_B1 1 | |
16 #define COEFF_A1 2 | |
17 | |
18 FeedbackOscillator::FeedbackOscillator() | |
19 : wavetable1(0), wavetable2(0) | |
20 { | |
21 | |
22 } | |
23 | |
24 FeedbackOscillator::~FeedbackOscillator() { | |
25 if(wavetable1 != 0) | |
26 free(wavetable1); | |
27 if(wavetable2 != 0) | |
28 free(wavetable2); | |
29 | |
30 } | |
31 | |
32 // Initialise the settings for the feedback oscillator | |
33 void FeedbackOscillator::initialise(int maxTableSize, float hpfCutoffFrequency, float matrixSampleRate) { | |
34 wavetableMaxLength = maxTableSize; | |
35 if(wavetable1 != 0) | |
36 free(wavetable1); | |
37 if(wavetable2 != 0) | |
38 free(wavetable2); | |
39 | |
40 wavetable1 = (float *)malloc(maxTableSize * sizeof(float)); | |
41 wavetable2 = (float *)malloc(maxTableSize * sizeof(float)); | |
42 | |
43 float omega = tan(M_PI * hpfCutoffFrequency / matrixSampleRate); | |
44 float n = 1.0f / (1.0f + omega); | |
45 | |
46 coeffs[COEFF_A1] = (omega - 1.0f) * n; | |
47 coeffs[COEFF_B0] = n; | |
48 coeffs[COEFF_B1] = -n; | |
49 | |
50 for(int n = 0; n < maxTableSize; n++) | |
51 wavetable1[n] = wavetable2[n] = 0; | |
52 | |
53 wavetableRead = wavetable1; | |
54 wavetableWrite = wavetable2; | |
55 wavetableWritePointer = 0; | |
56 sampleCount = lastTriggerCount = 0; | |
57 } | |
58 | |
59 // Process one sample and store the output value | |
60 // Returns true if the wavetable needs rendering | |
61 int FeedbackOscillator::process(uint16_t input, uint16_t *output) { | |
62 float inFloat = input / 65536.0; | |
63 float outFloat = coeffs[COEFF_B0] * inFloat + coeffs[COEFF_B1] * lastInput - coeffs[COEFF_A1] * lastOutput; | |
64 int requestRenderLength = 0; | |
65 | |
66 //outFloat *= 2.0; | |
67 | |
68 int intOut = outFloat * 65536.0 + 32768; | |
69 if(intOut > 65535) | |
70 intOut = 65535; | |
71 if(intOut < 0) | |
72 intOut = 0; | |
73 //intOut = (intOut & 0xFF) << 8; | |
74 //if(intOut > 65535) | |
75 // intOut = 65535; | |
76 | |
77 *output = (uint16_t)intOut; | |
78 | |
79 if(canTrigger && outFloat > 0 && lastOutput <= 0) { | |
80 triggered = true; | |
81 requestRenderLength = wavetableWritePointer; // How many samples stored thus far? | |
82 if(requestRenderLength < 4) | |
83 requestRenderLength = 0; // Ignore anything with fewer than 4 points | |
84 | |
85 lastTriggerCount = sampleCount; | |
86 canTrigger = false; | |
87 wavetableWritePointer = 0; | |
88 | |
89 // Swap buffers | |
90 float *temp = wavetableWrite; | |
91 wavetableWrite = wavetableRead; | |
92 wavetableRead = temp; | |
93 } | |
94 | |
95 if(triggered) { | |
96 wavetableWrite[wavetableWritePointer] = outFloat; | |
97 if(++wavetableWritePointer >= wavetableMaxLength) { | |
98 triggered = false; | |
99 wavetableWritePointer = 0; | |
100 } | |
101 } | |
102 | |
103 if(sampleCount - lastTriggerCount > 40) | |
104 canTrigger = true; | |
105 | |
106 sampleCount++; | |
107 | |
108 lastOutput = outFloat; | |
109 lastInput = inFloat; | |
110 | |
111 return requestRenderLength; | |
112 } |