X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=blobdiff_plain;f=vg_audio_dsp.h;h=4c7d85c931907f4e52b37a2c94c6543fbe469bab;hp=c973cc9a865daa8c4238e5b00ee4ad780ae71392;hb=HEAD;hpb=e6f73232f1b16af430e850646215d2c9e07dde2e diff --git a/vg_audio_dsp.h b/vg_audio_dsp.h index c973cc9..d74bc02 100644 --- a/vg_audio_dsp.h +++ b/vg_audio_dsp.h @@ -1,42 +1,27 @@ -#ifndef VG_AUDIO_DSP_H -#define VG_AUDIO_DSP_H +#pragma once -#define VG_GAME -#include "vg/vg.h" +//#define VG_ECHO_LPF_BUTTERWORTH -static struct vg_dsp -{ - float *buffer; - u32 allocations; - - u8 *view_texture_buffer; - GLuint view_texture; - - float echo_distances[14], - echo_tunings[8], - reverb_wet_mix, - reverb_dry_mix; -} -vg_dsp; +#include "vg_platform.h" +#include "dep/glad/glad.h" +#include "vg_m.h" -static float *dsp_allocate( u32 samples ) +struct vg_dsp { - samples = vg_align4( samples ); + float *buffer; + u32 allocations; - if( vg_dsp.allocations + samples > (1024*1024)/4 ) - vg_fatal_error( "too much dsp" ); + u8 *view_texture_buffer; + GLuint view_texture; - float *buf = &vg_dsp.buffer[ vg_dsp.allocations ]; - vg_dsp.allocations += samples; + float echo_distances[14], + echo_tunings[8], + reverb_wet_mix, + reverb_dry_mix; - return buf; + vg_rand rand; } - - -/* - * filters - * ---------------------------------------------- - */ +extern vg_dsp; struct dsp_delay { @@ -56,241 +41,27 @@ struct dsp_schroeder float gain; }; -static inline void dsp_read_delay( struct dsp_delay *delay, float *s ) -{ - u32 index = delay->cur+1; - - if( index >= delay->length ) - index = 0; - - *s = delay->buffer[ index ]; -} - -static inline void dsp_write_delay( struct dsp_delay *delay, float *s ) -{ - u32 index = delay->cur; - delay->buffer[ index ] = *s; - - delay->cur ++; - - if( delay->cur >= delay->length ) - delay->cur = 0; -} - -static void dsp_init_delay( struct dsp_delay *delay, float length ) -{ - delay->length = 44100.0f * length; - delay->cur = 0; - delay->buffer = dsp_allocate( delay->length ); - - for( int i=0; ilength; i++ ) - delay->buffer[i] = 0.0f; -} - -static void dsp_update_lpf( struct dsp_lpf *lpf, float freq ) -{ - lpf->exponent = 1.0f-expf( -(1.0f/44100.0f) * 2.0f * VG_PIf * freq ); -} - -static void dsp_init_lpf( struct dsp_lpf *lpf, float freq ) -{ - lpf->buffer = dsp_allocate( 4 ); - lpf->buffer[0] = 0.0f; - dsp_update_lpf( lpf, freq ); -} - -static inline void dsp_write_lpf( struct dsp_lpf *lpf, float *s ) -{ - float diff = *s - lpf->buffer[0]; - lpf->buffer[0] += diff * lpf->exponent; -} - -static inline void dsp_read_lpf( struct dsp_lpf *lpf, float *s ) -{ - *s = lpf->buffer[0]; -} - -static void dsp_init_schroeder( struct dsp_schroeder *sch, float length, - float gain ) -{ - dsp_init_delay( &sch->M, length ); - sch->gain = gain; -} - -static inline void dsp_process_schroeder( struct dsp_schroeder *sch, - float *input, float *output ) -{ - float dry = *input; - - float delay_output; - dsp_read_delay( &sch->M, &delay_output ); - - float feedback_attenuated = delay_output * sch->gain, - input_feedback_sum = dry + feedback_attenuated; - - dsp_write_delay( &sch->M, &input_feedback_sum ); - - *output = delay_output - input_feedback_sum*sch->gain; -} - -/* temporary global design */ -static struct dsp_lpf __lpf_mud_free; -static struct dsp_delay __echos[8]; -static struct dsp_lpf __echos_lpf[8]; -static struct dsp_schroeder __diffusion_chain[8]; - -static void async_vg_dsp_alloc_texture( void *payload, u32 size ) -{ - glGenTextures( 1, &vg_dsp.view_texture ); - glBindTexture( GL_TEXTURE_2D, vg_dsp.view_texture ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, - GL_RGBA, GL_UNSIGNED_BYTE, vg_dsp.view_texture_buffer ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); -} - -static void vg_dsp_init( void ) +struct dsp_biquad { - 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 ); - - vg_async_call( async_vg_dsp_alloc_texture, NULL, 0 ); - - /* temporary global design */ - dsp_init_lpf( &__lpf_mud_free, 125.0f ); - - float sizes[] = - { 2.0f, 4.0f, 8.0f, 16.0f, 32.0f, 64.0f, 128.0f, 256.0f }; - - float reflection_variance = 0.1f; - - for( int i=0; i<8; i++ ){ - float reflection_time = ((sizes[i])/343.0f) * 1000.0f; - - float var = 1.0f + (vg_randf()*2.0f - 1.0f) * reflection_variance, - total = reflection_time * var; - - dsp_init_delay( &__echos[i], total / 1000.0f ); - - float freq = vg_lerpf( 800.0f, 350.0f, sizes[i] / 256.0f ); - dsp_init_lpf( &__echos_lpf[i], freq ); - } - - float diffusions[] = { 187.0f, 159.0f, 143.0f, 121.0f, - 79.0f, 57.0f, 27.0f, 11.0f }; - - for( int i=0; i<8; i++ ){ - dsp_init_schroeder( __diffusion_chain+i, diffusions[i]/1000.0f, 0.7f ); - } -} - -static void vg_dsp_process( float *stereo_in, float *stereo_out ) -{ - float in_total = (stereo_in[0]+stereo_in[1])*0.5f; - float recieved = 0.0f; - - for( int i=0; i<8; i++ ){ - float echo; - dsp_read_delay( __echos+i, &echo ); - dsp_write_lpf( __echos_lpf+i, &echo ); - dsp_read_lpf( __echos_lpf+i, &echo ); - - recieved += echo * vg_dsp.echo_tunings[i]*0.98; - } - - float diffused = recieved; - - for( int i=0; i<8; i++ ){ - dsp_process_schroeder( __diffusion_chain+i, &diffused, &diffused ); - } - - float diffuse_mix = vg_dsp.reverb_wet_mix; - diffuse_mix = vg_lerpf( recieved, diffused, diffuse_mix ); - float total = in_total + diffuse_mix; - - float low_mud; - dsp_write_lpf( &__lpf_mud_free, &total ); - dsp_read_lpf( &__lpf_mud_free, &low_mud ); - - total -= low_mud; - - for( int i=0; i<8; i++ ) - dsp_write_delay( __echos+i, &total ); - - stereo_out[0] = stereo_in[0]*vg_dsp.reverb_dry_mix; - stereo_out[1] = stereo_in[1]*vg_dsp.reverb_dry_mix; - stereo_out[0] += diffuse_mix*2.0f*vg_dsp.reverb_wet_mix; - stereo_out[1] += diffuse_mix*2.0f*vg_dsp.reverb_wet_mix; -} - -static void dsp_update_tunings(void) -{ - float sizes[] = - { 2.0f, 4.0f, 8.0f, 16.0f, 32.0f, 64.0f, 128.0f, 256.0f }; - float volumes[] = - { 0.2f, 0.3f, 0.5f, 0.7f, 0.8f, 0.9f, 1.0f, 1.0f }; - - float avg_distance = 0.0f; - - for( int i=0; i<8; i++ ) - vg_dsp.echo_tunings[i] = 0.5f; - - for( int j=0; j<14; j++ ){ - float d = vg_dsp.echo_distances[j]; - - for( int i=0; i<7; i++ ){ - if( d < sizes[i+1] ){ - float range = sizes[i+1]-sizes[i]; - float t = vg_clampf( (d - sizes[i])/range, 0.0f, 1.0f ); - - vg_dsp.echo_tunings[i ] += 1.0f-t; - vg_dsp.echo_tunings[i+1] += t; - - break; - } - } - - avg_distance += d; - } - avg_distance /= 14.0f; - - - vg_dsp.reverb_wet_mix =1.0f-vg_clampf((avg_distance-30.0f)/200.0f,0.0f,1.0f); - vg_dsp.reverb_dry_mix =1.0f-vg_dsp.reverb_wet_mix*0.4f; - - float total = 0.0f; - for( int i=0; i<8; i++ ) - total += vg_dsp.echo_tunings[i]; - - if( total > 0.0f ){ - float inverse = 1.0f/total; - - for( int i=0;i<8; i++ ){ - vg_dsp.echo_tunings[i] *= inverse; - } - } - - for( int i=0; i<8; i++ ){ - float freq = vg_lerpf( 200.0f, 500.0f, vg_dsp.echo_tunings[i] ); - dsp_update_lpf( &__echos_lpf[i], freq ); - } - - for( int i=0;i<8; i++ ){ - vg_dsp.echo_tunings[i] *= volumes[i]; - } -} - -static void vg_dsp_free( void ) -{ - glDeleteTextures( 1, &vg_dsp.view_texture ); -} - -static void vg_dsp_update_texture( void ) -{ - for( int i=0; i<512*512; i++ ){ - float v = vg_clampf( vg_dsp.buffer[i] * 0.5f + 0.5f, 0.0f, 1.0f ); - vg_dsp.view_texture_buffer[i] = v * 255.0f; - } -} + f32 a0, a1, a2, b1, b2, c0, d0, + xnz1, xnz2, ynz1, ynz2, offset; +}; -#endif /* VG_AUDIO_DSP_H */ +void vg_dsp_init( void ); +void vg_dsp_free( void ); +void dsp_update_tunings(void); +void vg_dsp_process( float *stereo_in, float *stereo_out ); +void vg_dsp_update_texture( void ); + +f32 dsp_biquad_process( struct dsp_biquad *bq, f32 xn ); +void dsp_init_biquad_butterworth_lpf( struct dsp_biquad *bq, f32 fc ); +void dsp_read_delay( struct dsp_delay *delay, float *s, u32 t ); +void dsp_write_delay( struct dsp_delay *delay, float *s ); +void dsp_init_delay( struct dsp_delay *delay, float length ); +void dsp_update_lpf( struct dsp_lpf *lpf, float freq ); +void dsp_init_lpf( struct dsp_lpf *lpf, float freq ); +void dsp_write_lpf( struct dsp_lpf *lpf, float *s ); +void dsp_read_lpf( struct dsp_lpf *lpf, float *s ); +void dsp_init_schroeder( struct dsp_schroeder *sch, float length, float gain ); +void dsp_process_schroeder( struct dsp_schroeder *sch, + float *input, float *output );