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
{
12 float length
, pause
, /* timings in seconds */
13 x0
,x1
,x2
,x3
, /* polynomial coefficients for the fundemental */
14 v0
,v1
,v2
,v3
; /* volume of each oscillator */
16 int lfo_hz
; /* LFO frequency (30-60hz) */
17 float fm
; /* LFO modulation depth (+/- hz) */
27 int x
, length
, /* position/length of signature in samples */
28 gate
, adsr
, /* adsr ranges 0->44100 */
29 frame
; /* current frame of the pattern */
39 struct synth_bird_settings
{
40 int tones
[4][2]; /* fraction of the fundemental tone
41 for each oscillator */
42 float adsr_rise
, /* rise/fall in seconds */
46 k_bird_lfo_sine_approx
,
47 k_bird_lfo_bipolar_poly
52 struct synth_bird_signature pattern
[];
57 #define DEFAULT_VOL 1.0f,0.5f,0.2f,0.125f
58 #define DEFAULT_TONES { {1,1}, {6,5}, {8,7}, {13,12} }
59 #define DEFAULT_RISE 0.00090702947f
60 #define DEFAULT_FALL 0.00226757369f
62 static struct synth_bird_settings synth_bird__default_settings
=
64 .tones
= DEFAULT_TONES
,
65 .type
= k_bird_lfo_sine_approx
,
66 .adsr_rise
= DEFAULT_RISE
,
67 .adsr_fall
= DEFAULT_FALL
70 static struct synth_bird_signature synth_bird__warbling_vireo
[] =
72 /* timing fundemental volumes lfo hz,depth */
73 {0.13,0.10, 4000,100,100,0, DEFAULT_VOL
, 60,200 },
74 {0.10,0.05, 4200,-500,1700,0, DEFAULT_VOL
, 60,96 },
75 {0.10,0.00, 2400,-1200,1000,1700, DEFAULT_VOL
, 60,96 },
76 {0.06,0.04, 3100,200,-10,-1100, DEFAULT_VOL
, 60,90 },
77 {0.13,0.07, 4600,-2000,0,1300, DEFAULT_VOL
, 60,10 },
78 {0.05,0.00, 2700,-300,700,800, DEFAULT_VOL
, 60,10 },
79 {0.09,0.07, 3600,-300,0,0, DEFAULT_VOL
, 60,20 },
80 {0.05,0.07, 4800,1240,300,0, DEFAULT_VOL
, 60,20 },
81 {0.08,0.02, 2700,-800,150,1000, DEFAULT_VOL
, 60,160 },
82 {0.12,0.08, 2700,-800,150,1000, DEFAULT_VOL
, 60,160 },
83 {0.10,0.04, 6300,-100,-3200,1000, DEFAULT_VOL
, 60,100 },
84 {0.16,0.10, 4260,-200,300,1100, DEFAULT_VOL
, 60,20 }
87 static struct synth_bird_signature synth_bird__pied_monarch
[] =
89 /* timing fundemental volumes lfo hz,depth */
90 {0.18,0.13, 2200,700,-300,0, 0.6,0.05,0,0, 60,0 },
91 {0.17,0.12, 2200,700,-300,0, 0.8,0.05,0,0, 60,0 },
92 {0.16,0.11, 2200,700,-300,0, 0.9,0.05,0,0, 60,0 },
93 {0.14,0.09, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
94 {0.12,0.07, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
95 {0.11,0.06, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
96 {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
97 {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
98 {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
99 {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
100 {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
101 {0.10,0.10, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 }
104 static struct synth_bird_signature synth_bird__bridled_honeyeater
[] =
106 /* timing fundemental volumes lfo hz,depth */
107 {0.10,0.10, 2000,-1000,600,0, 1.00,0.00,0.00,0.00, 30,60},
108 {0.10,0.10, 4000,0,-200,-200, 0.80,0.25,0.25,0.25, 30,60},
109 {0.06,0.01, 4000,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
110 {0.07,0.01, 3950,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
111 {0.08,0.01, 3900,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
112 {0.09,0.01, 3850,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
113 {0.10,0.02, 3800,0,-700,-800, 0.90,0.20,0.10,0.00, 60,20},
114 {0.11,0.05, 3750,0,-700,-800, 0.90,0.40,0.20,0.00, 60,20},
115 {0.12,0.20, 3700,0,-700,-800, 0.30,0.10,0.00,0.00, 60,20},
116 {0.10,0.10, 2600,1300,600,0, 0.97,0.03,0.00,0.00, 60,20},
119 static struct synth_bird_signature synth_bird__cricket
[] =
121 /* timing fundemental volumes lfo hz, depth */
122 {0.10,0.15, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
123 {0.11,0.14, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
124 {0.13,0.15, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
125 {0.09,0.16, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
126 {0.10,0.12, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
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}
134 static struct synth_bird_signature synth_bird__gray_shrikethrush
[] =
136 /* timing fundemental volumes lfo hz, depth */
137 { 0.13,0.1, 2600,-200,-100,200, 0.9,0.1,0.05,0.001, 60,10 }
140 static struct synth_bird_signature synth_bird__boobook
[] =
142 /* timing fundemental volumes lfo hz, depth */
143 {0.3,0.14, 700,0,-100,100, 0.9,0.14,0.0,0.2, 30,18},
144 {0.3,1.20, 630,0,-100,100, 0.9,0.00,0.3,0.0, 30,18}
147 static struct synth_bird_signature synth_bird__shrike_tit
[] =
149 /* timing fundemental volumes lfo hz, depth */
150 {0.6,1.4, 2300,-300,-100,100, 1.0,0.14,0.0,0.1, 60,5 }
153 /* sine functions over the range [0, 44100] : [-pi, pi].
156 static float sine_1second_1( int o
)
158 float s
= (o
<(BIRD_SAMPLE_RATE
/2))?-1.0f
:1.0f
;
159 float t
= ((float)o
*(1.0f
/(float)(BIRD_SAMPLE_RATE
/2)))-1.0f
- s
*0.5f
;
162 return s
*(5.0f
*t2
-4.0f
*t4
-1.0f
);
165 static void sine_1second_4( int o
[4], float v
[4] )
167 float s
[4],t
[4],t2
[4],t4
[4];
168 s
[0] = (o
[0]<(BIRD_SAMPLE_RATE
/2))?-1.0f
:1.0f
;
169 s
[1] = (o
[1]<(BIRD_SAMPLE_RATE
/2))?-1.0f
:1.0f
;
170 s
[2] = (o
[2]<(BIRD_SAMPLE_RATE
/2))?-1.0f
:1.0f
;
171 s
[3] = (o
[3]<(BIRD_SAMPLE_RATE
/2))?-1.0f
:1.0f
;
173 t
[0] = ((float)o
[0]*(1.0f
/(float)(BIRD_SAMPLE_RATE
/2)))-1.0f
- s
[0]*0.5f
;
174 t
[1] = ((float)o
[1]*(1.0f
/(float)(BIRD_SAMPLE_RATE
/2)))-1.0f
- s
[1]*0.5f
;
175 t
[2] = ((float)o
[2]*(1.0f
/(float)(BIRD_SAMPLE_RATE
/2)))-1.0f
- s
[2]*0.5f
;
176 t
[3] = ((float)o
[3]*(1.0f
/(float)(BIRD_SAMPLE_RATE
/2)))-1.0f
- s
[3]*0.5f
;
188 v
[0] = s
[0]*(5.0f
*t2
[0]-4.0f
*t4
[0]-1.0f
);
189 v
[1] = s
[1]*(5.0f
*t2
[1]-4.0f
*t4
[1]-1.0f
);
190 v
[2] = s
[2]*(5.0f
*t2
[2]-4.0f
*t4
[2]-1.0f
);
191 v
[3] = s
[3]*(5.0f
*t2
[3]-4.0f
*t4
[3]-1.0f
);
194 static float saw_1second_1( int o
)
196 float t
= ((float)o
*(1.0f
/(float)(BIRD_SAMPLE_RATE
/2)))-1.0f
,
200 return -2.5f
*ttt
+2.5f
*t
;
203 static u32
synth_bird_get_length_in_samples( struct synth_bird
*bird
)
207 for( int i
=0; i
<bird
->settings
.pattern_length
; i
++ ){
208 struct synth_bird_signature
*sig
= &bird
->settings
.pattern
[i
];
210 u32 l
= sig
->length
* (float)BIRD_SAMPLE_RATE
,
211 p
= sig
->pause
* (float)BIRD_SAMPLE_RATE
;
219 static void synth_bird_reset( struct synth_bird
*bird
)
221 bird
->rt
.osc_main
[0] = 0;
222 bird
->rt
.osc_main
[1] = 0;
223 bird
->rt
.osc_main
[2] = 0;
224 bird
->rt
.osc_main
[3] = 0;
225 bird
->rt
.osc_lfo
= 0;
227 bird
->rt
.volume
[0] = 0.0f
;
228 bird
->rt
.volume
[1] = 0.0f
;
229 bird
->rt
.volume
[2] = 0.0f
;
230 bird
->rt
.volume
[3] = 0.0f
;
232 bird
->rt
.fundamental
= 0.0f
;
234 bird
->rt
.length
= bird
->settings
.pattern
[0].length
* (float)BIRD_SAMPLE_RATE
;
239 bird
->rt
.fm_depth
= 0.0f
;
241 bird
->rt
.adsr_rise
= bird
->settings
.adsr_rise
* (float)BIRD_SAMPLE_RATE
;
242 bird
->rt
.adsr_fall
= bird
->settings
.adsr_fall
* (float)BIRD_SAMPLE_RATE
;
245 static u32
synth_bird_save_size( struct synth_bird
*bird
)
247 return sizeof(struct synth_bird_signature
) * bird
->settings
.pattern_length
+
248 sizeof(struct synth_bird_settings
);
251 static void synth_bird_save( struct synth_bird
*bird
, void *txt
)
253 void *src
= &bird
->settings
;
254 vg_bin_str( src
, txt
, synth_bird_save_size( bird
) );
258 static void synth_bird_load( struct synth_bird
*bird
,
259 const char *txt
, u32 length
)
261 vg_str_bin( txt
, &bird
->settings
, length
);
262 synth_bird_reset( bird
);
265 /* expects a null terminated string */
266 static u32
synth_bird_memory_requirement( u32 string_length
)
268 return (string_length
/2) +
269 sizeof(struct synth_bird
) - sizeof(struct synth_bird_settings
);
273 #ifdef SYNTH_BIRD_STDLIB
277 static struct synth_bird
*synth_bird_create(
278 struct synth_bird_settings
*settings
,
279 struct synth_bird_signature
*pattern
,
282 u32 pattern_size
= sizeof( struct synth_bird_signature
) * pattern_length
;
283 u32 total_size
= sizeof( struct synth_bird
) + pattern_size
;
284 struct synth_bird
*bird
= malloc( total_size
);
286 bird
->settings
= *settings
;
288 memcpy( bird
->settings
.pattern
, pattern
, pattern_size
);
289 bird
->settings
.pattern_length
= pattern_length
;
291 synth_bird_reset( bird
);
297 static void synth_bird_think( struct synth_bird
*bird
)
299 struct synth_bird_signature
*sig
= &bird
->settings
.pattern
[ bird
->rt
.frame
];
302 if( bird
->rt
.x
>= bird
->rt
.length
)
304 if( bird
->rt
.gate
&& (sig
->pause
!= 0.0f
) )
307 bird
->rt
.length
= sig
->pause
* (float)BIRD_SAMPLE_RATE
;
313 if( bird
->rt
.frame
>= bird
->settings
.pattern_length
)
316 sig
= &bird
->settings
.pattern
[ bird
->rt
.frame
];
319 bird
->rt
.length
= sig
->length
* (float)BIRD_SAMPLE_RATE
;
327 bird
->rt
.adsr
+= bird
->rt
.adsr_rise
;
328 if( bird
->rt
.adsr
> BIRD_SAMPLE_RATE
)
329 bird
->rt
.adsr
= BIRD_SAMPLE_RATE
;
333 bird
->rt
.adsr
-= bird
->rt
.adsr_fall
;
334 if( bird
->rt
.adsr
< 0 )
340 float l
= (float)bird
->rt
.length
,
341 t
= ((float)bird
->rt
.x
* (1.0f
/l
))*2.0f
- 1.0f
,
345 bird
->rt
.fundamental
= sig
->x0
+ t
*sig
->x1
+ tt
*sig
->x2
+ ttt
*sig
->x3
;
348 float vol
= (float)bird
->rt
.adsr
* (1.0f
/(float)BIRD_SAMPLE_RATE
);
350 bird
->rt
.fm_depth
= sig
->fm
;
351 bird
->rt
.lfo_hz
= sig
->lfo_hz
;
352 bird
->rt
.volume
[0] = sig
->v0
* vol
;
353 bird
->rt
.volume
[1] = sig
->v1
* vol
;
354 bird
->rt
.volume
[2] = sig
->v2
* vol
;
355 bird
->rt
.volume
[3] = sig
->v3
* vol
;
358 static inline void int_add_mod( int *a
, int const b
)
362 if( *a
> BIRD_SAMPLE_RATE
)
363 *a
-= BIRD_SAMPLE_RATE
;
366 static void synth_bird_generate_samples( struct synth_bird
*bird
,
367 float *stereo_buffer
, int samples
)
369 for( int _
=0; _
<samples
; _
++ )
371 synth_bird_think( bird
);
373 int_add_mod( &bird
->rt
.osc_lfo
, bird
->rt
.lfo_hz
);
374 float fm
= sine_1second_1( bird
->rt
.osc_lfo
) * bird
->rt
.fm_depth
;
376 int freq
= bird
->rt
.fundamental
+ fm
;
379 (freq
* bird
->settings
.tones
[0][0]) / bird
->settings
.tones
[0][1],
380 (freq
* bird
->settings
.tones
[1][0]) / bird
->settings
.tones
[1][1],
381 (freq
* bird
->settings
.tones
[2][0]) / bird
->settings
.tones
[2][1],
382 (freq
* bird
->settings
.tones
[3][0]) / bird
->settings
.tones
[3][1],
385 int_add_mod( bird
->rt
.osc_main
+ 0, hz
[0] );
386 int_add_mod( bird
->rt
.osc_main
+ 1, hz
[1] );
387 int_add_mod( bird
->rt
.osc_main
+ 2, hz
[2] );
388 int_add_mod( bird
->rt
.osc_main
+ 3, hz
[3] );
391 sine_1second_4( bird
->rt
.osc_main
, v
);
393 float s
= v
[0] * bird
->rt
.volume
[0] +
394 v
[1] * bird
->rt
.volume
[1] +
395 v
[2] * bird
->rt
.volume
[2] +
396 v
[3] * bird
->rt
.volume
[3] ;
398 stereo_buffer
[ _
*2+0 ] = s
;
399 stereo_buffer
[ _
*2+1 ] = s
;
403 #ifdef SYNTH_BIRD_STDLIB
406 #define KNRM "\x1B[00m"
407 #define KRED "\x1B[31m"
408 #define KGRN "\x1B[32m"
409 #define KYEL "\x1B[33m"
410 #define KBLU "\x1B[34m"
411 #define KMAG "\x1B[35m"
412 #define KCYN "\x1B[36m"
413 #define KWHT "\x1B[37m"
415 #define LOG_BAR0 " . |"
416 #define LOG_BAR1 "-------+-------+-------+-------+"
419 static void synth_bird_log_pattern( struct synth_bird
*bird
)
421 synth_bird_reset( bird
);
423 char output
[][400]= {
424 KNRM
"9k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
425 KNRM
" -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
426 KNRM
"8k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
427 KNRM
" -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
428 KNRM
"7k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
429 KNRM
" -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
430 KMAG
"6k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
431 KMAG
" -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
432 KCYN
"5k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
433 KCYN
" -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
434 KBLU
"4k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
435 KBLU
" -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
436 KGRN
"3k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
437 KGRN
" -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
438 KYEL
"2k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
439 KYEL
" -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
440 KRED
"1k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
441 KRED
" -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0
,
442 KWHT
" +" LOG_BAR1 LOG_BAR1 LOG_BAR1 LOG_BAR1 LOG_BAR1
443 KWHT
" 0.0s"LOG_BAR2
"0.5s"LOG_BAR2
"1.0s"LOG_BAR2
"1.5s"LOG_BAR2
"2.0s"LOG_BAR2
446 for( int i
=0; i
<190*8; i
++ )
448 for( int j
=0; j
<BIRD_SAMPLE_RATE
/(32*8*2); j
++ )
449 synth_bird_think( bird
);
451 float hz
= bird
->rt
.fundamental
/ 500.0f
;
458 float level
= bird
->rt
.adsr
;
459 level
*= (1.0f
/(float)BIRD_SAMPLE_RATE
);
464 output
[j
][(i
/8)+7] = " *###"[ch
];
467 for( int i
=0; i
<20; i
++ )
474 #endif /* VG_AUDIO_SYNTH_BIRD_H */