annotate projects/airharp/render.cpp @ 269:ac8eb07afcf5

Oxygen text added to each render.cpp file for the default projects. Text includes project explanation from Wiki, edited in places. Empty project added as a default project. Doxyfile updated. Each of the project locations added to INPUT configuration option. Consider just watching the whole project file so all new projects are automatically pulled through.
author Robert Jack <robert.h.jack@gmail.com>
date Tue, 17 May 2016 15:40:16 +0100
parents 40badaff5729
children
rev   line source
chris@164 1 /*
chris@164 2 * AIR-HARP
chris@164 3 * Physically modelled strings using waveguide junctions and mass-spring-dampers
chris@164 4 *
chris@164 5 * render.cpp
chris@164 6 *
chris@164 7 * Christian Heinrichs 04/2015
chris@164 8 *
chris@164 9 */
chris@164 10
chris@164 11
chris@164 12 #include "MassSpringDamper.h"
chris@164 13 #include "String.h"
chris@164 14 #include "Plectrum.h"
chris@164 15
chris@164 16 #include <BeagleRT.h>
chris@164 17 #include <cmath>
chris@164 18 #include <stdio.h>
chris@164 19 #include <cstdlib>
chris@164 20 #include <rtdk.h>
chris@164 21 #include "../include/Utilities.h"
chris@164 22
chris@164 23 #define ACCEL_BUF_SIZE 8
chris@164 24 #define NUMBER_OF_STRINGS 9
chris@164 25
chris@164 26 // PENTATONIC SCALE
chris@164 27 float gMidinotes[NUMBER_OF_STRINGS] = {40,45,50,55,57,60,62,64,67};
chris@164 28
chris@164 29 float gInverseSampleRate;
chris@164 30
chris@164 31 float out_gain = 5.0;
chris@164 32
chris@164 33 int accelPin_x = 0;
chris@164 34 int accelPin_y = 1;
chris@164 35 int accelPin_z = 2;
chris@164 36
chris@164 37 MassSpringDamper msd = MassSpringDamper(1,0.1,10);// (10,0.001,10);
chris@164 38 String strings[NUMBER_OF_STRINGS];
chris@164 39 Plectrum plectrums[NUMBER_OF_STRINGS];
chris@164 40
chris@164 41 float gPlectrumDisplacement = 0;
chris@164 42
chris@164 43 float gAccel_x[ACCEL_BUF_SIZE] = {0};
chris@164 44 int gAccelReadPtr = 0;
chris@164 45
chris@164 46 // DC BLOCK BUTTERWORTH
chris@164 47
chris@164 48 // Coefficients for 100hz cut-off
chris@164 49 float a0_l = 0.9899759179893742;
chris@164 50 float a1_l = -1.9799518359787485;
chris@164 51 float a2_l = 0.9899759179893742;
chris@164 52 float a3_l = -1.979851353142371;
chris@164 53 float a4_l = 0.9800523188151258;
chris@164 54
chris@164 55 float a0_r = a0_l;
chris@164 56 float a1_r = a1_l;
chris@164 57 float a2_r = a2_l;
chris@164 58 float a3_r = a3_l;
chris@164 59 float a4_r = a4_l;
chris@164 60
chris@164 61 float x1_l = 0;
chris@164 62 float x2_l = 0;
chris@164 63 float y1_l = 0;
chris@164 64 float y2_l = 0;
chris@164 65
chris@164 66 float x1_r = 0;
chris@164 67 float x2_r = 0;
chris@164 68 float y1_r = 0;
chris@164 69 float y2_r = 0;
chris@164 70
chris@164 71
chris@164 72 bool setup(BeagleRTContext *context, void *userData)
chris@164 73 {
chris@164 74
chris@164 75 gInverseSampleRate = 1.0 / context->audioSampleRate;
chris@164 76
chris@164 77 // initialise strings & plectrums
chris@164 78 for(int i=0;i<NUMBER_OF_STRINGS;i++) {
chris@164 79
chris@164 80 plectrums[i] = Plectrum();
chris@164 81 plectrums[i].setup(250,0.25,0.05);
chris@164 82
chris@164 83 strings[i] = String();
chris@164 84 strings[i].setMidinote(gMidinotes[i]);
chris@164 85
chris@164 86 float spacing = 2.0 / (NUMBER_OF_STRINGS+1);
chris@164 87
chris@164 88 strings[i].setGlobalPosition( -1 + spacing*(i+1) );
chris@164 89
chris@164 90 rt_printf("STRING %d // midinote: %f position: %f\n",i,gMidinotes[i],( -1 + spacing*(i+1) ));
chris@164 91
chris@164 92 }
chris@164 93
chris@164 94 return true;
chris@164 95 }
chris@164 96
chris@164 97 void render(BeagleRTContext *context, void *userData)
chris@164 98 {
chris@164 99
chris@164 100 float lastAccel = 0;
chris@164 101
chris@164 102 for(int n = 0; n < context->audioFrames; n++) {
chris@164 103
chris@164 104 /*
chris@164 105 *
chris@164 106 * ACCELEROMETER DATA
chris@164 107 *
chris@164 108 */
chris@164 109
chris@164 110 // Read accelerometer data from analog input
chris@164 111 float accel_x = 0;
chris@164 112 if(n%2) {
chris@164 113 accel_x = (float)context->analogIn[(n/2)*8+accelPin_x] * 2 - 1; // 15800 - 28300 - 41500
chris@164 114 lastAccel = accel_x;
chris@164 115 } else {
chris@164 116 // grab previous value if !n%2
chris@164 117 accel_x = lastAccel;
chris@164 118 }
chris@164 119
chris@164 120 // Dead-zone avoids noise when box is lying horizontally on a surface
chris@164 121
chris@164 122 float accelDeadZone = 0.1;
chris@164 123
chris@164 124 if(accel_x <= accelDeadZone && accel_x >= -accelDeadZone)
chris@164 125 accel_x = 0;
chris@164 126
chris@164 127 // Perform smoothing (moving average) on acceleration value
chris@164 128 if(++gAccelReadPtr >= ACCEL_BUF_SIZE)
chris@164 129 gAccelReadPtr = 0;
chris@164 130 gAccel_x[gAccelReadPtr] = accel_x;
chris@164 131 float gravity = 0;
chris@164 132 for(int i=0;i<ACCEL_BUF_SIZE;i++) {
chris@164 133 gravity = gAccel_x[(gAccelReadPtr-i+ACCEL_BUF_SIZE)%ACCEL_BUF_SIZE];
chris@164 134 }
chris@164 135 gravity /= ACCEL_BUF_SIZE;
chris@164 136
chris@164 137 /*
chris@164 138 *
chris@164 139 * PHYSICS SIMULATION
chris@164 140 *
chris@164 141 */
chris@164 142
chris@164 143 // The horizontal force (which can be gravity if box is tipped on its side)
chris@164 144 // is used as the input to a Mass-Spring-Damper model
chris@164 145 // Plectrum displacement (i.e. when interacting with string) is included
chris@164 146 float massPosition = (float)msd.update(gravity - gPlectrumDisplacement);
chris@164 147
chris@164 148 float out_l = 0;
chris@164 149 float out_r = 0;
chris@164 150 // Use this parameter to quickly adjust output gain
chris@164 151 float gain = 0.0015; // 0.0015 is a good value or 12 strings
chris@164 152 gPlectrumDisplacement = 0;
chris@164 153
chris@164 154 for(int s=0;s<NUMBER_OF_STRINGS;s++) {
chris@164 155
chris@164 156 float stringPosition = strings[s].getGlobalPosition();
chris@164 157
chris@164 158 float plectrumForce = plectrums[s].update(massPosition, stringPosition);
chris@164 159 gPlectrumDisplacement += strings[s].getPlectrumDisplacement();
chris@164 160
chris@164 161 // calculate panning based on string position (-1->left / 1->right)
chris@164 162 float panRight = map(stringPosition,1,-1,0.1,1);
chris@164 163 float panLeft = map(stringPosition,-1,1,0.1,1);
chris@164 164 panRight *= panRight;
chris@164 165 panLeft *= panLeft;
chris@164 166
chris@164 167 float out = strings[s].update(plectrumForce)*gain;
chris@164 168
chris@164 169 out_l += out*panLeft;
chris@164 170 out_r += out*panRight;
chris@164 171
chris@164 172 }
chris@164 173
chris@164 174 // APPLY DC-BLOCK FILTER TO OUTPUTS
chris@164 175
chris@164 176 // LEFT CHANNEL
chris@164 177 float temp_in = out_l;
chris@164 178 /* compute result */
chris@164 179 out_l = a0_l * out_l + a1_l * x1_l + a2_l * x2_l - a3_l * y1_l - a4_l * y2_l;
chris@164 180 /* shift x1 to x2, sample to x1 */
chris@164 181 x2_l = x1_l;
chris@164 182 x1_l = temp_in;
chris@164 183 /* shift y1 to y2, result to y1 */
chris@164 184 y2_l = y1_l;
chris@164 185 y1_l = out_l;
chris@164 186
chris@164 187 // RIGHT CHANNEL
chris@164 188 temp_in = out_r;
chris@164 189 /* compute result */
chris@164 190 out_r = a0_r * out_r + a1_r * x1_r + a2_r * x2_r - a3_r * y1_r - a4_r * y2_r;
chris@164 191 /* shift x1 to x2, sample to x1 */
chris@164 192 x2_r = x1_r;
chris@164 193 x1_r = temp_in;
chris@164 194 /* shift y1 to y2, result to y1 */
chris@164 195 y2_r = y1_r;
chris@164 196 y1_r = out_r;
chris@164 197
chris@164 198 context->audioOut[n * context->audioChannels + 1] = out_l * out_gain;
chris@164 199 context->audioOut[n * context->audioChannels + 0] = out_r * out_gain;
chris@164 200
chris@164 201 }
chris@164 202
chris@164 203 }
chris@164 204
chris@164 205
chris@164 206 // cleanup_render() is called once at the end, after the audio has stopped.
chris@164 207 // Release any resources that were allocated in initialise_render().
chris@164 208
chris@164 209 void cleanup(BeagleRTContext *context, void *userData)
chris@164 210 {
chris@164 211
chris@164 212 }