Effects_Buffer.cpp (15240B)
1// Game_Music_Emu $vers. http://www.slack.net/~ant/ 2 3#include "Effects_Buffer.h" 4 5#include <string.h> 6 7/* Copyright (C) 2006-2007 Shay Green. This module is free software; you 8can redistribute it and/or modify it under the terms of the GNU Lesser 9General Public License as published by the Free Software Foundation; either 10version 2.1 of the License, or (at your option) any later version. This 11module is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14details. You should have received a copy of the GNU Lesser General Public 15License along with this module; if not, write to the Free Software Foundation, 16Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 17 18#include "blargg_source.h" 19 20int const fixed_shift = 12; 21#define TO_FIXED( f ) fixed_t ((f) * ((fixed_t) 1 << fixed_shift)) 22#define FROM_FIXED( f ) ((f) >> fixed_shift) 23 24int const max_read = 2560; // determines minimum delay 25 26Effects_Buffer::Effects_Buffer( int max_bufs, long echo_size_ ) : Multi_Buffer( stereo ) 27{ 28 echo_size = (int)max( max_read * (long) stereo, echo_size_ & ~1 ); 29 clock_rate_ = 0; 30 bass_freq_ = 90; 31 bufs = 0; 32 bufs_size = 0; 33 bufs_max = max( max_bufs, (int) extra_chans ); 34 no_echo = true; 35 no_effects = true; 36 37 // defaults 38 config_.enabled = false; 39 config_.delay [0] = 120; 40 config_.delay [1] = 122; 41 config_.feedback = 0.2f; 42 config_.treble = 0.4f; 43 44 static float const sep = 0.8f; 45 config_.side_chans [0].pan = -sep; 46 config_.side_chans [1].pan = +sep; 47 config_.side_chans [0].vol = 1.0f; 48 config_.side_chans [1].vol = 1.0f; 49 50 memset( &s, 0, sizeof s ); 51 clear(); 52} 53 54Effects_Buffer::~Effects_Buffer() 55{ 56 delete_bufs(); 57} 58 59// avoid using new [] 60blargg_err_t Effects_Buffer::new_bufs( int size ) 61{ 62 bufs = (buf_t*) malloc( size * sizeof *bufs ); 63 CHECK_ALLOC( bufs ); 64 for ( int i = 0; i < size; i++ ) 65 new (bufs + i) buf_t; 66 bufs_size = size; 67 return 0; 68} 69 70void Effects_Buffer::delete_bufs() 71{ 72 if ( bufs ) 73 { 74 for ( int i = bufs_size; --i >= 0; ) 75 bufs [i].~buf_t(); 76 free( bufs ); 77 bufs = 0; 78 } 79 bufs_size = 0; 80} 81 82blargg_err_t Effects_Buffer::set_sample_rate( long rate, int msec ) 83{ 84 // extra to allow farther past-the-end pointers 85 mixer.samples_read = 0; 86 RETURN_ERR( echo.resize( echo_size + stereo ) ); 87 return Multi_Buffer::set_sample_rate( rate, msec ); 88} 89 90void Effects_Buffer::clock_rate( long rate ) 91{ 92 clock_rate_ = rate; 93 for ( int i = bufs_size; --i >= 0; ) 94 bufs [i].clock_rate( clock_rate_ ); 95} 96 97void Effects_Buffer::bass_freq( int freq ) 98{ 99 bass_freq_ = freq; 100 for ( int i = bufs_size; --i >= 0; ) 101 bufs [i].bass_freq( bass_freq_ ); 102} 103 104blargg_err_t Effects_Buffer::set_channel_count( int count, int const* types ) 105{ 106 RETURN_ERR( Multi_Buffer::set_channel_count( count, types ) ); 107 108 delete_bufs(); 109 110 mixer.samples_read = 0; 111 112 RETURN_ERR( chans.resize( count + extra_chans ) ); 113 114 RETURN_ERR( new_bufs( min( bufs_max, count + extra_chans ) ) ); 115 116 for ( int i = bufs_size; --i >= 0; ) 117 RETURN_ERR( bufs [i].set_sample_rate( sample_rate(), length() ) ); 118 119 for ( int i = (int)chans.size(); --i >= 0; ) 120 { 121 chan_t& ch = chans [i]; 122 ch.cfg.vol = 1.0f; 123 ch.cfg.pan = 0.0f; 124 ch.cfg.surround = false; 125 ch.cfg.echo = false; 126 } 127 // side channels with echo 128 chans [2].cfg.echo = true; 129 chans [3].cfg.echo = true; 130 131 clock_rate( clock_rate_ ); 132 bass_freq( bass_freq_ ); 133 apply_config(); 134 clear(); 135 136 return 0; 137} 138 139void Effects_Buffer::clear_echo() 140{ 141 if ( echo.size() ) 142 memset( echo.begin(), 0, echo.size() * sizeof echo [0] ); 143} 144 145void Effects_Buffer::clear() 146{ 147 echo_pos = 0; 148 s.low_pass [0] = 0; 149 s.low_pass [1] = 0; 150 mixer.samples_read = 0; 151 152 for ( int i = bufs_size; --i >= 0; ) 153 bufs [i].clear(); 154 clear_echo(); 155} 156 157Effects_Buffer::channel_t Effects_Buffer::channel( int i ) 158{ 159 i += extra_chans; 160 require( extra_chans <= i && i < (int) chans.size() ); 161 return chans [i].channel; 162} 163 164 165// Configuration 166 167// 3 wave positions with/without surround, 2 multi (one with same config as wave) 168int const simple_bufs = 3 * 2 + 2 - 1; 169 170Simple_Effects_Buffer::Simple_Effects_Buffer() : 171 Effects_Buffer( extra_chans + simple_bufs, 18 * 1024L ) 172{ 173 config_.echo = 0.20f; 174 config_.stereo = 0.20f; 175 config_.surround = true; 176 config_.enabled = false; 177} 178 179void Simple_Effects_Buffer::apply_config() 180{ 181 Effects_Buffer::config_t& c = Effects_Buffer::config(); 182 183 c.enabled = config_.enabled; 184 if ( c.enabled ) 185 { 186 c.delay [0] = 120; 187 c.delay [1] = 122; 188 c.feedback = config_.echo * 0.7f; 189 c.treble = 0.6f - 0.3f * config_.echo; 190 191 float sep = config_.stereo + 0.80f; 192 if ( sep > 1.0f ) 193 sep = 1.0f; 194 195 c.side_chans [0].pan = -sep; 196 c.side_chans [1].pan = +sep; 197 198 for ( int i = channel_count(); --i >= 0; ) 199 { 200 chan_config_t& ch = Effects_Buffer::chan_config( i ); 201 202 ch.pan = 0.0f; 203 ch.surround = config_.surround; 204 ch.echo = false; 205 206 int const type = (channel_types() ? channel_types() [i] : 0); 207 if ( !(type & noise_type) ) 208 { 209 int index = (type & type_index_mask) % 6 - 3; 210 if ( index < 0 ) 211 { 212 index += 3; 213 ch.surround = false; 214 ch.echo = true; 215 } 216 if ( index >= 1 ) 217 { 218 ch.pan = config_.stereo; 219 if ( index == 1 ) 220 ch.pan = -ch.pan; 221 } 222 } 223 else if ( type & 1 ) 224 { 225 ch.surround = false; 226 } 227 } 228 } 229 230 Effects_Buffer::apply_config(); 231} 232 233int Effects_Buffer::min_delay() const 234{ 235 require( sample_rate() ); 236 return max_read * 1000L / sample_rate(); 237} 238 239int Effects_Buffer::max_delay() const 240{ 241 require( sample_rate() ); 242 return (echo_size / stereo - max_read) * 1000L / sample_rate(); 243} 244 245void Effects_Buffer::apply_config() 246{ 247 int i; 248 249 if ( !bufs_size ) 250 return; 251 252 s.treble = TO_FIXED( config_.treble ); 253 254 bool echo_dirty = false; 255 256 fixed_t old_feedback = s.feedback; 257 s.feedback = TO_FIXED( config_.feedback ); 258 if ( !old_feedback && s.feedback ) 259 echo_dirty = true; 260 261 // delays 262 for ( i = stereo; --i >= 0; ) 263 { 264 long delay = config_.delay [i] * sample_rate() / 1000 * stereo; 265 delay = max( delay, long (max_read * stereo) ); 266 delay = min( delay, long (echo_size - max_read * stereo) ); 267 if ( s.delay [i] != delay ) 268 { 269 s.delay [i] = delay; 270 echo_dirty = true; 271 } 272 } 273 274 // side channels 275 for ( i = 2; --i >= 0; ) 276 { 277 chans [i+2].cfg.vol = chans [i].cfg.vol = config_.side_chans [i].vol * 0.5f; 278 chans [i+2].cfg.pan = chans [i].cfg.pan = config_.side_chans [i].pan; 279 } 280 281 // convert volumes 282 for ( i = (int)chans.size(); --i >= 0; ) 283 { 284 chan_t& ch = chans [i]; 285 ch.vol [0] = TO_FIXED( ch.cfg.vol - ch.cfg.vol * ch.cfg.pan ); 286 ch.vol [1] = TO_FIXED( ch.cfg.vol + ch.cfg.vol * ch.cfg.pan ); 287 if ( ch.cfg.surround ) 288 ch.vol [0] = -ch.vol [0]; 289 } 290 291 assign_buffers(); 292 293 // set side channels 294 for ( i = (int)chans.size(); --i >= 0; ) 295 { 296 chan_t& ch = chans [i]; 297 ch.channel.left = chans [ch.cfg.echo*2 ].channel.center; 298 ch.channel.right = chans [ch.cfg.echo*2+1].channel.center; 299 } 300 301 bool old_echo = !no_echo && !no_effects; 302 303 // determine whether effects and echo are needed at all 304 no_effects = true; 305 no_echo = true; 306 for ( i = (int)chans.size(); --i >= extra_chans; ) 307 { 308 chan_t& ch = chans [i]; 309 if ( ch.cfg.echo && s.feedback ) 310 no_echo = false; 311 312 if ( ch.vol [0] != TO_FIXED( 1 ) || ch.vol [1] != TO_FIXED( 1 ) ) 313 no_effects = false; 314 } 315 if ( !no_echo ) 316 no_effects = false; 317 318 if ( chans [0].vol [0] != TO_FIXED( 1 ) || 319 chans [0].vol [1] != TO_FIXED( 0 ) || 320 chans [1].vol [0] != TO_FIXED( 0 ) || 321 chans [1].vol [1] != TO_FIXED( 1 ) ) 322 no_effects = false; 323 324 if ( !config_.enabled ) 325 no_effects = true; 326 327 if ( no_effects ) 328 { 329 for ( i = (int)chans.size(); --i >= 0; ) 330 { 331 chan_t& ch = chans [i]; 332 ch.channel.center = &bufs [2]; 333 ch.channel.left = &bufs [0]; 334 ch.channel.right = &bufs [1]; 335 } 336 } 337 338 mixer.bufs [0] = &bufs [0]; 339 mixer.bufs [1] = &bufs [1]; 340 mixer.bufs [2] = &bufs [2]; 341 342 if ( echo_dirty || (!old_echo && (!no_echo && !no_effects)) ) 343 clear_echo(); 344 345 channels_changed(); 346} 347 348void Effects_Buffer::assign_buffers() 349{ 350 // assign channels to buffers 351 int buf_count = 0; 352 for ( int i = 0; i < (int) chans.size(); i++ ) 353 { 354 // put second two side channels at end to give priority to main channels 355 // in case closest matching is necessary 356 int x = i; 357 if ( i > 1 ) 358 x += 2; 359 if ( x >= (int) chans.size() ) 360 x -= (chans.size() - 2); 361 chan_t& ch = chans [x]; 362 363 int b = 0; 364 for ( ; b < buf_count; b++ ) 365 { 366 if ( ch.vol [0] == bufs [b].vol [0] && 367 ch.vol [1] == bufs [b].vol [1] && 368 (ch.cfg.echo == bufs [b].echo || !s.feedback) ) 369 break; 370 } 371 372 if ( b >= buf_count ) 373 { 374 if ( buf_count < bufs_max ) 375 { 376 bufs [b].vol [0] = ch.vol [0]; 377 bufs [b].vol [1] = ch.vol [1]; 378 bufs [b].echo = ch.cfg.echo; 379 buf_count++; 380 } 381 else 382 { 383 // TODO: this is a mess, needs refinement 384 dprintf( "Effects_Buffer ran out of buffers; using closest match\n" ); 385 b = 0; 386 fixed_t best_dist = TO_FIXED( 8 ); 387 for ( int h = buf_count; --h >= 0; ) 388 { 389 #define CALC_LEVELS( vols, sum, diff, surround ) \ 390 fixed_t sum, diff;\ 391 bool surround = false;\ 392 {\ 393 fixed_t vol_0 = vols [0];\ 394 if ( vol_0 < 0 ) vol_0 = -vol_0, surround = true;\ 395 fixed_t vol_1 = vols [1];\ 396 if ( vol_1 < 0 ) vol_1 = -vol_1, surround = true;\ 397 sum = vol_0 + vol_1;\ 398 diff = vol_0 - vol_1;\ 399 } 400 CALC_LEVELS( ch.vol, ch_sum, ch_diff, ch_surround ); 401 CALC_LEVELS( bufs [h].vol, buf_sum, buf_diff, buf_surround ); 402 403 fixed_t dist = abs( ch_sum - buf_sum ) + abs( ch_diff - buf_diff ); 404 405 if ( ch_surround != buf_surround ) 406 dist += TO_FIXED( 1 ) / 2; 407 408 if ( s.feedback && ch.cfg.echo != bufs [h].echo ) 409 dist += TO_FIXED( 1 ) / 2; 410 411 if ( best_dist > dist ) 412 { 413 best_dist = dist; 414 b = h; 415 } 416 } 417 } 418 } 419 420 //dprintf( "ch %d->buf %d\n", x, b ); 421 ch.channel.center = &bufs [b]; 422 } 423} 424 425 426// Mixing 427 428void Effects_Buffer::end_frame( blip_time_t time ) 429{ 430 for ( int i = bufs_size; --i >= 0; ) 431 bufs [i].end_frame( time ); 432} 433 434long Effects_Buffer::read_samples( blip_sample_t* out, long out_size ) 435{ 436 out_size = min( out_size, samples_avail() ); 437 438 int pair_count = int (out_size >> 1); 439 require( pair_count * stereo == out_size ); // must read an even number of samples 440 if ( pair_count ) 441 { 442 if ( no_effects ) 443 { 444 mixer.read_pairs( out, pair_count ); 445 } 446 else 447 { 448 int pairs_remain = pair_count; 449 do 450 { 451 // mix at most max_read pairs at a time 452 int count = max_read; 453 if ( count > pairs_remain ) 454 count = pairs_remain; 455 456 if ( no_echo ) 457 { 458 // optimization: clear echo here to keep mix_effects() a leaf function 459 echo_pos = 0; 460 memset( echo.begin(), 0, count * stereo * sizeof echo [0] ); 461 } 462 mix_effects( out, count ); 463 464 blargg_long new_echo_pos = echo_pos + count * stereo; 465 if ( new_echo_pos >= echo_size ) 466 new_echo_pos -= echo_size; 467 echo_pos = new_echo_pos; 468 assert( echo_pos < echo_size ); 469 470 out += count * stereo; 471 mixer.samples_read += count; 472 pairs_remain -= count; 473 } 474 while ( pairs_remain ); 475 } 476 477 if ( samples_avail() <= 0 || immediate_removal() ) 478 { 479 for ( int i = bufs_size; --i >= 0; ) 480 { 481 buf_t& b = bufs [i]; 482 // TODO: might miss non-silence settling since it checks END of last read 483 if ( b.non_silent() ) 484 b.remove_samples( mixer.samples_read ); 485 else 486 b.remove_silence( mixer.samples_read ); 487 } 488 mixer.samples_read = 0; 489 } 490 } 491 return out_size; 492} 493 494void Effects_Buffer::mix_effects( blip_sample_t* out_, int pair_count ) 495{ 496 typedef fixed_t stereo_fixed_t [stereo]; 497 498 // add channels with echo, do echo, add channels without echo, then convert to 16-bit and output 499 int echo_phase = 1; 500 do 501 { 502 // mix any modified buffers 503 { 504 buf_t* buf = bufs; 505 int bufs_remain = bufs_size; 506 do 507 { 508 if ( buf->non_silent() && ( buf->echo == !!echo_phase ) ) 509 { 510 stereo_fixed_t* BLIP_RESTRICT out = (stereo_fixed_t*) &echo [echo_pos]; 511 int const bass = BLIP_READER_BASS( *buf ); 512 BLIP_READER_BEGIN( in, *buf ); 513 BLIP_READER_ADJ_( in, mixer.samples_read ); 514 fixed_t const vol_0 = buf->vol [0]; 515 fixed_t const vol_1 = buf->vol [1]; 516 517 int count = unsigned (echo_size - echo_pos) / stereo; 518 int remain = pair_count; 519 if ( count > remain ) 520 count = remain; 521 do 522 { 523 remain -= count; 524 BLIP_READER_ADJ_( in, count ); 525 526 out += count; 527 int offset = -count; 528 do 529 { 530 fixed_t s = BLIP_READER_READ( in ); 531 BLIP_READER_NEXT_IDX_( in, bass, offset ); 532 533 out [offset] [0] += s * vol_0; 534 out [offset] [1] += s * vol_1; 535 } 536 while ( ++offset ); 537 538 out = (stereo_fixed_t*) echo.begin(); 539 count = remain; 540 } 541 while ( remain ); 542 543 BLIP_READER_END( in, *buf ); 544 } 545 buf++; 546 } 547 while ( --bufs_remain ); 548 } 549 550 // add echo 551 if ( echo_phase && !no_echo ) 552 { 553 fixed_t const feedback = s.feedback; 554 fixed_t const treble = s.treble; 555 556 int i = 1; 557 do 558 { 559 fixed_t low_pass = s.low_pass [i]; 560 561 fixed_t* echo_end = &echo [echo_size + i]; 562 fixed_t const* BLIP_RESTRICT in_pos = &echo [echo_pos + i]; 563 blargg_long out_offset = (int)(echo_pos + i + s.delay [i]); 564 if ( out_offset >= echo_size ) 565 out_offset -= echo_size; 566 assert( out_offset < echo_size ); 567 fixed_t* BLIP_RESTRICT out_pos = &echo [out_offset]; 568 569 // break into up to three chunks to avoid having to handle wrap-around 570 // in middle of core loop 571 int remain = pair_count; 572 do 573 { 574 fixed_t const* pos = in_pos; 575 if ( pos < out_pos ) 576 pos = out_pos; 577 int count = blargg_ulong ((char*) echo_end - (char const*) pos) / 578 unsigned (stereo * sizeof (fixed_t)); 579 if ( count > remain ) 580 count = remain; 581 remain -= count; 582 583 in_pos += count * stereo; 584 out_pos += count * stereo; 585 int offset = -count; 586 do 587 { 588 low_pass += FROM_FIXED( in_pos [offset * stereo] - low_pass ) * treble; 589 out_pos [offset * stereo] = FROM_FIXED( low_pass ) * feedback; 590 } 591 while ( ++offset ); 592 593 if ( in_pos >= echo_end ) in_pos -= echo_size; 594 if ( out_pos >= echo_end ) out_pos -= echo_size; 595 } 596 while ( remain ); 597 598 s.low_pass [i] = low_pass; 599 } 600 while ( --i >= 0 ); 601 } 602 } 603 while ( --echo_phase >= 0 ); 604 605 // clamp to 16 bits 606 { 607 stereo_fixed_t const* BLIP_RESTRICT in = (stereo_fixed_t*) &echo [echo_pos]; 608 typedef blip_sample_t stereo_blip_sample_t [stereo]; 609 stereo_blip_sample_t* BLIP_RESTRICT out = (stereo_blip_sample_t*) out_; 610 int count = unsigned (echo_size - echo_pos) / (unsigned) stereo; 611 int remain = pair_count; 612 if ( count > remain ) 613 count = remain; 614 do 615 { 616 remain -= count; 617 in += count; 618 out += count; 619 int offset = -count; 620 do 621 { 622 fixed_t in_0 = FROM_FIXED( in [offset] [0] ); 623 fixed_t in_1 = FROM_FIXED( in [offset] [1] ); 624 625 BLIP_CLAMP( in_0, in_0 ); 626 out [offset] [0] = (blip_sample_t) in_0; 627 628 BLIP_CLAMP( in_1, in_1 ); 629 out [offset] [1] = (blip_sample_t) in_1; 630 } 631 while ( ++offset ); 632 633 in = (stereo_fixed_t*) echo.begin(); 634 count = remain; 635 } 636 while ( remain ); 637 } 638}