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