bird
[vg.git] / projects / birds.c
1 #include "stdint.h"
2 #include "stdio.h"
3 #include "stdlib.h"
4 #include "math.h"
5
6 /* Birds sounds
7 * TODO: THis can be embedded using 'song strings' in the path field of a sound
8 * entity for skaterift/vg. and the generation algorthm be placed in the
9 * decode section. will need to find a place to store its memory, though.
10 *
11 * */
12
13 #define WRAP1S( X ) (X)%44100
14
15
16 /*
17 * clang birds.c -lm -o birds && ./birds | aplay -f cd /dev/stdin
18 *
19 * Performance measurements: (generate 30seconds audio)
20 *
21 * DSP SINE_ACCURATE -O3 x Realtime
22 *
23 * on yes 0.182s 164x
24 * on no 0.134s 223x
25 * off yes 0.113s 265x
26 * off no 0.074s 405x
27 *
28 */
29
30 //#define SINE_ACCURATE
31
32 #ifdef SINE_ACCURATE
33 static float sine_44100_1( int o )
34 {
35 float t = (float)o*(1.0f/44100.0f);
36 return sinf(t*6.28318530717958647692528676655900576);
37 }
38
39 static void sine_44100_4( int o[4], float v[4] )
40 {
41 v[0] = sine_44100_1( o[0] );
42 v[1] = sine_44100_1( o[1] );
43 v[2] = sine_44100_1( o[2] );
44 v[3] = sine_44100_1( o[3] );
45 }
46 #else
47
48 /* sine functions over the range [0, 44100] : [-pi, pi].
49 * Not accurate! */
50
51 static float sine_44100_1( int o )
52 {
53 float s = (o<22050)?-1.0f:1.0f;
54 float t = ((float)o*(1.0f/22050.0f))-1.0f - s*0.5f;
55 float t2 = t*t;
56 float t4 = t2*t2;
57 return s*(5.0f*t2-4.0f*t4-1.0f);
58 }
59
60 static void sine_44100_4( int o[4], float v[4] )
61 {
62 float s[4],t[4],t2[4],t4[4];
63 s[0] = (o[0]<22050)?-1.0f:1.0f;
64 s[1] = (o[1]<22050)?-1.0f:1.0f;
65 s[2] = (o[2]<22050)?-1.0f:1.0f;
66 s[3] = (o[3]<22050)?-1.0f:1.0f;
67
68 t[0] = ((float)o[0]*(1.0f/22050.0f))-1.0f - s[0]*0.5f;
69 t[1] = ((float)o[1]*(1.0f/22050.0f))-1.0f - s[1]*0.5f;
70 t[2] = ((float)o[2]*(1.0f/22050.0f))-1.0f - s[2]*0.5f;
71 t[3] = ((float)o[3]*(1.0f/22050.0f))-1.0f - s[3]*0.5f;
72
73 t2[0] = t[0]*t[0];
74 t2[1] = t[1]*t[1];
75 t2[2] = t[2]*t[2];
76 t2[3] = t[3]*t[3];
77
78 t4[0] = t2[0]*t2[0];
79 t4[1] = t2[1]*t2[1];
80 t4[2] = t2[2]*t2[2];
81 t4[3] = t2[3]*t2[3];
82
83 v[0] = s[0]*(5.0f*t2[0]-4.0f*t4[0]-1.0f);
84 v[1] = s[1]*(5.0f*t2[1]-4.0f*t4[1]-1.0f);
85 v[2] = s[2]*(5.0f*t2[2]-4.0f*t4[2]-1.0f);
86 v[3] = s[3]*(5.0f*t2[3]-4.0f*t4[3]-1.0f);
87 }
88 #endif
89
90 static float saw_44100_1( int o )
91 {
92 float t = ((float)o*(1.0f/22050.0f))-1.0f,
93 tt = t*t,
94 ttt = tt*t;
95
96 return -2.5f*ttt+2.5f*t;
97 }
98
99 static double rand_float( double min, double max )
100 {
101 double r = (double)(rand()&(4096-1))*(1.0/4096.0);
102 return min + r*(max-min);
103 }
104
105 static int rand_seconds( double min, double max )
106 {
107 return rand_float( min*44100.0, max*44100.0 );
108 }
109
110 static void vg_dsp_init( void );
111 static void vg_dsp_process( float *stereo_in, float *stereo_out );
112
113 struct synth_bird
114 {
115 int harmonic_4[4];
116
117 int frame,length;
118 struct synth_bird_signature
119 {
120 float c0, c1, c2, c3, length, pause;
121
122 int lfo_hz,
123 fm; /* lfo modulation depth (+/- hz) */
124 }
125 pattern[];
126 };
127
128 static int birdsynth_pattern_count_signatures( const char *pattern )
129 {
130 /* {200,5000,1000,200,20,10,30,200}, {...} */
131
132 int signatures = 0;
133
134 const char *c = pattern;
135 while( *c )
136 {
137 if( *c == '{' )
138 signatures ++;
139
140 c ++;
141 }
142
143 return signatures;
144 }
145
146 static void birdsynth_pattern_decode( struct synth_bird *bird,
147 const char *pattern )
148 {
149 bird->length = 0;
150
151 const char *c = pattern;
152 while( *c )
153 {
154 if( *c == '{' )
155 {
156 struct synth_bird_signature *sig = &bird->pattern[ bird->length ++ ];
157 sig->c0 = 3000.0f;
158 sig->c1 = -800.0f;
159 sig->c2 = 1500.0f;
160 sig->c3 = -860.0f;
161 sig->length = 0.5f;
162 sig->pause = 0.1f;
163 sig->lfo_hz = 30;
164 sig->fm = 100;
165
166 sscanf( c, "{%f,%f,%f,%f,%f,%f,%d,%d}",
167 &sig->c0, &sig->c1, &sig->c2, &sig->c3,
168 &sig->length, &sig->pause, &sig->lfo_hz, &sig->fm );
169 }
170
171 c ++;
172 }
173 }
174
175 static struct synth_bird *birdsynth_malloc_create( const char *pattern )
176 {
177 int s = birdsynth_pattern_count_signatures( pattern );
178 if( s == 0 )
179 s = 1;
180
181 struct synth_bird *bird = malloc( sizeof(struct synth_bird) +
182 s * sizeof(struct synth_bird_signature) );
183
184 birdsynth_pattern_decode( bird, pattern );
185 return bird;
186 }
187
188 int main( int argc, char *argv[] )
189 {
190 vg_dsp_init();
191
192 struct synth_bird *bird = birdsynth_malloc_create( "" );
193
194 int f0=2500, o1=0, f1=30;
195 int adsr=0;
196
197 int o0[4]={0,0,0,0};
198
199 float c0=0.0f, c1=0.0f, c2=0.0f, c3=0.0f; /* signature coefficients */
200 int l=44100/2, /* length of thing */
201 x=0, /* frame of thing */
202 a=0; /* 0: silence 1: signature */
203
204 float poly=0.0f;
205
206 for(int _=0;_<44100*30;_++){
207 x ++;
208 if( x >= l ){ /* do new thing */
209 if( a ){
210 int retrigger = rand() % 4;
211 a=0;
212 if( retrigger ) l=rand_seconds(0.03,0.1);
213 else l=rand_seconds(0.5,10.0);
214 }
215 else{
216 c0=rand_float(-1.0,1.0);
217 c1=rand_float(-1.0,1.0);
218 c2=rand_float(-0.1,0.1);
219 c3=rand_float(-0.5,1.5);
220 l=rand_seconds(0.05,0.5);
221 a=1;
222 }
223 x=0;
224 }
225
226 if(a){
227 adsr += 40;
228 if( adsr > 44100 ) adsr = 44100;
229 }
230 else{
231 adsr -= 40;
232 if( adsr < 0 ) adsr = 0;
233 }
234
235 o1 += f1;
236 o1 = o1 % 44100;
237
238 float s1 = sine_44100_1( o1 );
239 float level = adsr;
240 level *= (1.0f/44100.0f);
241
242 if( a )
243 {
244 float t = ((float)x * (1.0f/(float)l))*2.0f - 1.0f,
245 tt = t*t,
246 ttt = tt*t;
247
248 poly = c0+t*c1+tt*c2+ttt*c3;
249 }
250
251 int fm = s1*100.0f*(1.0f+poly*0.5f) + poly*500.0f;
252
253 int ff = f0+fm;
254 o0[0] = WRAP1S( o0[0] + ff*1 );
255 o0[1] = WRAP1S( o0[1] + ff*2 );
256 o0[2] = WRAP1S( o0[2] + ff*3 );
257 o0[3] = WRAP1S( o0[3] + ff*4 );
258
259 float v[4];
260 sine_44100_4( o0, v );
261 float s0 = v[0] +
262 v[1] * 0.5f +
263 v[2] * 0.25f +
264 v[3] * 0.125f;
265 s0 *= level;
266
267 float stereo[2] = { s0, s0 };
268 //vg_dsp_process( stereo, stereo );
269
270 int16_t l = stereo[0] * 10000.0f,
271 r = stereo[1] * 10000.0f;
272
273 fwrite( &l, 2,1, stdout );
274 fwrite( &r, 2,1, stdout );
275 }
276 }
277
278
279 static float dsp_buffer[(1024*1024)/4];
280 static int dsp_allocations = 0;
281
282 struct dsp_delay
283 {
284 int length, cur;
285 float *buffer;
286 };
287
288 struct dsp_lpf
289 {
290 float exponent;
291 float *buffer;
292 };
293
294 struct dsp_schroeder
295 {
296 struct dsp_delay M;
297 float gain;
298 };
299
300 static float *dsp_allocate( int l )
301 {
302 float *buf = &dsp_buffer[ dsp_allocations ];
303 dsp_allocations += l;
304 return buf;
305 }
306
307 static inline void dsp_read_delay( struct dsp_delay *delay, float *s )
308 {
309 int index = delay->cur+1;
310 if( index >= delay->length ) index = 0;
311 *s = delay->buffer[ index ];
312 }
313
314 static inline void dsp_write_delay( struct dsp_delay *delay, float *s )
315 {
316 int index = delay->cur;
317 delay->buffer[ index ] = *s;
318 delay->cur ++;
319 if( delay->cur >= delay->length ) delay->cur = 0;
320 }
321
322 static void dsp_init_delay( struct dsp_delay *delay, float length )
323 {
324 delay->length = 44100.0f * length;
325 delay->cur = 0;
326 delay->buffer = dsp_allocate( delay->length );
327
328 for( int i=0; i<delay->length; i++ )
329 delay->buffer[i] = 0.0f;
330 }
331
332 static void dsp_update_lpf( struct dsp_lpf *lpf, float freq )
333 {
334 lpf->exponent = 1.0f-expf( -(1.0f/44100.0f) *2.0f*3.1415926535897f*freq );
335 }
336
337 static void dsp_init_lpf( struct dsp_lpf *lpf, float freq )
338 {
339 lpf->buffer = dsp_allocate( 4 );
340 lpf->buffer[0] = 0.0f;
341 dsp_update_lpf( lpf, freq );
342 }
343
344 static inline void dsp_write_lpf( struct dsp_lpf *lpf, float *s )
345 {
346 float diff = *s - lpf->buffer[0];
347 lpf->buffer[0] += diff * lpf->exponent;
348 }
349
350 static inline void dsp_read_lpf( struct dsp_lpf *lpf, float *s )
351 {
352 *s = lpf->buffer[0];
353 }
354
355 static void dsp_init_schroeder( struct dsp_schroeder *sch, float length,
356 float gain )
357 {
358 dsp_init_delay( &sch->M, length );
359 sch->gain = gain;
360 }
361
362 static inline void dsp_process_schroeder( struct dsp_schroeder *sch,
363 float *input, float *output )
364 {
365 float dry = *input;
366
367 float delay_output;
368 dsp_read_delay( &sch->M, &delay_output );
369
370 float feedback_attenuated = delay_output * sch->gain,
371 input_feedback_sum = dry + feedback_attenuated;
372
373 dsp_write_delay( &sch->M, &input_feedback_sum );
374
375 *output = delay_output - input_feedback_sum*sch->gain;
376 }
377
378 /* temporary global design */
379 static struct dsp_lpf __lpf_mud_free;
380 static struct dsp_delay __echos[8];
381 static struct dsp_lpf __echos_lpf[8];
382 static struct dsp_schroeder __diffusion_chain[8];
383
384 static inline float vg_lerpf( float a, float b, float t )
385 {
386 return a + t*(b-a);
387 }
388
389 static void vg_dsp_init( void )
390 {
391 /* temporary global design */
392
393
394 dsp_init_lpf( &__lpf_mud_free, 125.0f );
395
396 float sizes[] =
397 { 2.0f, 4.0f, 8.0f, 16.0f, 32.0f, 64.0f, 128.0f, 256.0f };
398
399 float reflection_variance = 0.1f;
400
401 for( int i=0; i<8; i++ )
402 {
403 float reflection_time = ((sizes[i])/343.0f) * 1000.0f;
404
405 float var = 1.0f + rand_float(-1.0,1.0) * reflection_variance,
406 total = reflection_time * var;
407
408 dsp_init_delay( &__echos[i], total / 1000.0f );
409
410 float freq = vg_lerpf( 800.0f, 350.0f, sizes[i] / 256.0f );
411 dsp_init_lpf( &__echos_lpf[i], freq );
412 }
413
414 float diffusions[] = { 187.0f, 159.0f, 143.0f, 121.0f,
415 79.0f, 57.0f, 27.0f, 11.0f };
416
417 for( int i=0; i<8; i++ )
418 {
419 dsp_init_schroeder( __diffusion_chain+i, diffusions[i]/1000.0f, 0.8f );
420 }
421 }
422
423 static void vg_dsp_process( float *stereo_in, float *stereo_out )
424 {
425 float in_total = (stereo_in[0]+stereo_in[1])*0.5f;
426 float recieved = 0.0f;
427
428 float echo_tunings[] = { 0.05f, 0.05f, 0.1f, 0.1f,
429 0.1f, 0.1f, 0.2f, 0.3f };
430
431 for( int i=0; i<8; i++ )
432 {
433 float echo;
434 dsp_read_delay( __echos+i, &echo );
435 dsp_write_lpf( __echos_lpf+i, &echo );
436 dsp_read_lpf( __echos_lpf+i, &echo );
437
438 recieved += echo * echo_tunings[i]*0.997;
439 }
440
441 float diffused = recieved;
442
443 for( int i=0; i<8; i++ )
444 {
445 dsp_process_schroeder( __diffusion_chain+i, &diffused, &diffused );
446 }
447
448 float total = in_total + (diffused*0.1f + recieved*0.9f);
449
450 float low_mud;
451 dsp_write_lpf( &__lpf_mud_free, &total );
452 dsp_read_lpf( &__lpf_mud_free, &low_mud );
453
454 total -= low_mud;
455
456 for( int i=0; i<8; i++ )
457 dsp_write_delay( __echos+i, &total );
458
459 stereo_out[0] = stereo_in[0]*0.25f;
460 stereo_out[1] = stereo_in[1]*0.25f;
461 stereo_out[0] += diffused*0.5f+recieved*0.9f;
462 stereo_out[1] += diffused*0.5f+recieved*0.9f;
463 }
464