Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/lynx/sound/Blip_Buffer.cpp
2 views
1
// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
2
3
#include "Blip_Buffer.h"
4
5
#include <assert.h>
6
#include <limits.h>
7
#include <string.h>
8
#include <stdlib.h>
9
#include <stdio.h>
10
#include <math.h>
11
12
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
13
can redistribute it and/or modify it under the terms of the GNU Lesser
14
General Public License as published by the Free Software Foundation; either
15
version 2.1 of the License, or (at your option) any later version. This
16
module is distributed in the hope that it will be useful, but WITHOUT ANY
17
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19
details. You should have received a copy of the GNU Lesser General Public
20
License along with this module; if not, write to the Free Software Foundation,
21
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
22
23
#ifdef BLARGG_ENABLE_OPTIMIZER
24
#include BLARGG_ENABLE_OPTIMIZER
25
#endif
26
27
int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
28
29
Blip_Buffer::Blip_Buffer()
30
{
31
factor_ = (blip_u64)ULLONG_MAX;
32
offset_ = 0;
33
buffer_ = 0;
34
buffer_size_ = 0;
35
sample_rate_ = 0;
36
reader_accum_ = 0;
37
bass_shift_ = 0;
38
clock_rate_ = 0;
39
bass_freq_ = 16;
40
length_ = 0;
41
42
// assumptions code makes about implementation-defined features
43
#ifndef NDEBUG
44
// right shift of negative value preserves sign
45
buf_t_ i = -0x7FFFFFFE;
46
assert( (i >> 1) == -0x3FFFFFFF );
47
48
// casting to short truncates to 16 bits and sign-extends
49
i = 0x18000;
50
assert( (short) i == -0x8000 );
51
#endif
52
}
53
54
Blip_Buffer::~Blip_Buffer()
55
{
56
if ( buffer_size_ != silent_buf_size )
57
free( buffer_ );
58
}
59
60
Silent_Blip_Buffer::Silent_Blip_Buffer()
61
{
62
factor_ = 0;
63
buffer_ = buf;
64
buffer_size_ = silent_buf_size;
65
memset( buf, 0, sizeof buf ); // in case machine takes exception for signed overflow
66
}
67
68
void Blip_Buffer::clear( int entire_buffer )
69
{
70
offset_ = 0;
71
reader_accum_ = 0;
72
modified_ = 0;
73
if ( buffer_ )
74
{
75
long count = (entire_buffer ? buffer_size_ : samples_avail());
76
memset( buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) );
77
}
78
}
79
80
Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec )
81
{
82
if ( buffer_size_ == silent_buf_size )
83
{
84
assert( 0 );
85
return "Internal (tried to resize Silent_Blip_Buffer)";
86
}
87
88
// start with maximum length that resampled time can represent
89
blip_s64 new_size = (ULLONG_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64;
90
91
// simple safety check, since code elsewhere may not be safe for sizes approaching (2 ^ 31).
92
if(new_size > ((1LL << 30) - 1))
93
new_size = (1LL << 30) - 1;
94
95
if ( msec != blip_max_length )
96
{
97
blip_s64 s = ((blip_s64)new_rate * (msec + 1) + 999) / 1000;
98
if ( s < new_size )
99
new_size = s;
100
else
101
assert( 0 ); // fails if requested buffer length exceeds limit
102
}
103
104
if ( buffer_size_ != new_size )
105
{
106
void* p = realloc( buffer_, (new_size + blip_buffer_extra_) * sizeof *buffer_ );
107
if ( !p )
108
return "Out of memory";
109
110
//if(new_size > buffer_size_)
111
// memset(buffer_ + buffer_size_, 0, (new_size + blip_buffer_extra_) * sizeof *buffer_
112
113
buffer_ = (buf_t_*) p;
114
}
115
116
buffer_size_ = new_size;
117
assert( buffer_size_ != silent_buf_size );
118
119
// update things based on the sample rate
120
sample_rate_ = new_rate;
121
length_ = new_size * 1000 / new_rate - 1;
122
if ( msec )
123
assert( length_ == msec ); // ensure length is same as that passed in
124
if ( clock_rate_ )
125
clock_rate( clock_rate_ );
126
bass_freq( bass_freq_ );
127
128
clear();
129
130
return 0; // success
131
}
132
133
blip_resampled_time_t Blip_Buffer::clock_rate_factor( long rate ) const
134
{
135
double ratio = (double) sample_rate_ / rate;
136
blip_s64 factor = (blip_s64) floor( ratio * (1LL << BLIP_BUFFER_ACCURACY) + 0.5 );
137
assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
138
return (blip_resampled_time_t) factor;
139
}
140
141
void Blip_Buffer::bass_freq( int freq )
142
{
143
bass_freq_ = freq;
144
int shift = 31;
145
if ( freq > 0 )
146
{
147
shift = 13;
148
long f = (freq << 16) / sample_rate_;
149
while ( (f >>= 1) && --shift ) { }
150
}
151
bass_shift_ = shift;
152
//printf("%d\n", bass_shift_);
153
}
154
155
void Blip_Buffer::end_frame( blip_time_t t )
156
{
157
offset_ += t * factor_;
158
assert( samples_avail() <= (long) buffer_size_ ); // time outside buffer length
159
}
160
161
void Blip_Buffer::remove_silence( long count )
162
{
163
assert( count <= samples_avail() ); // tried to remove more samples than available
164
offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
165
}
166
167
long Blip_Buffer::count_samples( blip_time_t t ) const
168
{
169
unsigned long last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
170
unsigned long first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
171
return (long) (last_sample - first_sample);
172
}
173
174
blip_time_t Blip_Buffer::count_clocks( long count ) const
175
{
176
if ( !factor_ )
177
{
178
assert( 0 ); // sample rate and clock rates must be set first
179
return 0;
180
}
181
182
if ( count > buffer_size_ )
183
count = buffer_size_;
184
blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
185
return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
186
}
187
188
void Blip_Buffer::remove_samples( long count )
189
{
190
if ( count )
191
{
192
remove_silence( count );
193
194
// copy remaining samples to beginning and clear old samples
195
long remain = samples_avail() + blip_buffer_extra_;
196
memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
197
memset( buffer_ + remain, 0, count * sizeof *buffer_ );
198
}
199
}
200
201
// Blip_Synth_
202
203
Blip_Synth_Fast_::Blip_Synth_Fast_()
204
{
205
buf = 0;
206
last_amp = 0;
207
delta_factor = 0;
208
}
209
210
void Blip_Synth_Fast_::volume_unit( double new_unit )
211
{
212
delta_factor = int (new_unit * (1L << blip_sample_bits) + 0.5);
213
}
214
215
#if !BLIP_BUFFER_FAST
216
217
Blip_Synth_::Blip_Synth_( short* p, int w ) :
218
impulses( p ),
219
width( w )
220
{
221
volume_unit_ = 0.0;
222
kernel_unit = 0;
223
buf = 0;
224
last_amp = 0;
225
delta_factor = 0;
226
}
227
228
#undef PI
229
#define PI 3.1415926535897932384626433832795029
230
231
static void gen_sinc( float* out, int count, double oversample, double treble, double cutoff )
232
{
233
if ( cutoff >= 0.999 )
234
cutoff = 0.999;
235
236
if ( treble < -300.0 )
237
treble = -300.0;
238
if ( treble > 5.0 )
239
treble = 5.0;
240
241
double const maxh = 4096.0;
242
double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) );
243
double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
244
double const to_angle = PI / 2 / maxh / oversample;
245
for ( int i = 0; i < count; i++ )
246
{
247
double angle = ((i - count) * 2 + 1) * to_angle;
248
double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
249
double cos_nc_angle = cos( maxh * cutoff * angle );
250
double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
251
double cos_angle = cos( angle );
252
253
c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
254
double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
255
double b = 2.0 - cos_angle - cos_angle;
256
double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
257
258
out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
259
}
260
}
261
262
void blip_eq_t::generate( float* out, int count ) const
263
{
264
// lower cutoff freq for narrow kernels with their wider transition band
265
// (8 points->1.49, 16 points->1.15)
266
double oversample = blip_res * 2.25 / count + 0.85;
267
double half_rate = sample_rate * 0.5;
268
if ( cutoff_freq )
269
oversample = half_rate / cutoff_freq;
270
double cutoff = rolloff_freq * oversample / half_rate;
271
272
gen_sinc( out, count, blip_res * oversample, treble, cutoff );
273
274
// apply (half of) hamming window
275
double to_fraction = PI / (count - 1);
276
for ( int i = count; i--; )
277
out [i] *= 0.54f - 0.46f * (float) cos( i * to_fraction );
278
}
279
280
void Blip_Synth_::adjust_impulse()
281
{
282
// sum pairs for each phase and add error correction to end of first half
283
int const size = impulses_size();
284
for ( int p = blip_res; p-- >= blip_res / 2; )
285
{
286
int p2 = blip_res - 2 - p;
287
long error = kernel_unit;
288
for ( int i = 1; i < size; i += blip_res )
289
{
290
error -= impulses [i + p ];
291
error -= impulses [i + p2];
292
}
293
if ( p == p2 )
294
error /= 2; // phase = 0.5 impulse uses same half for both sides
295
impulses [size - blip_res + p] += (short) error;
296
//printf( "error: %ld\n", error );
297
}
298
299
//for ( int i = blip_res; i--; printf( "\n" ) )
300
// for ( int j = 0; j < width / 2; j++ )
301
// printf( "%5ld,", impulses [j * blip_res + i + 1] );
302
}
303
304
void Blip_Synth_::treble_eq( blip_eq_t const& eq )
305
{
306
float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
307
308
int const half_size = blip_res / 2 * (width - 1);
309
eq.generate( &fimpulse [blip_res], half_size );
310
311
int i;
312
313
// need mirror slightly past center for calculation
314
for ( i = blip_res; i--; )
315
fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
316
317
// starts at 0
318
for ( i = 0; i < blip_res; i++ )
319
fimpulse [i] = 0.0f;
320
321
// find rescale factor
322
double total = 0.0;
323
for ( i = 0; i < half_size; i++ )
324
total += fimpulse [blip_res + i];
325
326
//double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
327
//double const base_unit = 37888.0; // allows treble to +5 dB
328
double const base_unit = 32768.0; // necessary for blip_unscaled to work
329
double rescale = base_unit / 2 / total;
330
kernel_unit = (long) base_unit;
331
332
// integrate, first difference, rescale, convert to int
333
double sum = 0.0;
334
double next = 0.0;
335
int const impulses_size_local = this->impulses_size();
336
for ( i = 0; i < impulses_size_local; i++ )
337
{
338
impulses [i] = (short) floor( (next - sum) * rescale + 0.5 );
339
sum += fimpulse [i];
340
next += fimpulse [i + blip_res];
341
}
342
adjust_impulse();
343
344
// volume might require rescaling
345
double vol = volume_unit_;
346
if ( vol )
347
{
348
volume_unit_ = 0.0;
349
volume_unit( vol );
350
}
351
}
352
353
void Blip_Synth_::volume_unit( double new_unit )
354
{
355
if ( new_unit != volume_unit_ )
356
{
357
// use default eq if it hasn't been set yet
358
if ( !kernel_unit )
359
treble_eq( -8.0 );
360
361
volume_unit_ = new_unit;
362
double factor = new_unit * (1L << blip_sample_bits) / kernel_unit;
363
364
if ( factor > 0.0 )
365
{
366
int shift = 0;
367
368
// if unit is really small, might need to attenuate kernel
369
while ( factor < 2.0 )
370
{
371
shift++;
372
factor *= 2.0;
373
}
374
375
if ( shift )
376
{
377
kernel_unit >>= shift;
378
assert( kernel_unit > 0 ); // fails if volume unit is too low
379
380
// keep values positive to avoid round-towards-zero of sign-preserving
381
// right shift for negative values
382
long offset = 0x8000 + (1 << (shift - 1));
383
long offset2 = 0x8000 >> shift;
384
for ( int i = impulses_size(); i--; )
385
impulses [i] = (short) (((impulses [i] + offset) >> shift) - offset2);
386
adjust_impulse();
387
}
388
}
389
delta_factor = (int) floor( factor + 0.5 );
390
//printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
391
}
392
}
393
#endif
394
395
long Blip_Buffer::read_samples( blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo )
396
{
397
long count = samples_avail();
398
if ( count > max_samples )
399
count = max_samples;
400
401
if ( count )
402
{
403
int const bass = BLIP_READER_BASS( *this );
404
BLIP_READER_BEGIN( reader, *this );
405
406
if ( !stereo )
407
{
408
for ( blip_long n = count; n; --n )
409
{
410
blip_long s = BLIP_READER_READ( reader );
411
if ( (blip_sample_t) s != s )
412
s = 0x7FFF - (s >> 24);
413
*out++ = (blip_sample_t) s;
414
BLIP_READER_NEXT( reader, bass );
415
}
416
}
417
else
418
{
419
for ( blip_long n = count; n; --n )
420
{
421
blip_long s = BLIP_READER_READ( reader );
422
if ( (blip_sample_t) s != s )
423
s = 0x7FFF - (s >> 24);
424
*out = (blip_sample_t) s;
425
out += 2;
426
BLIP_READER_NEXT( reader, bass );
427
}
428
}
429
BLIP_READER_END( reader, *this );
430
431
remove_samples( count );
432
}
433
return count;
434
}
435
436
void Blip_Buffer::mix_samples( blip_sample_t const* in, long count )
437
{
438
if ( buffer_size_ == silent_buf_size )
439
{
440
assert( 0 );
441
return;
442
}
443
444
buf_t_* out = buffer_ + (offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
445
446
int const sample_shift = blip_sample_bits - 16;
447
int prev = 0;
448
while ( count-- )
449
{
450
blip_long s = (blip_long) *in++ << sample_shift;
451
*out += s - prev;
452
prev = s;
453
++out;
454
}
455
*out -= prev;
456
}
457
458
459