Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/lynx/sound/Blip_Buffer.h
2 views
1
// Band-limited sound synthesis buffer
2
// Various changes and hacks for use in Mednafen.
3
4
#ifdef __GNUC__
5
#define blip_inline inline __attribute__((always_inline))
6
#else
7
#define blip_inline inline
8
#endif
9
10
#include <limits.h>
11
#include <inttypes.h>
12
13
// Blip_Buffer 0.4.1
14
#ifndef BLIP_BUFFER_H
15
#define BLIP_BUFFER_H
16
17
// Internal
18
typedef int32_t blip_long;
19
typedef uint32_t blip_ulong;
20
typedef int64_t blip_s64;
21
typedef uint64_t blip_u64;
22
23
// Time unit at source clock rate
24
typedef blip_long blip_time_t;
25
26
// Output samples are 16-bit signed, with a range of -32768 to 32767
27
typedef short blip_sample_t;
28
enum { blip_sample_max = 32767 };
29
30
class Blip_Buffer {
31
public:
32
typedef const char* blargg_err_t;
33
34
// Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
35
// to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
36
// isn't enough memory, returns error without affecting current buffer setup.
37
blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
38
39
// Set number of source time units per second
40
void clock_rate( long );
41
42
// End current time frame of specified duration and make its samples available
43
// (along with any still-unread samples) for reading with read_samples(). Begins
44
// a new time frame at the end of the current frame.
45
void end_frame( blip_time_t time );
46
47
// Read at most 'max_samples' out of buffer into 'dest', removing them from from
48
// the buffer. Returns number of samples actually read and removed. If stereo is
49
// true, increments 'dest' one extra time after writing each sample, to allow
50
// easy interleving of two channels into a stereo output buffer.
51
long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 );
52
53
// Additional optional features
54
55
// Current output sample rate
56
long sample_rate() const;
57
58
// Length of buffer, in milliseconds
59
int length() const;
60
61
// Number of source time units per second
62
long clock_rate() const;
63
64
// Set frequency high-pass filter frequency, where higher values reduce bass more
65
void bass_freq( int frequency );
66
67
// Number of samples delay from synthesis to samples read out
68
int output_latency() const;
69
70
// Remove all available samples and clear buffer to silence. If 'entire_buffer' is
71
// false, just clears out any samples waiting rather than the entire buffer.
72
void clear( int entire_buffer = 1 );
73
74
// Number of samples available for reading with read_samples()
75
long samples_avail() const;
76
77
// Remove 'count' samples from those waiting to be read
78
void remove_samples( long count );
79
80
// Experimental features
81
82
// Count number of clocks needed until 'count' samples will be available.
83
// If buffer can't even hold 'count' samples, returns number of clocks until
84
// buffer becomes full.
85
blip_time_t count_clocks( long count ) const;
86
87
// Number of raw samples that can be mixed within frame of specified duration.
88
long count_samples( blip_time_t duration ) const;
89
90
// Mix 'count' samples from 'buf' into buffer.
91
void mix_samples( blip_sample_t const* buf, long count );
92
93
// not documented yet
94
void set_modified() { modified_ = 1; }
95
int clear_modified() { int b = modified_; modified_ = 0; return b; }
96
typedef blip_u64 blip_resampled_time_t;
97
void remove_silence( long count );
98
blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
99
blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
100
blip_resampled_time_t clock_rate_factor( long clock_rate ) const;
101
public:
102
Blip_Buffer();
103
~Blip_Buffer();
104
105
// Deprecated
106
typedef blip_resampled_time_t resampled_time_t;
107
blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); }
108
blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); }
109
private:
110
// noncopyable
111
Blip_Buffer( const Blip_Buffer& );
112
Blip_Buffer& operator = ( const Blip_Buffer& );
113
public:
114
typedef blip_time_t buf_t_;
115
blip_u64 factor_;
116
blip_resampled_time_t offset_;
117
buf_t_* buffer_;
118
blip_long buffer_size_;
119
blip_long reader_accum_;
120
int bass_shift_;
121
private:
122
long sample_rate_;
123
long clock_rate_;
124
int bass_freq_;
125
int length_;
126
int modified_;
127
friend class Blip_Reader;
128
};
129
130
#ifdef HAVE_CONFIG_H
131
#include "config.h"
132
#endif
133
134
#define BLIP_BUFFER_ACCURACY 32
135
#define BLIP_PHASE_BITS 8
136
137
// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
138
// but reduce maximum buffer size.
139
//#ifndef BLIP_BUFFER_ACCURACY
140
// #define BLIP_BUFFER_ACCURACY 16
141
//#endif
142
143
// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in
144
// noticeable broadband noise when synthesizing high frequency square waves.
145
// Affects size of Blip_Synth objects since they store the waveform directly.
146
//#ifndef BLIP_PHASE_BITS
147
// #if BLIP_BUFFER_FAST
148
// #define BLIP_PHASE_BITS 8
149
// #else
150
// #define BLIP_PHASE_BITS 6
151
// #endif
152
//#endif
153
154
// Internal
155
typedef blip_u64 blip_resampled_time_t;
156
int const blip_widest_impulse_ = 16;
157
int const blip_buffer_extra_ = blip_widest_impulse_ + 2;
158
int const blip_res = 1 << BLIP_PHASE_BITS;
159
class blip_eq_t;
160
161
class Blip_Synth_Fast_ {
162
public:
163
Blip_Buffer* buf;
164
int last_amp;
165
int delta_factor;
166
167
void volume_unit( double );
168
Blip_Synth_Fast_();
169
void treble_eq( blip_eq_t const& ) { }
170
};
171
172
class Blip_Synth_ {
173
public:
174
Blip_Buffer* buf;
175
int last_amp;
176
int delta_factor;
177
178
void volume_unit( double );
179
Blip_Synth_( short* impulses, int width );
180
void treble_eq( blip_eq_t const& );
181
private:
182
double volume_unit_;
183
short* const impulses;
184
int const width;
185
blip_long kernel_unit;
186
int impulses_size() const { return blip_res / 2 * width + 1; }
187
void adjust_impulse();
188
};
189
190
// Quality level. Start with blip_good_quality.
191
const int blip_med_quality = 8;
192
const int blip_good_quality = 12;
193
const int blip_high_quality = 16;
194
195
// Range specifies the greatest expected change in amplitude. Calculate it
196
// by finding the difference between the maximum and minimum expected
197
// amplitudes (max - min).
198
template<int quality,int range>
199
class Blip_Synth {
200
public:
201
// Set overall volume of waveform
202
void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); }
203
204
// Configure low-pass filter (see blip_buffer.txt)
205
void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); }
206
207
// Get/set Blip_Buffer used for output
208
Blip_Buffer* output() const { return impl.buf; }
209
void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
210
211
// Update amplitude of waveform at given time. Using this requires a separate
212
// Blip_Synth for each waveform.
213
void update( blip_time_t time, int amplitude );
214
215
// Low-level interface
216
217
// Add an amplitude transition of specified delta, optionally into specified buffer
218
// rather than the one set with output(). Delta can be positive or negative.
219
// The actual change in amplitude is delta * (volume / range)
220
void offset( blip_time_t, int delta, Blip_Buffer* ) const;
221
void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
222
223
// Works directly in terms of fractional output samples. Contact author for more info.
224
void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
225
226
// Same as offset(), except code is inlined for higher performance
227
void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
228
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
229
}
230
void offset_inline( blip_time_t t, int delta ) const {
231
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
232
}
233
234
private:
235
#if BLIP_BUFFER_FAST
236
Blip_Synth_Fast_ impl;
237
#else
238
Blip_Synth_ impl;
239
typedef short imp_t;
240
imp_t impulses [blip_res * (quality / 2) + 1];
241
public:
242
Blip_Synth() : impl( impulses, quality ) { }
243
#endif
244
};
245
246
// Low-pass equalization parameters
247
class blip_eq_t {
248
public:
249
// Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
250
// treble, small positive values (0 to 5.0) increase treble.
251
blip_eq_t( double treble_db = 0 );
252
253
// See blip_buffer.txt
254
blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 );
255
256
private:
257
double treble;
258
long rolloff_freq;
259
long sample_rate;
260
long cutoff_freq;
261
void generate( float* out, int count ) const;
262
friend class Blip_Synth_;
263
};
264
265
int const blip_sample_bits = 30;
266
267
// Dummy Blip_Buffer to direct sound output to, for easy muting without
268
// having to stop sound code.
269
class Silent_Blip_Buffer : public Blip_Buffer {
270
buf_t_ buf [blip_buffer_extra_ + 1];
271
public:
272
// The following cannot be used (an assertion will fail if attempted):
273
blargg_err_t set_sample_rate( long samples_per_sec, int msec_length );
274
blip_time_t count_clocks( long count ) const;
275
void mix_samples( blip_sample_t const* buf, long count );
276
277
Silent_Blip_Buffer();
278
};
279
280
#if defined (__GNUC__) || _MSC_VER >= 1100
281
#define BLIP_RESTRICT __restrict
282
#else
283
#define BLIP_RESTRICT
284
#endif
285
286
// Optimized reading from Blip_Buffer, for use in custom sample output
287
288
// Begin reading from buffer. Name should be unique to the current block.
289
#define BLIP_READER_BEGIN( name, blip_buffer ) \
290
const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\
291
blip_long name##_reader_accum = (blip_buffer).reader_accum_
292
293
// Get value to pass to BLIP_READER_NEXT()
294
#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_)
295
296
// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
297
// code at the cost of having no bass control
298
int const blip_reader_default_bass = 9;
299
300
// Current sample
301
#define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16))
302
303
// Current raw sample in full internal resolution
304
#define BLIP_READER_READ_RAW( name ) (name##_reader_accum)
305
306
// Advance to next sample
307
#define BLIP_READER_NEXT( name, bass ) \
308
(void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
309
310
// End reading samples from buffer. The number of samples read must now be removed
311
// using Blip_Buffer::remove_samples().
312
#define BLIP_READER_END( name, blip_buffer ) \
313
(void) ((blip_buffer).reader_accum_ = name##_reader_accum)
314
315
316
// Compatibility with older version
317
const long blip_unscaled = 65535;
318
const int blip_low_quality = blip_med_quality;
319
const int blip_best_quality = blip_high_quality;
320
321
// Deprecated; use BLIP_READER macros as follows:
322
// Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf );
323
// int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf );
324
// r.read() -> BLIP_READER_READ( r )
325
// r.read_raw() -> BLIP_READER_READ_RAW( r )
326
// r.next( bass ) -> BLIP_READER_NEXT( r, bass )
327
// r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass )
328
// r.end( buf ) -> BLIP_READER_END( r, buf )
329
class Blip_Reader {
330
public:
331
int begin( Blip_Buffer& );
332
blip_long read() const { return accum >> (blip_sample_bits - 16); }
333
blip_long read_raw() const { return accum; }
334
void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); }
335
void end( Blip_Buffer& b ) { b.reader_accum_ = accum; }
336
337
private:
338
const Blip_Buffer::buf_t_* buf;
339
blip_long accum;
340
};
341
342
// End of public interface
343
344
#include <assert.h>
345
346
template<int quality,int range>
347
blip_inline void Blip_Synth<quality,range>::offset_resampled( blip_resampled_time_t time,
348
int delta, Blip_Buffer* blip_buf ) const
349
{
350
// Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the
351
// need for a longer buffer as set by set_sample_rate().
352
assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
353
delta *= impl.delta_factor;
354
blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
355
int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
356
357
#if BLIP_BUFFER_FAST
358
blip_long left = buf [0] + delta;
359
360
// Kind of crappy, but doing shift after multiply results in overflow.
361
// Alternate way of delaying multiply by delta_factor results in worse
362
// sub-sample resolution.
363
blip_long right = (delta >> BLIP_PHASE_BITS) * phase;
364
left -= right;
365
right += buf [1];
366
367
buf [0] = left;
368
buf [1] = right;
369
#else
370
371
int const fwd = (blip_widest_impulse_ - quality) / 2;
372
int const rev = fwd + quality - 2;
373
int const mid = quality / 2 - 1;
374
375
imp_t const* BLIP_RESTRICT imp = impulses + blip_res - phase;
376
377
#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
378
defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
379
380
// straight forward implementation resulted in better code on GCC for x86
381
382
#define ADD_IMP( out, in ) \
383
buf [out] += (blip_long) imp [blip_res * (in)] * delta
384
385
#define BLIP_FWD( i ) {\
386
ADD_IMP( fwd + i, i );\
387
ADD_IMP( fwd + 1 + i, i + 1 );\
388
}
389
#define BLIP_REV( r ) {\
390
ADD_IMP( rev - r, r + 1 );\
391
ADD_IMP( rev + 1 - r, r );\
392
}
393
394
BLIP_FWD( 0 )
395
if ( quality > 8 ) BLIP_FWD( 2 )
396
if ( quality > 12 ) BLIP_FWD( 4 )
397
{
398
ADD_IMP( fwd + mid - 1, mid - 1 );
399
ADD_IMP( fwd + mid , mid );
400
imp = impulses + phase;
401
}
402
if ( quality > 12 ) BLIP_REV( 6 )
403
if ( quality > 8 ) BLIP_REV( 4 )
404
BLIP_REV( 2 )
405
406
ADD_IMP( rev , 1 );
407
ADD_IMP( rev + 1, 0 );
408
409
#else
410
411
// for RISC processors, help compiler by reading ahead of writes
412
413
#define BLIP_FWD( i ) {\
414
blip_long t0 = i0 * delta + buf [fwd + i];\
415
blip_long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i];\
416
i0 = imp [blip_res * (i + 2)];\
417
buf [fwd + i] = t0;\
418
buf [fwd + 1 + i] = t1;\
419
}
420
#define BLIP_REV( r ) {\
421
blip_long t0 = i0 * delta + buf [rev - r];\
422
blip_long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r];\
423
i0 = imp [blip_res * (r - 1)];\
424
buf [rev - r] = t0;\
425
buf [rev + 1 - r] = t1;\
426
}
427
428
blip_long i0 = *imp;
429
BLIP_FWD( 0 )
430
if ( quality > 8 ) BLIP_FWD( 2 )
431
if ( quality > 12 ) BLIP_FWD( 4 )
432
{
433
blip_long t0 = i0 * delta + buf [fwd + mid - 1];
434
blip_long t1 = imp [blip_res * mid] * delta + buf [fwd + mid ];
435
imp = impulses + phase;
436
i0 = imp [blip_res * mid];
437
buf [fwd + mid - 1] = t0;
438
buf [fwd + mid ] = t1;
439
}
440
if ( quality > 12 ) BLIP_REV( 6 )
441
if ( quality > 8 ) BLIP_REV( 4 )
442
BLIP_REV( 2 )
443
444
blip_long t0 = i0 * delta + buf [rev ];
445
blip_long t1 = *imp * delta + buf [rev + 1];
446
buf [rev ] = t0;
447
buf [rev + 1] = t1;
448
#endif
449
450
#endif
451
}
452
453
#undef BLIP_FWD
454
#undef BLIP_REV
455
456
template<int quality,int range>
457
#if BLIP_BUFFER_FAST
458
blip_inline
459
#endif
460
void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
461
{
462
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
463
}
464
465
template<int quality,int range>
466
#if BLIP_BUFFER_FAST
467
blip_inline
468
#endif
469
void Blip_Synth<quality,range>::update( blip_time_t t, int amp )
470
{
471
int delta = amp - impl.last_amp;
472
impl.last_amp = amp;
473
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
474
}
475
476
blip_inline blip_eq_t::blip_eq_t( double t ) :
477
treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
478
blip_inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
479
treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
480
481
blip_inline int Blip_Buffer::length() const { return length_; }
482
blip_inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); }
483
blip_inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
484
blip_inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
485
blip_inline long Blip_Buffer::clock_rate() const { return clock_rate_; }
486
blip_inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
487
488
blip_inline int Blip_Reader::begin( Blip_Buffer& blip_buf )
489
{
490
buf = blip_buf.buffer_;
491
accum = blip_buf.reader_accum_;
492
return blip_buf.bass_shift_;
493
}
494
495
int const blip_max_length = 0;
496
int const blip_default_length = 250;
497
498
#endif
499
500