1 // Blip_Buffer $vers. http://www.slack.net/~ant/
2 
3 #include "Multi_Buffer.h"
4 
5 /* Copyright (C) 2003-2008 Shay Green. This module is free software; you
6 can redistribute it and/or modify it under the terms of the GNU Lesser
7 General Public License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version. This
9 module is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 details. You should have received a copy of the GNU Lesser General Public
13 License along with this module; if not, write to the Free Software Foundation,
14 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #include "blargg_source.h"
17 
Multi_Buffer(int spf)18 Multi_Buffer::Multi_Buffer( int spf ) : samples_per_frame_( spf )
19 {
20 	length_                 = 0;
21 	sample_rate_            = 0;
22 	channels_changed_count_ = 1;
23 	channel_types_          = NULL;
24 	channel_count_          = 0;
25 	immediate_removal_      = true;
26 }
27 
channel(int)28 Multi_Buffer::channel_t Multi_Buffer::channel( int /*index*/ )
29 {
30 	channel_t ch;
31 	ch.center = ch.left = ch.right = NULL;
32 	return ch;
33 }
34 
35 // Silent_Buffer
36 
Silent_Buffer()37 Silent_Buffer::Silent_Buffer() : Multi_Buffer( 1 ) // 0 channels would probably confuse
38 {
39 	// TODO: better to use empty Blip_Buffer so caller never has to check for NULL?
40 	chan.left   = NULL;
41 	chan.center = NULL;
42 	chan.right  = NULL;
43 }
44 
45 // Mono_Buffer
46 
Mono_Buffer()47 Mono_Buffer::Mono_Buffer() : Multi_Buffer( 1 )
48 {
49 	chan.center = &buf;
50 	chan.left   = &buf;
51 	chan.right  = &buf;
52 }
53 
~Mono_Buffer()54 Mono_Buffer::~Mono_Buffer() { }
55 
set_sample_rate(int rate,int msec)56 blargg_err_t Mono_Buffer::set_sample_rate( int rate, int msec )
57 {
58 	RETURN_ERR( buf.set_sample_rate( rate, msec ) );
59 	return Multi_Buffer::set_sample_rate( buf.sample_rate(), buf.length() );
60 }
61 
62 
63 // Tracked_Blip_Buffer
64 
65 int const blip_buffer_extra = 32; // TODO: explain why this value
66 
Tracked_Blip_Buffer()67 Tracked_Blip_Buffer::Tracked_Blip_Buffer()
68 {
69 	last_non_silence = 0;
70 }
71 
clear()72 void Tracked_Blip_Buffer::clear()
73 {
74 	last_non_silence = 0;
75 	Blip_Buffer::clear();
76 }
77 
end_frame(blip_time_t t)78 void Tracked_Blip_Buffer::end_frame( blip_time_t t )
79 {
80 	Blip_Buffer::end_frame( t );
81 	if ( modified() )
82 	{
83 		clear_modified();
84 		last_non_silence = samples_avail() + blip_buffer_extra;
85 	}
86 }
87 
non_silent() const88 unsigned Tracked_Blip_Buffer::non_silent() const
89 {
90 	return last_non_silence | unsettled();
91 }
92 
remove_(int n)93 inline void Tracked_Blip_Buffer::remove_( int n )
94 {
95 	if ( (last_non_silence -= n) < 0 )
96 		last_non_silence = 0;
97 }
98 
remove_silence(int n)99 void Tracked_Blip_Buffer::remove_silence( int n )
100 {
101 	remove_( n );
102 	Blip_Buffer::remove_silence( n );
103 }
104 
remove_samples(int n)105 void Tracked_Blip_Buffer::remove_samples( int n )
106 {
107 	remove_( n );
108 	Blip_Buffer::remove_samples( n );
109 }
110 
remove_all_samples()111 void Tracked_Blip_Buffer::remove_all_samples()
112 {
113 	int avail = samples_avail();
114 	if ( !non_silent() )
115 		remove_silence( avail );
116 	else
117 		remove_samples( avail );
118 }
119 
read_samples(blip_sample_t out[],int count)120 int Tracked_Blip_Buffer::read_samples( blip_sample_t out [], int count )
121 {
122 	count = Blip_Buffer::read_samples( out, count );
123 	remove_( count );
124 	return count;
125 }
126 
127 // Stereo_Buffer
128 
129 int const stereo = 2;
130 
Stereo_Buffer()131 Stereo_Buffer::Stereo_Buffer() : Multi_Buffer( 2 )
132 {
133 	chan.center = mixer.bufs [2] = &bufs [2];
134 	chan.left   = mixer.bufs [0] = &bufs [0];
135 	chan.right  = mixer.bufs [1] = &bufs [1];
136 	mixer.samples_read = 0;
137 }
138 
~Stereo_Buffer()139 Stereo_Buffer::~Stereo_Buffer() { }
140 
set_sample_rate(int rate,int msec)141 blargg_err_t Stereo_Buffer::set_sample_rate( int rate, int msec )
142 {
143 	mixer.samples_read = 0;
144 	for ( int i = bufs_size; --i >= 0; )
145 		RETURN_ERR( bufs [i].set_sample_rate( rate, msec ) );
146 	return Multi_Buffer::set_sample_rate( bufs [0].sample_rate(), bufs [0].length() );
147 }
148 
clock_rate(int rate)149 void Stereo_Buffer::clock_rate( int rate )
150 {
151 	for ( int i = bufs_size; --i >= 0; )
152 		bufs [i].clock_rate( rate );
153 }
154 
bass_freq(int bass)155 void Stereo_Buffer::bass_freq( int bass )
156 {
157 	for ( int i = bufs_size; --i >= 0; )
158 		bufs [i].bass_freq( bass );
159 }
160 
clear()161 void Stereo_Buffer::clear()
162 {
163 	mixer.samples_read = 0;
164 	for ( int i = bufs_size; --i >= 0; )
165 		bufs [i].clear();
166 }
167 
end_frame(blip_time_t time)168 void Stereo_Buffer::end_frame( blip_time_t time )
169 {
170 	for ( int i = bufs_size; --i >= 0; )
171 		bufs [i].end_frame( time );
172 }
173 
read_samples(blip_sample_t out[],int out_size)174 int Stereo_Buffer::read_samples( blip_sample_t out [], int out_size )
175 {
176 	require( (out_size & 1) == 0 ); // must read an even number of samples
177 	out_size = min( out_size, samples_avail() );
178 
179 	int pair_count = int (out_size >> 1);
180 	if ( pair_count )
181 	{
182 		mixer.read_pairs( out, pair_count );
183 
184 		if ( samples_avail() <= 0 || immediate_removal() )
185 		{
186 			for ( int i = bufs_size; --i >= 0; )
187 			{
188 				buf_t& b = bufs [i];
189 				// TODO: might miss non-silence settling since it checks END of last read
190 				if ( !b.non_silent() )
191 					b.remove_silence( mixer.samples_read );
192 				else
193 					b.remove_samples( mixer.samples_read );
194 			}
195 			mixer.samples_read = 0;
196 		}
197 	}
198 	return out_size;
199 }
200 
201 
202 // Stereo_Mixer
203 
204 // mixers use a single index value to improve performance on register-challenged processors
205 // offset goes from negative to zero
206 
read_pairs(blip_sample_t out[],int count)207 void Stereo_Mixer::read_pairs( blip_sample_t out [], int count )
208 {
209 	// TODO: if caller never marks buffers as modified, uses mono
210 	// except that buffer isn't cleared, so caller can encounter
211 	// subtle problems and not realize the cause.
212 	samples_read += count;
213 	if ( bufs [0]->non_silent() | bufs [1]->non_silent() )
214 		mix_stereo( out, count );
215 	else
216 		mix_mono( out, count );
217 }
218 
mix_mono(blip_sample_t out_[],int count)219 void Stereo_Mixer::mix_mono( blip_sample_t out_ [], int count )
220 {
221 	int const bass = bufs [2]->highpass_shift();
222 	Blip_Buffer::delta_t const* center = bufs [2]->read_pos() + samples_read;
223 	int center_sum = bufs [2]->integrator();
224 
225 	typedef blip_sample_t stereo_blip_sample_t [stereo];
226 	stereo_blip_sample_t* BLARGG_RESTRICT out = (stereo_blip_sample_t*) out_ + count;
227 	int offset = -count;
228 	do
229 	{
230 		int s = center_sum >> bufs [2]->delta_bits;
231 
232 		center_sum -= center_sum >> bass;
233 		center_sum += center [offset];
234 
235 		BLIP_CLAMP( s, s );
236 
237 		out [offset] [0] = (blip_sample_t) s;
238 		out [offset] [1] = (blip_sample_t) s;
239 	}
240 	while ( ++offset );
241 
242 	bufs [2]->set_integrator( center_sum );
243 }
244 
mix_stereo(blip_sample_t out_[],int count)245 void Stereo_Mixer::mix_stereo( blip_sample_t out_ [], int count )
246 {
247 	blip_sample_t* BLARGG_RESTRICT out = out_ + count * stereo;
248 
249 	// do left + center and right + center separately to reduce register load
250 	Tracked_Blip_Buffer* const* buf = &bufs [2];
251 	while ( true ) // loop runs twice
252 	{
253 		--buf;
254 		--out;
255 
256 		int const bass = bufs [2]->highpass_shift();
257 		Blip_Buffer::delta_t const* side = (*buf)->read_pos() + samples_read;
258 		Blip_Buffer::delta_t const* center = bufs [2]->read_pos() + samples_read;
259 
260 		int side_sum = (*buf)->integrator();
261 		int center_sum = bufs [2]->integrator();
262 
263 		int offset = -count;
264 		do
265 		{
266 			int s = (center_sum + side_sum) >> Blip_Buffer::delta_bits;
267 
268 			side_sum   -= side_sum   >> bass;
269 			center_sum -= center_sum >> bass;
270 
271 			side_sum   += side   [offset];
272 			center_sum += center [offset];
273 
274 			BLIP_CLAMP( s, s );
275 
276 			++offset; // before write since out is decremented to slightly before end
277 			out [offset * stereo] = (blip_sample_t) s;
278 		}
279 		while ( offset );
280 
281 		(*buf)->set_integrator( side_sum );
282 
283 		if ( buf != bufs )
284 			continue;
285 
286 		// only end center once
287 		bufs [2]->set_integrator( center_sum );
288 		break;
289 	}
290 }
291