Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/quicknes/nes_emu/Blip_Buffer.h
2 views
1
2
// Band-limited sound synthesis and buffering
3
4
// Blip_Buffer 0.4.0
5
6
#ifndef BLIP_BUFFER_H
7
#define BLIP_BUFFER_H
8
9
// Time unit at source clock rate
10
typedef long blip_time_t;
11
12
// Output samples are 16-bit signed, with a range of -32768 to 32767
13
typedef short blip_sample_t;
14
enum { blip_sample_max = 32767 };
15
16
class Blip_Buffer {
17
public:
18
typedef const char* blargg_err_t;
19
20
// Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
21
// to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
22
// isn't enough memory, returns error without affecting current buffer setup.
23
blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
24
25
// Set number of source time units per second
26
void clock_rate( long );
27
28
// End current time frame of specified duration and make its samples available
29
// (along with any still-unread samples) for reading with read_samples(). Begins
30
// a new time frame at the end of the current frame.
31
void end_frame( blip_time_t time );
32
33
// Read at most 'max_samples' out of buffer into 'dest', removing them from from
34
// the buffer. Returns number of samples actually read and removed. If stereo is
35
// true, increments 'dest' one extra time after writing each sample, to allow
36
// easy interleving of two channels into a stereo output buffer.
37
long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 );
38
39
// Additional optional features
40
41
// Current output sample rate
42
long sample_rate() const;
43
44
// Length of buffer, in milliseconds
45
int length() const;
46
47
// Number of source time units per second
48
long clock_rate() const;
49
50
// Set frequency high-pass filter frequency, where higher values reduce bass more
51
void bass_freq( int frequency );
52
53
// Number of samples delay from synthesis to samples read out
54
int output_latency() const;
55
56
// Remove all available samples and clear buffer to silence. If 'entire_buffer' is
57
// false, just clears out any samples waiting rather than the entire buffer.
58
void clear( int entire_buffer = 1 );
59
60
// Number of samples available for reading with read_samples()
61
long samples_avail() const;
62
63
// Remove 'count' samples from those waiting to be read
64
void remove_samples( long count );
65
66
// Experimental features
67
68
// Number of raw samples that can be mixed within frame of specified duration.
69
long count_samples( blip_time_t duration ) const;
70
71
// Mix 'count' samples from 'buf' into buffer.
72
void mix_samples( blip_sample_t const* buf, long count );
73
74
// Count number of clocks needed until 'count' samples will be available.
75
// If buffer can't even hold 'count' samples, returns number of clocks until
76
// buffer becomes full.
77
blip_time_t count_clocks( long count ) const;
78
79
// not documented yet
80
typedef unsigned long blip_resampled_time_t;
81
void remove_silence( long count );
82
blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
83
blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
84
blip_resampled_time_t clock_rate_factor( long clock_rate ) const;
85
public:
86
Blip_Buffer();
87
~Blip_Buffer();
88
89
// Deprecated
90
typedef blip_resampled_time_t resampled_time_t;
91
blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); }
92
blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); }
93
private:
94
// noncopyable
95
Blip_Buffer( const Blip_Buffer& );
96
Blip_Buffer& operator = ( const Blip_Buffer& );
97
public:
98
typedef long buf_t_;
99
unsigned long factor_;
100
blip_resampled_time_t offset_;
101
buf_t_* buffer_;
102
long buffer_size_;
103
private:
104
long reader_accum;
105
int bass_shift;
106
long sample_rate_;
107
long clock_rate_;
108
int bass_freq_;
109
int length_;
110
friend class Blip_Reader;
111
};
112
113
#ifdef HAVE_CONFIG_H
114
#include "config.h"
115
#endif
116
117
// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
118
// but reduce maximum buffer size.
119
#ifndef BLIP_BUFFER_ACCURACY
120
#define BLIP_BUFFER_ACCURACY 16
121
#endif
122
123
// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in
124
// noticeable broadband noise when synthesizing high frequency square waves.
125
// Affects size of Blip_Synth objects since they store the waveform directly.
126
#ifndef BLIP_PHASE_BITS
127
#define BLIP_PHASE_BITS 6
128
#endif
129
130
// Internal
131
typedef unsigned long blip_resampled_time_t;
132
int const blip_widest_impulse_ = 16;
133
int const blip_res = 1 << BLIP_PHASE_BITS;
134
class blip_eq_t;
135
136
class Blip_Synth_ {
137
double volume_unit_;
138
short* const impulses;
139
int const width;
140
long kernel_unit;
141
int impulses_size() const { return blip_res / 2 * width + 1; }
142
void adjust_impulse();
143
public:
144
Blip_Buffer* buf;
145
int last_amp;
146
int delta_factor;
147
148
Blip_Synth_( short* impulses, int width );
149
void treble_eq( blip_eq_t const& );
150
void volume_unit( double );
151
};
152
153
// Quality level. Start with blip_good_quality.
154
const int blip_med_quality = 8;
155
const int blip_good_quality = 12;
156
const int blip_high_quality = 16;
157
158
// Range specifies the greatest expected change in amplitude. Calculate it
159
// by finding the difference between the maximum and minimum expected
160
// amplitudes (max - min).
161
template<int quality,int range>
162
class Blip_Synth {
163
public:
164
// Set overall volume of waveform
165
void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); }
166
167
// Configure low-pass filter (see notes.txt)
168
void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); }
169
170
// Get/set Blip_Buffer used for output
171
Blip_Buffer* output() const { return impl.buf; }
172
void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
173
174
// Update amplitude of waveform at given time. Using this requires a separate
175
// Blip_Synth for each waveform.
176
void update( blip_time_t time, int amplitude );
177
178
// Low-level interface
179
180
// Add an amplitude transition of specified delta, optionally into specified buffer
181
// rather than the one set with output(). Delta can be positive or negative.
182
// The actual change in amplitude is delta * (volume / range)
183
void offset( blip_time_t, int delta, Blip_Buffer* ) const;
184
void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
185
186
// Works directly in terms of fractional output samples. Contact author for more.
187
void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
188
189
// Same as offset(), except code is inlined for higher performance
190
void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
191
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
192
}
193
void offset_inline( blip_time_t t, int delta ) const {
194
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
195
}
196
197
public:
198
Blip_Synth() : impl( impulses, quality ) { }
199
private:
200
typedef short imp_t;
201
imp_t impulses [blip_res * (quality / 2) + 1];
202
Blip_Synth_ impl;
203
};
204
205
// Low-pass equalization parameters
206
class blip_eq_t {
207
public:
208
// Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce
209
// treble, small positive values (0 to 5.0) increase treble.
210
blip_eq_t( double treble_db = 0 );
211
212
// See notes.txt
213
blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 );
214
215
private:
216
double treble;
217
long rolloff_freq;
218
long sample_rate;
219
long cutoff_freq;
220
void generate( float* out, int count ) const;
221
friend class Blip_Synth_;
222
};
223
224
int const blip_sample_bits = 30;
225
226
// Optimized inline sample reader for custom sample formats and mixing of Blip_Buffer samples
227
class Blip_Reader {
228
public:
229
// Begin reading samples from buffer. Returns value to pass to next() (can
230
// be ignored if default bass_freq is acceptable).
231
int begin( Blip_Buffer& );
232
233
// Current sample
234
long read() const { return accum >> (blip_sample_bits - 16); }
235
236
// Current raw sample in full internal resolution
237
long read_raw() const { return accum; }
238
239
// Advance to next sample
240
void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); }
241
242
// End reading samples from buffer. The number of samples read must now be removed
243
// using Blip_Buffer::remove_samples().
244
void end( Blip_Buffer& b ) { b.reader_accum = accum; }
245
246
private:
247
const Blip_Buffer::buf_t_* buf;
248
long accum;
249
};
250
251
252
// End of public interface
253
254
255
#include <assert.h>
256
257
// Compatibility with older version
258
const long blip_unscaled = 65535;
259
const int blip_low_quality = blip_med_quality;
260
const int blip_best_quality = blip_high_quality;
261
262
#define BLIP_FWD( i ) { \
263
long t0 = i0 * delta + buf [fwd + i]; \
264
long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i]; \
265
i0 = imp [blip_res * (i + 2)]; \
266
buf [fwd + i] = t0; \
267
buf [fwd + 1 + i] = t1; }
268
269
#define BLIP_REV( r ) { \
270
long t0 = i0 * delta + buf [rev - r]; \
271
long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r]; \
272
i0 = imp [blip_res * (r - 1)]; \
273
buf [rev - r] = t0; \
274
buf [rev + 1 - r] = t1; }
275
276
template<int quality,int range>
277
inline void Blip_Synth<quality,range>::offset_resampled( blip_resampled_time_t time,
278
int delta, Blip_Buffer* blip_buf ) const
279
{
280
// Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the
281
// need for a longer buffer as set by set_sample_rate().
282
assert( (long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
283
delta *= impl.delta_factor;
284
int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
285
imp_t const* imp = impulses + blip_res - phase;
286
long* buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
287
long i0 = *imp;
288
289
int const fwd = (blip_widest_impulse_ - quality) / 2;
290
int const rev = fwd + quality - 2;
291
292
BLIP_FWD( 0 )
293
if ( quality > 8 ) BLIP_FWD( 2 )
294
if ( quality > 12 ) BLIP_FWD( 4 )
295
{
296
int const mid = quality / 2 - 1;
297
long t0 = i0 * delta + buf [fwd + mid - 1];
298
long t1 = imp [blip_res * mid] * delta + buf [fwd + mid];
299
imp = impulses + phase;
300
i0 = imp [blip_res * mid];
301
buf [fwd + mid - 1] = t0;
302
buf [fwd + mid] = t1;
303
}
304
if ( quality > 12 ) BLIP_REV( 6 )
305
if ( quality > 8 ) BLIP_REV( 4 )
306
BLIP_REV( 2 )
307
308
long t0 = i0 * delta + buf [rev];
309
long t1 = *imp * delta + buf [rev + 1];
310
buf [rev] = t0;
311
buf [rev + 1] = t1;
312
}
313
314
#undef BLIP_FWD
315
#undef BLIP_REV
316
317
template<int quality,int range>
318
void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
319
{
320
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
321
}
322
323
template<int quality,int range>
324
void Blip_Synth<quality,range>::update( blip_time_t t, int amp )
325
{
326
int delta = amp - impl.last_amp;
327
impl.last_amp = amp;
328
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
329
}
330
331
inline blip_eq_t::blip_eq_t( double t ) :
332
treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
333
inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
334
treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
335
336
inline int Blip_Buffer::length() const { return length_; }
337
inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); }
338
inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
339
inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
340
inline long Blip_Buffer::clock_rate() const { return clock_rate_; }
341
inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
342
343
inline int Blip_Reader::begin( Blip_Buffer& blip_buf )
344
{
345
buf = blip_buf.buffer_;
346
accum = blip_buf.reader_accum;
347
return blip_buf.bass_shift;
348
}
349
350
int const blip_max_length = 0;
351
int const blip_default_length = 250;
352
353
#endif
354
355
356