annotate examples/airharp/Waveguide.cpp @ 402:c29f07b7350e prerelease

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