birds read
[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 float poly;
119 int x,a,l,v, frame;
120
121 int pattern_length;
122 struct synth_bird_signature
123 {
124 float c0, c1, c2, c3, length, pause;
125
126 int lfo_hz;
127 float fm; /* lfo modulation depth (+/- hz) */
128 }
129 pattern[];
130 };
131
132 static int birdsynth_pattern_count_signatures( const char *pattern )
133 {
134 /* {200,5000,1000,200,20,10,30,200}, {...} */
135
136 int signatures = 0;
137
138 const char *c = pattern;
139 while( *c )
140 {
141 if( *c == '{' )
142 signatures ++;
143
144 c ++;
145 }
146
147 return signatures;
148 }
149
150 static void birdsynth_pattern_decode( struct synth_bird *bird,
151 const char *pattern )
152 {
153 bird->pattern_length = 0;
154
155 const char *c = pattern;
156 while( *c )
157 {
158 if( *c == '{' )
159 {
160 struct synth_bird_signature *sig =
161 &bird->pattern[ bird->pattern_length ++ ];
162
163 sig->c0 = 3000.0f;
164 sig->c1 = -800.0f;
165 sig->c2 = 1500.0f;
166 sig->c3 = -860.0f;
167 sig->length = 0.5f;
168 sig->pause = 0.1f;
169 sig->lfo_hz = 30;
170 sig->fm = 10.0f;
171
172 #if 0
173 sscanf( c, "{%f,%f,%f,%f,%f,%f,%d,%f}",
174 &sig->c0, &sig->c1, &sig->c2, &sig->c3,
175 &sig->length, &sig->pause, &sig->lfo_hz, &sig->fm );
176 #endif
177 }
178
179 c ++;
180 }
181 }
182
183 static struct synth_bird *birdsynth_malloc_create( const char *pattern )
184 {
185 int s = birdsynth_pattern_count_signatures( pattern );
186 if( s == 0 )
187 s = 1;
188
189 struct synth_bird *bird = malloc( sizeof(struct synth_bird) +
190 s * sizeof(struct synth_bird_signature) );
191
192 birdsynth_pattern_decode( bird, pattern );
193
194 bird->harmonic_4[0] = 0;
195 bird->harmonic_4[1] = 0;
196 bird->harmonic_4[2] = 0;
197 bird->harmonic_4[3] = 0;
198 bird->fm_oscillator = 0;
199 bird->poly = 0.0f;
200 bird->x = 0;
201 bird->a = 1;
202 bird->l = bird->pattern[0].length * 44100.0f;
203 bird->v = 0;
204 bird->frame = 0;
205
206 return bird;
207 }
208
209 static void synthbird_generate_samples( struct synth_bird *bird,
210 float *stereo_buffer, int samples )
211 {
212 for( int _=0; _<samples; _++ )
213 {
214 bird->x ++;
215 if( bird->x >= bird->l )
216 {
217 if( bird->a )
218 {
219 bird->a = 0;
220 bird->l = bird->pattern[ bird->frame ].pause * 44100.0f;
221 }
222 else
223 {
224 bird->frame ++;
225
226 if( bird->frame >= bird->pattern_length )
227 bird->frame = 0;
228
229 bird->a = 1;
230 bird->l = bird->pattern[ bird->frame ].length * 44100.0f;
231 }
232
233 bird->x = 0;
234 }
235
236 if( bird->a )
237 {
238 bird->v += 40;
239 if( bird->v > 44100 ) bird->v = 44100;
240 }
241 else
242 {
243 bird->v -= 40;
244 if( bird->v < 0 ) bird->v = 0;
245 }
246
247 struct synth_bird_signature *sig = &bird->pattern[ bird->frame ];
248
249 sig->c0 = 3000.0f;
250 sig->c1 = -800.0f;
251 sig->c2 = 1500.0f;
252 sig->c3 = -860.0f;
253 sig->length = 0.5f;
254 sig->pause = 0.1f;
255 sig->lfo_hz = 30;
256 sig->fm = 10.0f;
257 float level = bird->v;
258 level *= (1.0f/44100.0f);
259
260 if( bird->a )
261 {
262 float t = ((float)bird->x * (1.0f/(float)bird->l))*2.0f - 1.0f,
263 tt = t*t,
264 ttt = tt*t;
265
266 bird->poly = sig->c0 + t*sig->c1 + tt*sig->c2 + ttt*sig->c3;
267 }
268
269 bird->fm_oscillator = WRAP1S( bird->fm_oscillator + sig->lfo_hz );
270 float fm = sine_44100_1( bird->fm_oscillator ) * sig->fm;
271
272 int freq = bird->poly + fm;
273 bird->harmonic_4[0] = WRAP1S( bird->harmonic_4[0] + freq*1 );
274 bird->harmonic_4[1] = WRAP1S( bird->harmonic_4[1] + freq*2 );
275 bird->harmonic_4[2] = WRAP1S( bird->harmonic_4[2] + freq*3 );
276 bird->harmonic_4[3] = WRAP1S( bird->harmonic_4[3] + freq*4 );
277
278 float v[4];
279 sine_44100_4( bird->harmonic_4, v );
280 float s = v[0] +
281 v[1] * 0.5f +
282 v[2] * 0.25f +
283 v[3] * 0.125f;
284
285 s *= level;
286
287 stereo_buffer[ _*2+0 ] = s;
288 stereo_buffer[ _*2+1 ] = s;
289 }
290 }
291
292 int main( int argc, char *argv[] )
293 {
294 vg_dsp_init();
295
296 #if RANDOM_BIRD
297 int f0=4500, o1=0, f1=30;
298 int adsr=0;
299
300 int o0[4]={0,0,0,0};
301
302 float c0=0.0f, c1=0.0f, c2=0.0f, c3=0.0f; /* signature coefficients */
303 int l=44100/2, /* length of thing */
304 x=0, /* frame of thing */
305 a=0; /* 0: silence 1: signature */
306
307 float poly=0.0f;
308
309 for(int _=0;_<44100*30;_++){
310 x ++;
311 if( x >= l ){ /* do new thing */
312 if( a ){
313 int retrigger = rand() % 4;
314 a=0;
315 if( retrigger ) l=rand_seconds(0.03,0.1);
316 else l=rand_seconds(0.5,10.0);
317 }
318 else{
319 c0=rand_float(-1.0,1.0);
320 c1=rand_float(-1.0,1.0);
321 c2=rand_float(-0.1,0.1);
322 c3=rand_float(-0.5,1.5);
323 l=rand_seconds(0.05,0.5);
324 a=1;
325 }
326 x=0;
327 }
328
329 if(a){
330 adsr += 40;
331 if( adsr > 44100 ) adsr = 44100;
332 }
333 else{
334 adsr -= 40;
335 if( adsr < 0 ) adsr = 0;
336 }
337
338 o1 += f1;
339 o1 = o1 % 44100;
340
341 float s1 = sine_44100_1( o1 );
342 float level = adsr;
343 level *= (1.0f/44100.0f);
344
345 if( a )
346 {
347 float t = ((float)x * (1.0f/(float)l))*2.0f - 1.0f,
348 tt = t*t,
349 ttt = tt*t;
350
351 poly = c0+t*c1+tt*c2+ttt*c3;
352 }
353
354 int fm = s1*100.0f*(1.0f+poly*0.5f) + poly*500.0f;
355
356 int ff = f0+fm;
357 o0[0] = WRAP1S( o0[0] + ff*1 );
358 o0[1] = WRAP1S( o0[1] + ff*2 );
359 o0[2] = WRAP1S( o0[2] + ff*3 );
360 o0[3] = WRAP1S( o0[3] + ff*4 );
361
362 float v[4];
363 sine_44100_4( o0, v );
364 float s0 = v[0] +
365 v[1] * 0.5f +
366 v[2] * 0.25f +
367 v[3] * 0.125f;
368 s0 *= level;
369
370 float stereo[2] = { s0, s0 };
371 vg_dsp_process( stereo, stereo );
372
373 int16_t l = stereo[0] * 10000.0f,
374 r = stereo[1] * 10000.0f;
375
376 fwrite( &l, 2,1, stdout );
377 fwrite( &r, 2,1, stdout );
378 }
379 #else
380
381 struct synth_bird *bird = birdsynth_malloc_create( "" );
382
383 for(int _=0;_<44100*60;_++){
384 float stereo[2] = { 0.0f, 0.0f };
385
386 synthbird_generate_samples( bird, stereo, 1 );
387 #if 0
388 vg_dsp_process( stereo, stereo );
389 #endif
390
391 int16_t l = stereo[0] * 10000.0f,
392 r = stereo[1] * 10000.0f;
393
394 fwrite( &l, 2,1, stdout );
395 fwrite( &r, 2,1, stdout );
396 }
397 #endif
398 }
399
400
401 static float dsp_buffer[(1024*1024)/4];
402 static int dsp_allocations = 0;
403
404 struct dsp_delay
405 {
406 int length, cur;
407 float *buffer;
408 };
409
410 struct dsp_lpf
411 {
412 float exponent;
413 float *buffer;
414 };
415
416 struct dsp_schroeder
417 {
418 struct dsp_delay M;
419 float gain;
420 };
421
422 static float *dsp_allocate( int l )
423 {
424 float *buf = &dsp_buffer[ dsp_allocations ];
425 dsp_allocations += l;
426 return buf;
427 }
428
429 static inline void dsp_read_delay( struct dsp_delay *delay, float *s )
430 {
431 int index = delay->cur+1;
432 if( index >= delay->length ) index = 0;
433 *s = delay->buffer[ index ];
434 }
435
436 static inline void dsp_write_delay( struct dsp_delay *delay, float *s )
437 {
438 int index = delay->cur;
439 delay->buffer[ index ] = *s;
440 delay->cur ++;
441 if( delay->cur >= delay->length ) delay->cur = 0;
442 }
443
444 static void dsp_init_delay( struct dsp_delay *delay, float length )
445 {
446 delay->length = 44100.0f * length;
447 delay->cur = 0;
448 delay->buffer = dsp_allocate( delay->length );
449
450 for( int i=0; i<delay->length; i++ )
451 delay->buffer[i] = 0.0f;
452 }
453
454 static void dsp_update_lpf( struct dsp_lpf *lpf, float freq )
455 {
456 lpf->exponent = 1.0f-expf( -(1.0f/44100.0f) *2.0f*3.1415926535897f*freq );
457 }
458
459 static void dsp_init_lpf( struct dsp_lpf *lpf, float freq )
460 {
461 lpf->buffer = dsp_allocate( 4 );
462 lpf->buffer[0] = 0.0f;
463 dsp_update_lpf( lpf, freq );
464 }
465
466 static inline void dsp_write_lpf( struct dsp_lpf *lpf, float *s )
467 {
468 float diff = *s - lpf->buffer[0];
469 lpf->buffer[0] += diff * lpf->exponent;
470 }
471
472 static inline void dsp_read_lpf( struct dsp_lpf *lpf, float *s )
473 {
474 *s = lpf->buffer[0];
475 }
476
477 static void dsp_init_schroeder( struct dsp_schroeder *sch, float length,
478 float gain )
479 {
480 dsp_init_delay( &sch->M, length );
481 sch->gain = gain;
482 }
483
484 static inline void dsp_process_schroeder( struct dsp_schroeder *sch,
485 float *input, float *output )
486 {
487 float dry = *input;
488
489 float delay_output;
490 dsp_read_delay( &sch->M, &delay_output );
491
492 float feedback_attenuated = delay_output * sch->gain,
493 input_feedback_sum = dry + feedback_attenuated;
494
495 dsp_write_delay( &sch->M, &input_feedback_sum );
496
497 *output = delay_output - input_feedback_sum*sch->gain;
498 }
499
500 /* temporary global design */
501 static struct dsp_lpf __lpf_mud_free;
502 static struct dsp_delay __echos[8];
503 static struct dsp_lpf __echos_lpf[8];
504 static struct dsp_schroeder __diffusion_chain[8];
505
506 static inline float vg_lerpf( float a, float b, float t )
507 {
508 return a + t*(b-a);
509 }
510
511 static void vg_dsp_init( void )
512 {
513 /* temporary global design */
514
515
516 dsp_init_lpf( &__lpf_mud_free, 125.0f );
517
518 float sizes[] =
519 { 2.0f, 4.0f, 8.0f, 16.0f, 32.0f, 64.0f, 128.0f, 256.0f };
520
521 float reflection_variance = 0.1f;
522
523 for( int i=0; i<8; i++ )
524 {
525 float reflection_time = ((sizes[i])/343.0f) * 1000.0f;
526
527 float var = 1.0f + rand_float(-1.0,1.0) * reflection_variance,
528 total = reflection_time * var;
529
530 dsp_init_delay( &__echos[i], total / 1000.0f );
531
532 float freq = vg_lerpf( 800.0f, 350.0f, sizes[i] / 256.0f );
533 dsp_init_lpf( &__echos_lpf[i], freq );
534 }
535
536 float diffusions[] = { 187.0f, 159.0f, 143.0f, 121.0f,
537 79.0f, 57.0f, 27.0f, 11.0f };
538
539 for( int i=0; i<8; i++ )
540 {
541 dsp_init_schroeder( __diffusion_chain+i, diffusions[i]/1000.0f, 0.8f );
542 }
543 }
544
545 static void vg_dsp_process( float *stereo_in, float *stereo_out )
546 {
547 float in_total = (stereo_in[0]+stereo_in[1])*0.5f;
548 float recieved = 0.0f;
549
550 float echo_tunings[] = { 0.05f, 0.05f, 0.1f, 0.1f,
551 0.1f, 0.1f, 0.2f, 0.3f };
552
553 for( int i=0; i<8; i++ )
554 {
555 float echo;
556 dsp_read_delay( __echos+i, &echo );
557 dsp_write_lpf( __echos_lpf+i, &echo );
558 dsp_read_lpf( __echos_lpf+i, &echo );
559
560 recieved += echo * echo_tunings[i]*0.997;
561 }
562
563 float diffused = recieved;
564
565 for( int i=0; i<8; i++ )
566 {
567 dsp_process_schroeder( __diffusion_chain+i, &diffused, &diffused );
568 }
569
570 float total = in_total + (diffused*0.1f + recieved*0.9f);
571
572 float low_mud;
573 dsp_write_lpf( &__lpf_mud_free, &total );
574 dsp_read_lpf( &__lpf_mud_free, &low_mud );
575
576 total -= low_mud;
577
578 for( int i=0; i<8; i++ )
579 dsp_write_delay( __echos+i, &total );
580
581 stereo_out[0] = stereo_in[0]*0.25f;
582 stereo_out[1] = stereo_in[1]*0.25f;
583 stereo_out[0] += diffused*0.5f+recieved*0.9f;
584 stereo_out[1] += diffused*0.5f+recieved*0.9f;
585 }
586