11 u8
*view_texture_buffer
;
14 float echo_distances
[14],
23 static float *dsp_allocate( u32 samples
)
25 samples
= vg_align4( samples
);
27 if( vg_dsp
.allocations
+ samples
> (1024*1024)/4 )
28 vg_fatal_error( "too much dsp" );
30 float *buf
= &vg_dsp
.buffer
[ vg_dsp
.allocations
];
31 vg_dsp
.allocations
+= samples
;
39 * ----------------------------------------------
61 f32 a0
, a1
, a2
, b1
, b2
, c0
, d0
,
62 xnz1
, xnz2
, ynz1
, ynz2
, offset
;
65 static f32
dsp_biquad_process( struct dsp_biquad
*bq
, f32 xn
){
66 f32 yn
= + bq
->a0
*xn
+ bq
->a1
*bq
->xnz1
+ bq
->a2
*bq
->xnz2
67 - bq
->b1
*bq
->ynz1
- bq
->b2
*bq
->ynz2
;
72 return yn
+ bq
->offset
;
75 static void dsp_init_biquad_butterworth_lpf( struct dsp_biquad
*bq
, f32 fc
){
76 f32 c
= 1.0f
/tanf(VG_PIf
*fc
/ 44100.0f
);
77 bq
->a0
= 1.0f
/ (1.0f
+ sqrtf(2.0f
)*c
+ powf(c
, 2.0f
) );
78 bq
->a1
= 2.0f
* bq
->a0
;
80 bq
->b1
= 2.0f
* bq
->a0
*(1.0f
- powf(c
, 2.0f
));
81 bq
->b2
= bq
->a0
* (1.0f
- sqrtf(2.0f
)*c
+ powf(c
, 2.0f
) );
84 static inline void dsp_read_delay( struct dsp_delay
*delay
, float *s
, u32 t
){
85 u32 index
= delay
->cur
+t
;
87 if( index
>= delay
->length
)
88 index
-= delay
->length
;
90 *s
= delay
->buffer
[ index
];
93 static inline void dsp_write_delay( struct dsp_delay
*delay
, float *s
)
95 u32 index
= delay
->cur
;
96 delay
->buffer
[ index
] = *s
;
100 if( delay
->cur
>= delay
->length
)
104 static void dsp_init_delay( struct dsp_delay
*delay
, float length
)
106 delay
->length
= 44100.0f
* length
;
108 delay
->buffer
= dsp_allocate( delay
->length
);
110 for( int i
=0; i
<delay
->length
; i
++ )
111 delay
->buffer
[i
] = 0.0f
;
114 static void dsp_update_lpf( struct dsp_lpf
*lpf
, float freq
)
116 lpf
->exponent
= 1.0f
-expf( -(1.0f
/44100.0f
) * 2.0f
* VG_PIf
* freq
);
119 static void dsp_init_lpf( struct dsp_lpf
*lpf
, float freq
)
121 lpf
->buffer
= dsp_allocate( 4 );
122 lpf
->buffer
[0] = 0.0f
;
123 dsp_update_lpf( lpf
, freq
);
126 static inline void dsp_write_lpf( struct dsp_lpf
*lpf
, float *s
)
128 float diff
= *s
- lpf
->buffer
[0];
129 lpf
->buffer
[0] += diff
* lpf
->exponent
;
132 static inline void dsp_read_lpf( struct dsp_lpf
*lpf
, float *s
)
137 static void dsp_init_schroeder( struct dsp_schroeder
*sch
, float length
,
140 dsp_init_delay( &sch
->M
, length
);
144 static inline void dsp_process_schroeder( struct dsp_schroeder
*sch
,
145 float *input
, float *output
)
150 dsp_read_delay( &sch
->M
, &delay_output
, 1 );
152 float feedback_attenuated
= delay_output
* sch
->gain
,
153 input_feedback_sum
= dry
+ feedback_attenuated
;
155 dsp_write_delay( &sch
->M
, &input_feedback_sum
);
157 *output
= delay_output
- input_feedback_sum
*sch
->gain
;
160 /* temporary global design */
161 static struct dsp_lpf __lpf_mud_free
;
162 static struct dsp_delay __echos
[8];
163 static struct dsp_lpf __echos_lpf
[8];
164 static struct dsp_schroeder __diffusion_chain
[8];
166 static void async_vg_dsp_alloc_texture( void *payload
, u32 size
)
168 glGenTextures( 1, &vg_dsp
.view_texture
);
169 glBindTexture( GL_TEXTURE_2D
, vg_dsp
.view_texture
);
170 glTexImage2D( GL_TEXTURE_2D
, 0, GL_RGBA
, 256, 256, 0,
171 GL_RGBA
, GL_UNSIGNED_BYTE
, vg_dsp
.view_texture_buffer
);
172 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
173 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
176 static void vg_dsp_init( void ){
177 vg_rand_seed( &vg_dsp
.rand
, 461 );
178 vg_dsp
.buffer
= vg_linear_alloc( vg_mem
.rtmemory
, 1024*1024*1 );
179 vg_dsp
.view_texture_buffer
= vg_linear_alloc( vg_mem
.rtmemory
, 512*512 );
181 vg_async_call( async_vg_dsp_alloc_texture
, NULL
, 0 );
183 /* temporary global design */
184 dsp_init_lpf( &__lpf_mud_free
, 125.0f
);
187 { 2.0f
, 4.0f
, 8.0f
, 16.0f
, 32.0f
, 64.0f
, 128.0f
, 256.0f
};
189 float variance
= 0.1f
;
191 for( int i
=0; i
<8; i
++ ){
192 float reflection_time
= ((sizes
[i
])/343.0f
) * 1000.0f
;
194 float var
= 1.0f
+ (vg_randf64(&vg_dsp
.rand
)*2.0f
- 1.0f
) * variance
,
195 total
= reflection_time
* var
;
197 dsp_init_delay( &__echos
[i
], total
/ 1000.0f
);
199 float freq
= vg_lerpf( 800.0f
, 350.0f
, sizes
[i
] / 256.0f
);
200 dsp_init_lpf( &__echos_lpf
[i
], freq
);
203 float diffusions
[] = { 187.0f
, 159.0f
, 143.0f
, 121.0f
,
204 79.0f
, 57.0f
, 27.0f
, 11.0f
};
206 for( int i
=0; i
<8; i
++ ){
207 dsp_init_schroeder( __diffusion_chain
+i
, diffusions
[i
]/1000.0f
, 0.7f
);
211 static void vg_dsp_process( float *stereo_in
, float *stereo_out
)
213 float in_total
= (stereo_in
[0]+stereo_in
[1])*0.5f
;
214 float recieved
= 0.0f
;
216 for( int i
=0; i
<8; i
++ ){
218 dsp_read_delay( __echos
+i
, &echo
, 1 );
219 dsp_write_lpf( __echos_lpf
+i
, &echo
);
220 dsp_read_lpf( __echos_lpf
+i
, &echo
);
222 recieved
+= echo
* vg_dsp
.echo_tunings
[i
]*0.98;
225 float diffused
= recieved
;
227 for( int i
=0; i
<8; i
++ ){
228 dsp_process_schroeder( __diffusion_chain
+i
, &diffused
, &diffused
);
231 float diffuse_mix
= vg_dsp
.reverb_wet_mix
;
232 diffuse_mix
= vg_lerpf( recieved
, diffused
, diffuse_mix
);
233 float total
= in_total
+ diffuse_mix
;
236 dsp_write_lpf( &__lpf_mud_free
, &total
);
237 dsp_read_lpf( &__lpf_mud_free
, &low_mud
);
241 for( int i
=0; i
<8; i
++ )
242 dsp_write_delay( __echos
+i
, &total
);
244 stereo_out
[0] = stereo_in
[0]*vg_dsp
.reverb_dry_mix
;
245 stereo_out
[1] = stereo_in
[1]*vg_dsp
.reverb_dry_mix
;
246 stereo_out
[0] += diffuse_mix
*2.0f
*vg_dsp
.reverb_wet_mix
;
247 stereo_out
[1] += diffuse_mix
*2.0f
*vg_dsp
.reverb_wet_mix
;
250 static void dsp_update_tunings(void)
253 { 2.0f
, 4.0f
, 8.0f
, 16.0f
, 32.0f
, 64.0f
, 128.0f
, 256.0f
};
255 { 0.2f
, 0.3f
, 0.5f
, 0.7f
, 0.8f
, 0.9f
, 1.0f
, 1.0f
};
257 float avg_distance
= 0.0f
;
259 for( int i
=0; i
<8; i
++ )
260 vg_dsp
.echo_tunings
[i
] = 0.5f
;
262 for( int j
=0; j
<14; j
++ ){
263 float d
= vg_dsp
.echo_distances
[j
];
265 for( int i
=0; i
<7; i
++ ){
266 if( d
< sizes
[i
+1] ){
267 float range
= sizes
[i
+1]-sizes
[i
];
268 float t
= vg_clampf( (d
- sizes
[i
])/range
, 0.0f
, 1.0f
);
270 vg_dsp
.echo_tunings
[i
] += 1.0f
-t
;
271 vg_dsp
.echo_tunings
[i
+1] += t
;
279 avg_distance
/= 14.0f
;
282 vg_dsp
.reverb_wet_mix
=1.0f
-vg_clampf((avg_distance
-30.0f
)/200.0f
,0.0f
,1.0f
);
283 vg_dsp
.reverb_dry_mix
=1.0f
-vg_dsp
.reverb_wet_mix
*0.4f
;
286 for( int i
=0; i
<8; i
++ )
287 total
+= vg_dsp
.echo_tunings
[i
];
290 float inverse
= 1.0f
/total
;
292 for( int i
=0;i
<8; i
++ ){
293 vg_dsp
.echo_tunings
[i
] *= inverse
;
297 for( int i
=0; i
<8; i
++ ){
298 float freq
= vg_lerpf( 200.0f
, 500.0f
, vg_dsp
.echo_tunings
[i
] );
299 dsp_update_lpf( &__echos_lpf
[i
], freq
);
302 for( int i
=0;i
<8; i
++ ){
303 vg_dsp
.echo_tunings
[i
] *= volumes
[i
];
307 static void vg_dsp_free( void )
309 glDeleteTextures( 1, &vg_dsp
.view_texture
);
312 static void vg_dsp_update_texture( void )
314 for( int i
=0; i
<512*512; i
++ ){
315 float v
= vg_clampf( vg_dsp
.buffer
[i
] * 0.5f
+ 0.5f
, 0.0f
, 1.0f
);
316 vg_dsp
.view_texture_buffer
[i
] = v
* 255.0f
;
320 #endif /* VG_AUDIO_DSP_H */