7 //#define VG_ECHO_LPF_BUTTERWORTH
13 u8
*view_texture_buffer
;
16 float echo_distances
[14],
25 static float *dsp_allocate( u32 samples
)
27 samples
= vg_align4( samples
);
29 if( vg_dsp
.allocations
+ samples
> (1024*1024)/4 )
30 vg_fatal_error( "too much dsp" );
32 float *buf
= &vg_dsp
.buffer
[ vg_dsp
.allocations
];
33 vg_dsp
.allocations
+= samples
;
41 * ----------------------------------------------
63 f32 a0
, a1
, a2
, b1
, b2
, c0
, d0
,
64 xnz1
, xnz2
, ynz1
, ynz2
, offset
;
67 static f32
dsp_biquad_process( struct dsp_biquad
*bq
, f32 xn
){
68 f32 yn
= + bq
->a0
*xn
+ bq
->a1
*bq
->xnz1
+ bq
->a2
*bq
->xnz2
69 - bq
->b1
*bq
->ynz1
- bq
->b2
*bq
->ynz2
;
74 return yn
+ bq
->offset
;
77 static void dsp_init_biquad_butterworth_lpf( struct dsp_biquad
*bq
, f32 fc
){
78 f32 c
= 1.0f
/tanf(VG_PIf
*fc
/ 44100.0f
);
79 bq
->a0
= 1.0f
/ (1.0f
+ sqrtf(2.0f
)*c
+ powf(c
, 2.0f
) );
80 bq
->a1
= 2.0f
* bq
->a0
;
82 bq
->b1
= 2.0f
* bq
->a0
*(1.0f
- powf(c
, 2.0f
));
83 bq
->b2
= bq
->a0
* (1.0f
- sqrtf(2.0f
)*c
+ powf(c
, 2.0f
) );
86 static inline void dsp_read_delay( struct dsp_delay
*delay
, float *s
, u32 t
){
87 u32 index
= delay
->cur
+t
;
89 if( index
>= delay
->length
)
90 index
-= delay
->length
;
92 *s
= delay
->buffer
[ index
];
95 static inline void dsp_write_delay( struct dsp_delay
*delay
, float *s
)
97 u32 index
= delay
->cur
;
98 delay
->buffer
[ index
] = *s
;
102 if( delay
->cur
>= delay
->length
)
106 static void dsp_init_delay( struct dsp_delay
*delay
, float length
)
108 delay
->length
= 44100.0f
* length
;
110 delay
->buffer
= dsp_allocate( delay
->length
);
112 for( int i
=0; i
<delay
->length
; i
++ )
113 delay
->buffer
[i
] = 0.0f
;
116 static void dsp_update_lpf( struct dsp_lpf
*lpf
, float freq
)
118 lpf
->exponent
= 1.0f
-expf( -(1.0f
/44100.0f
) * 2.0f
* VG_PIf
* freq
);
121 static void dsp_init_lpf( struct dsp_lpf
*lpf
, float freq
)
123 lpf
->buffer
= dsp_allocate( 4 );
124 lpf
->buffer
[0] = 0.0f
;
125 dsp_update_lpf( lpf
, freq
);
128 static inline void dsp_write_lpf( struct dsp_lpf
*lpf
, float *s
)
130 float diff
= *s
- lpf
->buffer
[0];
131 lpf
->buffer
[0] += diff
* lpf
->exponent
;
134 static inline void dsp_read_lpf( struct dsp_lpf
*lpf
, float *s
)
139 static void dsp_init_schroeder( struct dsp_schroeder
*sch
, float length
,
142 dsp_init_delay( &sch
->M
, length
);
146 static inline void dsp_process_schroeder( struct dsp_schroeder
*sch
,
147 float *input
, float *output
)
152 dsp_read_delay( &sch
->M
, &delay_output
, 1 );
154 float feedback_attenuated
= delay_output
* sch
->gain
,
155 input_feedback_sum
= dry
+ feedback_attenuated
;
157 dsp_write_delay( &sch
->M
, &input_feedback_sum
);
159 *output
= delay_output
- input_feedback_sum
*sch
->gain
;
162 /* temporary global design */
163 static struct dsp_lpf __lpf_mud_free
;
164 static struct dsp_delay __echos
[8];
166 #ifdef VG_ECHO_LPF_BUTTERWORTH
167 static struct dsp_biquad __echos_lpf
[8];
169 static struct dsp_lpf __echos_lpf
[8];
171 static struct dsp_schroeder __diffusion_chain
[8];
173 static void async_vg_dsp_alloc_texture( void *payload
, u32 size
)
175 glGenTextures( 1, &vg_dsp
.view_texture
);
176 glBindTexture( GL_TEXTURE_2D
, vg_dsp
.view_texture
);
177 glTexImage2D( GL_TEXTURE_2D
, 0, GL_RGBA
, 256, 256, 0,
178 GL_RGBA
, GL_UNSIGNED_BYTE
, vg_dsp
.view_texture_buffer
);
179 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
180 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
183 static void vg_dsp_init( void ){
184 vg_rand_seed( &vg_dsp
.rand
, 461 );
185 vg_dsp
.buffer
= vg_linear_alloc( vg_mem
.rtmemory
, 1024*1024*1 );
186 vg_dsp
.view_texture_buffer
= vg_linear_alloc( vg_mem
.rtmemory
, 512*512 );
188 vg_async_call( async_vg_dsp_alloc_texture
, NULL
, 0 );
190 /* temporary global design */
191 dsp_init_lpf( &__lpf_mud_free
, 125.0f
);
194 { 2.0f
, 4.0f
, 8.0f
, 16.0f
, 32.0f
, 64.0f
, 128.0f
, 256.0f
};
196 float variance
= 0.1f
;
198 for( int i
=0; i
<8; i
++ ){
199 float reflection_time
= ((sizes
[i
])/343.0f
) * 1000.0f
;
201 float var
= 1.0f
+ (vg_randf64(&vg_dsp
.rand
)*2.0f
- 1.0f
) * variance
,
202 total
= reflection_time
* var
;
204 dsp_init_delay( &__echos
[i
], total
/ 1000.0f
);
206 float freq
= vg_lerpf( 800.0f
, 350.0f
, sizes
[i
] / 256.0f
);
208 #ifdef VG_ECHO_LPF_BUTTERWORTH
209 dsp_init_biquad_butterworth_lpf( &__echos_lpf
[i
], freq
);
211 dsp_init_lpf( &__echos_lpf
[i
], freq
);
215 float diffusions
[] = { 187.0f
, 159.0f
, 143.0f
, 121.0f
,
216 79.0f
, 57.0f
, 27.0f
, 11.0f
};
218 for( int i
=0; i
<8; i
++ ){
219 dsp_init_schroeder( __diffusion_chain
+i
, diffusions
[i
]/1000.0f
, 0.7f
);
223 static void vg_dsp_process( float *stereo_in
, float *stereo_out
)
225 float in_total
= (stereo_in
[0]+stereo_in
[1])*0.5f
;
226 float recieved
= 0.0f
;
228 for( int i
=0; i
<8; i
++ ){
230 dsp_read_delay( __echos
+i
, &echo
, 1 );
232 #ifdef VG_ECHO_LPF_BUTTERWORTH
233 echo
= dsp_biquad_process( __echos_lpf
+i
, echo
);
235 dsp_write_lpf( __echos_lpf
+i
, &echo
);
236 dsp_read_lpf( __echos_lpf
+i
, &echo
);
239 recieved
+= echo
* vg_dsp
.echo_tunings
[i
]*0.98;
242 float diffused
= recieved
;
244 for( int i
=0; i
<8; i
++ ){
245 dsp_process_schroeder( __diffusion_chain
+i
, &diffused
, &diffused
);
248 float diffuse_mix
= vg_dsp
.reverb_wet_mix
;
249 diffuse_mix
= vg_lerpf( recieved
, diffused
, diffuse_mix
);
250 float total
= in_total
+ diffuse_mix
;
253 dsp_write_lpf( &__lpf_mud_free
, &total
);
254 dsp_read_lpf( &__lpf_mud_free
, &low_mud
);
258 for( int i
=0; i
<8; i
++ )
259 dsp_write_delay( __echos
+i
, &total
);
261 stereo_out
[0] = stereo_in
[0]*vg_dsp
.reverb_dry_mix
;
262 stereo_out
[1] = stereo_in
[1]*vg_dsp
.reverb_dry_mix
;
263 stereo_out
[0] += diffuse_mix
*2.0f
*vg_dsp
.reverb_wet_mix
;
264 stereo_out
[1] += diffuse_mix
*2.0f
*vg_dsp
.reverb_wet_mix
;
267 static void dsp_update_tunings(void)
270 { 2.0f
, 4.0f
, 8.0f
, 16.0f
, 32.0f
, 64.0f
, 128.0f
, 256.0f
};
272 { 0.2f
, 0.3f
, 0.5f
, 0.7f
, 0.8f
, 0.9f
, 1.0f
, 1.0f
};
274 float avg_distance
= 0.0f
;
276 for( int i
=0; i
<8; i
++ )
277 vg_dsp
.echo_tunings
[i
] = 0.5f
;
279 for( int j
=0; j
<14; j
++ ){
280 float d
= vg_dsp
.echo_distances
[j
];
282 for( int i
=0; i
<7; i
++ ){
283 if( d
< sizes
[i
+1] ){
284 float range
= sizes
[i
+1]-sizes
[i
];
285 float t
= vg_clampf( (d
- sizes
[i
])/range
, 0.0f
, 1.0f
);
287 vg_dsp
.echo_tunings
[i
] += 1.0f
-t
;
288 vg_dsp
.echo_tunings
[i
+1] += t
;
296 avg_distance
/= 14.0f
;
299 vg_dsp
.reverb_wet_mix
=1.0f
-vg_clampf((avg_distance
-30.0f
)/200.0f
,0.0f
,1.0f
);
300 vg_dsp
.reverb_dry_mix
=1.0f
-vg_dsp
.reverb_wet_mix
*0.4f
;
303 for( int i
=0; i
<8; i
++ )
304 total
+= vg_dsp
.echo_tunings
[i
];
307 float inverse
= 1.0f
/total
;
309 for( int i
=0;i
<8; i
++ ){
310 vg_dsp
.echo_tunings
[i
] *= inverse
;
314 for( int i
=0; i
<8; i
++ ){
315 float freq
= vg_lerpf( 200.0f
, 500.0f
, vg_dsp
.echo_tunings
[i
] );
317 #ifdef VG_ECHO_LPF_BUTTERWORTH
318 dsp_init_biquad_butterworth_lpf( &__echos_lpf
[i
], freq
);
320 dsp_update_lpf( &__echos_lpf
[i
], freq
);
324 for( int i
=0;i
<8; i
++ ){
325 vg_dsp
.echo_tunings
[i
] *= volumes
[i
];
329 static void vg_dsp_free( void )
331 glDeleteTextures( 1, &vg_dsp
.view_texture
);
334 static void vg_dsp_update_texture( void )
336 for( int i
=0; i
<512*512; i
++ ){
337 float v
= vg_clampf( vg_dsp
.buffer
[i
] * 0.5f
+ 0.5f
, 0.0f
, 1.0f
);
338 vg_dsp
.view_texture_buffer
[i
] = v
* 255.0f
;
342 #endif /* VG_AUDIO_DSP_H */