6 #define SYNTH_BIRD_STDLIB
7 #include "vg_audio_synth_bird.h"
9 #define WRAP1S( X ) (X)%44100
12 * clang birds.c -lm -o birds && ./birds | aplay -f cd /dev/stdin
14 * Performance measurements: (generate 30seconds audio)
16 * DSP SINE_ACCURATE -O3 x Realtime
25 static double rand_float( double min
, double max
)
27 double r
= (double)(rand()&(4096-1))*(1.0/4096.0);
28 return min
+ r
*(max
-min
);
31 static int rand_seconds( double min
, double max
)
33 return rand_float( min
*44100.0, max
*44100.0 );
36 static void vg_dsp_init( void );
37 static void vg_dsp_process( float *stereo_in
, float *stereo_out
);
39 static void write_profile( FILE *fp
, struct synth_bird_settings
*settings
,
40 struct synth_bird_signature
*pattern
,
41 u32 pattern_count
, const char *name
)
43 struct synth_bird
*bird
=
44 synth_bird_create( settings
, pattern
, pattern_count
);
46 u32 size
= synth_bird_save_size( bird
);
48 synth_bird_save( bird
, save
);
50 fprintf( fp
, "%s:\n%.*s\n\n", name
, size
*2, save
);
53 #define _PROFILE( FP, SETTINGS, ARRAY ) \
54 write_profile( FP, SETTINGS, ARRAY, sizeof(ARRAY)/sizeof(ARRAY[0]), \
57 static void export_all_profiles(void)
59 FILE *fp
= fopen( "bird_profiles.txt", "w" );
61 struct synth_bird_settings
*settings
= &synth_bird__default_settings
;
63 _PROFILE( fp
, settings
, synth_bird__warbling_vireo
);
64 _PROFILE( fp
, settings
, synth_bird__pied_monarch
);
65 _PROFILE( fp
, settings
, synth_bird__bridled_honeyeater
);
66 _PROFILE( fp
, settings
, synth_bird__cricket
);
67 _PROFILE( fp
, settings
, synth_bird__gray_shrikethrush
);
68 _PROFILE( fp
, settings
, synth_bird__boobook
);
69 _PROFILE( fp
, settings
, synth_bird__shrike_tit
);
74 int main( int argc
, char *argv
[] )
78 export_all_profiles();
80 struct synth_bird
*warbling_vireo
=
81 synth_bird_create( &synth_bird__default_settings
,
82 synth_bird__warbling_vireo
,
83 sizeof(synth_bird__warbling_vireo
)/
84 sizeof(struct synth_bird_signature
) );
87 float stereo
[2] = { 0.0f
, 0.0f
};
91 synth_bird_generate_samples( warbling_vireo
, b
, 1 );
96 vg_dsp_process( stereo
, stereo
);
99 int16_t l
= stereo
[0] * 14000.0f
,
100 r
= stereo
[1] * 14000.0f
;
102 fwrite( &l
, 2,1, stdout
);
103 fwrite( &r
, 2,1, stdout
);
108 static float dsp_buffer
[(1024*1024)/4];
109 static int dsp_allocations
= 0;
129 static float *dsp_allocate( int l
)
131 float *buf
= &dsp_buffer
[ dsp_allocations
];
132 dsp_allocations
+= l
;
136 static inline void dsp_read_delay( struct dsp_delay
*delay
, float *s
)
138 int index
= delay
->cur
+1;
139 if( index
>= delay
->length
) index
= 0;
140 *s
= delay
->buffer
[ index
];
143 static inline void dsp_write_delay( struct dsp_delay
*delay
, float *s
)
145 int index
= delay
->cur
;
146 delay
->buffer
[ index
] = *s
;
148 if( delay
->cur
>= delay
->length
) delay
->cur
= 0;
151 static void dsp_init_delay( struct dsp_delay
*delay
, float length
)
153 delay
->length
= 44100.0f
* length
;
155 delay
->buffer
= dsp_allocate( delay
->length
);
157 for( int i
=0; i
<delay
->length
; i
++ )
158 delay
->buffer
[i
] = 0.0f
;
161 static void dsp_update_lpf( struct dsp_lpf
*lpf
, float freq
)
163 lpf
->exponent
= 1.0f
-expf( -(1.0f
/44100.0f
) *2.0f
*3.1415926535897f
*freq
);
166 static void dsp_init_lpf( struct dsp_lpf
*lpf
, float freq
)
168 lpf
->buffer
= dsp_allocate( 4 );
169 lpf
->buffer
[0] = 0.0f
;
170 dsp_update_lpf( lpf
, freq
);
173 static inline void dsp_write_lpf( struct dsp_lpf
*lpf
, float *s
)
175 float diff
= *s
- lpf
->buffer
[0];
176 lpf
->buffer
[0] += diff
* lpf
->exponent
;
179 static inline void dsp_read_lpf( struct dsp_lpf
*lpf
, float *s
)
184 static void dsp_init_schroeder( struct dsp_schroeder
*sch
, float length
,
187 dsp_init_delay( &sch
->M
, length
);
191 static inline void dsp_process_schroeder( struct dsp_schroeder
*sch
,
192 float *input
, float *output
)
197 dsp_read_delay( &sch
->M
, &delay_output
);
199 float feedback_attenuated
= delay_output
* sch
->gain
,
200 input_feedback_sum
= dry
+ feedback_attenuated
;
202 dsp_write_delay( &sch
->M
, &input_feedback_sum
);
204 *output
= delay_output
- input_feedback_sum
*sch
->gain
;
207 /* temporary global design */
208 static struct dsp_lpf __lpf_mud_free
,
211 static struct dsp_delay __echos
[8];
212 static struct dsp_lpf __echos_lpf
[8];
213 static struct dsp_schroeder __diffusion_chain
[8];
215 static inline float vg_lerpf( float a
, float b
, float t
)
220 static void vg_dsp_init( void )
222 /* temporary global design */
225 dsp_init_lpf( &__lpf_mud_free
, 125.0f
);
226 dsp_init_lpf( &__hpf_mud_free
, 500.0f
);
229 { 2.0f
, 4.0f
, 8.0f
, 16.0f
, 32.0f
, 64.0f
, 128.0f
, 256.0f
};
231 float reflection_variance
= 0.04f
;
233 for( int i
=0; i
<8; i
++ )
235 float reflection_time
= ((sizes
[i
])/343.0f
) * 1000.0f
;
237 float var
= 1.0f
+ rand_float(-1.0,1.0) * reflection_variance
,
238 total
= reflection_time
* var
;
240 dsp_init_delay( &__echos
[i
], total
/ 1000.0f
);
242 float freq
= vg_lerpf( 800.0f
, 350.0f
, sizes
[i
] / 256.0f
);
243 dsp_init_lpf( &__echos_lpf
[i
], freq
);
246 float diffusions
[] = { 187.0f
, 159.0f
, 143.0f
, 121.0f
,
247 79.0f
, 57.0f
, 27.0f
, 11.0f
};
249 for( int i
=0; i
<8; i
++ )
251 dsp_init_schroeder( __diffusion_chain
+i
, diffusions
[i
]/1000.0f
, 0.7f
);
255 static void vg_dsp_process( float *stereo_in
, float *stereo_out
)
257 float in_total
= (stereo_in
[0]+stereo_in
[1])*0.5f
;
258 float recieved
= 0.0f
;
260 float echo_tunings
[] = { 0.05f
, 0.05f
, 0.1f
, 0.1f
,
261 0.1f
, 0.1f
, 0.2f
, 0.3f
};
263 for( int i
=0; i
<8; i
++ )
266 dsp_read_delay( __echos
+i
, &echo
);
267 dsp_write_lpf( __echos_lpf
+i
, &echo
);
268 dsp_read_lpf( __echos_lpf
+i
, &echo
);
270 recieved
+= echo
* echo_tunings
[i
]*0.9;
273 float diffused
= recieved
;
275 for( int i
=0; i
<8; i
++ )
277 dsp_process_schroeder( __diffusion_chain
+i
, &diffused
, &diffused
);
280 float total
= in_total
+ (diffused
*0.5f
+ recieved
*0.5f
);
282 dsp_write_lpf( &__hpf_mud_free
, &total
);
283 dsp_read_lpf( &__hpf_mud_free
, &total
);
286 dsp_write_lpf( &__lpf_mud_free
, &total
);
287 dsp_read_lpf( &__lpf_mud_free
, &low_mud
);
291 for( int i
=0; i
<8; i
++ )
292 dsp_write_delay( __echos
+i
, &total
);
294 stereo_out
[0] = stereo_in
[0]*0.5f
;
295 stereo_out
[1] = stereo_in
[1]*0.5f
;
296 stereo_out
[0] += diffused
*0.8f
+recieved
*0.9f
;
297 stereo_out
[1] += diffused
*0.8f
+recieved
*0.9f
;