1 #include "vg_audio_dsp.h"
7 float *dsp_allocate( u32 samples
)
9 samples
= vg_align4( samples
);
11 if( vg_dsp
.allocations
+ samples
> (1024*1024)/4 )
12 vg_fatal_error( "too much dsp" );
14 float *buf
= &vg_dsp
.buffer
[ vg_dsp
.allocations
];
15 vg_dsp
.allocations
+= samples
;
23 * ----------------------------------------------
26 f32
dsp_biquad_process( struct dsp_biquad
*bq
, f32 xn
){
27 f32 yn
= + bq
->a0
*xn
+ bq
->a1
*bq
->xnz1
+ bq
->a2
*bq
->xnz2
28 - bq
->b1
*bq
->ynz1
- bq
->b2
*bq
->ynz2
;
33 return yn
+ bq
->offset
;
36 void dsp_init_biquad_butterworth_lpf( struct dsp_biquad
*bq
, f32 fc
){
37 f32 c
= 1.0f
/tanf(VG_PIf
*fc
/ 44100.0f
);
38 bq
->a0
= 1.0f
/ (1.0f
+ sqrtf(2.0f
)*c
+ powf(c
, 2.0f
) );
39 bq
->a1
= 2.0f
* bq
->a0
;
41 bq
->b1
= 2.0f
* bq
->a0
*(1.0f
- powf(c
, 2.0f
));
42 bq
->b2
= bq
->a0
* (1.0f
- sqrtf(2.0f
)*c
+ powf(c
, 2.0f
) );
45 void dsp_read_delay( struct dsp_delay
*delay
, float *s
, u32 t
){
46 u32 index
= delay
->cur
+t
;
48 if( index
>= delay
->length
)
49 index
-= delay
->length
;
51 *s
= delay
->buffer
[ index
];
54 void dsp_write_delay( struct dsp_delay
*delay
, float *s
)
56 u32 index
= delay
->cur
;
57 delay
->buffer
[ index
] = *s
;
61 if( delay
->cur
>= delay
->length
)
65 void dsp_init_delay( struct dsp_delay
*delay
, float length
)
67 delay
->length
= 44100.0f
* length
;
69 delay
->buffer
= dsp_allocate( delay
->length
);
71 for( int i
=0; i
<delay
->length
; i
++ )
72 delay
->buffer
[i
] = 0.0f
;
75 void dsp_update_lpf( struct dsp_lpf
*lpf
, float freq
)
77 lpf
->exponent
= 1.0f
-expf( -(1.0f
/44100.0f
) * 2.0f
* VG_PIf
* freq
);
80 void dsp_init_lpf( struct dsp_lpf
*lpf
, float freq
)
82 lpf
->buffer
= dsp_allocate( 4 );
83 lpf
->buffer
[0] = 0.0f
;
84 dsp_update_lpf( lpf
, freq
);
87 void dsp_write_lpf( struct dsp_lpf
*lpf
, float *s
)
89 float diff
= *s
- lpf
->buffer
[0];
90 lpf
->buffer
[0] += diff
* lpf
->exponent
;
93 void dsp_read_lpf( struct dsp_lpf
*lpf
, float *s
)
98 void dsp_init_schroeder( struct dsp_schroeder
*sch
, float length
, float gain
)
100 dsp_init_delay( &sch
->M
, length
);
104 void dsp_process_schroeder( struct dsp_schroeder
*sch
,
105 float *input
, float *output
)
110 dsp_read_delay( &sch
->M
, &delay_output
, 1 );
112 float feedback_attenuated
= delay_output
* sch
->gain
,
113 input_feedback_sum
= dry
+ feedback_attenuated
;
115 dsp_write_delay( &sch
->M
, &input_feedback_sum
);
117 *output
= delay_output
- input_feedback_sum
*sch
->gain
;
120 /* temporary global design */
121 static struct dsp_lpf __lpf_mud_free
;
122 static struct dsp_delay __echos
[8];
124 #ifdef VG_ECHO_LPF_BUTTERWORTH
125 static struct dsp_biquad __echos_lpf
[8];
127 static struct dsp_lpf __echos_lpf
[8];
129 static struct dsp_schroeder __diffusion_chain
[8];
131 static void async_vg_dsp_alloc_texture( void *payload
, u32 size
)
133 glGenTextures( 1, &vg_dsp
.view_texture
);
134 glBindTexture( GL_TEXTURE_2D
, vg_dsp
.view_texture
);
135 glTexImage2D( GL_TEXTURE_2D
, 0, GL_RGBA
, 256, 256, 0,
136 GL_RGBA
, GL_UNSIGNED_BYTE
, vg_dsp
.view_texture_buffer
);
137 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
138 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
141 void vg_dsp_init( void ){
142 vg_rand_seed( &vg_dsp
.rand
, 461 );
143 vg_dsp
.buffer
= vg_linear_alloc( vg_mem
.rtmemory
, 1024*1024*1 );
144 vg_dsp
.view_texture_buffer
= vg_linear_alloc( vg_mem
.rtmemory
, 512*512 );
146 vg_async_call( async_vg_dsp_alloc_texture
, NULL
, 0 );
148 /* temporary global design */
149 dsp_init_lpf( &__lpf_mud_free
, 125.0f
);
152 { 2.0f
, 4.0f
, 8.0f
, 16.0f
, 32.0f
, 64.0f
, 128.0f
, 256.0f
};
154 float variance
= 0.1f
;
156 for( int i
=0; i
<8; i
++ ){
157 float reflection_time
= ((sizes
[i
])/343.0f
) * 1000.0f
;
159 float var
= 1.0f
+ (vg_randf64(&vg_dsp
.rand
)*2.0f
- 1.0f
) * variance
,
160 total
= reflection_time
* var
;
162 dsp_init_delay( &__echos
[i
], total
/ 1000.0f
);
164 float freq
= vg_lerpf( 800.0f
, 350.0f
, sizes
[i
] / 256.0f
);
166 #ifdef VG_ECHO_LPF_BUTTERWORTH
167 dsp_init_biquad_butterworth_lpf( &__echos_lpf
[i
], freq
);
169 dsp_init_lpf( &__echos_lpf
[i
], freq
);
173 float diffusions
[] = { 187.0f
, 159.0f
, 143.0f
, 121.0f
,
174 79.0f
, 57.0f
, 27.0f
, 11.0f
};
176 for( int i
=0; i
<8; i
++ ){
177 dsp_init_schroeder( __diffusion_chain
+i
, diffusions
[i
]/1000.0f
, 0.7f
);
181 void vg_dsp_process( float *stereo_in
, float *stereo_out
)
183 float in_total
= (stereo_in
[0]+stereo_in
[1])*0.5f
;
184 float recieved
= 0.0f
;
186 for( int i
=0; i
<8; i
++ ){
188 dsp_read_delay( __echos
+i
, &echo
, 1 );
190 #ifdef VG_ECHO_LPF_BUTTERWORTH
191 echo
= dsp_biquad_process( __echos_lpf
+i
, echo
);
193 dsp_write_lpf( __echos_lpf
+i
, &echo
);
194 dsp_read_lpf( __echos_lpf
+i
, &echo
);
197 recieved
+= echo
* vg_dsp
.echo_tunings
[i
]*0.98;
200 float diffused
= recieved
;
202 for( int i
=0; i
<8; i
++ ){
203 dsp_process_schroeder( __diffusion_chain
+i
, &diffused
, &diffused
);
206 float diffuse_mix
= vg_dsp
.reverb_wet_mix
;
207 diffuse_mix
= vg_lerpf( recieved
, diffused
, diffuse_mix
);
208 float total
= in_total
+ diffuse_mix
;
211 dsp_write_lpf( &__lpf_mud_free
, &total
);
212 dsp_read_lpf( &__lpf_mud_free
, &low_mud
);
216 for( int i
=0; i
<8; i
++ )
217 dsp_write_delay( __echos
+i
, &total
);
219 stereo_out
[0] = stereo_in
[0]*vg_dsp
.reverb_dry_mix
;
220 stereo_out
[1] = stereo_in
[1]*vg_dsp
.reverb_dry_mix
;
221 stereo_out
[0] += diffuse_mix
*2.0f
*vg_dsp
.reverb_wet_mix
;
222 stereo_out
[1] += diffuse_mix
*2.0f
*vg_dsp
.reverb_wet_mix
;
225 void dsp_update_tunings(void)
228 { 2.0f
, 4.0f
, 8.0f
, 16.0f
, 32.0f
, 64.0f
, 128.0f
, 256.0f
};
230 { 0.2f
, 0.3f
, 0.5f
, 0.7f
, 0.8f
, 0.9f
, 1.0f
, 1.0f
};
232 float avg_distance
= 0.0f
;
234 for( int i
=0; i
<8; i
++ )
235 vg_dsp
.echo_tunings
[i
] = 0.5f
;
237 for( int j
=0; j
<14; j
++ ){
238 float d
= vg_dsp
.echo_distances
[j
];
240 for( int i
=0; i
<7; i
++ ){
241 if( d
< sizes
[i
+1] ){
242 float range
= sizes
[i
+1]-sizes
[i
];
243 float t
= vg_clampf( (d
- sizes
[i
])/range
, 0.0f
, 1.0f
);
245 vg_dsp
.echo_tunings
[i
] += 1.0f
-t
;
246 vg_dsp
.echo_tunings
[i
+1] += t
;
254 avg_distance
/= 14.0f
;
257 vg_dsp
.reverb_wet_mix
=1.0f
-vg_clampf((avg_distance
-30.0f
)/200.0f
,0.0f
,1.0f
);
258 vg_dsp
.reverb_dry_mix
=1.0f
-vg_dsp
.reverb_wet_mix
*0.4f
;
261 for( int i
=0; i
<8; i
++ )
262 total
+= vg_dsp
.echo_tunings
[i
];
265 float inverse
= 1.0f
/total
;
267 for( int i
=0;i
<8; i
++ ){
268 vg_dsp
.echo_tunings
[i
] *= inverse
;
272 for( int i
=0; i
<8; i
++ ){
273 float freq
= vg_lerpf( 200.0f
, 500.0f
, vg_dsp
.echo_tunings
[i
] );
275 #ifdef VG_ECHO_LPF_BUTTERWORTH
276 dsp_init_biquad_butterworth_lpf( &__echos_lpf
[i
], freq
);
278 dsp_update_lpf( &__echos_lpf
[i
], freq
);
282 for( int i
=0;i
<8; i
++ ){
283 vg_dsp
.echo_tunings
[i
] *= volumes
[i
];
287 void vg_dsp_free( void )
289 glDeleteTextures( 1, &vg_dsp
.view_texture
);
292 void vg_dsp_update_texture( void )
294 for( int i
=0; i
<512*512; i
++ ){
295 float v
= vg_clampf( vg_dsp
.buffer
[i
] * 0.5f
+ 0.5f
, 0.0f
, 1.0f
);
296 vg_dsp
.view_texture_buffer
[i
] = v
* 255.0f
;