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.
13 #define WRAP1S( X ) (X)%44100
17 * clang birds.c -lm -o birds && ./birds | aplay -f cd /dev/stdin
19 * Performance measurements: (generate 30seconds audio)
21 * DSP SINE_ACCURATE -O3 x Realtime
31 //#define SINE_ACCURATE
34 static float sine_44100_1( int o
)
36 float t
= (float)o
*(1.0f
/44100.0f
);
37 return sinf(t
*6.28318530717958647692528676655900576);
40 static void sine_44100_4( int o
[4], float v
[4] )
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] );
49 /* sine functions over the range [0, 44100] : [-pi, pi].
52 static float sine_44100_1( int o
)
54 float s
= (o
<22050)?-1.0f
:1.0f
;
55 float t
= ((float)o
*(1.0f
/22050.0f
))-1.0f
- s
*0.5f
;
58 return s
*(5.0f
*t2
-4.0f
*t4
-1.0f
);
61 static void sine_44100_4( int o
[4], float v
[4] )
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
;
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
;
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
);
91 static float saw_44100_1( int o
)
93 float t
= ((float)o
*(1.0f
/22050.0f
))-1.0f
,
97 return -2.5f
*ttt
+2.5f
*t
;
100 static double rand_float( double min
, double max
)
102 double r
= (double)(rand()&(4096-1))*(1.0/4096.0);
103 return min
+ r
*(max
-min
);
106 static int rand_seconds( double min
, double max
)
108 return rand_float( min
*44100.0, max
*44100.0 );
111 static void vg_dsp_init( void );
112 static void vg_dsp_process( float *stereo_in
, float *stereo_out
);
122 struct synth_bird_signature
124 float c0
, c1
, c2
, c3
, length
, pause
;
127 float fm
; /* lfo modulation depth (+/- hz) */
132 static int birdsynth_pattern_count_signatures( const char *pattern
)
134 /* {200,5000,1000,200,20,10,30,200}, {...} */
138 const char *c
= pattern
;
150 static void birdsynth_pattern_decode( struct synth_bird
*bird
,
151 const char *pattern
)
153 bird
->pattern_length
= 0;
155 const char *c
= pattern
;
160 struct synth_bird_signature
*sig
=
161 &bird
->pattern
[ bird
->pattern_length
++ ];
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
);
183 static struct synth_bird
*birdsynth_malloc_create( const char *pattern
)
185 int s
= birdsynth_pattern_count_signatures( pattern
);
189 struct synth_bird
*bird
= malloc( sizeof(struct synth_bird
) +
190 s
* sizeof(struct synth_bird_signature
) );
192 birdsynth_pattern_decode( bird
, pattern
);
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;
202 bird
->l
= bird
->pattern
[0].length
* 44100.0f
;
209 static void synthbird_generate_samples( struct synth_bird
*bird
,
210 float *stereo_buffer
, int samples
)
212 for( int _
=0; _
<samples
; _
++ )
215 if( bird
->x
>= bird
->l
)
220 bird
->l
= bird
->pattern
[ bird
->frame
].pause
* 44100.0f
;
226 if( bird
->frame
>= bird
->pattern_length
)
230 bird
->l
= bird
->pattern
[ bird
->frame
].length
* 44100.0f
;
239 if( bird
->v
> 44100 ) bird
->v
= 44100;
244 if( bird
->v
< 0 ) bird
->v
= 0;
247 struct synth_bird_signature
*sig
= &bird
->pattern
[ bird
->frame
];
257 float level
= bird
->v
;
258 level
*= (1.0f
/44100.0f
);
262 float t
= ((float)bird
->x
* (1.0f
/(float)bird
->l
))*2.0f
- 1.0f
,
266 bird
->poly
= sig
->c0
+ t
*sig
->c1
+ tt
*sig
->c2
+ ttt
*sig
->c3
;
269 bird
->fm_oscillator
= WRAP1S( bird
->fm_oscillator
+ sig
->lfo_hz
);
270 float fm
= sine_44100_1( bird
->fm_oscillator
) * sig
->fm
;
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 );
279 sine_44100_4( bird
->harmonic_4
, v
);
287 stereo_buffer
[ _
*2+0 ] = s
;
288 stereo_buffer
[ _
*2+1 ] = s
;
292 int main( int argc
, char *argv
[] )
297 int f0
=4500, o1
=0, f1
=30;
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 */
309 for(int _
=0;_
<44100*30;_
++){
311 if( x
>= l
){ /* do new thing */
313 int retrigger
= rand() % 4;
315 if( retrigger
) l
=rand_seconds(0.03,0.1);
316 else l
=rand_seconds(0.5,10.0);
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);
331 if( adsr
> 44100 ) adsr
= 44100;
335 if( adsr
< 0 ) adsr
= 0;
341 float s1
= sine_44100_1( o1
);
343 level
*= (1.0f
/44100.0f
);
347 float t
= ((float)x
* (1.0f
/(float)l
))*2.0f
- 1.0f
,
351 poly
= c0
+t
*c1
+tt
*c2
+ttt
*c3
;
354 int fm
= s1
*100.0f
*(1.0f
+poly
*0.5f
) + poly
*500.0f
;
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 );
363 sine_44100_4( o0
, v
);
370 float stereo
[2] = { s0
, s0
};
371 vg_dsp_process( stereo
, stereo
);
373 int16_t l
= stereo
[0] * 10000.0f
,
374 r
= stereo
[1] * 10000.0f
;
376 fwrite( &l
, 2,1, stdout
);
377 fwrite( &r
, 2,1, stdout
);
381 struct synth_bird
*bird
= birdsynth_malloc_create( "" );
383 for(int _
=0;_
<44100*60;_
++){
384 float stereo
[2] = { 0.0f
, 0.0f
};
386 synthbird_generate_samples( bird
, stereo
, 1 );
388 vg_dsp_process( stereo
, stereo
);
391 int16_t l
= stereo
[0] * 10000.0f
,
392 r
= stereo
[1] * 10000.0f
;
394 fwrite( &l
, 2,1, stdout
);
395 fwrite( &r
, 2,1, stdout
);
401 static float dsp_buffer
[(1024*1024)/4];
402 static int dsp_allocations
= 0;
422 static float *dsp_allocate( int l
)
424 float *buf
= &dsp_buffer
[ dsp_allocations
];
425 dsp_allocations
+= l
;
429 static inline void dsp_read_delay( struct dsp_delay
*delay
, float *s
)
431 int index
= delay
->cur
+1;
432 if( index
>= delay
->length
) index
= 0;
433 *s
= delay
->buffer
[ index
];
436 static inline void dsp_write_delay( struct dsp_delay
*delay
, float *s
)
438 int index
= delay
->cur
;
439 delay
->buffer
[ index
] = *s
;
441 if( delay
->cur
>= delay
->length
) delay
->cur
= 0;
444 static void dsp_init_delay( struct dsp_delay
*delay
, float length
)
446 delay
->length
= 44100.0f
* length
;
448 delay
->buffer
= dsp_allocate( delay
->length
);
450 for( int i
=0; i
<delay
->length
; i
++ )
451 delay
->buffer
[i
] = 0.0f
;
454 static void dsp_update_lpf( struct dsp_lpf
*lpf
, float freq
)
456 lpf
->exponent
= 1.0f
-expf( -(1.0f
/44100.0f
) *2.0f
*3.1415926535897f
*freq
);
459 static void dsp_init_lpf( struct dsp_lpf
*lpf
, float freq
)
461 lpf
->buffer
= dsp_allocate( 4 );
462 lpf
->buffer
[0] = 0.0f
;
463 dsp_update_lpf( lpf
, freq
);
466 static inline void dsp_write_lpf( struct dsp_lpf
*lpf
, float *s
)
468 float diff
= *s
- lpf
->buffer
[0];
469 lpf
->buffer
[0] += diff
* lpf
->exponent
;
472 static inline void dsp_read_lpf( struct dsp_lpf
*lpf
, float *s
)
477 static void dsp_init_schroeder( struct dsp_schroeder
*sch
, float length
,
480 dsp_init_delay( &sch
->M
, length
);
484 static inline void dsp_process_schroeder( struct dsp_schroeder
*sch
,
485 float *input
, float *output
)
490 dsp_read_delay( &sch
->M
, &delay_output
);
492 float feedback_attenuated
= delay_output
* sch
->gain
,
493 input_feedback_sum
= dry
+ feedback_attenuated
;
495 dsp_write_delay( &sch
->M
, &input_feedback_sum
);
497 *output
= delay_output
- input_feedback_sum
*sch
->gain
;
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];
506 static inline float vg_lerpf( float a
, float b
, float t
)
511 static void vg_dsp_init( void )
513 /* temporary global design */
516 dsp_init_lpf( &__lpf_mud_free
, 125.0f
);
519 { 2.0f
, 4.0f
, 8.0f
, 16.0f
, 32.0f
, 64.0f
, 128.0f
, 256.0f
};
521 float reflection_variance
= 0.1f
;
523 for( int i
=0; i
<8; i
++ )
525 float reflection_time
= ((sizes
[i
])/343.0f
) * 1000.0f
;
527 float var
= 1.0f
+ rand_float(-1.0,1.0) * reflection_variance
,
528 total
= reflection_time
* var
;
530 dsp_init_delay( &__echos
[i
], total
/ 1000.0f
);
532 float freq
= vg_lerpf( 800.0f
, 350.0f
, sizes
[i
] / 256.0f
);
533 dsp_init_lpf( &__echos_lpf
[i
], freq
);
536 float diffusions
[] = { 187.0f
, 159.0f
, 143.0f
, 121.0f
,
537 79.0f
, 57.0f
, 27.0f
, 11.0f
};
539 for( int i
=0; i
<8; i
++ )
541 dsp_init_schroeder( __diffusion_chain
+i
, diffusions
[i
]/1000.0f
, 0.8f
);
545 static void vg_dsp_process( float *stereo_in
, float *stereo_out
)
547 float in_total
= (stereo_in
[0]+stereo_in
[1])*0.5f
;
548 float recieved
= 0.0f
;
550 float echo_tunings
[] = { 0.05f
, 0.05f
, 0.1f
, 0.1f
,
551 0.1f
, 0.1f
, 0.2f
, 0.3f
};
553 for( int i
=0; i
<8; i
++ )
556 dsp_read_delay( __echos
+i
, &echo
);
557 dsp_write_lpf( __echos_lpf
+i
, &echo
);
558 dsp_read_lpf( __echos_lpf
+i
, &echo
);
560 recieved
+= echo
* echo_tunings
[i
]*0.997;
563 float diffused
= recieved
;
565 for( int i
=0; i
<8; i
++ )
567 dsp_process_schroeder( __diffusion_chain
+i
, &diffused
, &diffused
);
570 float total
= in_total
+ (diffused
*0.1f
+ recieved
*0.9f
);
573 dsp_write_lpf( &__lpf_mud_free
, &total
);
574 dsp_read_lpf( &__lpf_mud_free
, &low_mud
);
578 for( int i
=0; i
<8; i
++ )
579 dsp_write_delay( __echos
+i
, &total
);
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
;