--- /dev/null
+synth_bird__warbling_vireo:
+BAAAAAAABAAAAAAAGAAAAAAAFAAAAAAAIAAAAAAAHAAAAAAANAAAAAAAMAAAAAAAILFMNGKDDJLJEBLDAAAAAAAAMAAAAAAAILOBFAODNMMMMMNDAAAAKHFEAAAAIMCEAAAAIMCEAAAAAAAAAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAIEDENMMMMMNDNMMMMENDAAAEDIFEAAAAKPDMAAAIENEEAAAAAAAAAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAAMCENMMMMMNDAAAAAAAAAAAAGBFEAAAAGJEMAAAAKHEEAAAIENEEAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAAMCEPICMFHNDKAHNDCNDAAAMBEFEAAAAIEDEAAAAACBMAAAIJIEMAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAELCEILOBFAODJCMFPINDAAAMPIFEAAAAKPEMAAAAAAAAAAAICKEEAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAACBENMMMMENDAAAAAAAAAAAMICFEAAAAGJDMAAAAPCEEAAAAIEEEAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAACBEMOBFILNDJCMFPINDAAAABGFEAAAAGJDMAAAAAAAAAAAAAAAAAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAAKBENMMMMENDJCMFPINDAAAAGJFEAAAALJEEAAAAGJDEAAAAAAAAAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAAKBEKAHNDKNDKAHNDKMDAAAMICFEAAAAIEEMAAAAGBDEAAAAKHEEAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAACDEPICMFPNDKAHNDKNDAAAMICFEAAAAIEEMAAAAGBDEAAAAKHEEAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAACDENMMMMMNDKAHNDCNDAAAOEMFEAAAAIMCMAAAAIEFMAAAAKHEEAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAIMCEKAHNDCODNMMMMMNDAAACFIFEAAAAIEDMAAAAGJDEAAAIJIEEAAAAAIPDAAAAAAPDNMMMMEODAAAAAAODMDAAAAAAAAAAAKBE
+
+synth_bird__pied_monarch:
+BAAAAAAABAAAAAAAGAAAAAAAFAAAAAAAIAAAAAAAHAAAAAAANAAAAAAAMAAAAAAAILFMNGKDDJLJEBLDAAAAAAAAMAAAAAAAMOBFIDODILOBFAODAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAAKJJJJBPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAALHEBOCODPICMFPNDAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAANMMMMEPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAAKAHNDCODOKHEBONDAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAAGGGGGGPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAAJCMFPAODMOBFILNDAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAAAAAAAIPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAAPICMFPNDJCMFPINDAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAAAAAAAIPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAAOKHEBONDPICMFHNDAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAAAAAAAIPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAANMMMMMNDNMMMMENDAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAAAAAAAIPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAANMMMMMNDNMMMMENDAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAAAAAAAIPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAANMMMMMNDNMMMMENDAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAAAAAAAIPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAANMMMMMNDNMMMMENDAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAAAAAAAIPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAANMMMMMNDNMMMMENDAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAAAAAAAIPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAANMMMMMNDNMMMMMNDAAAIJAFEAAAAPCEEAAAAGJDMAAAAAAAAAAAAAIPDNMMMMENDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAAAA
+
+synth_bird__bridled_honeyeater:
+BAAAAAAABAAAAAAAGAAAAAAAFAAAAAAAIAAAAAAAHAAAAAAANAAAAAAAMAAAAAAAILFMNGKDDJLJEBLDAAAAAAAAKAAAAAAANMMMMMNDNMMMMMNDAAAAKPEEAAAAKHEMAAAAGBEEAAAAAAAAAAAAAIPDAAAAAAAAAAAAAAAAAAAAAAAAOBAAAAAAAAAAAHCENMMMMMNDNMMMMMNDAAAAKHFEAAAAAAAAAAAAIEDMAAAAIEDMNMMMMEPDAAAAAIODAAAAAIODAAAAAIODOBAAAAAAAAAAAHCEPICMFHNDKAHNDCMDAAAAKHFEAAAAAAAAAAAAPCEMAAAAIEEMGGGGGGPDNMMMMMNDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAKBEJCMFPINDKAHNDCMDAAAOGHFEAAAAAAAAAAAAPCEMAAAAIEEMGGGGGGPDNMMMMMNDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAKBEKAHNDKNDKAHNDCMDAAAMDHFEAAAAAAAAAAAAPCEMAAAAIEEMGGGGGGPDNMMMMMNDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAKBEMOBFILNDKAHNDCMDAAAKAHFEAAAAAAAAAAAAPCEMAAAAIEEMGGGGGGPDNMMMMMNDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAKBENMMMMMNDKAHNDKMDAAAINGFEAAAAAAAAAAAAPCEMAAAAIEEMGGGGGGPDNMMMMEODNMMMMMNDAAAAAAAAMDAAAAAAAAAAAKBEOKHEBONDNMMMMENDAAAGKGFEAAAAAAAAAAAAPCEMAAAAIEEMGGGGGGPDNMMMMMODNMMMMEODAAAAAAAAMDAAAAAAAAAAAKBEPICMFPNDNMMMMEODAAAEHGFEAAAAAAAAAAAAPCEMAAAAIEEMKJJJJJODNMMMMMNDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAKBENMMMMMNDNMMMMMNDAAAICCFEAAAICKEEAAAAGBEEAAAAAAAAMOBFIHPDPICMFPMDAAAAAAAAAAAAAAAAMDAAAAAAAAAAAKBE
+
+synth_bird__cricket:
+BAAAAAAABAAAAAAAGAAAAAAAFAAAAAAAIAAAAAAAHAAAAAAANAAAAAAAMAAAAAAAILFMNGKDDJLJEBLDAAAAAAAAKAAAAAAANMMMMMNDKJJJJBODAAAEMJFEAAAAAAAAAAAAAAAAAAAAIMCEAAAAAIODAAAAAIODAAAAAIODAAAAAIODICAAAAAAAAAAIEDEOKHEBONDJCMFPAODAAAEMJFEAAAAAAAAAAAAAAAAAAAAIMCEAAAAAIODAAAAAIODAAAAAIODAAAAAIODICAAAAAAAAAAIEDEILOBFAODKJJJJBODAAAEMJFEAAAAAAAAAAAAAAAAAAAAIMCEAAAAAIODAAAAAIODAAAAAIODAAAAAIODICAAAAAAAAAAIEDEMOBFILNDKAHNDCODAAAEMJFEAAAAAAAAAAAAAAAAAAAAIMCEAAAAAIODAAAAAIODAAAAAIODAAAAAIODICAAAAAAAAAAIEDENMMMMMNDPICMFPNDAAAEMJFEAAAAAAAAAAAAAAAAAAAAIMCEAAAAAIODAAAAAIODAAAAAIODAAAAAIODICAAAAAAAAAAIEDENMMMMMNDKJJJJBODAAAEMJFEAAAAAAAAAAAAAAAAAAAAIMCEAAAAAIODAAAAAIODAAAAAIODAAAAAIODICAAAAAAAAAAIEDEOKHEBONDJCMFPAODAAAEMJFEAAAAAAAAAAAAAAAAAAAAIMCEAAAAAIODAAAAAIODAAAAAIODAAAAAIODICAAAAAAAAAAIEDEILOBFAODKJJJJBODAAAEMJFEAAAAAAAAAAAAAAAAAAAAIMCEAAAAAIODAAAAAIODAAAAAIODAAAAAIODICAAAAAAAAAAIEDEMOBFILNDKAHNDCODAAAEMJFEAAAAAAAAAAAAAAAAAAAAIMCEAAAAAIODAAAAAIODAAAAAIODAAAAAIODICAAAAAAAAAAIEDENMMMMMNDPICMFPNDAAAEMJFEAAAAAAAAAAAAAAAAAAAAIMCEAAAAAIODAAAAAIODAAAAAIODAAAAAIODICAAAAAAAAAAIEDE
+
+synth_bird__gray_shrikethrush:
+BAAAAAAABAAAAAAAGAAAAAAAFAAAAAAAIAAAAAAAHAAAAAAANAAAAAAAMAAAAAAAILFMNGKDDJLJEBLDAAAAAAAABAAAAAAAILOBFAODNMMMMMNDAAAICCFEAAAAIEDMAAAAIMCMAAAAIEDEGGGGGGPDNMMMMMNDNMMMMENDPGCBDIKDMDAAAAAAAAAAACBE
+
+synth_bird__boobook:
+BAAAAAAABAAAAAAAGAAAAAAAFAAAAAAAIAAAAAAAHAAAAAAANAAAAAAAMAAAAAAAILFMNGKDDJLJEBLDAAAAAAAACAAAAAAAKJJJJJODJCMFPAODAAAAPCEEAAAAAAAAAAAAIMCMAAAAIMCEGGGGGGPDJCMFPAODAAAAAAAANMMMMEODOBAAAAAAAAAAAJBEKJJJJJODKJJJJJPDAAAINBEEAAAAAAAAAAAAIMCMAAAAIMCEGGGGGGPDAAAAAAAAKJJJJJODAAAAAAAAOBAAAAAAAAAAAJBE
+
+synth_bird__shrike_tit:
+BAAAAAAABAAAAAAAGAAAAAAAFAAAAAAAIAAAAAAAHAAAAAAANAAAAAAAMAAAAAAAILFMNGKDDJLJEBLDAAAAAAAABAAAAAAAKJJJJBPDDDDDDLPDAAAMPAFEAAAAGJDMAAAAIMCMAAAAIMCEAAAAAIPDJCMFPAODAAAAAAAANMMMMMNDMDAAAAAAAAAAAKAE
+
#include "stdlib.h"
#include "math.h"
-/* Birds sounds
- * TODO: THis can be embedded using 'song strings' in the path field of a sound
- * entity for skaterift/vg. and the generation algorthm be placed in the
- * decode section. will need to find a place to store its memory, though.
- *
- * */
+#define SYNTH_BIRD_STDLIB
+#include "vg_audio_synth_bird.h"
#define WRAP1S( X ) (X)%44100
-
/*
* clang birds.c -lm -o birds && ./birds | aplay -f cd /dev/stdin
*
*
*/
-//#define RANDOM_BIRD
-//#define SINE_ACCURATE
-
-#ifdef SINE_ACCURATE
-static float sine_44100_1( int o )
-{
- float t = (float)o*(1.0f/44100.0f);
- return sinf(t*6.28318530717958647692528676655900576);
-}
-
-static void sine_44100_4( int o[4], float v[4] )
-{
- v[0] = sine_44100_1( o[0] );
- v[1] = sine_44100_1( o[1] );
- v[2] = sine_44100_1( o[2] );
- v[3] = sine_44100_1( o[3] );
-}
-#else
-
-/* sine functions over the range [0, 44100] : [-pi, pi].
- * Not accurate! */
-
-static float sine_44100_1( int o )
-{
- float s = (o<22050)?-1.0f:1.0f;
- float t = ((float)o*(1.0f/22050.0f))-1.0f - s*0.5f;
- float t2 = t*t;
- float t4 = t2*t2;
- return s*(5.0f*t2-4.0f*t4-1.0f);
-}
-
-static void sine_44100_4( int o[4], float v[4] )
-{
- float s[4],t[4],t2[4],t4[4];
- s[0] = (o[0]<22050)?-1.0f:1.0f;
- s[1] = (o[1]<22050)?-1.0f:1.0f;
- s[2] = (o[2]<22050)?-1.0f:1.0f;
- s[3] = (o[3]<22050)?-1.0f:1.0f;
-
- t[0] = ((float)o[0]*(1.0f/22050.0f))-1.0f - s[0]*0.5f;
- t[1] = ((float)o[1]*(1.0f/22050.0f))-1.0f - s[1]*0.5f;
- t[2] = ((float)o[2]*(1.0f/22050.0f))-1.0f - s[2]*0.5f;
- t[3] = ((float)o[3]*(1.0f/22050.0f))-1.0f - s[3]*0.5f;
-
- t2[0] = t[0]*t[0];
- t2[1] = t[1]*t[1];
- t2[2] = t[2]*t[2];
- t2[3] = t[3]*t[3];
-
- t4[0] = t2[0]*t2[0];
- t4[1] = t2[1]*t2[1];
- t4[2] = t2[2]*t2[2];
- t4[3] = t2[3]*t2[3];
-
- v[0] = s[0]*(5.0f*t2[0]-4.0f*t4[0]-1.0f);
- v[1] = s[1]*(5.0f*t2[1]-4.0f*t4[1]-1.0f);
- v[2] = s[2]*(5.0f*t2[2]-4.0f*t4[2]-1.0f);
- v[3] = s[3]*(5.0f*t2[3]-4.0f*t4[3]-1.0f);
-}
-#endif
-
-static float saw_44100_1( int o )
-{
- float t = ((float)o*(1.0f/22050.0f))-1.0f,
- tt = t*t,
- ttt = tt*t;
-
- return -2.5f*ttt+2.5f*t;
-}
-
static double rand_float( double min, double max )
{
double r = (double)(rand()&(4096-1))*(1.0/4096.0);
static void vg_dsp_init( void );
static void vg_dsp_process( float *stereo_in, float *stereo_out );
-struct synth_bird
+static void write_profile( FILE *fp, struct synth_bird_settings *settings,
+ struct synth_bird_signature *pattern,
+ u32 pattern_count, const char *name )
{
- int harmonic_4[4],
- fm_oscillator;
-
- float poly;
- int x,a,l,v, frame;
-
- int pattern_length;
- struct synth_bird_signature
- {
- float c0, c1, c2, c3, length, pause, h0, h1, h2, h3;
+ struct synth_bird *bird =
+ synth_bird_create( settings, pattern, pattern_count );
- int lfo_hz;
- float fm; /* lfo modulation depth (+/- hz) */
- }
- pattern[];
-};
+ u32 size = synth_bird_save_size( bird );
+ char save[ size*2 ];
+ synth_bird_save( bird, save );
-static int birdsynth_pattern_count_signatures( const char *pattern )
-{
- /* {200,5000,1000,200,20,10,30,200}, {...} */
-
- int signatures = 0;
-
- const char *c = pattern;
- while( *c )
- {
- if( *c == '{' )
- signatures ++;
-
- c ++;
- }
-
- return signatures;
+ fprintf( fp, "%s:\n%.*s\n\n", name, size*2, save );
}
-static void birdsynth_pattern_decode( struct synth_bird *bird,
- const char *pattern )
+#define _PROFILE( FP, SETTINGS, ARRAY ) \
+ write_profile( FP, SETTINGS, ARRAY, sizeof(ARRAY)/sizeof(ARRAY[0]), \
+ #ARRAY )
+
+static void export_all_profiles(void)
{
- bird->pattern_length = 0;
+ FILE *fp = fopen( "bird_profiles.txt", "w" );
- const char *c = pattern;
- while( *c )
- {
- if( *c == '{' )
- {
- struct synth_bird_signature *sig =
- &bird->pattern[ bird->pattern_length ++ ];
-
- sig->c0 = 3000.0f;
- sig->c1 = -800.0f;
- sig->c2 = 1500.0f;
- sig->c3 = -860.0f;
- sig->length = 0.5f;
- sig->pause = 0.1f;
- sig->lfo_hz = 30;
- sig->fm = 10.0f;
- sig->h0 = 1.0f;
- sig->h1 = 0.5f;
- sig->h2 = 0.2f;
- sig->h3 = 0.125f;
-
- sscanf( c, "{%f,%f,%f,%f,%d,%f,%f,%f,%f,%f,%f,%f}",
- &sig->c0, &sig->c1, &sig->c2, &sig->c3,
- &sig->lfo_hz, &sig->fm, &sig->length, &sig->pause,
- &sig->h0, &sig->h1, &sig->h2, &sig->h3 );
- }
-
- c ++;
- }
-}
+ struct synth_bird_settings *settings = &synth_bird__default_settings;
-static struct synth_bird *birdsynth_malloc_create( const char *pattern )
-{
- int s = birdsynth_pattern_count_signatures( pattern );
- if( s == 0 )
- s = 1;
-
- struct synth_bird *bird = malloc( sizeof(struct synth_bird) +
- s * sizeof(struct synth_bird_signature) );
-
- birdsynth_pattern_decode( bird, pattern );
-
- bird->harmonic_4[0] = 0;
- bird->harmonic_4[1] = 0;
- bird->harmonic_4[2] = 0;
- bird->harmonic_4[3] = 0;
- bird->fm_oscillator = 0;
- bird->poly = 0.0f;
- bird->x = 0;
- bird->a = 1;
- bird->l = bird->pattern[0].length * 44100.0f;
- bird->v = 0;
- bird->frame = 0;
-
- return bird;
-}
+ _PROFILE( fp, settings, synth_bird__warbling_vireo );
+ _PROFILE( fp, settings, synth_bird__pied_monarch );
+ _PROFILE( fp, settings, synth_bird__bridled_honeyeater );
+ _PROFILE( fp, settings, synth_bird__cricket );
+ _PROFILE( fp, settings, synth_bird__gray_shrikethrush );
+ _PROFILE( fp, settings, synth_bird__boobook );
+ _PROFILE( fp, settings, synth_bird__shrike_tit );
-static void synthbird_generate_samples( struct synth_bird *bird,
- float *stereo_buffer, int samples )
-{
- for( int _=0; _<samples; _++ )
- {
- bird->x ++;
- if( bird->x >= bird->l )
- {
- if( bird->a && (bird->pattern[bird->frame].pause!=0.0f) )
- {
- bird->a = 0;
- bird->l = bird->pattern[ bird->frame ].pause * 44100.0f;
- }
- else
- {
- bird->frame ++;
-
- if( bird->frame >= bird->pattern_length )
- bird->frame = 0;
-
- bird->a = 1;
- bird->l = bird->pattern[ bird->frame ].length * 44100.0f;
- }
-
- bird->x = 0;
- }
-
- if( bird->a )
- {
- bird->v += 40;
- if( bird->v > 44100 ) bird->v = 44100;
- }
- else
- {
- bird->v -= 100;
- if( bird->v < 0 ) bird->v = 0;
- }
-
- struct synth_bird_signature *sig = &bird->pattern[ bird->frame ];
-
- float level = bird->v;
- level *= (1.0f/44100.0f);
-
- if( bird->a )
- {
- float t = ((float)bird->x * (1.0f/(float)bird->l))*2.0f - 1.0f,
- tt = t*t,
- ttt = tt*t;
-
- bird->poly = sig->c0 + t*sig->c1 + tt*sig->c2 + ttt*sig->c3;
- }
-
- bird->fm_oscillator = WRAP1S( bird->fm_oscillator + sig->lfo_hz );
- float fm = sine_44100_1( bird->fm_oscillator ) * sig->fm;
-
- int freq = bird->poly + fm;
- bird->harmonic_4[0] = WRAP1S( bird->harmonic_4[0] + (freq*1) );
- bird->harmonic_4[1] = WRAP1S( bird->harmonic_4[1] + (freq*6)/5 );
- bird->harmonic_4[2] = WRAP1S( bird->harmonic_4[2] + (freq*8)/7 );
- bird->harmonic_4[3] = WRAP1S( bird->harmonic_4[3] + (freq*13)/12 );
-
- float v[4];
- sine_44100_4( bird->harmonic_4, v );
- float s = v[0] * sig->h0 +
- v[1] * sig->h1 +
- v[2] * sig->h2 +
- v[3] * sig->h3 ;
-
- s *= level;
-
- stereo_buffer[ _*2+0 ] = s;
- stereo_buffer[ _*2+1 ] = s;
- }
+ fclose( fp );
}
int main( int argc, char *argv[] )
{
vg_dsp_init();
-#if RANDOM_BIRD
- int f0=4500, o1=0, f1=30;
- int adsr=0;
-
- int o0[4]={0,0,0,0};
-
- float c0=0.0f, c1=0.0f, c2=0.0f, c3=0.0f; /* signature coefficients */
- int l=44100/2, /* length of thing */
- x=0, /* frame of thing */
- a=0; /* 0: silence 1: signature */
-
- float poly=0.0f;
-
- for(int _=0;_<44100*30;_++){
- x ++;
- if( x >= l ){ /* do new thing */
- if( a ){
- int retrigger = rand() % 4;
- a=0;
- if( retrigger ) l=rand_seconds(0.03,0.1);
- else l=rand_seconds(0.5,10.0);
- }
- else{
- c0=rand_float(-1.0,1.0);
- c1=rand_float(-1.0,1.0);
- c2=rand_float(-0.1,0.1);
- c3=rand_float(-0.5,1.5);
- l=rand_seconds(0.05,0.5);
- a=1;
- }
- x=0;
- }
-
- if(a){
- adsr += 40;
- if( adsr > 44100 ) adsr = 44100;
- }
- else{
- adsr -= 40;
- if( adsr < 0 ) adsr = 0;
- }
-
- o1 += f1;
- o1 = o1 % 44100;
-
- float s1 = sine_44100_1( o1 );
- float level = adsr;
- level *= (1.0f/44100.0f);
-
- if( a )
- {
- float t = ((float)x * (1.0f/(float)l))*2.0f - 1.0f,
- tt = t*t,
- ttt = tt*t;
-
- poly = c0+t*c1+tt*c2+ttt*c3;
- }
-
- int fm = s1*100.0f*(1.0f+poly*0.5f) + poly*500.0f;
-
- int ff = f0+fm;
- o0[0] = WRAP1S( o0[0] + ff*1 );
- o0[1] = WRAP1S( o0[1] + ff*2 );
- o0[2] = WRAP1S( o0[2] + ff*3 );
- o0[3] = WRAP1S( o0[3] + ff*4 );
-
- float v[4];
- sine_44100_4( o0, v );
- float s0 = v[0] +
- v[1] * 0.5f +
- v[2] * 0.25f +
- v[3] * 0.125f;
- s0 *= level;
-
- float stereo[2] = { s0, s0 };
- vg_dsp_process( stereo, stereo );
-
- int16_t l = stereo[0] * 10000.0f,
- r = stereo[1] * 10000.0f;
+ export_all_profiles();
- fwrite( &l, 2,1, stdout );
- fwrite( &r, 2,1, stdout );
- }
-#else
-
- struct synth_bird *warbling_vireo = birdsynth_malloc_create(
- "{4000,100,100,0,60,200,0.134,0.1}," /* 1 */
- "{4200,-500,1700,0,60,96,0.1,0.05}," /* 2 */
- "{2400,-1200,1000,1700,60,96,0.1,0.0}," /* 3 */
- "{3100,200,-10,-1100,60,90,0.06,0.04}," /* 4 */
- "{4600,-2000,0,1300,60,10,0.13,0.07}," /* 5 */
- "{2700,-300,700,800,60,10,0.05,0.0}," /* 6 */
- "{3600,-300,0,0,60,20,0.09,0.07}," /* 7 */
- "{4800,1240,300,0,60,20,0.05,0.07}," /* 8 */
- "{2700,-800,150,1000,60,160,0.08,0.02}," /* 9 */
- "{2700,-800,150,1000,60,160,0.12,0.08}," /* 10 */
- "{6300,-100,-3200,1000,60,100,0.1,0.04}," /* 11 */
- "{4260,-200,300,1100,60,20,0.16,3.0}," /* 12 */
- );
-
- struct synth_bird *pied_monarch = birdsynth_malloc_create(
- "{2200,700,-300,0,60,0,0.18,0.13, 0.6,0.05,0,0},"
- "{2200,700,-300,0,60,0,0.17,0.12, 0.8,0.05,0,0},"
- "{2200,700,-300,0,60,0,0.16,0.11, 0.9,0.05,0,0},"
- "{2200,700,-300,0,60,0,0.14,0.09, 1,0.05,0,0},"
- "{2200,700,-300,0,60,0,0.12,0.07, 1,0.05,0,0},"
- "{2200,700,-300,0,60,0,0.11,0.06, 1,0.05,0,0},"
- "{2200,700,-300,0,60,0,0.10,0.05, 1,0.05,0,0},"
- "{2200,700,-300,0,60,0,0.10,0.05, 1,0.05,0,0},"
- "{2200,700,-300,0,60,0,0.10,0.05, 1,0.05,0,0},"
- "{2200,700,-300,0,60,0,0.10,0.05, 1,0.05,0,0},"
- "{2200,700,-300,0,60,0,0.10,0.05, 1,0.05,0,0},"
- "{2200,700,-300,0,60,0,0.10,6.05, 1,0.05,0,0},"
- );
-
- struct synth_bird *bridled_honeyeater = birdsynth_malloc_create(
- "{2000,-1000,600,0,30,60,0.1,0.1, 1.0,0.0,0.0,0.0},"
- "{4000,0,-200,-200,30,60,0.1,0.1, 0.8,0.25,0.25,0.25},"
- "{4000,0,-700,-800,60,20,0.06,0.01, 0.9,0.1,0,0},"
- "{3950,0,-700,-800,60,20,0.07,0.01, 0.9,0.1,0,0},"
- "{3900,0,-700,-800,60,20,0.08,0.01, 0.9,0.1,0,0},"
- "{3850,0,-700,-800,60,20,0.09,0.01, 0.9,0.1,0,0},"
- "{3800,0,-700,-800,60,20,0.10,0.02, 0.9,0.2,0.1,0},"
- "{3750,0,-700,-800,60,20,0.11,0.05, 0.9,0.4,0.2,0},"
- "{3700,0,-700,-800,60,20,0.12,0.2, 0.3,0.1,0,0},"
- "{2600,1300,600,0,60,20,0.1,4.0, 0.97,0.03,0,0},"
- );
+ struct synth_bird *warbling_vireo =
+ synth_bird_create( &synth_bird__default_settings,
+ synth_bird__warbling_vireo,
+ sizeof(synth_bird__warbling_vireo)/
+ sizeof(struct synth_bird_signature) );
for(;;){
float stereo[2] = { 0.0f, 0.0f };
float b[2];
- synthbird_generate_samples( pied_monarch, b, 1 );
- stereo[0] += b[0] * 0.4f;
- stereo[1] += b[1] * 0.3f;
-
- synthbird_generate_samples( warbling_vireo, b, 1 );
- stereo[0] += b[0] * 0.5f;
- stereo[1] += b[1] * 0.4f;
-
- synthbird_generate_samples( bridled_honeyeater, b, 1 );
- stereo[0] += b[0] * 0.6f;
- stereo[1] += b[1] * 0.6f;
+ synth_bird_generate_samples( warbling_vireo, b, 1 );
+ stereo[0] += b[0];
+ stereo[1] += b[1];
+#if 0
vg_dsp_process( stereo, stereo );
+#endif
- int16_t l = stereo[0] * 10000.0f,
- r = stereo[1] * 10000.0f;
+ int16_t l = stereo[0] * 14000.0f,
+ r = stereo[1] * 14000.0f;
fwrite( &l, 2,1, stdout );
fwrite( &r, 2,1, stdout );
}
-#endif
}
for( int i=0; i<8; i++ )
dsp_write_delay( __echos+i, &total );
- stereo_out[0] = stereo_in[0]*0.1f;
- stereo_out[1] = stereo_in[1]*0.1f;
- stereo_out[0] += diffused*0.4f+recieved*0.9f;
- stereo_out[1] += diffused*0.4f+recieved*0.9f;
+ stereo_out[0] = stereo_in[0]*0.5f;
+ stereo_out[1] = stereo_in[1]*0.5f;
+ stereo_out[0] += diffused*0.8f+recieved*0.9f;
+ stereo_out[1] += diffused*0.8f+recieved*0.9f;
}
--- /dev/null
+#include "../vg_platform.h"
+
+
+struct yo
+{
+ float a, b, c, d;
+};
+
+int main( int argc, const char *argv[] )
+{
+ struct yo yo = { 300.324, 2023.334, -324.1232, 30.494 };
+ printf( "{%f %f %f %f}\n", yo.a, yo.b, yo.c, yo.d );
+
+ char text[ sizeof(yo)*2 ];
+ vg_bin_str( &yo, text, sizeof(yo) );
+
+ printf( "encoded: %.*s\n", (int)(sizeof(yo)*2), text );
+
+ vg_str_bin( text, &yo, sizeof(yo)*2 );
+
+ printf( "{%f %f %f %f}\n", yo.a, yo.b, yo.c, yo.d );
+}
-Subproject commit 06492c598158cf825a18aececaf7511d7fd04f48
+Subproject commit eef4d3c86a653f91b7221c80809ba8ab56f94cf1
#include "vg/vg_console.h"
#include "vg/vg_store.h"
#include "vg/vg_profiler.h"
+#include "vg/vg_audio_synth_bird.h"
#include <sys/time.h>
#include <math.h>
/* Vorbis will ALWAYS use the maximum amount of channels it can */
//#define AUDIO_FLAG_MONO 0x100 NOTE: This is the default, so its not used
-#define AUDIO_FLAG_STEREO 0x200
-#define AUDIO_FLAG_VORBIS 0x400
+//#define AUDIO_FLAG_STEREO 0x200
+//#define AUDIO_FLAG_VORBIS 0x400
+//#define AUDIO_FLAG_BIRD_SYNTH 0x800
+
+#define AUDIO_FLAG_FORMAT 0x1E00
+
+enum audio_format
+{
+ k_audio_format_mono = 0x000u,
+ k_audio_format_stereo = 0x200u,
+ k_audio_format_vorbis = 0x400u,
+ k_audio_format_none0 = 0x600u,
+ k_audio_format_none1 = 0x800u,
+ k_audio_format_none2 = 0xA00u,
+ k_audio_format_none3 = 0xC00u,
+ k_audio_format_none4 = 0xE00u,
+
+ k_audio_format_bird = 0x1000u,
+ k_audio_format_none5 = 0x1200u,
+ k_audio_format_none6 = 0x1400u,
+ k_audio_format_none7 = 0x1600u,
+ k_audio_format_none8 = 0x1800u,
+ k_audio_format_none9 = 0x1A00u,
+ k_audio_format_none10 = 0x1C00u,
+ k_audio_format_none11 = 0x1E00u,
+};
#define AUDIO_DECODE_SIZE (1024*256) /* 256 kb decoding buffers */
#define AUDIO_MUTE_VOLUME 0.0f
u32 volume_movement,
pan_movement;
- stb_vorbis *vorbis_handle;
+ union
+ {
+ struct synth_bird *bird_handle;
+ stb_vorbis *vorbis_handle;
+ };
+
stb_vorbis_alloc vorbis_alloc;
enum channel_activity
int debug_ui, debug_ui_3d;
v3f listener_pos,
- listener_ears;
+ listener_ears,
+ listener_velocity;
float volume,
volume_target,
ch->source = clip;
ch->flags = flags;
ch->colour = 0x00333333;
- strcpy( ch->name, clip->path );
+
+ if( (ch->source->flags & AUDIO_FLAG_FORMAT) == k_audio_format_bird )
+ strcpy( ch->name, "[array]" );
+ else
+ strncpy( ch->name, clip->path, 31 );
ch->allocated = 1;
lfo->editble_state_write_mask |= AUDIO_EDIT_LFO_PERIOD;
}
+
+
/*
* Committers
* -----------------------------------------------------------------------------
*/
static int audio_channel_load_source( audio_channel *ch )
{
- if( ch->source->flags & AUDIO_FLAG_VORBIS )
+ u32 format = ch->source->flags & AUDIO_FLAG_FORMAT;
+
+ if( format == k_audio_format_vorbis )
{
/* Setup vorbis decoder */
u32 index = ch - vg_audio.channels;
ch->vorbis_handle = decoder;
}
}
- else if( ch->source->flags & AUDIO_FLAG_STEREO )
+ else if( format == k_audio_format_bird )
+ {
+ u32 index = ch - vg_audio.channels;
+
+ u8 *buf = (u8*)vg_audio.decode_buffer;
+ struct synth_bird *loc = (void *)&buf[AUDIO_DECODE_SIZE*index];
+
+ memcpy( loc, ch->source->data, ch->source->size );
+ synth_bird_reset( loc );
+
+ ch->bird_handle = loc;
+ ch->source_length = synth_bird_get_length_in_samples( loc );
+ }
+ else if( format == k_audio_format_stereo )
{
ch->source_length = ch->source->size / 2;
}
u32 remaining = count;
u32 buffer_pos = 0;
+ u32 format = ch->source->flags & AUDIO_FLAG_FORMAT;
+
while( remaining )
{
- u32 samples_this_run = VG_MIN( remaining, ch->source_length -ch->cursor );
+ u32 samples_this_run = VG_MIN(remaining, ch->source_length - ch->cursor);
remaining -= samples_this_run;
float *dst = &buf[ buffer_pos * 2 ];
- if( ch->source->flags & AUDIO_FLAG_STEREO )
+ if( format == k_audio_format_stereo )
{
for( int i=0;i<samples_this_run; i++ )
{
dst[i*2+1] = 0.0f;
}
}
- else if( ch->source->flags & AUDIO_FLAG_VORBIS )
+ else if( format == k_audio_format_vorbis )
{
int read_samples = stb_vorbis_get_samples_float_interleaved_stereo(
ch->vorbis_handle,
}
}
}
+ else if( format == k_audio_format_bird )
+ {
+ synth_bird_generate_samples( ch->bird_handle, dst, samples_this_run );
+ }
else
{
i16 *src_buffer = ch->source->data,
if( (ch->flags & AUDIO_FLAG_LOOP) && remaining )
{
- if( ch->source->flags & AUDIO_FLAG_VORBIS )
+ if( format == k_audio_format_vorbis )
stb_vorbis_seek_start( ch->vorbis_handle );
+ else if( format == k_audio_format_bird )
+ synth_bird_reset( ch->bird_handle );
ch->cursor = 0;
continue;
static void audio_channel_mix( audio_channel *ch, float *buffer )
{
- u32 buffer_length = AUDIO_MIX_FRAME_SIZE;
- if( ch->_.sampling_rate != 1.0f )
- {
- float l = ceilf( (float)(AUDIO_MIX_FRAME_SIZE) * ch->_.sampling_rate );
- buffer_length = l+1;
- }
-
- float pcf[ AUDIO_MIX_FRAME_SIZE * 2 * 2 ];
-
- audio_channel_get_samples( ch, buffer_length, pcf );
-
float framevol_l = 1.0f,
framevol_r = 1.0f;
+ float frame_samplerate = ch->_.sampling_rate;
+
if( ch->flags & AUDIO_FLAG_SPACIAL_3D )
{
if( !vg_validf(vg_audio.listener_pos[0]) ||
!vg_validf(vg_audio.listener_pos[1]) ||
!vg_validf(vg_audio.listener_pos[2]) ||
+ !vg_validf(vg_audio.listener_velocity[0]) ||
+ !vg_validf(vg_audio.listener_velocity[1]) ||
+ !vg_validf(vg_audio.listener_velocity[2]) ||
!vg_validf(ch->_.spacial_falloff[0]) ||
!vg_validf(ch->_.spacial_falloff[1]) ||
!vg_validf(ch->_.spacial_falloff[2]) )
framevol_l *= (vol * 0.5f) * (1.0f - pan);
framevol_r *= (vol * 0.5f) * (1.0f + pan);
+
+ v3_muls( delta, 1.0f/dist, delta );
+
+ const float vs = 100.0f;
+ float doppler = (vs+v3_dot(delta,vg_audio.listener_velocity))/vs;
+ doppler = vg_clampf( doppler, 0.6f, 1.4f );
+
+ if( fabsf(doppler-1.0f) > 0.01f )
+ frame_samplerate *= doppler;
+ }
+
+ u32 buffer_length = AUDIO_MIX_FRAME_SIZE;
+ if( frame_samplerate != 1.0f )
+ {
+ float l = ceilf( (float)(AUDIO_MIX_FRAME_SIZE) * frame_samplerate );
+ buffer_length = l+1;
}
+ float pcf[ AUDIO_MIX_FRAME_SIZE * 2 * 2 ];
+
+ audio_channel_get_samples( ch, buffer_length, pcf );
+
vg_profile_begin( &_vg_prof_audio_mix );
float volume_movement = ch->volume_movement;
sample_l,
sample_r;
- if( ch->_.sampling_rate != 1.0f )
+ if( frame_samplerate != 1.0f )
{
/* absolutely garbage resampling, but it will do
*/
- float sample_index = ch->_.sampling_rate * (float)j;
+ float sample_index = frame_samplerate * (float)j;
float t = vg_fractf( sample_index );
u32 i0 = floorf( sample_index ),
if( ch->editble_state_write_mask & AUDIO_EDIT_VOLUME )
+ {
ch->_.volume = ch->editable_state.volume;
+ ch->_.volume_target = ch->editable_state.volume;
+ }
else
+ {
ch->editable_state.volume = ch->_.volume;
+ }
if( ch->editble_state_write_mask & AUDIO_EDIT_VOLUME_SLOPE )
if( lin_alloc == NULL )
lin_alloc = vg_audio.audio_pool;
-
/* load in directly */
- if( clip->flags & AUDIO_FLAG_VORBIS )
+ u32 format = clip->flags & AUDIO_FLAG_FORMAT;
+
+ /* TODO: This contains audio_lock() and unlock, but i don't know why
+ * can probably remove them. Low priority to check this */
+
+ if( format == k_audio_format_vorbis )
{
audio_lock();
clip->data = vg_file_read( lin_alloc, clip->path, &clip->size );
float mb = (float)(clip->size) / (1024.0f*1024.0f);
vg_info( "Loaded audio clip '%s' (%.1fmb)\n", clip->path, mb );
}
- else if( clip->flags & AUDIO_FLAG_STEREO )
+ else if( format == k_audio_format_stereo )
{
vg_fatal_exit_loop( "Unsupported format (Stereo uncompressed)" );
}
+ else if( format == k_audio_format_bird )
+ {
+ u32 len = strlen( clip->path ),
+ size = synth_bird_memory_requirement( len );
+
+ if( size > AUDIO_DECODE_SIZE )
+ vg_fatal_exit_loop( "Bird code too long\n" );
+
+ clip->size = size;
+ clip->data = vg_linear_alloc( lin_alloc, size );
+
+ synth_bird_load( clip->data, clip->path, len );
+ }
else
{
vg_linear_clear( vg_mem.scratch );
const char *formats[] =
{
- "------",
- "Mono ",
- "Stereo",
- "Vorbis"
+ " mono ",
+ " stereo ",
+ " vorbis ",
+ " none0 ",
+ " none1 ",
+ " none2 ",
+ " none3 ",
+ " none4 ",
+ "synth:bird",
+ " none5 ",
+ " none6 ",
+ " none7 ",
+ " none8 ",
+ " none9 ",
+ " none10 ",
+ " none11 ",
};
const char *activties[] =
"error"
};
- int format_index = 0;
-
- if( ch->source->flags & AUDIO_FLAG_STEREO )
- format_index = 2;
- else if( ch->source->flags & AUDIO_FLAG_VORBIS )
- format_index = 3;
- else
- format_index = 1;
+ u32 format_index = (ch->source->flags & AUDIO_FLAG_FORMAT)>>9;
snprintf( perf, 127, "%02d %c%c%cD %s [%s] %4.2fv'%s'",
i,
ch->editable_state.volume,
ch->name );
- if( format_index == 0 )
- {
- ui_fill_rect( vg_uictx.cursor, 0xa00000ff );
- }
- else
- {
- ui_fill_rect( vg_uictx.cursor, 0xa0000000 | ch->colour );
- }
+ ui_fill_rect( vg_uictx.cursor, 0xa0000000 | ch->colour );
vg_uictx.cursor[0] += 2;
vg_uictx.cursor[1] += 2;
--- /dev/null
+#ifndef VG_AUDIO_SYNTH_BIRD_H
+#define VG_AUDIO_SYNTH_BIRD_H
+
+#include "vg_binstr.h"
+#include "vg_stdint.h"
+
+#ifndef BIRD_SAMPLE_RATE
+ #define BIRD_SAMPLE_RATE 44100
+#endif
+
+struct synth_bird_signature
+{
+ float length, pause, /* timings in seconds */
+ x0,x1,x2,x3, /* polynomial coefficients for the fundemental */
+ v0,v1,v2,v3; /* volume of each oscillator */
+
+ int lfo_hz; /* LFO frequency (30-60hz) */
+ float fm; /* LFO modulation depth (+/- hz) */
+};
+
+struct synth_bird
+{
+ struct
+ {
+ int osc_main[4],
+ osc_lfo;
+ float volume[4];
+
+ float fundamental;
+ int x, length, /* position/length of signature in samples */
+ gate, adsr, /* adsr ranges 0->44100 */
+ frame; /* current frame of the pattern */
+
+ int lfo_hz;
+ float fm_depth;
+
+ int adsr_rise,
+ adsr_fall;
+ }
+ rt;
+
+ struct synth_bird_settings
+ {
+ int tones[4][2]; /* fraction of the fundemental tone
+ for each oscillator */
+ float adsr_rise, /* rise/fall in seconds */
+ adsr_fall;
+
+ enum bird_lfo_wave
+ {
+ k_bird_lfo_sine_approx,
+ k_bird_lfo_bipolar_poly
+ }
+ type;
+
+ int pattern_length;
+ struct synth_bird_signature pattern[];
+ }
+ settings;
+};
+
+#define DEFAULT_VOL 1.0f,0.5f,0.2f,0.125f
+#define DEFAULT_TONES { {1,1}, {6,5}, {8,7}, {13,12} }
+#define DEFAULT_RISE 0.00090702947f
+#define DEFAULT_FALL 0.00226757369f
+
+static struct synth_bird_settings synth_bird__default_settings =
+{
+ .tones = DEFAULT_TONES,
+ .type = k_bird_lfo_sine_approx,
+ .adsr_rise = DEFAULT_RISE,
+ .adsr_fall = DEFAULT_FALL
+};
+
+static struct synth_bird_signature synth_bird__warbling_vireo[] =
+{
+ /* timing fundemental volumes lfo hz,depth */
+ {0.13,0.10, 4000,100,100,0, DEFAULT_VOL, 60,200 },
+ {0.10,0.05, 4200,-500,1700,0, DEFAULT_VOL, 60,96 },
+ {0.10,0.00, 2400,-1200,1000,1700, DEFAULT_VOL, 60,96 },
+ {0.06,0.04, 3100,200,-10,-1100, DEFAULT_VOL, 60,90 },
+ {0.13,0.07, 4600,-2000,0,1300, DEFAULT_VOL, 60,10 },
+ {0.05,0.00, 2700,-300,700,800, DEFAULT_VOL, 60,10 },
+ {0.09,0.07, 3600,-300,0,0, DEFAULT_VOL, 60,20 },
+ {0.05,0.07, 4800,1240,300,0, DEFAULT_VOL, 60,20 },
+ {0.08,0.02, 2700,-800,150,1000, DEFAULT_VOL, 60,160 },
+ {0.12,0.08, 2700,-800,150,1000, DEFAULT_VOL, 60,160 },
+ {0.10,0.04, 6300,-100,-3200,1000, DEFAULT_VOL, 60,100 },
+ {0.16,0.10, 4260,-200,300,1100, DEFAULT_VOL, 60,20 }
+};
+
+static struct synth_bird_signature synth_bird__pied_monarch[] =
+{
+ /* timing fundemental volumes lfo hz,depth */
+ {0.18,0.13, 2200,700,-300,0, 0.6,0.05,0,0, 60,0 },
+ {0.17,0.12, 2200,700,-300,0, 0.8,0.05,0,0, 60,0 },
+ {0.16,0.11, 2200,700,-300,0, 0.9,0.05,0,0, 60,0 },
+ {0.14,0.09, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
+ {0.12,0.07, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
+ {0.11,0.06, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
+ {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
+ {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
+ {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
+ {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
+ {0.10,0.05, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 },
+ {0.10,0.10, 2200,700,-300,0, 1.0,0.05,0,0, 60,0 }
+};
+
+static struct synth_bird_signature synth_bird__bridled_honeyeater[] =
+{
+ /* timing fundemental volumes lfo hz,depth */
+ {0.10,0.10, 2000,-1000,600,0, 1.00,0.00,0.00,0.00, 30,60},
+ {0.10,0.10, 4000,0,-200,-200, 0.80,0.25,0.25,0.25, 30,60},
+ {0.06,0.01, 4000,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
+ {0.07,0.01, 3950,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
+ {0.08,0.01, 3900,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
+ {0.09,0.01, 3850,0,-700,-800, 0.90,0.10,0.00,0.00, 60,20},
+ {0.10,0.02, 3800,0,-700,-800, 0.90,0.20,0.10,0.00, 60,20},
+ {0.11,0.05, 3750,0,-700,-800, 0.90,0.40,0.20,0.00, 60,20},
+ {0.12,0.20, 3700,0,-700,-800, 0.30,0.10,0.00,0.00, 60,20},
+ {0.10,0.10, 2600,1300,600,0, 0.97,0.03,0.00,0.00, 60,20},
+};
+
+static struct synth_bird_signature synth_bird__cricket[] =
+{
+ /* timing fundemental volumes lfo hz, depth */
+ {0.10,0.15, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
+ {0.11,0.14, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
+ {0.13,0.15, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
+ {0.09,0.16, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
+ {0.10,0.12, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
+ {0.10,0.15, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
+ {0.11,0.14, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
+ {0.13,0.15, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
+ {0.09,0.16, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200},
+ {0.10,0.12, 5000,0,0,100, 0.25,0.25,0.25,0.25, 40,200}
+};
+
+static struct synth_bird_signature synth_bird__gray_shrikethrush[] =
+{
+ /* timing fundemental volumes lfo hz, depth */
+ { 0.13,0.1, 2600,-200,-100,200, 0.9,0.1,0.05,0.001, 60,10 }
+};
+
+static struct synth_bird_signature synth_bird__boobook[] =
+{
+ /* timing fundemental volumes lfo hz, depth */
+ {0.3,0.14, 700,0,-100,100, 0.9,0.14,0.0,0.2, 30,18},
+ {0.3,1.20, 630,0,-100,100, 0.9,0.00,0.3,0.0, 30,18}
+};
+
+static struct synth_bird_signature synth_bird__shrike_tit[] =
+{
+ /* timing fundemental volumes lfo hz, depth */
+ {0.6,1.4, 2300,-300,-100,100, 1.0,0.14,0.0,0.1, 60,5 }
+};
+
+/* sine functions over the range [0, 44100] : [-pi, pi].
+ * Not accurate! */
+
+static float sine_1second_1( int o )
+{
+ float s = (o<(BIRD_SAMPLE_RATE/2))?-1.0f:1.0f;
+ float t = ((float)o*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f - s*0.5f;
+ float t2 = t*t;
+ float t4 = t2*t2;
+ return s*(5.0f*t2-4.0f*t4-1.0f);
+}
+
+static void sine_1second_4( int o[4], float v[4] )
+{
+ float s[4],t[4],t2[4],t4[4];
+ s[0] = (o[0]<(BIRD_SAMPLE_RATE/2))?-1.0f:1.0f;
+ s[1] = (o[1]<(BIRD_SAMPLE_RATE/2))?-1.0f:1.0f;
+ s[2] = (o[2]<(BIRD_SAMPLE_RATE/2))?-1.0f:1.0f;
+ s[3] = (o[3]<(BIRD_SAMPLE_RATE/2))?-1.0f:1.0f;
+
+ t[0] = ((float)o[0]*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f - s[0]*0.5f;
+ t[1] = ((float)o[1]*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f - s[1]*0.5f;
+ t[2] = ((float)o[2]*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f - s[2]*0.5f;
+ t[3] = ((float)o[3]*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f - s[3]*0.5f;
+
+ t2[0] = t[0]*t[0];
+ t2[1] = t[1]*t[1];
+ t2[2] = t[2]*t[2];
+ t2[3] = t[3]*t[3];
+
+ t4[0] = t2[0]*t2[0];
+ t4[1] = t2[1]*t2[1];
+ t4[2] = t2[2]*t2[2];
+ t4[3] = t2[3]*t2[3];
+
+ v[0] = s[0]*(5.0f*t2[0]-4.0f*t4[0]-1.0f);
+ v[1] = s[1]*(5.0f*t2[1]-4.0f*t4[1]-1.0f);
+ v[2] = s[2]*(5.0f*t2[2]-4.0f*t4[2]-1.0f);
+ v[3] = s[3]*(5.0f*t2[3]-4.0f*t4[3]-1.0f);
+}
+
+static float saw_1second_1( int o )
+{
+ float t = ((float)o*(1.0f/(float)(BIRD_SAMPLE_RATE/2)))-1.0f,
+ tt = t*t,
+ ttt = tt*t;
+
+ return -2.5f*ttt+2.5f*t;
+}
+
+static u32 synth_bird_get_length_in_samples( struct synth_bird *bird )
+{
+ u32 total = 0;
+
+ for( int i=0; i<bird->settings.pattern_length; i ++ )
+ {
+ struct synth_bird_signature *sig = &bird->settings.pattern[i];
+
+ u32 l = sig->length * (float)BIRD_SAMPLE_RATE,
+ p = sig->pause * (float)BIRD_SAMPLE_RATE;
+
+ total += l+p;
+ }
+
+ return total;
+}
+
+static void synth_bird_reset( struct synth_bird *bird )
+{
+ bird->rt.osc_main[0] = 0;
+ bird->rt.osc_main[1] = 0;
+ bird->rt.osc_main[2] = 0;
+ bird->rt.osc_main[3] = 0;
+ bird->rt.osc_lfo = 0;
+
+ bird->rt.volume[0] = 0.0f;
+ bird->rt.volume[1] = 0.0f;
+ bird->rt.volume[2] = 0.0f;
+ bird->rt.volume[3] = 0.0f;
+
+ bird->rt.fundamental = 0.0f;
+ bird->rt.x = 0;
+ bird->rt.length = bird->settings.pattern[0].length * (float)BIRD_SAMPLE_RATE;
+ bird->rt.gate = 1;
+ bird->rt.adsr = 0;
+ bird->rt.frame = 0;
+ bird->rt.lfo_hz = 0;
+ bird->rt.fm_depth = 0.0f;
+
+ bird->rt.adsr_rise = bird->settings.adsr_rise * (float)BIRD_SAMPLE_RATE;
+ bird->rt.adsr_fall = bird->settings.adsr_fall * (float)BIRD_SAMPLE_RATE;
+}
+
+static u32 synth_bird_save_size( struct synth_bird *bird )
+{
+ return sizeof(struct synth_bird_signature) * bird->settings.pattern_length +
+ sizeof(struct synth_bird_settings);
+}
+
+static void synth_bird_save( struct synth_bird *bird, void *txt )
+{
+ void *src = &bird->settings;
+ vg_bin_str( src, txt, synth_bird_save_size( bird ) );
+}
+
+static void synth_bird_load( struct synth_bird *bird,
+ const char *txt, u32 length )
+{
+ vg_str_bin( txt, &bird->settings, length );
+ synth_bird_reset( bird );
+}
+
+/* expects a null terminated string */
+static u32 synth_bird_memory_requirement( u32 string_length )
+{
+ return (string_length/2) +
+ sizeof(struct synth_bird) - sizeof(struct synth_bird_settings);
+}
+
+#ifdef SYNTH_BIRD_STDLIB
+#include "stdlib.h"
+#include "string.h"
+
+static struct synth_bird *synth_bird_create(
+ struct synth_bird_settings *settings,
+ struct synth_bird_signature *pattern,
+ u32 pattern_length )
+{
+ u32 pattern_size = sizeof( struct synth_bird_signature ) * pattern_length;
+ u32 total_size = sizeof( struct synth_bird ) + pattern_size;
+ struct synth_bird *bird = malloc( total_size );
+
+ bird->settings = *settings;
+
+ memcpy( bird->settings.pattern, pattern, pattern_size );
+ bird->settings.pattern_length = pattern_length;
+
+ synth_bird_reset( bird );
+ return bird;
+}
+
+#endif
+
+static void synth_bird_think( struct synth_bird *bird )
+{
+ struct synth_bird_signature *sig = &bird->settings.pattern[ bird->rt.frame ];
+
+ bird->rt.x ++;
+ if( bird->rt.x >= bird->rt.length )
+ {
+ if( bird->rt.gate && (sig->pause != 0.0f) )
+ {
+ bird->rt.gate = 0;
+ bird->rt.length = sig->pause * (float)BIRD_SAMPLE_RATE;
+ }
+ else
+ {
+ bird->rt.frame ++;
+
+ if( bird->rt.frame >= bird->settings.pattern_length )
+ bird->rt.frame = 0;
+
+ sig = &bird->settings.pattern[ bird->rt.frame ];
+
+ bird->rt.gate = 1;
+ bird->rt.length = sig->length * (float)BIRD_SAMPLE_RATE;
+ }
+
+ bird->rt.x = 0;
+ }
+
+ if( bird->rt.gate )
+ {
+ bird->rt.adsr += bird->rt.adsr_rise;
+ if( bird->rt.adsr > BIRD_SAMPLE_RATE )
+ bird->rt.adsr = BIRD_SAMPLE_RATE;
+ }
+ else
+ {
+ bird->rt.adsr -= bird->rt.adsr_fall;
+ if( bird->rt.adsr < 0 )
+ bird->rt.adsr = 0;
+ }
+
+ if( bird->rt.gate )
+ {
+ float l = (float)bird->rt.length,
+ t = ((float)bird->rt.x * (1.0f/l))*2.0f - 1.0f,
+ tt = t*t,
+ ttt = tt*t;
+
+ bird->rt.fundamental = sig->x0 + t*sig->x1 + tt*sig->x2 + ttt*sig->x3;
+ }
+
+ float vol = (float)bird->rt.adsr * (1.0f/(float)BIRD_SAMPLE_RATE);
+
+ bird->rt.fm_depth = sig->fm;
+ bird->rt.lfo_hz = sig->lfo_hz;
+ bird->rt.volume[0] = sig->v0 * vol;
+ bird->rt.volume[1] = sig->v1 * vol;
+ bird->rt.volume[2] = sig->v2 * vol;
+ bird->rt.volume[3] = sig->v3 * vol;
+}
+
+static inline void int_add_mod( int *a, int const b )
+{
+ *a += b;
+
+ if( *a > BIRD_SAMPLE_RATE )
+ *a -= BIRD_SAMPLE_RATE;
+}
+
+static void synth_bird_generate_samples( struct synth_bird *bird,
+ float *stereo_buffer, int samples )
+{
+ for( int _=0; _<samples; _++ )
+ {
+ synth_bird_think( bird );
+
+ int_add_mod( &bird->rt.osc_lfo, bird->rt.lfo_hz );
+ float fm = sine_1second_1( bird->rt.osc_lfo ) * bird->rt.fm_depth;
+
+ int freq = bird->rt.fundamental + fm;
+ int hz[4] =
+ {
+ (freq * bird->settings.tones[0][0]) / bird->settings.tones[0][1],
+ (freq * bird->settings.tones[1][0]) / bird->settings.tones[1][1],
+ (freq * bird->settings.tones[2][0]) / bird->settings.tones[2][1],
+ (freq * bird->settings.tones[3][0]) / bird->settings.tones[3][1],
+ };
+
+ int_add_mod( bird->rt.osc_main + 0, hz[0] );
+ int_add_mod( bird->rt.osc_main + 1, hz[1] );
+ int_add_mod( bird->rt.osc_main + 2, hz[2] );
+ int_add_mod( bird->rt.osc_main + 3, hz[3] );
+
+ float v[4];
+ sine_1second_4( bird->rt.osc_main, v );
+
+ float s = v[0] * bird->rt.volume[0] +
+ v[1] * bird->rt.volume[1] +
+ v[2] * bird->rt.volume[2] +
+ v[3] * bird->rt.volume[3] ;
+
+ stereo_buffer[ _*2+0 ] = s;
+ stereo_buffer[ _*2+1 ] = s;
+ }
+}
+
+#ifdef SYNTH_BIRD_STDLIB
+#include "stdio.h"
+
+#define KNRM "\x1B[00m"
+#define KRED "\x1B[31m"
+#define KGRN "\x1B[32m"
+#define KYEL "\x1B[33m"
+#define KBLU "\x1B[34m"
+#define KMAG "\x1B[35m"
+#define KCYN "\x1B[36m"
+#define KWHT "\x1B[37m"
+
+#define LOG_BAR0 " . |"
+#define LOG_BAR1 "-------+-------+-------+-------+"
+#define LOG_BAR2 " "
+
+static void synth_bird_log_pattern( struct synth_bird *bird )
+{
+ synth_bird_reset( bird );
+
+ char output[][400]= {
+KNRM "9k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KNRM " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KNRM "8k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KNRM " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KNRM "7k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KNRM " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KMAG "6k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KMAG " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KCYN "5k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KCYN " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KBLU "4k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KBLU " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KGRN "3k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KGRN " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KYEL "2k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KYEL " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KRED "1k-" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KRED " -" LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0 LOG_BAR0,
+KWHT " +" LOG_BAR1 LOG_BAR1 LOG_BAR1 LOG_BAR1 LOG_BAR1
+KWHT " 0.0s"LOG_BAR2"0.5s"LOG_BAR2"1.0s"LOG_BAR2"1.5s"LOG_BAR2"2.0s"LOG_BAR2
+ };
+
+ for( int i=0; i<190*8; i++ )
+ {
+ for( int j=0; j<BIRD_SAMPLE_RATE/(32*8*2); j++ )
+ synth_bird_think( bird );
+
+ float hz = bird->rt.fundamental / 500.0f;
+ int j = hz;
+
+ if( j < 0 ) j = 0;
+ if( j > 18 ) j = 18;
+ j = 18-j;
+
+ float level = bird->rt.adsr;
+ level *= (1.0f/(float)BIRD_SAMPLE_RATE);
+
+ int ch = level*3.0f;
+
+ if( ch )
+ output[j][(i/8)+7] = " *###"[ch];
+ }
+
+ for( int i=0; i<20; i++ )
+ {
+ puts( output[i] );
+ }
+}
+#endif
+
+#endif /* VG_AUDIO_SYNTH_BIRD_H */
--- /dev/null
+#ifndef VG_BINSTR
+#define VG_BINSTR
+
+/* dead simple.. 4 bits/character encoding */
+
+#include "vg_stdint.h"
+
+#define VG_BINSTR_BASECHAR 0x41
+
+static void vg_str_bin( const void *txt, void *bin, int size )
+{
+ const u8 *src = txt;
+ u8 *dst = bin;
+
+ for( u32 i=0; i<size/2; i++ )
+ {
+ dst[i] = (src[i*2+0]-VG_BINSTR_BASECHAR);
+ dst[i] |= (src[i*2+1]-VG_BINSTR_BASECHAR)<<4u;
+ }
+}
+
+static void vg_bin_str( const void *bin, void *txt, u32 size )
+{
+ u8 *dst = txt;
+ const u8 *src = bin;
+
+ for( u32 i=0; i<size; i++ )
+ {
+ dst[i*2+0] = VG_BINSTR_BASECHAR + ((src[i] ) & 0xf);
+ dst[i*2+1] = VG_BINSTR_BASECHAR + ((src[i]>>4u) & 0xf);
+ }
+}
+
+#endif /* VG_BINSTR */
#include <stdlib.h>
#include <malloc.h>
-#define VG_MAX_ALLOCATIONS 64
+#define VG_MAX_ALLOCATIONS 128
#define VG_FUZZ_ALLOCATIONS
typedef struct vg_linear_allocator vg_linear_allocator;