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