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