1 #ifndef VG_AUDIO_SYNTH_BIRD_H
2 #define VG_AUDIO_SYNTH_BIRD_H
7 #ifndef BIRD_SAMPLE_RATE
8 #define BIRD_SAMPLE_RATE 44100
11 struct synth_bird_signature
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 */
17 int lfo_hz
; /* LFO frequency (30-60hz) */
18 float fm
; /* LFO modulation depth (+/- hz) */
30 int x
, length
, /* position/length of signature in samples */
31 gate
, adsr
, /* adsr ranges 0->44100 */
32 frame
; /* current frame of the pattern */
42 struct synth_bird_settings
44 int tones
[4][2]; /* fraction of the fundemental tone
45 for each oscillator */
46 float adsr_rise
, /* rise/fall in seconds */
51 k_bird_lfo_sine_approx
,
52 k_bird_lfo_bipolar_poly
57 struct synth_bird_signature pattern
[];
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
67 static struct synth_bird_settings synth_bird__default_settings
=
69 .tones
= DEFAULT_TONES
,
70 .type
= k_bird_lfo_sine_approx
,
71 .adsr_rise
= DEFAULT_RISE
,
72 .adsr_fall
= DEFAULT_FALL
75 static struct synth_bird_signature synth_bird__warbling_vireo
[] =
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 }
92 static struct synth_bird_signature synth_bird__pied_monarch
[] =
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 }
109 static struct synth_bird_signature synth_bird__bridled_honeyeater
[] =
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},
124 static struct synth_bird_signature synth_bird__cricket
[] =
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}
139 static struct synth_bird_signature synth_bird__gray_shrikethrush
[] =
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 }
145 static struct synth_bird_signature synth_bird__boobook
[] =
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}
152 static struct synth_bird_signature synth_bird__shrike_tit
[] =
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 }
158 /* sine functions over the range [0, 44100] : [-pi, pi].
161 static float sine_1second_1( int o
)
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
;
167 return s
*(5.0f
*t2
-4.0f
*t4
-1.0f
);
170 static void sine_1second_4( int o
[4], float v
[4] )
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
;
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
;
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
);
199 static float saw_1second_1( int o
)
201 float t
= ((float)o
*(1.0f
/(float)(BIRD_SAMPLE_RATE
/2)))-1.0f
,
205 return -2.5f
*ttt
+2.5f
*t
;
208 static u32
synth_bird_get_length_in_samples( struct synth_bird
*bird
)
212 for( int i
=0; i
<bird
->settings
.pattern_length
; i
++ )
214 struct synth_bird_signature
*sig
= &bird
->settings
.pattern
[i
];
216 u32 l
= sig
->length
* (float)BIRD_SAMPLE_RATE
,
217 p
= sig
->pause
* (float)BIRD_SAMPLE_RATE
;
225 static void synth_bird_reset( struct synth_bird
*bird
)
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;
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
;
238 bird
->rt
.fundamental
= 0.0f
;
240 bird
->rt
.length
= bird
->settings
.pattern
[0].length
* (float)BIRD_SAMPLE_RATE
;
245 bird
->rt
.fm_depth
= 0.0f
;
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
;
251 static u32
synth_bird_save_size( struct synth_bird
*bird
)
253 return sizeof(struct synth_bird_signature
) * bird
->settings
.pattern_length
+
254 sizeof(struct synth_bird_settings
);
257 static void synth_bird_save( struct synth_bird
*bird
, void *txt
)
259 void *src
= &bird
->settings
;
260 vg_bin_str( src
, txt
, synth_bird_save_size( bird
) );
263 static void synth_bird_load( struct synth_bird
*bird
,
264 const char *txt
, u32 length
)
266 vg_str_bin( txt
, &bird
->settings
, length
);
267 synth_bird_reset( bird
);
270 /* expects a null terminated string */
271 static u32
synth_bird_memory_requirement( u32 string_length
)
273 return (string_length
/2) +
274 sizeof(struct synth_bird
) - sizeof(struct synth_bird_settings
);
277 #ifdef SYNTH_BIRD_STDLIB
281 static struct synth_bird
*synth_bird_create(
282 struct synth_bird_settings
*settings
,
283 struct synth_bird_signature
*pattern
,
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
);
290 bird
->settings
= *settings
;
292 memcpy( bird
->settings
.pattern
, pattern
, pattern_size
);
293 bird
->settings
.pattern_length
= pattern_length
;
295 synth_bird_reset( bird
);
301 static void synth_bird_think( struct synth_bird
*bird
)
303 struct synth_bird_signature
*sig
= &bird
->settings
.pattern
[ bird
->rt
.frame
];
306 if( bird
->rt
.x
>= bird
->rt
.length
)
308 if( bird
->rt
.gate
&& (sig
->pause
!= 0.0f
) )
311 bird
->rt
.length
= sig
->pause
* (float)BIRD_SAMPLE_RATE
;
317 if( bird
->rt
.frame
>= bird
->settings
.pattern_length
)
320 sig
= &bird
->settings
.pattern
[ bird
->rt
.frame
];
323 bird
->rt
.length
= sig
->length
* (float)BIRD_SAMPLE_RATE
;
331 bird
->rt
.adsr
+= bird
->rt
.adsr_rise
;
332 if( bird
->rt
.adsr
> BIRD_SAMPLE_RATE
)
333 bird
->rt
.adsr
= BIRD_SAMPLE_RATE
;
337 bird
->rt
.adsr
-= bird
->rt
.adsr_fall
;
338 if( bird
->rt
.adsr
< 0 )
344 float l
= (float)bird
->rt
.length
,
345 t
= ((float)bird
->rt
.x
* (1.0f
/l
))*2.0f
- 1.0f
,
349 bird
->rt
.fundamental
= sig
->x0
+ t
*sig
->x1
+ tt
*sig
->x2
+ ttt
*sig
->x3
;
352 float vol
= (float)bird
->rt
.adsr
* (1.0f
/(float)BIRD_SAMPLE_RATE
);
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
;
362 static inline void int_add_mod( int *a
, int const b
)
366 if( *a
> BIRD_SAMPLE_RATE
)
367 *a
-= BIRD_SAMPLE_RATE
;
370 static void synth_bird_generate_samples( struct synth_bird
*bird
,
371 float *stereo_buffer
, int samples
)
373 for( int _
=0; _
<samples
; _
++ )
375 synth_bird_think( bird
);
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
;
380 int freq
= bird
->rt
.fundamental
+ fm
;
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],
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] );
395 sine_1second_4( bird
->rt
.osc_main
, v
);
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] ;
402 stereo_buffer
[ _
*2+0 ] = s
;
403 stereo_buffer
[ _
*2+1 ] = s
;
407 #ifdef SYNTH_BIRD_STDLIB
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"
419 #define LOG_BAR0 " . |"
420 #define LOG_BAR1 "-------+-------+-------+-------+"
423 static void synth_bird_log_pattern( struct synth_bird
*bird
)
425 synth_bird_reset( bird
);
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
450 for( int i
=0; i
<190*8; i
++ )
452 for( int j
=0; j
<BIRD_SAMPLE_RATE
/(32*8*2); j
++ )
453 synth_bird_think( bird
);
455 float hz
= bird
->rt
.fundamental
/ 500.0f
;
462 float level
= bird
->rt
.adsr
;
463 level
*= (1.0f
/(float)BIRD_SAMPLE_RATE
);
468 output
[j
][(i
/8)+7] = " *###"[ch
];
471 for( int i
=0; i
<20; i
++ )
478 #endif /* VG_AUDIO_SYNTH_BIRD_H */