1 | |
2 | // Blip_Buffer 0.3.3. http://www.slack.net/~ant/libs/ |
3 | |
4 | #include "Blip_Buffer.h" |
5 | |
6 | #include <string.h> |
7 | #include <math.h> |
8 | |
9 | /* Copyright (C) 2003-2005 Shay Green. This module is free software; you |
10 | can redistribute it and/or modify it under the terms of the GNU Lesser |
11 | General Public License as published by the Free Software Foundation; either |
12 | version 2.1 of the License, or (at your option) any later version. This |
13 | module is distributed in the hope that it will be useful, but WITHOUT ANY |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
15 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for |
16 | more details. You should have received a copy of the GNU Lesser General |
17 | Public License along with this module; if not, write to the Free Software |
18 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ |
19 | |
20 | #include BLARGG_SOURCE_BEGIN |
21 | |
22 | Blip_Buffer::Blip_Buffer() |
23 | { |
24 | samples_per_sec = 44100; |
25 | buffer_ = NULL; |
26 | |
27 | // try to cause assertion failure if buffer is used before these are set |
28 | clocks_per_sec = 0; |
29 | factor_ = ~0ul; |
30 | offset_ = 0; |
31 | buffer_size_ = 0; |
32 | length_ = 0; |
33 | |
34 | bass_freq_ = 16; |
35 | } |
36 | |
37 | void Blip_Buffer::clear( bool entire_buffer ) |
38 | { |
39 | long count = (entire_buffer ? buffer_size_ : samples_avail()); |
40 | offset_ = 0; |
41 | reader_accum = 0; |
42 | memset( buffer_, sample_offset & 0xFF, (count + widest_impulse_) * sizeof (buf_t_) ); |
43 | } |
44 | |
45 | blargg_err_t Blip_Buffer::sample_rate( long new_rate, int msec ) |
46 | { |
47 | unsigned new_size = (UINT_MAX >> BLIP_BUFFER_ACCURACY) + 1 - widest_impulse_ - 64; |
48 | if ( msec != blip_default_length ) |
49 | { |
50 | size_t s = (new_rate * (msec + 1) + 999) / 1000; |
51 | if ( s < new_size ) |
52 | new_size = s; |
53 | else |
54 | require( false ); // requested buffer length exceeds limit |
55 | } |
56 | |
57 | if ( buffer_size_ != new_size ) |
58 | { |
59 | delete [] buffer_; |
60 | buffer_ = NULL; // allow for exception in allocation below |
61 | buffer_size_ = 0; |
62 | offset_ = 0; |
63 | |
64 | buffer_ = BLARGG_NEW buf_t_ [new_size + widest_impulse_]; |
65 | BLARGG_CHECK_ALLOC( buffer_ ); |
66 | } |
67 | |
68 | buffer_size_ = new_size; |
69 | length_ = new_size * 1000 / new_rate - 1; |
70 | if ( msec ) |
71 | assert( length_ == msec ); // ensure length is same as that passed in |
72 | |
73 | samples_per_sec = new_rate; |
74 | if ( clocks_per_sec ) |
75 | clock_rate( clocks_per_sec ); // recalculate factor |
76 | |
77 | bass_freq( bass_freq_ ); // recalculate shift |
78 | |
79 | clear(); |
80 | |
81 | return blargg_success; |
82 | } |
83 | |
84 | void Blip_Buffer::clock_rate( long cps ) |
85 | { |
86 | clocks_per_sec = cps; |
87 | factor_ = (unsigned long) floor( (double) samples_per_sec / cps * |
88 | (1L << BLIP_BUFFER_ACCURACY) + 0.5 ); |
89 | require( factor_ > 0 ); // clock_rate/sample_rate ratio is too large |
90 | } |
91 | |
92 | Blip_Buffer::~Blip_Buffer() |
93 | { |
94 | delete [] buffer_; |
95 | } |
96 | |
97 | void Blip_Buffer::bass_freq( int freq ) |
98 | { |
99 | bass_freq_ = freq; |
100 | if ( freq == 0 ) { |
101 | bass_shift = 31; // 32 or greater invokes undefined behavior elsewhere |
102 | return; |
103 | } |
104 | bass_shift = 1 + (int) floor( 1.442695041 * log( 0.124 * samples_per_sec / freq ) ); |
105 | if ( bass_shift < 0 ) |
106 | bass_shift = 0; |
107 | if ( bass_shift > 24 ) |
108 | bass_shift = 24; |
109 | } |
110 | |
111 | long Blip_Buffer::count_samples( blip_time_t t ) const { |
112 | return (resampled_time( t ) >> BLIP_BUFFER_ACCURACY) - (offset_ >> BLIP_BUFFER_ACCURACY); |
113 | } |
114 | |
115 | void Blip_Impulse_::init( blip_pair_t_* imps, int w, int r, int fb ) |
116 | { |
117 | fine_bits = fb; |
118 | width = w; |
119 | impulses = (imp_t*) imps; |
120 | generate = true; |
121 | volume_unit_ = -1.0; |
122 | res = r; |
123 | buf = NULL; |
124 | |
125 | impulse = &impulses [width * res * 2 * (fine_bits ? 2 : 1)]; |
126 | offset = 0; |
127 | } |
128 | |
129 | const int impulse_bits = 15; |
130 | const long impulse_amp = 1L << impulse_bits; |
131 | const long impulse_offset = impulse_amp / 2; |
132 | |
133 | void Blip_Impulse_::scale_impulse( int unit, imp_t* imp_in ) const |
134 | { |
135 | long offset = ((long) unit << impulse_bits) - impulse_offset * unit + |
136 | (1 << (impulse_bits - 1)); |
137 | imp_t* imp = imp_in; |
138 | imp_t* fimp = impulse; |
139 | for ( int n = res / 2 + 1; n--; ) |
140 | { |
141 | int error = unit; |
142 | for ( int nn = width; nn--; ) |
143 | { |
144 | long a = ((long) *fimp++ * unit + offset) >> impulse_bits; |
145 | error -= a - unit; |
146 | *imp++ = (imp_t) a; |
147 | } |
148 | |
149 | // add error to middle |
150 | imp [-width / 2 - 1] += (imp_t) error; |
151 | } |
152 | |
153 | if ( res > 2 ) { |
154 | // second half is mirror-image |
155 | const imp_t* rev = imp - width - 1; |
156 | for ( int nn = (res / 2 - 1) * width - 1; nn--; ) |
157 | *imp++ = *--rev; |
158 | *imp++ = (imp_t) unit; |
159 | } |
160 | |
161 | // copy to odd offset |
162 | *imp++ = (imp_t) unit; |
163 | memcpy( imp, imp_in, (res * width - 1) * sizeof *imp ); |
164 | } |
165 | |
166 | const int max_res = 1 << blip_res_bits_; |
167 | |
168 | void Blip_Impulse_::fine_volume_unit() |
169 | { |
170 | // to do: find way of merging in-place without temporary buffer |
171 | |
172 | imp_t temp [max_res * 2 * Blip_Buffer::widest_impulse_]; |
173 | scale_impulse( (offset & 0xffff) << fine_bits, temp ); |
174 | imp_t* imp2 = impulses + res * 2 * width; |
175 | scale_impulse( offset & 0xffff, imp2 ); |
176 | |
177 | // merge impulses |
178 | imp_t* imp = impulses; |
179 | imp_t* src2 = temp; |
180 | for ( int n = res / 2 * 2 * width; n--; ) { |
181 | *imp++ = *imp2++; |
182 | *imp++ = *imp2++; |
183 | *imp++ = *src2++; |
184 | *imp++ = *src2++; |
185 | } |
186 | } |
187 | |
188 | void Blip_Impulse_::volume_unit( double new_unit ) |
189 | { |
190 | if ( new_unit == volume_unit_ ) |
191 | return; |
192 | |
193 | if ( generate ) |
194 | treble_eq( blip_eq_t( -8.87, 8800, 44100 ) ); |
195 | |
196 | volume_unit_ = new_unit; |
197 | |
198 | offset = 0x10001 * (unsigned long) floor( volume_unit_ * 0x10000 + 0.5 ); |
199 | |
200 | if ( fine_bits ) |
201 | fine_volume_unit(); |
202 | else |
203 | scale_impulse( offset & 0xffff, impulses ); |
204 | } |
205 | |
206 | static const double pi = 3.1415926535897932384626433832795029L; |
207 | |
208 | void Blip_Impulse_::treble_eq( const blip_eq_t& new_eq ) |
209 | { |
210 | if ( !generate && new_eq.treble == eq.treble && new_eq.cutoff == eq.cutoff && |
211 | new_eq.sample_rate == eq.sample_rate ) |
212 | return; // already calculated with same parameters |
213 | |
214 | generate = false; |
215 | eq = new_eq; |
216 | |
217 | double treble = pow( 10.0, 1.0 / 20 * eq.treble ); // dB (-6dB = 0.50) |
218 | if ( treble < 0.000005 ) |
219 | treble = 0.000005; |
220 | |
221 | const double treble_freq = 22050.0; // treble level at 22 kHz harmonic |
222 | const double sample_rate = eq.sample_rate; |
223 | const double pt = treble_freq * 2 / sample_rate; |
224 | double cutoff = eq.cutoff * 2 / sample_rate; |
225 | if ( cutoff >= pt * 0.95 || cutoff >= 0.95 ) { |
226 | cutoff = 0.5; |
227 | treble = 1.0; |
228 | } |
229 | |
230 | // DSF Synthesis (See T. Stilson & J. Smith (1996), |
231 | // Alias-free digital synthesis of classic analog waveforms) |
232 | |
233 | // reduce adjacent impulse interference by using small part of wide impulse |
234 | const double n_harm = 4096; |
235 | const double rolloff = pow( treble, 1.0 / (n_harm * pt - n_harm * cutoff) ); |
236 | const double rescale = 1.0 / pow( rolloff, n_harm * cutoff ); |
237 | |
238 | const double pow_a_n = rescale * pow( rolloff, n_harm ); |
239 | const double pow_a_nc = rescale * pow( rolloff, n_harm * cutoff ); |
240 | |
241 | double total = 0.0; |
242 | const double to_angle = pi / 2 / n_harm / max_res; |
243 | |
244 | float buf [max_res * (Blip_Buffer::widest_impulse_ - 2) / 2]; |
245 | const int size = max_res * (width - 2) / 2; |
246 | for ( int i = size; i--; ) |
247 | { |
248 | double angle = (i * 2 + 1) * to_angle; |
249 | |
250 | // equivalent |
251 | //double y = dsf( angle, n_harm * cutoff, 1.0 ); |
252 | //y -= rescale * dsf( angle, n_harm * cutoff, rolloff ); |
253 | //y += rescale * dsf( angle, n_harm, rolloff ); |
254 | |
255 | const double cos_angle = cos( angle ); |
256 | const double cos_nc_angle = cos( n_harm * cutoff * angle ); |
257 | const double cos_nc1_angle = cos( (n_harm * cutoff - 1.0) * angle ); |
258 | |
259 | double b = 2.0 - 2.0 * cos_angle; |
260 | double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle; |
261 | |
262 | double d = 1.0 + rolloff * (rolloff - 2.0 * cos_angle); |
263 | double c = pow_a_n * rolloff * cos( (n_harm - 1.0) * angle ) - |
264 | pow_a_n * cos( n_harm * angle ) - |
265 | pow_a_nc * rolloff * cos_nc1_angle + |
266 | pow_a_nc * cos_nc_angle; |
267 | |
268 | // optimization of a / b + c / d |
269 | double y = (a * d + c * b) / (b * d); |
270 | |
271 | // fixed window which affects wider impulses more |
272 | if ( width > 12 ) { |
273 | double window = cos( n_harm / 1.25 / Blip_Buffer::widest_impulse_ * angle ); |
274 | y *= window * window; |
275 | } |
276 | |
277 | total += (float) y; |
278 | buf [i] = (float) y; |
279 | } |
280 | |
281 | // integrate runs of length 'max_res' |
282 | double factor = impulse_amp * 0.5 / total; // 0.5 accounts for other mirrored half |
283 | imp_t* imp = impulse; |
284 | const int step = max_res / res; |
285 | int offset = res > 1 ? max_res : max_res / 2; |
286 | for ( int n = res / 2 + 1; n--; offset -= step ) |
287 | { |
288 | for ( int w = -width / 2; w < width / 2; w++ ) |
289 | { |
290 | double sum = 0; |
291 | for ( int i = max_res; i--; ) |
292 | { |
293 | int index = w * max_res + offset + i; |
294 | if ( index < 0 ) |
295 | index = -index - 1; |
296 | if ( index < size ) |
297 | sum += buf [index]; |
298 | } |
299 | *imp++ = (imp_t) floor( sum * factor + (impulse_offset + 0.5) ); |
300 | } |
301 | } |
302 | |
303 | // rescale |
304 | double unit = volume_unit_; |
305 | if ( unit >= 0 ) { |
306 | volume_unit_ = -1; |
307 | volume_unit( unit ); |
308 | } |
309 | } |
310 | |
311 | void Blip_Buffer::remove_samples( long count ) |
312 | { |
313 | require( buffer_ ); // sample rate must have been set |
314 | |
315 | if ( !count ) // optimization |
316 | return; |
317 | |
318 | remove_silence( count ); |
319 | |
320 | // Allows synthesis slightly past time passed to end_frame(), as long as it's |
321 | // not more than an output sample. |
322 | // to do: kind of hacky, could add run_until() which keeps track of extra synthesis |
323 | int const = 1; |
324 | |
325 | // copy remaining samples to beginning and clear old samples |
326 | long remain = samples_avail() + widest_impulse_ + copy_extra; |
327 | if ( count >= remain ) |
328 | memmove( buffer_, buffer_ + count, remain * sizeof (buf_t_) ); |
329 | else |
330 | memcpy( buffer_, buffer_ + count, remain * sizeof (buf_t_) ); |
331 | memset( buffer_ + remain, sample_offset & 0xFF, count * sizeof (buf_t_) ); |
332 | } |
333 | |
334 | #include BLARGG_ENABLE_OPTIMIZER |
335 | |
336 | long Blip_Buffer::read_samples( blip_sample_t* out, long max_samples, bool stereo ) |
337 | { |
338 | require( buffer_ ); // sample rate must have been set |
339 | |
340 | long count = samples_avail(); |
341 | if ( count > max_samples ) |
342 | count = max_samples; |
343 | |
344 | if ( !count ) |
345 | return 0; // optimization |
346 | |
347 | int sample_offset = this->sample_offset; |
348 | int bass_shift = this->bass_shift; |
349 | buf_t_* buf = buffer_; |
350 | long accum = reader_accum; |
351 | |
352 | if ( !stereo ) { |
353 | for ( long n = count; n--; ) { |
354 | long s = accum >> accum_fract; |
355 | accum -= accum >> bass_shift; |
356 | accum += (long (*buf++) - sample_offset) << accum_fract; |
357 | *out++ = (blip_sample_t) s; |
358 | |
359 | // clamp sample |
360 | if ( (BOOST::int16_t) s != s ) |
361 | out [-1] = blip_sample_t (0x7FFF - (s >> 24)); |
362 | } |
363 | } |
364 | else { |
365 | for ( long n = count; n--; ) { |
366 | long s = accum >> accum_fract; |
367 | accum -= accum >> bass_shift; |
368 | accum += (long (*buf++) - sample_offset) << accum_fract; |
369 | *out = (blip_sample_t) s; |
370 | out += 2; |
371 | |
372 | // clamp sample |
373 | if ( (BOOST::int16_t) s != s ) |
374 | out [-2] = blip_sample_t (0x7FFF - (s >> 24)); |
375 | } |
376 | } |
377 | |
378 | reader_accum = accum; |
379 | |
380 | remove_samples( count ); |
381 | |
382 | return count; |
383 | } |
384 | |
385 | void Blip_Buffer::mix_samples( const blip_sample_t* in, long count ) |
386 | { |
387 | buf_t_* buf = &buffer_ [(offset_ >> BLIP_BUFFER_ACCURACY) + (widest_impulse_ / 2 - 1)]; |
388 | |
389 | int prev = 0; |
390 | while ( count-- ) { |
391 | int s = *in++; |
392 | *buf += s - prev; |
393 | prev = s; |
394 | ++buf; |
395 | } |
396 | *buf -= *--in; |
397 | } |
398 | |
399 | |