a015fe65f56c9f3c9636927a1ecb3e412ca0a51f
[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 RANDOM_BIRD
31 //#define SINE_ACCURATE
32
33 #ifdef SINE_ACCURATE
34 static float sine_44100_1( int o )
35 {
36 float t = (float)o*(1.0f/44100.0f);
37 return sinf(t*6.28318530717958647692528676655900576);
38 }
39
40 static void sine_44100_4( int o[4], float v[4] )
41 {
42 v[0] = sine_44100_1( o[0] );
43 v[1] = sine_44100_1( o[1] );
44 v[2] = sine_44100_1( o[2] );
45 v[3] = sine_44100_1( o[3] );
46 }
47 #else
48
49 /* sine functions over the range [0, 44100] : [-pi, pi].
50 * Not accurate! */
51
52 static float sine_44100_1( int o )
53 {
54 float s = (o<22050)?-1.0f:1.0f;
55 float t = ((float)o*(1.0f/22050.0f))-1.0f - s*0.5f;
56 float t2 = t*t;
57 float t4 = t2*t2;
58 return s*(5.0f*t2-4.0f*t4-1.0f);
59 }
60
61 static void sine_44100_4( int o[4], float v[4] )
62 {
63 float s[4],t[4],t2[4],t4[4];
64 s[0] = (o[0]<22050)?-1.0f:1.0f;
65 s[1] = (o[1]<22050)?-1.0f:1.0f;
66 s[2] = (o[2]<22050)?-1.0f:1.0f;
67 s[3] = (o[3]<22050)?-1.0f:1.0f;
68
69 t[0] = ((float)o[0]*(1.0f/22050.0f))-1.0f - s[0]*0.5f;
70 t[1] = ((float)o[1]*(1.0f/22050.0f))-1.0f - s[1]*0.5f;
71 t[2] = ((float)o[2]*(1.0f/22050.0f))-1.0f - s[2]*0.5f;
72 t[3] = ((float)o[3]*(1.0f/22050.0f))-1.0f - s[3]*0.5f;
73
74 t2[0] = t[0]*t[0];
75 t2[1] = t[1]*t[1];
76 t2[2] = t[2]*t[2];
77 t2[3] = t[3]*t[3];
78
79 t4[0] = t2[0]*t2[0];
80 t4[1] = t2[1]*t2[1];
81 t4[2] = t2[2]*t2[2];
82 t4[3] = t2[3]*t2[3];
83
84 v[0] = s[0]*(5.0f*t2[0]-4.0f*t4[0]-1.0f);
85 v[1] = s[1]*(5.0f*t2[1]-4.0f*t4[1]-1.0f);
86 v[2] = s[2]*(5.0f*t2[2]-4.0f*t4[2]-1.0f);
87 v[3] = s[3]*(5.0f*t2[3]-4.0f*t4[3]-1.0f);
88 }
89 #endif
90
91 static float saw_44100_1( int o )
92 {
93 float t = ((float)o*(1.0f/22050.0f))-1.0f,
94 tt = t*t,
95 ttt = tt*t;
96
97 return -2.5f*ttt+2.5f*t;
98 }
99
100 static double rand_float( double min, double max )
101 {
102 double r = (double)(rand()&(4096-1))*(1.0/4096.0);
103 return min + r*(max-min);
104 }
105
106 static int rand_seconds( double min, double max )
107 {
108 return rand_float( min*44100.0, max*44100.0 );
109 }
110
111 static void vg_dsp_init( void );
112 static void vg_dsp_process( float *stereo_in, float *stereo_out );
113
114 struct synth_bird
115 {
116 int harmonic_4[4],
117 fm_oscillator;
118
119 float poly;
120 int x,a,l,v, frame;
121
122 int pattern_length;
123 struct synth_bird_signature
124 {
125 float c0, c1, c2, c3, length, pause, h0, h1, h2, h3;
126
127 int lfo_hz;
128 float fm; /* lfo modulation depth (+/- hz) */
129 }
130 pattern[];
131 };
132
133 static int birdsynth_pattern_count_signatures( const char *pattern )
134 {
135 /* {200,5000,1000,200,20,10,30,200}, {...} */
136
137 int signatures = 0;
138
139 const char *c = pattern;
140 while( *c )
141 {
142 if( *c == '{' )
143 signatures ++;
144
145 c ++;
146 }
147
148 return signatures;
149 }
150
151 static void birdsynth_pattern_decode( struct synth_bird *bird,
152 const char *pattern )
153 {
154 bird->pattern_length = 0;
155
156 const char *c = pattern;
157 while( *c )
158 {
159 if( *c == '{' )
160 {
161 struct synth_bird_signature *sig =
162 &bird->pattern[ bird->pattern_length ++ ];
163
164 sig->c0 = 3000.0f;
165 sig->c1 = -800.0f;
166 sig->c2 = 1500.0f;
167 sig->c3 = -860.0f;
168 sig->length = 0.5f;
169 sig->pause = 0.1f;
170 sig->lfo_hz = 30;
171 sig->fm = 10.0f;
172 sig->h0 = 1.0f;
173 sig->h1 = 0.5f;
174 sig->h2 = 0.2f;
175 sig->h3 = 0.125f;
176
177 sscanf( c, "{%f,%f,%f,%f,%d,%f,%f,%f,%f,%f,%f,%f}",
178 &sig->c0, &sig->c1, &sig->c2, &sig->c3,
179 &sig->lfo_hz, &sig->fm, &sig->length, &sig->pause,
180 &sig->h0, &sig->h1, &sig->h2, &sig->h3 );
181 }
182
183 c ++;
184 }
185 }
186
187 static struct synth_bird *birdsynth_malloc_create( const char *pattern )
188 {
189 int s = birdsynth_pattern_count_signatures( pattern );
190 if( s == 0 )
191 s = 1;
192
193 struct synth_bird *bird = malloc( sizeof(struct synth_bird) +
194 s * sizeof(struct synth_bird_signature) );
195
196 birdsynth_pattern_decode( bird, pattern );
197
198 bird->harmonic_4[0] = 0;
199 bird->harmonic_4[1] = 0;
200 bird->harmonic_4[2] = 0;
201 bird->harmonic_4[3] = 0;
202 bird->fm_oscillator = 0;
203 bird->poly = 0.0f;
204 bird->x = 0;
205 bird->a = 1;
206 bird->l = bird->pattern[0].length * 44100.0f;
207 bird->v = 0;
208 bird->frame = 0;
209
210 return bird;
211 }
212
213 static void synthbird_generate_samples( struct synth_bird *bird,
214 float *stereo_buffer, int samples )
215 {
216 for( int _=0; _<samples; _++ )
217 {
218 bird->x ++;
219 if( bird->x >= bird->l )
220 {
221 if( bird->a && (bird->pattern[bird->frame].pause!=0.0f) )
222 {
223 bird->a = 0;
224 bird->l = bird->pattern[ bird->frame ].pause * 44100.0f;
225 }
226 else
227 {
228 bird->frame ++;
229
230 if( bird->frame >= bird->pattern_length )
231 bird->frame = 0;
232
233 bird->a = 1;
234 bird->l = bird->pattern[ bird->frame ].length * 44100.0f;
235 }
236
237 bird->x = 0;
238 }
239
240 if( bird->a )
241 {
242 bird->v += 40;
243 if( bird->v > 44100 ) bird->v = 44100;
244 }
245 else
246 {
247 bird->v -= 100;
248 if( bird->v < 0 ) bird->v = 0;
249 }
250
251 struct synth_bird_signature *sig = &bird->pattern[ bird->frame ];
252
253 float level = bird->v;
254 level *= (1.0f/44100.0f);
255
256 if( bird->a )
257 {
258 float t = ((float)bird->x * (1.0f/(float)bird->l))*2.0f - 1.0f,
259 tt = t*t,
260 ttt = tt*t;
261
262 bird->poly = sig->c0 + t*sig->c1 + tt*sig->c2 + ttt*sig->c3;
263 }
264
265 bird->fm_oscillator = WRAP1S( bird->fm_oscillator + sig->lfo_hz );
266 float fm = sine_44100_1( bird->fm_oscillator ) * sig->fm;
267
268 int freq = bird->poly + fm;
269 bird->harmonic_4[0] = WRAP1S( bird->harmonic_4[0] + (freq*1) );
270 bird->harmonic_4[1] = WRAP1S( bird->harmonic_4[1] + (freq*6)/5 );
271 bird->harmonic_4[2] = WRAP1S( bird->harmonic_4[2] + (freq*8)/7 );
272 bird->harmonic_4[3] = WRAP1S( bird->harmonic_4[3] + (freq*13)/12 );
273
274 float v[4];
275 sine_44100_4( bird->harmonic_4, v );
276 float s = v[0] * sig->h0 +
277 v[1] * sig->h1 +
278 v[2] * sig->h2 +
279 v[3] * sig->h3 ;
280
281 s *= level;
282
283 stereo_buffer[ _*2+0 ] = s;
284 stereo_buffer[ _*2+1 ] = s;
285 }
286 }
287
288 int main( int argc, char *argv[] )
289 {
290 vg_dsp_init();
291
292 #if RANDOM_BIRD
293 int f0=4500, o1=0, f1=30;
294 int adsr=0;
295
296 int o0[4]={0,0,0,0};
297
298 float c0=0.0f, c1=0.0f, c2=0.0f, c3=0.0f; /* signature coefficients */
299 int l=44100/2, /* length of thing */
300 x=0, /* frame of thing */
301 a=0; /* 0: silence 1: signature */
302
303 float poly=0.0f;
304
305 for(int _=0;_<44100*30;_++){
306 x ++;
307 if( x >= l ){ /* do new thing */
308 if( a ){
309 int retrigger = rand() % 4;
310 a=0;
311 if( retrigger ) l=rand_seconds(0.03,0.1);
312 else l=rand_seconds(0.5,10.0);
313 }
314 else{
315 c0=rand_float(-1.0,1.0);
316 c1=rand_float(-1.0,1.0);
317 c2=rand_float(-0.1,0.1);
318 c3=rand_float(-0.5,1.5);
319 l=rand_seconds(0.05,0.5);
320 a=1;
321 }
322 x=0;
323 }
324
325 if(a){
326 adsr += 40;
327 if( adsr > 44100 ) adsr = 44100;
328 }
329 else{
330 adsr -= 40;
331 if( adsr < 0 ) adsr = 0;
332 }
333
334 o1 += f1;
335 o1 = o1 % 44100;
336
337 float s1 = sine_44100_1( o1 );
338 float level = adsr;
339 level *= (1.0f/44100.0f);
340
341 if( a )
342 {
343 float t = ((float)x * (1.0f/(float)l))*2.0f - 1.0f,
344 tt = t*t,
345 ttt = tt*t;
346
347 poly = c0+t*c1+tt*c2+ttt*c3;
348 }
349
350 int fm = s1*100.0f*(1.0f+poly*0.5f) + poly*500.0f;
351
352 int ff = f0+fm;
353 o0[0] = WRAP1S( o0[0] + ff*1 );
354 o0[1] = WRAP1S( o0[1] + ff*2 );
355 o0[2] = WRAP1S( o0[2] + ff*3 );
356 o0[3] = WRAP1S( o0[3] + ff*4 );
357
358 float v[4];
359 sine_44100_4( o0, v );
360 float s0 = v[0] +
361 v[1] * 0.5f +
362 v[2] * 0.25f +
363 v[3] * 0.125f;
364 s0 *= level;
365
366 float stereo[2] = { s0, s0 };
367 vg_dsp_process( stereo, stereo );
368
369 int16_t l = stereo[0] * 10000.0f,
370 r = stereo[1] * 10000.0f;
371
372 fwrite( &l, 2,1, stdout );
373 fwrite( &r, 2,1, stdout );
374 }
375 #else
376
377 struct synth_bird *warbling_vireo = birdsynth_malloc_create(
378 "{4000,100,100,0,60,200,0.134,0.1}," /* 1 */
379 "{4200,-500,1700,0,60,96,0.1,0.05}," /* 2 */
380 "{2400,-1200,1000,1700,60,96,0.1,0.0}," /* 3 */
381 "{3100,200,-10,-1100,60,90,0.06,0.04}," /* 4 */
382 "{4600,-2000,0,1300,60,10,0.13,0.07}," /* 5 */
383 "{2700,-300,700,800,60,10,0.05,0.0}," /* 6 */
384 "{3600,-300,0,0,60,20,0.09,0.07}," /* 7 */
385 "{4800,1240,300,0,60,20,0.05,0.07}," /* 8 */
386 "{2700,-800,150,1000,60,160,0.08,0.02}," /* 9 */
387 "{2700,-800,150,1000,60,160,0.12,0.08}," /* 10 */
388 "{6300,-100,-3200,1000,60,100,0.1,0.04}," /* 11 */
389 "{4260,-200,300,1100,60,20,0.16,3.0}," /* 12 */
390 );
391
392 struct synth_bird *pied_monarch = birdsynth_malloc_create(
393 "{2200,700,-300,0,60,0,0.18,0.13, 0.6,0.05,0,0},"
394 "{2200,700,-300,0,60,0,0.17,0.12, 0.8,0.05,0,0},"
395 "{2200,700,-300,0,60,0,0.16,0.11, 0.9,0.05,0,0},"
396 "{2200,700,-300,0,60,0,0.14,0.09, 1,0.05,0,0},"
397 "{2200,700,-300,0,60,0,0.12,0.07, 1,0.05,0,0},"
398 "{2200,700,-300,0,60,0,0.11,0.06, 1,0.05,0,0},"
399 "{2200,700,-300,0,60,0,0.10,0.05, 1,0.05,0,0},"
400 "{2200,700,-300,0,60,0,0.10,0.05, 1,0.05,0,0},"
401 "{2200,700,-300,0,60,0,0.10,0.05, 1,0.05,0,0},"
402 "{2200,700,-300,0,60,0,0.10,0.05, 1,0.05,0,0},"
403 "{2200,700,-300,0,60,0,0.10,0.05, 1,0.05,0,0},"
404 "{2200,700,-300,0,60,0,0.10,6.05, 1,0.05,0,0},"
405 );
406
407 struct synth_bird *bridled_honeyeater = birdsynth_malloc_create(
408 "{2000,-1000,600,0,30,60,0.1,0.1, 1.0,0.0,0.0,0.0},"
409 "{4000,0,-200,-200,30,60,0.1,0.1, 0.8,0.25,0.25,0.25},"
410 "{4000,0,-700,-800,60,20,0.06,0.01, 0.9,0.1,0,0},"
411 "{3950,0,-700,-800,60,20,0.07,0.01, 0.9,0.1,0,0},"
412 "{3900,0,-700,-800,60,20,0.08,0.01, 0.9,0.1,0,0},"
413 "{3850,0,-700,-800,60,20,0.09,0.01, 0.9,0.1,0,0},"
414 "{3800,0,-700,-800,60,20,0.10,0.02, 0.9,0.2,0.1,0},"
415 "{3750,0,-700,-800,60,20,0.11,0.05, 0.9,0.4,0.2,0},"
416 "{3700,0,-700,-800,60,20,0.12,0.2, 0.3,0.1,0,0},"
417 "{2600,1300,600,0,60,20,0.1,4.0, 0.97,0.03,0,0},"
418 );
419
420 for(;;){
421 float stereo[2] = { 0.0f, 0.0f };
422
423 float b[2];
424 synthbird_generate_samples( pied_monarch, b, 1 );
425 stereo[0] += b[0] * 0.4f;
426 stereo[1] += b[1] * 0.3f;
427
428 synthbird_generate_samples( warbling_vireo, b, 1 );
429 stereo[0] += b[0] * 0.5f;
430 stereo[1] += b[1] * 0.4f;
431
432 synthbird_generate_samples( bridled_honeyeater, b, 1 );
433 stereo[0] += b[0] * 0.6f;
434 stereo[1] += b[1] * 0.6f;
435
436
437 vg_dsp_process( stereo, stereo );
438
439 int16_t l = stereo[0] * 10000.0f,
440 r = stereo[1] * 10000.0f;
441
442 fwrite( &l, 2,1, stdout );
443 fwrite( &r, 2,1, stdout );
444 }
445 #endif
446 }
447
448
449 static float dsp_buffer[(1024*1024)/4];
450 static int dsp_allocations = 0;
451
452 struct dsp_delay
453 {
454 int length, cur;
455 float *buffer;
456 };
457
458 struct dsp_lpf
459 {
460 float exponent;
461 float *buffer;
462 };
463
464 struct dsp_schroeder
465 {
466 struct dsp_delay M;
467 float gain;
468 };
469
470 static float *dsp_allocate( int l )
471 {
472 float *buf = &dsp_buffer[ dsp_allocations ];
473 dsp_allocations += l;
474 return buf;
475 }
476
477 static inline void dsp_read_delay( struct dsp_delay *delay, float *s )
478 {
479 int index = delay->cur+1;
480 if( index >= delay->length ) index = 0;
481 *s = delay->buffer[ index ];
482 }
483
484 static inline void dsp_write_delay( struct dsp_delay *delay, float *s )
485 {
486 int index = delay->cur;
487 delay->buffer[ index ] = *s;
488 delay->cur ++;
489 if( delay->cur >= delay->length ) delay->cur = 0;
490 }
491
492 static void dsp_init_delay( struct dsp_delay *delay, float length )
493 {
494 delay->length = 44100.0f * length;
495 delay->cur = 0;
496 delay->buffer = dsp_allocate( delay->length );
497
498 for( int i=0; i<delay->length; i++ )
499 delay->buffer[i] = 0.0f;
500 }
501
502 static void dsp_update_lpf( struct dsp_lpf *lpf, float freq )
503 {
504 lpf->exponent = 1.0f-expf( -(1.0f/44100.0f) *2.0f*3.1415926535897f*freq );
505 }
506
507 static void dsp_init_lpf( struct dsp_lpf *lpf, float freq )
508 {
509 lpf->buffer = dsp_allocate( 4 );
510 lpf->buffer[0] = 0.0f;
511 dsp_update_lpf( lpf, freq );
512 }
513
514 static inline void dsp_write_lpf( struct dsp_lpf *lpf, float *s )
515 {
516 float diff = *s - lpf->buffer[0];
517 lpf->buffer[0] += diff * lpf->exponent;
518 }
519
520 static inline void dsp_read_lpf( struct dsp_lpf *lpf, float *s )
521 {
522 *s = lpf->buffer[0];
523 }
524
525 static void dsp_init_schroeder( struct dsp_schroeder *sch, float length,
526 float gain )
527 {
528 dsp_init_delay( &sch->M, length );
529 sch->gain = gain;
530 }
531
532 static inline void dsp_process_schroeder( struct dsp_schroeder *sch,
533 float *input, float *output )
534 {
535 float dry = *input;
536
537 float delay_output;
538 dsp_read_delay( &sch->M, &delay_output );
539
540 float feedback_attenuated = delay_output * sch->gain,
541 input_feedback_sum = dry + feedback_attenuated;
542
543 dsp_write_delay( &sch->M, &input_feedback_sum );
544
545 *output = delay_output - input_feedback_sum*sch->gain;
546 }
547
548 /* temporary global design */
549 static struct dsp_lpf __lpf_mud_free,
550 __hpf_mud_free;
551
552 static struct dsp_delay __echos[8];
553 static struct dsp_lpf __echos_lpf[8];
554 static struct dsp_schroeder __diffusion_chain[8];
555
556 static inline float vg_lerpf( float a, float b, float t )
557 {
558 return a + t*(b-a);
559 }
560
561 static void vg_dsp_init( void )
562 {
563 /* temporary global design */
564
565
566 dsp_init_lpf( &__lpf_mud_free, 125.0f );
567 dsp_init_lpf( &__hpf_mud_free, 500.0f );
568
569 float sizes[] =
570 { 2.0f, 4.0f, 8.0f, 16.0f, 32.0f, 64.0f, 128.0f, 256.0f };
571
572 float reflection_variance = 0.04f;
573
574 for( int i=0; i<8; i++ )
575 {
576 float reflection_time = ((sizes[i])/343.0f) * 1000.0f;
577
578 float var = 1.0f + rand_float(-1.0,1.0) * reflection_variance,
579 total = reflection_time * var;
580
581 dsp_init_delay( &__echos[i], total / 1000.0f );
582
583 float freq = vg_lerpf( 800.0f, 350.0f, sizes[i] / 256.0f );
584 dsp_init_lpf( &__echos_lpf[i], freq );
585 }
586
587 float diffusions[] = { 187.0f, 159.0f, 143.0f, 121.0f,
588 79.0f, 57.0f, 27.0f, 11.0f };
589
590 for( int i=0; i<8; i++ )
591 {
592 dsp_init_schroeder( __diffusion_chain+i, diffusions[i]/1000.0f, 0.7f );
593 }
594 }
595
596 static void vg_dsp_process( float *stereo_in, float *stereo_out )
597 {
598 float in_total = (stereo_in[0]+stereo_in[1])*0.5f;
599 float recieved = 0.0f;
600
601 float echo_tunings[] = { 0.05f, 0.05f, 0.1f, 0.1f,
602 0.1f, 0.1f, 0.2f, 0.3f };
603
604 for( int i=0; i<8; i++ )
605 {
606 float echo;
607 dsp_read_delay( __echos+i, &echo );
608 dsp_write_lpf( __echos_lpf+i, &echo );
609 dsp_read_lpf( __echos_lpf+i, &echo );
610
611 recieved += echo * echo_tunings[i]*0.9;
612 }
613
614 float diffused = recieved;
615
616 for( int i=0; i<8; i++ )
617 {
618 dsp_process_schroeder( __diffusion_chain+i, &diffused, &diffused );
619 }
620
621 float total = in_total + (diffused*0.5f + recieved*0.5f);
622
623 dsp_write_lpf( &__hpf_mud_free, &total );
624 dsp_read_lpf( &__hpf_mud_free, &total );
625
626 float low_mud;
627 dsp_write_lpf( &__lpf_mud_free, &total );
628 dsp_read_lpf( &__lpf_mud_free, &low_mud );
629
630 total -= low_mud;
631
632 for( int i=0; i<8; i++ )
633 dsp_write_delay( __echos+i, &total );
634
635 stereo_out[0] = stereo_in[0]*0.1f;
636 stereo_out[1] = stereo_in[1]*0.1f;
637 stereo_out[0] += diffused*0.4f+recieved*0.9f;
638 stereo_out[1] += diffused*0.4f+recieved*0.9f;
639 }
640