From: hgn Date: Sun, 10 Dec 2023 19:57:40 +0000 (+0000) Subject: add generic synthesizer clip option and biquad lpf X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=commitdiff_plain;h=44847e656f2bded5d2c4be87eb5a1ae8e598c798 add generic synthesizer clip option and biquad lpf --- diff --git a/vg_audio.h b/vg_audio.h index dbc6ff6..38290ff 100644 --- a/vg_audio.h +++ b/vg_audio.h @@ -61,7 +61,7 @@ enum audio_format k_audio_format_none4 = 0xE00u, k_audio_format_bird = 0x1000u, - k_audio_format_none5 = 0x1200u, + k_audio_format_gen = 0x1200u, k_audio_format_none6 = 0x1400u, k_audio_format_none7 = 0x1600u, k_audio_format_none8 = 0x1800u, @@ -82,6 +82,7 @@ struct audio_clip{ union { /* TODO oof.. */ u64 _p64_; const char *path; + void *func; }; u32 flags; @@ -329,8 +330,8 @@ static void vg_audio_free(void) #define AUDIO_EDIT_OWNERSHIP 0x40 #define AUDIO_EDIT_SAMPLING_RATE 0x80 -static void audio_channel_init( audio_channel *ch, audio_clip *clip, u32 flags ) -{ +static void audio_channel_init( audio_channel *ch, audio_clip *clip, + u32 flags ){ audio_require_lock(); ch->group = 0; ch->world_id = 0; @@ -340,6 +341,8 @@ static void audio_channel_init( audio_channel *ch, audio_clip *clip, u32 flags ) if( (ch->source->flags & AUDIO_FLAG_FORMAT) == k_audio_format_bird ) strcpy( ch->name, "[array]" ); + else if( (ch->source->flags & AUDIO_FLAG_FORMAT) == k_audio_format_gen ) + strcpy( ch->name, "[program]" ); else vg_strncpy( clip->path, ch->name, 32, k_strncpy_always_add_null ); @@ -636,6 +639,9 @@ static int audio_channel_load_source( audio_channel *ch ) else if( format == k_audio_format_stereo ){ ch->source_length = ch->source->size / 2; } + else if( format == k_audio_format_gen ){ + ch->source_length = 0xffffffff; + } else{ ch->source_length = ch->source->size; } @@ -798,6 +804,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 if( format == k_audio_format_gen ){ + void (*fn)( void *data, f32 *buf, u32 count ) = ch->source->func; + fn( ch->source->data, dst, samples_this_run ); + } else{ i16 *src_buffer = ch->source->data, *src = &src_buffer[ch->cursor]; diff --git a/vg_audio_dsp.h b/vg_audio_dsp.h index 0eaeb54..48926e2 100644 --- a/vg_audio_dsp.h +++ b/vg_audio_dsp.h @@ -4,8 +4,7 @@ #define VG_GAME #include "vg/vg.h" -static struct vg_dsp -{ +static struct vg_dsp{ float *buffer; u32 allocations; @@ -16,6 +15,8 @@ static struct vg_dsp echo_tunings[8], reverb_wet_mix, reverb_dry_mix; + + vg_rand rand; } vg_dsp; @@ -56,12 +57,35 @@ struct dsp_schroeder float gain; }; -static inline void dsp_read_delay( struct dsp_delay *delay, float *s ) -{ - u32 index = delay->cur+1; +struct dsp_biquad { + f32 a0, a1, a2, b1, b2, c0, d0, + xnz1, xnz2, ynz1, ynz2, offset; +}; + +static f32 dsp_biquad_process( struct dsp_biquad *bq, f32 xn ){ + f32 yn = + bq->a0*xn + bq->a1*bq->xnz1 + bq->a2*bq->xnz2 + - bq->b1*bq->ynz1 - bq->b2*bq->ynz2; + bq->xnz2 = bq->xnz1; + bq->xnz1 = xn; + bq->ynz2 = bq->ynz1; + bq->ynz1 = yn; + return yn + bq->offset; +} + +static void dsp_init_biquad_butterworth_lpf( struct dsp_biquad *bq, f32 fc ){ + f32 c = 1.0f/tanf(VG_PIf*fc / 44100.0f); + bq->a0 = 1.0f / (1.0f + sqrtf(2.0f)*c + powf(c, 2.0f) ); + bq->a1 = 2.0f * bq->a0; + bq->a2 = bq->a0; + bq->b1 = 2.0f * bq->a0*(1.0f - powf(c, 2.0f)); + bq->b2 = bq->a0 * (1.0f - sqrtf(2.0f)*c + powf(c, 2.0f) ); +} + +static inline void dsp_read_delay( struct dsp_delay *delay, float *s, u32 t ){ + u32 index = delay->cur+t; if( index >= delay->length ) - index = 0; + index -= delay->length; *s = delay->buffer[ index ]; } @@ -123,7 +147,7 @@ static inline void dsp_process_schroeder( struct dsp_schroeder *sch, float dry = *input; float delay_output; - dsp_read_delay( &sch->M, &delay_output ); + dsp_read_delay( &sch->M, &delay_output, 1 ); float feedback_attenuated = delay_output * sch->gain, input_feedback_sum = dry + feedback_attenuated; @@ -149,8 +173,8 @@ static void async_vg_dsp_alloc_texture( void *payload, u32 size ) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); } -static void vg_dsp_init( void ) -{ +static void vg_dsp_init( void ){ + vg_rand_seed( &vg_dsp.rand, 461 ); vg_dsp.buffer = vg_linear_alloc( vg_mem.rtmemory, 1024*1024*1 ); vg_dsp.view_texture_buffer = vg_linear_alloc( vg_mem.rtmemory, 512*512 ); @@ -162,12 +186,12 @@ static void vg_dsp_init( void ) float sizes[] = { 2.0f, 4.0f, 8.0f, 16.0f, 32.0f, 64.0f, 128.0f, 256.0f }; - float reflection_variance = 0.1f; + float variance = 0.1f; for( int i=0; i<8; i++ ){ float reflection_time = ((sizes[i])/343.0f) * 1000.0f; - float var = 1.0f + (vg_randf64()*2.0f - 1.0f) * reflection_variance, + float var = 1.0f + (vg_randf64(&vg_dsp.rand)*2.0f - 1.0f) * variance, total = reflection_time * var; dsp_init_delay( &__echos[i], total / 1000.0f ); @@ -191,7 +215,7 @@ static void vg_dsp_process( float *stereo_in, float *stereo_out ) for( int i=0; i<8; i++ ){ float echo; - dsp_read_delay( __echos+i, &echo ); + dsp_read_delay( __echos+i, &echo, 1 ); dsp_write_lpf( __echos_lpf+i, &echo ); dsp_read_lpf( __echos_lpf+i, &echo );