Mercurial > audlegacy-plugins
comparison src/console/Effects_Buffer.cxx @ 316:fb513e10174e trunk
[svn] - merge libconsole-blargg into mainline libconsole:
+ obsoletes plugins-ugly:sapplug
author | nenolod |
---|---|
date | Thu, 30 Nov 2006 19:54:33 -0800 |
parents | |
children | 986f098da058 |
comparison
equal
deleted
inserted
replaced
315:2294f3a6f136 | 316:fb513e10174e |
---|---|
1 // Game_Music_Emu 0.5.1. http://www.slack.net/~ant/ | |
2 | |
3 #include "Effects_Buffer.h" | |
4 | |
5 #include <string.h> | |
6 | |
7 /* Copyright (C) 2003-2006 Shay Green. This module is free software; you | |
8 can redistribute it and/or modify it under the terms of the GNU Lesser | |
9 General Public License as published by the Free Software Foundation; either | |
10 version 2.1 of the License, or (at your option) any later version. This | |
11 module is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
13 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | |
14 details. You should have received a copy of the GNU Lesser General Public | |
15 License along with this module; if not, write to the Free Software Foundation, | |
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ | |
17 | |
18 #include "blargg_source.h" | |
19 | |
20 #ifdef BLARGG_ENABLE_OPTIMIZER | |
21 #include BLARGG_ENABLE_OPTIMIZER | |
22 #endif | |
23 | |
24 typedef blargg_long fixed_t; | |
25 | |
26 #define TO_FIXED( f ) fixed_t ((f) * (1L << 15) + 0.5) | |
27 #define FMUL( x, y ) (((x) * (y)) >> 15) | |
28 | |
29 const unsigned echo_size = 4096; | |
30 const unsigned echo_mask = echo_size - 1; | |
31 BOOST_STATIC_ASSERT( (echo_size & echo_mask) == 0 ); // must be power of 2 | |
32 | |
33 const unsigned reverb_size = 8192 * 2; | |
34 const unsigned reverb_mask = reverb_size - 1; | |
35 BOOST_STATIC_ASSERT( (reverb_size & reverb_mask) == 0 ); // must be power of 2 | |
36 | |
37 Effects_Buffer::config_t::config_t() | |
38 { | |
39 pan_1 = -0.15f; | |
40 pan_2 = 0.15f; | |
41 reverb_delay = 88.0f; | |
42 reverb_level = 0.12f; | |
43 echo_delay = 61.0f; | |
44 echo_level = 0.10f; | |
45 delay_variance = 18.0f; | |
46 effects_enabled = false; | |
47 } | |
48 | |
49 void Effects_Buffer::set_depth( double d ) | |
50 { | |
51 float f = (float) d; | |
52 config_t c; | |
53 c.pan_1 = -0.6f * f; | |
54 c.pan_2 = 0.6f * f; | |
55 c.reverb_delay = 880 * 0.1f; | |
56 c.echo_delay = 610 * 0.1f; | |
57 if ( f > 0.5 ) | |
58 f = 0.5; // TODO: more linear reduction of extreme reverb/echo | |
59 c.reverb_level = 0.5f * f; | |
60 c.echo_level = 0.30f * f; | |
61 c.delay_variance = 180 * 0.1f; | |
62 c.effects_enabled = (d > 0.0f); | |
63 config( c ); | |
64 } | |
65 | |
66 Effects_Buffer::Effects_Buffer( bool center_only ) : Multi_Buffer( 2 ) | |
67 { | |
68 buf_count = center_only ? max_buf_count - 4 : max_buf_count; | |
69 | |
70 echo_pos = 0; | |
71 reverb_pos = 0; | |
72 | |
73 stereo_remain = 0; | |
74 effect_remain = 0; | |
75 effects_enabled = false; | |
76 set_depth( 0 ); | |
77 } | |
78 | |
79 Effects_Buffer::~Effects_Buffer() { } | |
80 | |
81 blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec ) | |
82 { | |
83 if ( !echo_buf.size() ) | |
84 RETURN_ERR( echo_buf.resize( echo_size ) ); | |
85 | |
86 if ( !reverb_buf.size() ) | |
87 RETURN_ERR( reverb_buf.resize( reverb_size ) ); | |
88 | |
89 for ( int i = 0; i < buf_count; i++ ) | |
90 RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) ); | |
91 | |
92 config( config_ ); | |
93 clear(); | |
94 | |
95 return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() ); | |
96 } | |
97 | |
98 void Effects_Buffer::clock_rate( long rate ) | |
99 { | |
100 for ( int i = 0; i < buf_count; i++ ) | |
101 bufs [i].clock_rate( rate ); | |
102 } | |
103 | |
104 void Effects_Buffer::bass_freq( int freq ) | |
105 { | |
106 for ( int i = 0; i < buf_count; i++ ) | |
107 bufs [i].bass_freq( freq ); | |
108 } | |
109 | |
110 void Effects_Buffer::clear() | |
111 { | |
112 stereo_remain = 0; | |
113 effect_remain = 0; | |
114 if ( echo_buf.size() ) | |
115 memset( &echo_buf [0], 0, echo_size * sizeof echo_buf [0] ); | |
116 | |
117 if ( reverb_buf.size() ) | |
118 memset( &reverb_buf [0], 0, reverb_size * sizeof reverb_buf [0] ); | |
119 | |
120 for ( int i = 0; i < buf_count; i++ ) | |
121 bufs [i].clear(); | |
122 } | |
123 | |
124 inline int pin_range( int n, int max, int min = 0 ) | |
125 { | |
126 if ( n < min ) | |
127 return min; | |
128 if ( n > max ) | |
129 return max; | |
130 return n; | |
131 } | |
132 | |
133 void Effects_Buffer::config( const config_t& cfg ) | |
134 { | |
135 channels_changed(); | |
136 | |
137 // clear echo and reverb buffers | |
138 if ( !config_.effects_enabled && cfg.effects_enabled && echo_buf.size() ) | |
139 { | |
140 memset( &echo_buf [0], 0, echo_size * sizeof echo_buf [0] ); | |
141 memset( &reverb_buf [0], 0, reverb_size * sizeof reverb_buf [0] ); | |
142 } | |
143 | |
144 config_ = cfg; | |
145 | |
146 if ( config_.effects_enabled ) | |
147 { | |
148 // convert to internal format | |
149 | |
150 chans.pan_1_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_1 ); | |
151 chans.pan_1_levels [1] = TO_FIXED( 2 ) - chans.pan_1_levels [0]; | |
152 | |
153 chans.pan_2_levels [0] = TO_FIXED( 1 ) - TO_FIXED( config_.pan_2 ); | |
154 chans.pan_2_levels [1] = TO_FIXED( 2 ) - chans.pan_2_levels [0]; | |
155 | |
156 chans.reverb_level = TO_FIXED( config_.reverb_level ); | |
157 chans.echo_level = TO_FIXED( config_.echo_level ); | |
158 | |
159 int delay_offset = int (1.0 / 2000 * config_.delay_variance * sample_rate()); | |
160 | |
161 int reverb_sample_delay = int (1.0 / 1000 * config_.reverb_delay * sample_rate()); | |
162 chans.reverb_delay_l = pin_range( reverb_size - | |
163 (reverb_sample_delay - delay_offset) * 2, reverb_size - 2, 0 ); | |
164 chans.reverb_delay_r = pin_range( reverb_size + 1 - | |
165 (reverb_sample_delay + delay_offset) * 2, reverb_size - 1, 1 ); | |
166 | |
167 int echo_sample_delay = int (1.0 / 1000 * config_.echo_delay * sample_rate()); | |
168 chans.echo_delay_l = pin_range( echo_size - 1 - (echo_sample_delay - delay_offset), | |
169 echo_size - 1 ); | |
170 chans.echo_delay_r = pin_range( echo_size - 1 - (echo_sample_delay + delay_offset), | |
171 echo_size - 1 ); | |
172 | |
173 chan_types [0].center = &bufs [0]; | |
174 chan_types [0].left = &bufs [3]; | |
175 chan_types [0].right = &bufs [4]; | |
176 | |
177 chan_types [1].center = &bufs [1]; | |
178 chan_types [1].left = &bufs [3]; | |
179 chan_types [1].right = &bufs [4]; | |
180 | |
181 chan_types [2].center = &bufs [2]; | |
182 chan_types [2].left = &bufs [5]; | |
183 chan_types [2].right = &bufs [6]; | |
184 assert( 2 < chan_types_count ); | |
185 } | |
186 else | |
187 { | |
188 // set up outputs | |
189 for ( unsigned i = 0; i < chan_types_count; i++ ) | |
190 { | |
191 channel_t& c = chan_types [i]; | |
192 c.center = &bufs [0]; | |
193 c.left = &bufs [1]; | |
194 c.right = &bufs [2]; | |
195 } | |
196 } | |
197 | |
198 if ( buf_count < max_buf_count ) | |
199 { | |
200 for ( int i = 0; i < chan_types_count; i++ ) | |
201 { | |
202 channel_t& c = chan_types [i]; | |
203 c.left = c.center; | |
204 c.right = c.center; | |
205 } | |
206 } | |
207 } | |
208 | |
209 Effects_Buffer::channel_t Effects_Buffer::channel( int i, int type ) | |
210 { | |
211 int out = 2; | |
212 if ( !type ) | |
213 { | |
214 out = i % 5; | |
215 if ( out > 2 ) | |
216 out = 2; | |
217 } | |
218 else if ( !(type & noise_type) && (type & type_index_mask) % 3 != 0 ) | |
219 { | |
220 out = type & 1; | |
221 } | |
222 return chan_types [out]; | |
223 } | |
224 | |
225 void Effects_Buffer::end_frame( blip_time_t clock_count ) | |
226 { | |
227 int bufs_used = 0; | |
228 for ( int i = 0; i < buf_count; i++ ) | |
229 { | |
230 bufs_used |= bufs [i].clear_modified() << i; | |
231 bufs [i].end_frame( clock_count ); | |
232 } | |
233 | |
234 int stereo_mask = (config_.effects_enabled ? 0x78 : 0x06); | |
235 if ( (bufs_used & stereo_mask) && buf_count == max_buf_count ) | |
236 stereo_remain = bufs [0].samples_avail() + bufs [0].output_latency(); | |
237 | |
238 if ( effects_enabled || config_.effects_enabled ) | |
239 effect_remain = bufs [0].samples_avail() + bufs [0].output_latency(); | |
240 | |
241 effects_enabled = config_.effects_enabled; | |
242 } | |
243 | |
244 long Effects_Buffer::samples_avail() const | |
245 { | |
246 return bufs [0].samples_avail() * 2; | |
247 } | |
248 | |
249 long Effects_Buffer::read_samples( blip_sample_t* out, long total_samples ) | |
250 { | |
251 require( total_samples % 2 == 0 ); // count must be even | |
252 | |
253 long remain = bufs [0].samples_avail(); | |
254 if ( remain > (total_samples >> 1) ) | |
255 remain = (total_samples >> 1); | |
256 total_samples = remain; | |
257 while ( remain ) | |
258 { | |
259 int active_bufs = buf_count; | |
260 long count = remain; | |
261 | |
262 // optimizing mixing to skip any channels which had nothing added | |
263 if ( effect_remain ) | |
264 { | |
265 if ( count > effect_remain ) | |
266 count = effect_remain; | |
267 | |
268 if ( stereo_remain ) | |
269 { | |
270 mix_enhanced( out, count ); | |
271 } | |
272 else | |
273 { | |
274 mix_mono_enhanced( out, count ); | |
275 active_bufs = 3; | |
276 } | |
277 } | |
278 else if ( stereo_remain ) | |
279 { | |
280 mix_stereo( out, count ); | |
281 active_bufs = 3; | |
282 } | |
283 else | |
284 { | |
285 mix_mono( out, count ); | |
286 active_bufs = 1; | |
287 } | |
288 | |
289 out += count * 2; | |
290 remain -= count; | |
291 | |
292 stereo_remain -= count; | |
293 if ( stereo_remain < 0 ) | |
294 stereo_remain = 0; | |
295 | |
296 effect_remain -= count; | |
297 if ( effect_remain < 0 ) | |
298 effect_remain = 0; | |
299 | |
300 for ( int i = 0; i < buf_count; i++ ) | |
301 { | |
302 if ( i < active_bufs ) | |
303 bufs [i].remove_samples( count ); | |
304 else | |
305 bufs [i].remove_silence( count ); // keep time synchronized | |
306 } | |
307 } | |
308 | |
309 return total_samples * 2; | |
310 } | |
311 | |
312 void Effects_Buffer::mix_mono( blip_sample_t* out_, blargg_long count ) | |
313 { | |
314 blip_sample_t* BLIP_RESTRICT out = out_; | |
315 int const bass = BLIP_READER_BASS( bufs [0] ); | |
316 BLIP_READER_BEGIN( c, bufs [0] ); | |
317 | |
318 // unrolled loop | |
319 for ( blargg_long n = count >> 1; n; --n ) | |
320 { | |
321 blargg_long cs0 = BLIP_READER_READ( c ); | |
322 BLIP_READER_NEXT( c, bass ); | |
323 | |
324 blargg_long cs1 = BLIP_READER_READ( c ); | |
325 BLIP_READER_NEXT( c, bass ); | |
326 | |
327 if ( (BOOST::int16_t) cs0 != cs0 ) | |
328 cs0 = 0x7FFF - (cs0 >> 24); | |
329 ((BOOST::uint32_t*) out) [0] = ((BOOST::uint16_t) cs0) | (cs0 << 16); | |
330 | |
331 if ( (BOOST::int16_t) cs1 != cs1 ) | |
332 cs1 = 0x7FFF - (cs1 >> 24); | |
333 ((BOOST::uint32_t*) out) [1] = ((BOOST::uint16_t) cs1) | (cs1 << 16); | |
334 out += 4; | |
335 } | |
336 | |
337 if ( count & 1 ) | |
338 { | |
339 int s = BLIP_READER_READ( c ); | |
340 BLIP_READER_NEXT( c, bass ); | |
341 out [0] = s; | |
342 out [1] = s; | |
343 if ( (BOOST::int16_t) s != s ) | |
344 { | |
345 s = 0x7FFF - (s >> 24); | |
346 out [0] = s; | |
347 out [1] = s; | |
348 } | |
349 } | |
350 | |
351 BLIP_READER_END( c, bufs [0] ); | |
352 } | |
353 | |
354 void Effects_Buffer::mix_stereo( blip_sample_t* out_, blargg_long count ) | |
355 { | |
356 blip_sample_t* BLIP_RESTRICT out = out_; | |
357 int const bass = BLIP_READER_BASS( bufs [0] ); | |
358 BLIP_READER_BEGIN( c, bufs [0] ); | |
359 BLIP_READER_BEGIN( l, bufs [1] ); | |
360 BLIP_READER_BEGIN( r, bufs [2] ); | |
361 | |
362 while ( count-- ) | |
363 { | |
364 int cs = BLIP_READER_READ( c ); | |
365 BLIP_READER_NEXT( c, bass ); | |
366 int left = cs + BLIP_READER_READ( l ); | |
367 int right = cs + BLIP_READER_READ( r ); | |
368 BLIP_READER_NEXT( l, bass ); | |
369 BLIP_READER_NEXT( r, bass ); | |
370 | |
371 if ( (BOOST::int16_t) left != left ) | |
372 left = 0x7FFF - (left >> 24); | |
373 | |
374 out [0] = left; | |
375 out [1] = right; | |
376 | |
377 out += 2; | |
378 | |
379 if ( (BOOST::int16_t) right != right ) | |
380 out [-1] = 0x7FFF - (right >> 24); | |
381 } | |
382 | |
383 BLIP_READER_END( r, bufs [2] ); | |
384 BLIP_READER_END( l, bufs [1] ); | |
385 BLIP_READER_END( c, bufs [0] ); | |
386 } | |
387 | |
388 void Effects_Buffer::mix_mono_enhanced( blip_sample_t* out_, blargg_long count ) | |
389 { | |
390 blip_sample_t* BLIP_RESTRICT out = out_; | |
391 int const bass = BLIP_READER_BASS( bufs [2] ); | |
392 BLIP_READER_BEGIN( center, bufs [2] ); | |
393 BLIP_READER_BEGIN( sq1, bufs [0] ); | |
394 BLIP_READER_BEGIN( sq2, bufs [1] ); | |
395 | |
396 blip_sample_t* const reverb_buf = this->reverb_buf.begin(); | |
397 blip_sample_t* const echo_buf = this->echo_buf.begin(); | |
398 int echo_pos = this->echo_pos; | |
399 int reverb_pos = this->reverb_pos; | |
400 | |
401 while ( count-- ) | |
402 { | |
403 int sum1_s = BLIP_READER_READ( sq1 ); | |
404 int sum2_s = BLIP_READER_READ( sq2 ); | |
405 | |
406 BLIP_READER_NEXT( sq1, bass ); | |
407 BLIP_READER_NEXT( sq2, bass ); | |
408 | |
409 int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) + | |
410 FMUL( sum2_s, chans.pan_2_levels [0] ) + | |
411 reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask]; | |
412 | |
413 int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) + | |
414 FMUL( sum2_s, chans.pan_2_levels [1] ) + | |
415 reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask]; | |
416 | |
417 fixed_t reverb_level = chans.reverb_level; | |
418 reverb_buf [reverb_pos] = FMUL( new_reverb_l, reverb_level ); | |
419 reverb_buf [reverb_pos + 1] = FMUL( new_reverb_r, reverb_level ); | |
420 reverb_pos = (reverb_pos + 2) & reverb_mask; | |
421 | |
422 int sum3_s = BLIP_READER_READ( center ); | |
423 BLIP_READER_NEXT( center, bass ); | |
424 | |
425 int left = new_reverb_l + sum3_s + FMUL( chans.echo_level, | |
426 echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] ); | |
427 int right = new_reverb_r + sum3_s + FMUL( chans.echo_level, | |
428 echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] ); | |
429 | |
430 echo_buf [echo_pos] = sum3_s; | |
431 echo_pos = (echo_pos + 1) & echo_mask; | |
432 | |
433 if ( (BOOST::int16_t) left != left ) | |
434 left = 0x7FFF - (left >> 24); | |
435 | |
436 out [0] = left; | |
437 out [1] = right; | |
438 | |
439 out += 2; | |
440 | |
441 if ( (BOOST::int16_t) right != right ) | |
442 out [-1] = 0x7FFF - (right >> 24); | |
443 } | |
444 this->reverb_pos = reverb_pos; | |
445 this->echo_pos = echo_pos; | |
446 | |
447 BLIP_READER_END( sq1, bufs [0] ); | |
448 BLIP_READER_END( sq2, bufs [1] ); | |
449 BLIP_READER_END( center, bufs [2] ); | |
450 } | |
451 | |
452 void Effects_Buffer::mix_enhanced( blip_sample_t* out_, blargg_long count ) | |
453 { | |
454 blip_sample_t* BLIP_RESTRICT out = out_; | |
455 int const bass = BLIP_READER_BASS( bufs [2] ); | |
456 BLIP_READER_BEGIN( center, bufs [2] ); | |
457 BLIP_READER_BEGIN( l1, bufs [3] ); | |
458 BLIP_READER_BEGIN( r1, bufs [4] ); | |
459 BLIP_READER_BEGIN( l2, bufs [5] ); | |
460 BLIP_READER_BEGIN( r2, bufs [6] ); | |
461 BLIP_READER_BEGIN( sq1, bufs [0] ); | |
462 BLIP_READER_BEGIN( sq2, bufs [1] ); | |
463 | |
464 blip_sample_t* const reverb_buf = this->reverb_buf.begin(); | |
465 blip_sample_t* const echo_buf = this->echo_buf.begin(); | |
466 int echo_pos = this->echo_pos; | |
467 int reverb_pos = this->reverb_pos; | |
468 | |
469 while ( count-- ) | |
470 { | |
471 int sum1_s = BLIP_READER_READ( sq1 ); | |
472 int sum2_s = BLIP_READER_READ( sq2 ); | |
473 | |
474 BLIP_READER_NEXT( sq1, bass ); | |
475 BLIP_READER_NEXT( sq2, bass ); | |
476 | |
477 int new_reverb_l = FMUL( sum1_s, chans.pan_1_levels [0] ) + | |
478 FMUL( sum2_s, chans.pan_2_levels [0] ) + BLIP_READER_READ( l1 ) + | |
479 reverb_buf [(reverb_pos + chans.reverb_delay_l) & reverb_mask]; | |
480 | |
481 int new_reverb_r = FMUL( sum1_s, chans.pan_1_levels [1] ) + | |
482 FMUL( sum2_s, chans.pan_2_levels [1] ) + BLIP_READER_READ( r1 ) + | |
483 reverb_buf [(reverb_pos + chans.reverb_delay_r) & reverb_mask]; | |
484 | |
485 BLIP_READER_NEXT( l1, bass ); | |
486 BLIP_READER_NEXT( r1, bass ); | |
487 | |
488 fixed_t reverb_level = chans.reverb_level; | |
489 reverb_buf [reverb_pos] = FMUL( new_reverb_l, reverb_level ); | |
490 reverb_buf [reverb_pos + 1] = FMUL( new_reverb_r, reverb_level ); | |
491 reverb_pos = (reverb_pos + 2) & reverb_mask; | |
492 | |
493 int sum3_s = BLIP_READER_READ( center ); | |
494 BLIP_READER_NEXT( center, bass ); | |
495 | |
496 int left = new_reverb_l + sum3_s + BLIP_READER_READ( l2 ) + FMUL( chans.echo_level, | |
497 echo_buf [(echo_pos + chans.echo_delay_l) & echo_mask] ); | |
498 int right = new_reverb_r + sum3_s + BLIP_READER_READ( r2 ) + FMUL( chans.echo_level, | |
499 echo_buf [(echo_pos + chans.echo_delay_r) & echo_mask] ); | |
500 | |
501 BLIP_READER_NEXT( l2, bass ); | |
502 BLIP_READER_NEXT( r2, bass ); | |
503 | |
504 echo_buf [echo_pos] = sum3_s; | |
505 echo_pos = (echo_pos + 1) & echo_mask; | |
506 | |
507 if ( (BOOST::int16_t) left != left ) | |
508 left = 0x7FFF - (left >> 24); | |
509 | |
510 out [0] = left; | |
511 out [1] = right; | |
512 | |
513 out += 2; | |
514 | |
515 if ( (BOOST::int16_t) right != right ) | |
516 out [-1] = 0x7FFF - (right >> 24); | |
517 } | |
518 this->reverb_pos = reverb_pos; | |
519 this->echo_pos = echo_pos; | |
520 | |
521 BLIP_READER_END( l1, bufs [3] ); | |
522 BLIP_READER_END( r1, bufs [4] ); | |
523 BLIP_READER_END( l2, bufs [5] ); | |
524 BLIP_READER_END( r2, bufs [6] ); | |
525 BLIP_READER_END( sq1, bufs [0] ); | |
526 BLIP_READER_END( sq2, bufs [1] ); | |
527 BLIP_READER_END( center, bufs [2] ); | |
528 } | |
529 |