From: hgn Date: Wed, 15 Mar 2023 19:16:00 +0000 (+0000) Subject: reduction X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=commitdiff_plain;h=28ec4a17033cc45198adab23ddf66ccd7a230db8 reduction --- diff --git a/projects/bird_profiles.txt b/projects/bird_profiles.txt new file mode 100644 index 0000000..321724f --- /dev/null +++ b/projects/bird_profiles.txt @@ -0,0 +1,21 @@ +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 + diff --git a/projects/birds b/projects/birds index 9c38f4e..80cf40c 100755 Binary files a/projects/birds and b/projects/birds differ diff --git a/projects/birds.c b/projects/birds.c index a015fe6..81646be 100644 --- a/projects/birds.c +++ b/projects/birds.c @@ -3,16 +3,11 @@ #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 * @@ -27,76 +22,6 @@ * */ -//#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); @@ -111,338 +36,72 @@ static int rand_seconds( double min, double max ) 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; _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 } @@ -632,9 +291,9 @@ static void vg_dsp_process( float *stereo_in, float *stereo_out ) 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; } diff --git a/projects/encode.c b/projects/encode.c new file mode 100644 index 0000000..8298bc8 --- /dev/null +++ b/projects/encode.c @@ -0,0 +1,22 @@ +#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 ); +} diff --git a/projects/struct b/projects/struct new file mode 100755 index 0000000..34d1298 Binary files /dev/null and b/projects/struct differ diff --git a/submodules/SDL b/submodules/SDL index 06492c5..eef4d3c 160000 --- a/submodules/SDL +++ b/submodules/SDL @@ -1 +1 @@ -Subproject commit 06492c598158cf825a18aececaf7511d7fd04f48 +Subproject commit eef4d3c86a653f91b7221c80809ba8ab56f94cf1 diff --git a/vg_audio.h b/vg_audio.h index 0968957..5b65ccb 100644 --- a/vg_audio.h +++ b/vg_audio.h @@ -14,6 +14,7 @@ #include "vg/vg_console.h" #include "vg/vg_store.h" #include "vg/vg_profiler.h" +#include "vg/vg_audio_synth_bird.h" #include #include @@ -52,8 +53,32 @@ /* 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 @@ -128,7 +153,12 @@ static struct vg_audio_system 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 @@ -174,7 +204,8 @@ static struct vg_audio_system int debug_ui, debug_ui_3d; v3f listener_pos, - listener_ears; + listener_ears, + listener_velocity; float volume, volume_target, @@ -334,7 +365,11 @@ static audio_channel *audio_request_channel( audio_clip *clip, u32 flags ) 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; @@ -506,13 +541,17 @@ static void audio_set_lfo_frequency( int id, float freq ) 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; @@ -542,7 +581,20 @@ static int audio_channel_load_source( audio_channel *ch ) 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; } @@ -684,14 +736,16 @@ static void audio_channel_get_samples( audio_channel *ch, 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;isource->flags & AUDIO_FLAG_VORBIS ) + else if( format == k_audio_format_vorbis ) { int read_samples = stb_vorbis_get_samples_float_interleaved_stereo( ch->vorbis_handle, @@ -717,6 +771,10 @@ static void audio_channel_get_samples( audio_channel *ch, } } } + 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, @@ -730,8 +788,10 @@ static void audio_channel_get_samples( audio_channel *ch, 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; @@ -754,25 +814,19 @@ static void audio_channel_get_samples( audio_channel *ch, 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]) ) @@ -795,8 +849,28 @@ static void audio_channel_mix( audio_channel *ch, float *buffer ) 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; @@ -837,12 +911,12 @@ static void audio_channel_mix( audio_channel *ch, float *buffer ) 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 ), @@ -920,9 +994,14 @@ VG_STATIC void audio_mixer_callback( void *user, u8 *stream, int byte_count ) 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 ) @@ -1103,9 +1182,13 @@ VG_STATIC void audio_clip_load( audio_clip *clip, void *lin_alloc ) 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 ); @@ -1117,10 +1200,23 @@ VG_STATIC void audio_clip_load( audio_clip *clip, void *lin_alloc ) 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 ); @@ -1254,10 +1350,22 @@ VG_STATIC void audio_debug_ui( m4x4f mtx_pv ) 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[] = @@ -1269,14 +1377,7 @@ VG_STATIC void audio_debug_ui( m4x4f mtx_pv ) "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, @@ -1288,14 +1389,7 @@ VG_STATIC void audio_debug_ui( m4x4f mtx_pv ) 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; diff --git a/vg_audio_synth_bird.h b/vg_audio_synth_bird.h new file mode 100644 index 0000000..62c30e6 --- /dev/null +++ b/vg_audio_synth_bird.h @@ -0,0 +1,478 @@ +#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; isettings.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; _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; jrt.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 */ diff --git a/vg_binstr.h b/vg_binstr.h new file mode 100644 index 0000000..da41ce0 --- /dev/null +++ b/vg_binstr.h @@ -0,0 +1,34 @@ +#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>4u) & 0xf); + } +} + +#endif /* VG_BINSTR */ diff --git a/vg_mem.h b/vg_mem.h index 666a4c6..9a9b31b 100644 --- a/vg_mem.h +++ b/vg_mem.h @@ -8,7 +8,7 @@ #include #include -#define VG_MAX_ALLOCATIONS 64 +#define VG_MAX_ALLOCATIONS 128 #define VG_FUZZ_ALLOCATIONS typedef struct vg_linear_allocator vg_linear_allocator;