| 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 | |