annotate projects/d-box/FeedbackOscillator.cpp @ 0:8a575ba3ab52

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