6 #define SYNTH_BIRD_STDLIB
7 #include "vg_audio_synth_bird.h"
10 #define WRAP1S( X ) (X)%44100
13 * clang birds.c -lm -o birds && ./birds | aplay -f cd /dev/stdin
15 * Performance measurements: (generate 30seconds audio)
17 * DSP SINE_ACCURATE -O3 x Realtime
26 static void vg_dsp_init( void );
27 static void vg_dsp_process( float *stereo_in
, float *stereo_out
);
29 static void write_profile( FILE *fp
, struct synth_bird_settings
*settings
,
30 struct synth_bird_signature
*pattern
,
31 u32 pattern_count
, const char *name
)
33 struct synth_bird
*bird
=
34 synth_bird_create( settings
, pattern
, pattern_count
);
36 u32 size
= synth_bird_save_size( bird
);
38 synth_bird_save( bird
, save
);
40 fprintf( fp
, "%s:\n%.*s\n\n", name
, size
*2, save
);
43 #define _PROFILE( FP, SETTINGS, ARRAY ) \
44 write_profile( FP, SETTINGS, ARRAY, sizeof(ARRAY)/sizeof(ARRAY[0]), \
47 static void export_all_profiles(void)
49 FILE *fp
= fopen( "bird_profiles.txt", "w" );
51 struct synth_bird_settings
*settings
= &synth_bird__default_settings
;
53 _PROFILE( fp
, settings
, synth_bird__warbling_vireo
);
54 _PROFILE( fp
, settings
, synth_bird__pied_monarch
);
55 _PROFILE( fp
, settings
, synth_bird__bridled_honeyeater
);
56 _PROFILE( fp
, settings
, synth_bird__cricket
);
57 _PROFILE( fp
, settings
, synth_bird__gray_shrikethrush
);
58 _PROFILE( fp
, settings
, synth_bird__boobook
);
59 _PROFILE( fp
, settings
, synth_bird__shrike_tit
);
64 int main( int argc
, char *argv
[] )
68 export_all_profiles();
70 struct synth_bird
*warbling_vireo
=
71 synth_bird_create( &synth_bird__default_settings
,
72 synth_bird__warbling_vireo
,
73 sizeof(synth_bird__warbling_vireo
)/
74 sizeof(struct synth_bird_signature
) );
77 float stereo
[2] = { 0.0f
, 0.0f
};
81 synth_bird_generate_samples( warbling_vireo
, b
, 1 );
86 vg_dsp_process( stereo
, stereo
);
89 int16_t l
= stereo
[0] * 14000.0f
,
90 r
= stereo
[1] * 14000.0f
;
92 fwrite( &l
, 2,1, stdout
);
93 fwrite( &r
, 2,1, stdout
);
98 static float dsp_buffer
[(1024*1024)/4];
99 static int dsp_allocations
= 0;
119 static float *dsp_allocate( int l
)
121 float *buf
= &dsp_buffer
[ dsp_allocations
];
122 dsp_allocations
+= l
;
126 static inline void dsp_read_delay( struct dsp_delay
*delay
, float *s
)
128 int index
= delay
->cur
+1;
129 if( index
>= delay
->length
) index
= 0;
130 *s
= delay
->buffer
[ index
];
133 static inline void dsp_write_delay( struct dsp_delay
*delay
, float *s
)
135 int index
= delay
->cur
;
136 delay
->buffer
[ index
] = *s
;
138 if( delay
->cur
>= delay
->length
) delay
->cur
= 0;
141 static void dsp_init_delay( struct dsp_delay
*delay
, float length
)
143 delay
->length
= 44100.0f
* length
;
145 delay
->buffer
= dsp_allocate( delay
->length
);
147 for( int i
=0; i
<delay
->length
; i
++ )
148 delay
->buffer
[i
] = 0.0f
;
151 static void dsp_update_lpf( struct dsp_lpf
*lpf
, float freq
)
153 lpf
->exponent
= 1.0f
-expf( -(1.0f
/44100.0f
) *2.0f
*3.1415926535897f
*freq
);
156 static void dsp_init_lpf( struct dsp_lpf
*lpf
, float freq
)
158 lpf
->buffer
= dsp_allocate( 4 );
159 lpf
->buffer
[0] = 0.0f
;
160 dsp_update_lpf( lpf
, freq
);
163 static inline void dsp_write_lpf( struct dsp_lpf
*lpf
, float *s
)
165 float diff
= *s
- lpf
->buffer
[0];
166 lpf
->buffer
[0] += diff
* lpf
->exponent
;
169 static inline void dsp_read_lpf( struct dsp_lpf
*lpf
, float *s
)
174 static void dsp_init_schroeder( struct dsp_schroeder
*sch
, float length
,
177 dsp_init_delay( &sch
->M
, length
);
181 static inline void dsp_process_schroeder( struct dsp_schroeder
*sch
,
182 float *input
, float *output
)
187 dsp_read_delay( &sch
->M
, &delay_output
);
189 float feedback_attenuated
= delay_output
* sch
->gain
,
190 input_feedback_sum
= dry
+ feedback_attenuated
;
192 dsp_write_delay( &sch
->M
, &input_feedback_sum
);
194 *output
= delay_output
- input_feedback_sum
*sch
->gain
;
197 /* temporary global design */
198 static struct dsp_lpf __lpf_mud_free
,
201 static struct dsp_delay __echos
[8];
202 static struct dsp_lpf __echos_lpf
[8];
203 static struct dsp_schroeder __diffusion_chain
[8];
205 static void vg_dsp_init( void )
207 /* temporary global design */
209 dsp_init_lpf( &__lpf_mud_free
, 125.0f
);
210 dsp_init_lpf( &__hpf_mud_free
, 500.0f
);
213 { 2.0f
, 4.0f
, 8.0f
, 16.0f
, 32.0f
, 64.0f
, 128.0f
, 256.0f
};
215 float reflection_variance
= 0.04f
;
217 for( int i
=0; i
<8; i
++ )
219 float reflection_time
= ((sizes
[i
])/343.0f
) * 1000.0f
;
221 float var
= 1.0f
+ vg_randf64_range(-1.0,1.0) * reflection_variance
,
222 total
= reflection_time
* var
;
224 dsp_init_delay( &__echos
[i
], total
/ 1000.0f
);
226 float freq
= vg_lerpf( 800.0f
, 350.0f
, sizes
[i
] / 256.0f
);
227 dsp_init_lpf( &__echos_lpf
[i
], freq
);
230 float diffusions
[] = { 187.0f
, 159.0f
, 143.0f
, 121.0f
,
231 79.0f
, 57.0f
, 27.0f
, 11.0f
};
233 for( int i
=0; i
<8; i
++ )
235 dsp_init_schroeder( __diffusion_chain
+i
, diffusions
[i
]/1000.0f
, 0.7f
);
239 static void vg_dsp_process( float *stereo_in
, float *stereo_out
)
241 float in_total
= (stereo_in
[0]+stereo_in
[1])*0.5f
;
242 float recieved
= 0.0f
;
244 float echo_tunings
[] = { 0.05f
, 0.05f
, 0.1f
, 0.1f
,
245 0.1f
, 0.1f
, 0.2f
, 0.3f
};
247 for( int i
=0; i
<8; i
++ )
250 dsp_read_delay( __echos
+i
, &echo
);
251 dsp_write_lpf( __echos_lpf
+i
, &echo
);
252 dsp_read_lpf( __echos_lpf
+i
, &echo
);
254 recieved
+= echo
* echo_tunings
[i
]*0.9;
257 float diffused
= recieved
;
259 for( int i
=0; i
<8; i
++ )
261 dsp_process_schroeder( __diffusion_chain
+i
, &diffused
, &diffused
);
264 float total
= in_total
+ (diffused
*0.5f
+ recieved
*0.5f
);
266 dsp_write_lpf( &__hpf_mud_free
, &total
);
267 dsp_read_lpf( &__hpf_mud_free
, &total
);
270 dsp_write_lpf( &__lpf_mud_free
, &total
);
271 dsp_read_lpf( &__lpf_mud_free
, &low_mud
);
275 for( int i
=0; i
<8; i
++ )
276 dsp_write_delay( __echos
+i
, &total
);
278 stereo_out
[0] = stereo_in
[0]*0.5f
;
279 stereo_out
[1] = stereo_in
[1]*0.5f
;
280 stereo_out
[0] += diffused
*0.8f
+recieved
*0.9f
;
281 stereo_out
[1] += diffused
*0.8f
+recieved
*0.9f
;