Mercurial > audlegacy
comparison Plugins/Input/console/Blip_Buffer.h @ 493:c04dff121e1d trunk
[svn] hostile merge, phase 2: reimport based on new plugin code
author | nenolod |
---|---|
date | Tue, 24 Jan 2006 20:19:01 -0800 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
492:ccb68bad47b2 | 493:c04dff121e1d |
---|---|
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 |