bad char
[vg.git] / vg_audio_synth_bird.h
1 #ifndef VG_AUDIO_SYNTH_BIRD_H
2 #define VG_AUDIO_SYNTH_BIRD_H
3
4 #include "vg_binstr.h"
5 #include "vg_stdint.h"
6
7 #ifndef BIRD_SAMPLE_RATE
8 #define BIRD_SAMPLE_RATE 44100
9 #endif
10
11 struct synth_bird_signature
12 {
13 float length, pause, /* timings in seconds */
14 x0,x1,x2,x3, /* polynomial coefficients for the fundemental */
15 v0,v1,v2,v3; /* volume of each oscillator */
16
17 int lfo_hz; /* LFO frequency (30-60hz) */
18 float fm; /* LFO modulation depth (+/- hz) */
19 };
20
21 struct synth_bird
22 {
23 struct
24 {
25 int osc_main[4],
26 osc_lfo;
27 float volume[4];
28
29 float fundamental;
30 int x, length, /* position/length of signature in samples */
31 gate, adsr, /* adsr ranges 0->44100 */
32 frame; /* current frame of the pattern */
33
34 int lfo_hz;
35 float fm_depth;
36
37 int adsr_rise,
38 adsr_fall;
39 }
40 rt;
41
42 struct synth_bird_settings
43 {
44 int tones[4][2]; /* fraction of the fundemental tone
45 for each oscillator */
46 float adsr_rise, /* rise/fall in seconds */
47 adsr_fall;
48
49 enum bird_lfo_wave
50 {
51 k_bird_lfo_sine_approx,
52 k_bird_lfo_bipolar_poly
53 }
54 type;
55
56 int pattern_length;
57 struct synth_bird_signature pattern[];
58 }
59 settings;
60 };
61
62 #define DEFAULT_VOL 1.0f,0.5f,0.2f,0.125f
63 #define DEFAULT_TONES { {1,1}, {6,5}, {8,7}, {13,12} }
64 #define DEFAULT_RISE 0.00090702947f
65 #define DEFAULT_FALL 0.00226757369f
66
67 static struct synth_bird_settings synth_bird__default_settings =
68 {
69 .tones = DEFAULT_TONES,
70 .type = k_bird_lfo_sine_approx,
71 .adsr_rise = DEFAULT_RISE,
72 .adsr_fall = DEFAULT_FALL
73 };
74
75 static struct synth_bird_signature synth_bird__warbling_vireo[] =
76 {
77 /* timing fundemental volumes lfo hz,depth */
78 {0.13,0.10, 4000,100,100,0, DEFAULT_VOL, 60,200 },
79 {0.10,0.05, 4200,-500,1700,0, DEFAULT_VOL, 60,96 },
80 {0.10,0.00, 2400,-1200,1000,1700, DEFAULT_VOL, 60,96 },
81 {0.06,0.04, 3100,200,-10,-1100, DEFAULT_VOL, 60,90 },
82 {0.13,0.07, 4600,-2000,0,1300, DEFAULT_VOL, 60,10 },
83 {0.05,0.00, 2700,-300,700,800, DEFAULT_VOL, 60,10 },
84 {0.09,0.07, 3600,-300,0,0, DEFAULT_VOL, 60,20 },
85 {0.05,0.07, 4800,1240,300,0, DEFAULT_VOL, 60,20 },
86 {0.08,0.02, 2700,-800,150,1000, DEFAULT_VOL, 60,160 },
87 {0.12,0.08, 2700,-800,150,1000, DEFAULT_VOL, 60,160 },
88 {0.10,0.04, 6300,-100,-3200,1000, DEFAULT_VOL, 60,100 },
89 {0.16,0.10, 4260,-200,300,1100, DEFAULT_VOL, 60,20 }
90 };
91
92 static struct synth_bird_signature synth_bird__pied_monarch[] =
93 {
94 /* timing fundemental volumes lfo hz,depth */
95 {0.18,0.13, 2200,700,-300,0, 0.6,0.05,0,0, 60,0 },
96 {0.17,0.12, 2200,700,-300,0, 0.8,0.05,0,0, 60,0 },
97 {0.16,0.11, 2200,700,-300,0, 0.9,0.05,0,0, 60,0 },
98 {0.14,0.09, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
99 {0.12,0.07, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
100 {0.11,0.06, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
101 {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
102 {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
103 {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
104 {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
105 {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
106 {0.10,0.10, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 }
107 };
108
109 static struct synth_bird_signature synth_bird__bridled_honeyeater[] =
110 {
111 /* timing fundemental volumes lfo hz,depth */
112 {0.10,0.10, 2000,-1000,600,0, 1.00,0.00,0.00,0.00, 30,60},
113 {0.10,0.10, 4000,0,-200,-200, 0.80,0.25,0.25,0.25, 30,60},
114 {0.06,0.01, 4000,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
115 {0.07,0.01, 3950,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
116 {0.08,0.01, 3900,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
117 {0.09,0.01, 3850,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
118 {0.10,0.02, 3800,0,-700,-800, 0.90,0.20,0.10,0.00, 60,20},
119 {0.11,0.05, 3750,0,-700,-800, 0.90,0.40,0.20,0.00, 60,20},
120 {0.12,0.20, 3700,0,-700,-800, 0.30,0.10,0.00,0.00, 60,20},
121 {0.10,0.10, 2600,1300,600,0, 0.97,0.03,0.00,0.00, 60,20},
122 };
123
124 static struct synth_bird_signature synth_bird__cricket[] =
125 {
126 /* timing fundemental volumes lfo hz, depth */
127 {0.10,0.15, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
128 {0.11,0.14, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
129 {0.13,0.15, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
130 {0.09,0.16, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
131 {0.10,0.12, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
132 {0.10,0.15, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
133 {0.11,0.14, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
134 {0.13,0.15, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
135 {0.09,0.16, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
136 {0.10,0.12, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200}
137 };
138
139 static struct synth_bird_signature synth_bird__gray_shrikethrush[] =
140 {
141 /* timing fundemental volumes lfo hz, depth */
142 { 0.13,0.1, 2600,-200,-100,200, 0.9,0.1,0.05,0.001, 60,10 }
143 };
144
145 static struct synth_bird_signature synth_bird__boobook[] =
146 {
147 /* timing fundemental volumes lfo hz, depth */
148 {0.3,0.14, 700,0,-100,100, 0.9,0.14,0.0,0.2, 30,18},
149 {0.3,1.20, 630,0,-100,100, 0.9,0.00,0.3,0.0, 30,18}
150 };
151
152 static struct synth_bird_signature synth_bird__shrike_tit[] =
153 {
154 /* timing fundemental volumes lfo hz, depth */
155 {0.6,1.4, 2300,-300,-100,100, 1.0,0.14,0.0,0.1, 60,5 }
156 };
157
158 /* sine functions over the range [0, 44100] : [-pi, pi].
159 * Not accurate! */
160
161 static float sine_1second_1( int o )
162 {
163 float s = (o<(BIRD_SAMPLE_RATE/2))?-1.0f:1.0f;
164 float t = ((float)o*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f - s*0.5f;
165 float t2 = t*t;
166 float t4 = t2*t2;
167 return s*(5.0f*t2-4.0f*t4-1.0f);
168 }
169
170 static void sine_1second_4( int o[4], float v[4] )
171 {
172 float s[4],t[4],t2[4],t4[4];
173 s[0] = (o[0]<(BIRD_SAMPLE_RATE/2))?-1.0f:1.0f;
174 s[1] = (o[1]<(BIRD_SAMPLE_RATE/2))?-1.0f:1.0f;
175 s[2] = (o[2]<(BIRD_SAMPLE_RATE/2))?-1.0f:1.0f;
176 s[3] = (o[3]<(BIRD_SAMPLE_RATE/2))?-1.0f:1.0f;
177
178 t[0] = ((float)o[0]*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f - s[0]*0.5f;
179 t[1] = ((float)o[1]*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f - s[1]*0.5f;
180 t[2] = ((float)o[2]*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f - s[2]*0.5f;
181 t[3] = ((float)o[3]*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f - s[3]*0.5f;
182
183 t2[0] = t[0]*t[0];
184 t2[1] = t[1]*t[1];
185 t2[2] = t[2]*t[2];
186 t2[3] = t[3]*t[3];
187
188 t4[0] = t2[0]*t2[0];
189 t4[1] = t2[1]*t2[1];
190 t4[2] = t2[2]*t2[2];
191 t4[3] = t2[3]*t2[3];
192
193 v[0] = s[0]*(5.0f*t2[0]-4.0f*t4[0]-1.0f);
194 v[1] = s[1]*(5.0f*t2[1]-4.0f*t4[1]-1.0f);
195 v[2] = s[2]*(5.0f*t2[2]-4.0f*t4[2]-1.0f);
196 v[3] = s[3]*(5.0f*t2[3]-4.0f*t4[3]-1.0f);
197 }
198
199 static float saw_1second_1( int o )
200 {
201 float t = ((float)o*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f,
202 tt = t*t,
203 ttt = tt*t;
204
205 return -2.5f*ttt+2.5f*t;
206 }
207
208 static u32 synth_bird_get_length_in_samples( struct synth_bird *bird )
209 {
210 u32 total = 0;
211
212 for( int i=0; i<bird->settings.pattern_length; i ++ )
213 {
214 struct synth_bird_signature *sig = &bird->settings.pattern[i];
215
216 u32 l = sig->length * (float)BIRD_SAMPLE_RATE,
217 p = sig->pause * (float)BIRD_SAMPLE_RATE;
218
219 total += l+p;
220 }
221
222 return total;
223 }
224
225 static void synth_bird_reset( struct synth_bird *bird )
226 {
227 bird->rt.osc_main[0] = 0;
228 bird->rt.osc_main[1] = 0;
229 bird->rt.osc_main[2] = 0;
230 bird->rt.osc_main[3] = 0;
231 bird->rt.osc_lfo = 0;
232
233 bird->rt.volume[0] = 0.0f;
234 bird->rt.volume[1] = 0.0f;
235 bird->rt.volume[2] = 0.0f;
236 bird->rt.volume[3] = 0.0f;
237
238 bird->rt.fundamental = 0.0f;
239 bird->rt.x = 0;
240 bird->rt.length = bird->settings.pattern[0].length * (float)BIRD_SAMPLE_RATE;
241 bird->rt.gate = 1;
242 bird->rt.adsr = 0;
243 bird->rt.frame = 0;
244 bird->rt.lfo_hz = 0;
245 bird->rt.fm_depth = 0.0f;
246
247 bird->rt.adsr_rise = bird->settings.adsr_rise * (float)BIRD_SAMPLE_RATE;
248 bird->rt.adsr_fall = bird->settings.adsr_fall * (float)BIRD_SAMPLE_RATE;
249 }
250
251 static u32 synth_bird_save_size( struct synth_bird *bird )
252 {
253 return sizeof(struct synth_bird_signature) * bird->settings.pattern_length +
254 sizeof(struct synth_bird_settings);
255 }
256
257 static void synth_bird_save( struct synth_bird *bird, void *txt )
258 {
259 void *src = &bird->settings;
260 vg_bin_str( src, txt, synth_bird_save_size( bird ) );
261 }
262
263 static void synth_bird_load( struct synth_bird *bird,
264 const char *txt, u32 length )
265 {
266 vg_str_bin( txt, &bird->settings, length );
267 synth_bird_reset( bird );
268 }
269
270 /* expects a null terminated string */
271 static u32 synth_bird_memory_requirement( u32 string_length )
272 {
273 return (string_length/2) +
274 sizeof(struct synth_bird) - sizeof(struct synth_bird_settings);
275 }
276
277 #ifdef SYNTH_BIRD_STDLIB
278 #include "stdlib.h"
279 #include "string.h"
280
281 static struct synth_bird *synth_bird_create(
282 struct synth_bird_settings *settings,
283 struct synth_bird_signature *pattern,
284 u32 pattern_length )
285 {
286 u32 pattern_size = sizeof( struct synth_bird_signature ) * pattern_length;
287 u32 total_size = sizeof( struct synth_bird ) + pattern_size;
288 struct synth_bird *bird = malloc( total_size );
289
290 bird->settings = *settings;
291
292 memcpy( bird->settings.pattern, pattern, pattern_size );
293 bird->settings.pattern_length = pattern_length;
294
295 synth_bird_reset( bird );
296 return bird;
297 }
298
299 #endif
300
301 static void synth_bird_think( struct synth_bird *bird )
302 {
303 struct synth_bird_signature *sig = &bird->settings.pattern[ bird->rt.frame ];
304
305 bird->rt.x ++;
306 if( bird->rt.x >= bird->rt.length )
307 {
308 if( bird->rt.gate && (sig->pause != 0.0f) )
309 {
310 bird->rt.gate = 0;
311 bird->rt.length = sig->pause * (float)BIRD_SAMPLE_RATE;
312 }
313 else
314 {
315 bird->rt.frame ++;
316
317 if( bird->rt.frame >= bird->settings.pattern_length )
318 bird->rt.frame = 0;
319
320 sig = &bird->settings.pattern[ bird->rt.frame ];
321
322 bird->rt.gate = 1;
323 bird->rt.length = sig->length * (float)BIRD_SAMPLE_RATE;
324 }
325
326 bird->rt.x = 0;
327 }
328
329 if( bird->rt.gate )
330 {
331 bird->rt.adsr += bird->rt.adsr_rise;
332 if( bird->rt.adsr > BIRD_SAMPLE_RATE )
333 bird->rt.adsr = BIRD_SAMPLE_RATE;
334 }
335 else
336 {
337 bird->rt.adsr -= bird->rt.adsr_fall;
338 if( bird->rt.adsr < 0 )
339 bird->rt.adsr = 0;
340 }
341
342 if( bird->rt.gate )
343 {
344 float l = (float)bird->rt.length,
345 t = ((float)bird->rt.x * (1.0f/l))*2.0f - 1.0f,
346 tt = t*t,
347 ttt = tt*t;
348
349 bird->rt.fundamental = sig->x0 + t*sig->x1 + tt*sig->x2 + ttt*sig->x3;
350 }
351
352 float vol = (float)bird->rt.adsr * (1.0f/(float)BIRD_SAMPLE_RATE);
353
354 bird->rt.fm_depth = sig->fm;
355 bird->rt.lfo_hz = sig->lfo_hz;
356 bird->rt.volume[0] = sig->v0 * vol;
357 bird->rt.volume[1] = sig->v1 * vol;
358 bird->rt.volume[2] = sig->v2 * vol;
359 bird->rt.volume[3] = sig->v3 * vol;
360 }
361
362 static inline void int_add_mod( int *a, int const b )
363 {
364 *a += b;
365
366 if( *a > BIRD_SAMPLE_RATE )
367 *a -= BIRD_SAMPLE_RATE;
368 }
369
370 static void synth_bird_generate_samples( struct synth_bird *bird,
371 float *stereo_buffer, int samples )
372 {
373 for( int _=0; _<samples; _++ )
374 {
375 synth_bird_think( bird );
376
377 int_add_mod( &bird->rt.osc_lfo, bird->rt.lfo_hz );
378 float fm = sine_1second_1( bird->rt.osc_lfo ) * bird->rt.fm_depth;
379
380 int freq = bird->rt.fundamental + fm;
381 int hz[4] =
382 {
383 (freq * bird->settings.tones[0][0]) / bird->settings.tones[0][1],
384 (freq * bird->settings.tones[1][0]) / bird->settings.tones[1][1],
385 (freq * bird->settings.tones[2][0]) / bird->settings.tones[2][1],
386 (freq * bird->settings.tones[3][0]) / bird->settings.tones[3][1],
387 };
388
389 int_add_mod( bird->rt.osc_main + 0, hz[0] );
390 int_add_mod( bird->rt.osc_main + 1, hz[1] );
391 int_add_mod( bird->rt.osc_main + 2, hz[2] );
392 int_add_mod( bird->rt.osc_main + 3, hz[3] );
393
394 float v[4];
395 sine_1second_4( bird->rt.osc_main, v );
396
397 float s = v[0] * bird->rt.volume[0] +
398 v[1] * bird->rt.volume[1] +
399 v[2] * bird->rt.volume[2] +
400 v[3] * bird->rt.volume[3] ;
401
402 stereo_buffer[ _*2+0 ] = s;
403 stereo_buffer[ _*2+1 ] = s;
404 }
405 }
406
407 #ifdef SYNTH_BIRD_STDLIB
408 #include "stdio.h"
409
410 #define KNRM "\x1B[00m"
411 #define KRED "\x1B[31m"
412 #define KGRN "\x1B[32m"
413 #define KYEL "\x1B[33m"
414 #define KBLU "\x1B[34m"
415 #define KMAG "\x1B[35m"
416 #define KCYN "\x1B[36m"
417 #define KWHT "\x1B[37m"
418
419 #define LOG_BAR0 " . |"
420 #define LOG_BAR1 "-------+-------+-------+-------+"
421 #define LOG_BAR2 " "
422
423 static void synth_bird_log_pattern( struct synth_bird *bird )
424 {
425 synth_bird_reset( bird );
426
427 char output[][400]= {
428 KNRM "9k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
429 KNRM " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
430 KNRM "8k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
431 KNRM " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
432 KNRM "7k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
433 KNRM " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
434 KMAG "6k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
435 KMAG " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
436 KCYN "5k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
437 KCYN " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
438 KBLU "4k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
439 KBLU " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
440 KGRN "3k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
441 KGRN " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
442 KYEL "2k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
443 KYEL " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
444 KRED "1k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
445 KRED " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
446 KWHT " +" LOG_BAR1 LOG_BAR1 LOG_BAR1 LOG_BAR1 LOG_BAR1
447 KWHT " 0.0s"LOG_BAR2"0.5s"LOG_BAR2"1.0s"LOG_BAR2"1.5s"LOG_BAR2"2.0s"LOG_BAR2
448 };
449
450 for( int i=0; i<190*8; i++ )
451 {
452 for( int j=0; j<BIRD_SAMPLE_RATE/(32*8*2); j++ )
453 synth_bird_think( bird );
454
455 float hz = bird->rt.fundamental / 500.0f;
456 int j = hz;
457
458 if( j < 0 ) j = 0;
459 if( j > 18 ) j = 18;
460 j = 18-j;
461
462 float level = bird->rt.adsr;
463 level *= (1.0f/(float)BIRD_SAMPLE_RATE);
464
465 int ch = level*3.0f;
466
467 if( ch )
468 output[j][(i/8)+7] = " *###"[ch];
469 }
470
471 for( int i=0; i<20; i++ )
472 {
473 puts( output[i] );
474 }
475 }
476 #endif
477
478 #endif /* VG_AUDIO_SYNTH_BIRD_H */