// Blip_Buffer 0.3.0. http://www.slack.net/~ant/nes-emu/ #include /* Library Copyright (C) 2004 Shay Green. Blip_Buffer is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Stereo_Buffer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Stereo_Buffer; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ Stereo_Buffer::Stereo_Buffer() { } Stereo_Buffer::~Stereo_Buffer() { } bool Stereo_Buffer::set_sample_rate( long rate, int msec ) { for ( int i = 0; i < buf_count; i++ ) { if ( bufs [i].set_sample_rate( rate, msec ) ) { return false; } } return true; } void Stereo_Buffer::clock_rate( long rate ) { for ( int i = 0; i < buf_count; i++ ) bufs [i].clock_rate( rate ); } void Stereo_Buffer::bass_freq( int bass ) { for ( unsigned i = 0; i < buf_count; i++ ) bufs [i].bass_freq( bass ); } void Stereo_Buffer::clear() { stereo_added = false; was_stereo = false; for ( int i = 0; i < buf_count; i++ ) bufs [i].clear(); } void Stereo_Buffer::end_frame( blip_time_t clock_count, bool stereo ) { for ( unsigned i = 0; i < buf_count; i++ ) { bufs [i].end_frame( clock_count ); } stereo_added = stereo; } long Stereo_Buffer::read_samples( blip_sample_t* out, long max_samples ) { long count = bufs [0].samples_avail(); if ( count > max_samples / 2 ) count = max_samples / 2; if ( count ) { if ( stereo_added || was_stereo ) { mix_stereo( out, count ); bufs [0].remove_samples( count ); bufs [1].remove_samples( count ); bufs [2].remove_samples( count ); } #ifndef WANT_STEREO_SOUND else { mix_mono( out, count ); bufs [0].remove_samples( count ); bufs [1].remove_silence( count ); bufs [2].remove_silence( count ); } #endif // to do: this might miss opportunities for optimization if ( !bufs [0].samples_avail() ) { was_stereo = stereo_added; stereo_added = false; } } return count * 2; } void Stereo_Buffer::mix_stereo( blip_sample_t* out, long count ) { Blip_Reader left; Blip_Reader right; Blip_Reader center; left.begin( bufs [1] ); right.begin( bufs [2] ); int bass = center.begin( bufs [0] ); while ( count-- ) { int c = center.read(); out [0] = c + left.read(); out [1] = c + right.read(); out += 2; center.next( bass ); left.next( bass ); right.next( bass ); } center.end( bufs [0] ); right.end( bufs [2] ); left.end( bufs [1] ); } void Stereo_Buffer::mix_stereo( float* out, long count ) { Blip_Reader left; Blip_Reader right; Blip_Reader center; left.begin( bufs [1] ); right.begin( bufs [2] ); int bass = center.begin( bufs [0] ); while ( count-- ) { int c = center.read(); out [0] = (float)(c + left.read()) / 32768; out [1] = (float)(c + right.read()) / 32768; out += 2; center.next( bass ); left.next( bass ); right.next( bass ); } center.end( bufs [0] ); right.end( bufs [2] ); left.end( bufs [1] ); } #ifndef WANT_STEREO_SOUND void Stereo_Buffer::mix_mono( blip_sample_t* out, long count ) { Blip_Reader in; int bass = in.begin( bufs [0] ); while ( count-- ) { int sample = in.read(); out [0] = sample; out [1] = sample; out += 2; in.next( bass ); } in.end( bufs [0] ); } void Stereo_Buffer::mix_mono( float* out, long count ) { Blip_Reader in; int bass = in.begin( bufs [0] ); while ( count-- ) { int sample = in.read(); out [0] = (float)(sample) / 32768; out [1] = (float)(sample) / 32768; out += 2; in.next( bass ); } in.end( bufs [0] ); } #endif