X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=blobdiff_plain;f=vg_audio_synth_bird.h;h=62c30e672c8a03c17792929e2c2ba38b0fe68b23;hp=ff6ef50153c1f99a13bf132c624f70fc535a10ad;hb=HEAD;hpb=8110d74786fb065c0e69f1e171a69e519c3f8c74 diff --git a/vg_audio_synth_bird.h b/vg_audio_synth_bird.h index ff6ef50..0a2f418 100644 --- a/vg_audio_synth_bird.h +++ b/vg_audio_synth_bird.h @@ -1,14 +1,11 @@ -#ifndef VG_AUDIO_SYNTH_BIRD_H -#define VG_AUDIO_SYNTH_BIRD_H - -#include "vg_binstr.h" -#include "vg_stdint.h" +#pragma once #ifndef BIRD_SAMPLE_RATE #define BIRD_SAMPLE_RATE 44100 #endif -struct synth_bird_signature{ +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 */ @@ -17,7 +14,8 @@ struct synth_bird_signature{ float fm; /* LFO modulation depth (+/- hz) */ }; -struct synth_bird{ +struct synth_bird +{ struct{ int osc_main[4], osc_lfo; @@ -54,421 +52,7 @@ struct synth_bird{ 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 ) ); -} - -#if 0 -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); -} -#endif - -#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 */ +void synth_bird_reset( struct synth_bird *bird ); +u32 synth_bird_get_length_in_samples( struct synth_bird *bird ); +void synth_bird_generate_samples( struct synth_bird *bird, + float *stereo_buffer, int samples );