comparison Plugins/Input/console/Blip_Buffer.cpp @ 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 f12d7e208b43
comparison
equal deleted inserted replaced
492:ccb68bad47b2 493:c04dff121e1d
1
2 // Blip_Buffer 0.4.0. http://www.slack.net/~ant/
3
4 #include "Blip_Buffer.h"
5
6 #include <assert.h>
7 #include <limits.h>
8 #include <string.h>
9 #include <stdlib.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
19 more details. You should have received a copy of the GNU Lesser General
20 Public License along with this module; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
22
23 int const buffer_extra = blip_widest_impulse_ + 2;
24
25 Blip_Buffer::Blip_Buffer()
26 {
27 factor_ = LONG_MAX;
28 offset_ = 0;
29 buffer_ = 0;
30 buffer_size_ = 0;
31 sample_rate_ = 0;
32 reader_accum = 0;
33 bass_shift = 0;
34 clock_rate_ = 0;
35 bass_freq_ = 16;
36 length_ = 0;
37
38 // assumptions code makes about implementation-defined features
39 #ifndef NDEBUG
40 // right shift of negative value preserves sign
41 buf_t_ i = -0x7FFFFFFE;
42 assert( (i >> 1) == -0x3FFFFFFF );
43
44 // casting to short truncates to 16 bits and sign-extends
45 i = 0x18000;
46 assert( (short) i == -0x8000 );
47 #endif
48 }
49
50 Blip_Buffer::~Blip_Buffer()
51 {
52 free( buffer_ );
53 }
54
55 void Blip_Buffer::clear( int entire_buffer )
56 {
57 offset_ = 0;
58 reader_accum = 0;
59 if ( buffer_ )
60 {
61 long count = (entire_buffer ? buffer_size_ : samples_avail());
62 memset( buffer_, 0, (count + buffer_extra) * sizeof (buf_t_) );
63 }
64 }
65
66 Blip_Buffer::blargg_err_t Blip_Buffer::set_sample_rate( long new_rate, int msec )
67 {
68 // start with maximum length that resampled time can represent
69 long new_size = (ULONG_MAX >> BLIP_BUFFER_ACCURACY) - buffer_extra - 64;
70 if ( msec != blip_max_length )
71 {
72 long s = (new_rate * (msec + 1) + 999) / 1000;
73 if ( s < new_size )
74 new_size = s;
75 else
76 assert( 0 ); // fails if requested buffer length exceeds limit
77 }
78
79 if ( buffer_size_ != new_size )
80 {
81 void* p = realloc( buffer_, (new_size + buffer_extra) * sizeof *buffer_ );
82 if ( !p )
83 return "Out of memory";
84 buffer_ = (buf_t_*) p;
85 }
86
87 buffer_size_ = new_size;
88
89 // update things based on the sample rate
90 sample_rate_ = new_rate;
91 length_ = new_size * 1000 / new_rate - 1;
92 if ( msec )
93 assert( length_ == msec ); // ensure length is same as that passed in
94 if ( clock_rate_ )
95 clock_rate( clock_rate_ );
96 bass_freq( bass_freq_ );
97
98 clear();
99
100 return 0; // success
101 }
102
103 blip_resampled_time_t Blip_Buffer::clock_rate_factor( long clock_rate ) const
104 {
105 double ratio = (double) sample_rate_ / clock_rate;
106 long factor = (long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
107 assert( factor > 0 || !sample_rate_ ); // fails if clock/output ratio is too large
108 return (blip_resampled_time_t) factor;
109 }
110
111 void Blip_Buffer::bass_freq( int freq )
112 {
113 bass_freq_ = freq;
114 int shift = 31;
115 if ( freq > 0 )
116 {
117 shift = 13;
118 long f = (freq << 16) / sample_rate_;
119 while ( (f >>= 1) && --shift ) { }
120 }
121 bass_shift = shift;
122 }
123
124 void Blip_Buffer::end_frame( blip_time_t t )
125 {
126 offset_ += t * factor_;
127 assert( samples_avail() <= (long) buffer_size_ ); // time outside buffer length
128 }
129
130 void Blip_Buffer::remove_silence( long count )
131 {
132 assert( count <= samples_avail() ); // tried to remove more samples than available
133 offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
134 }
135
136 long Blip_Buffer::count_samples( blip_time_t t ) const
137 {
138 unsigned long last_sample = resampled_time( t ) >> BLIP_BUFFER_ACCURACY;
139 unsigned long first_sample = offset_ >> BLIP_BUFFER_ACCURACY;
140 return (long) (last_sample - first_sample);
141 }
142
143 blip_time_t Blip_Buffer::count_clocks( long count ) const
144 {
145 if ( count > buffer_size_ )
146 count = buffer_size_;
147 blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
148 return (blip_time_t) ((time - offset_ + factor_ - 1) / factor_);
149 }
150
151 void Blip_Buffer::remove_samples( long count )
152 {
153 if ( count )
154 {
155 remove_silence( count );
156
157 // copy remaining samples to beginning and clear old samples
158 long remain = samples_avail() + buffer_extra;
159 memmove( buffer_, buffer_ + count, remain * sizeof *buffer_ );
160 memset( buffer_ + remain, 0, count * sizeof *buffer_ );
161 }
162 }
163
164 // Blip_Synth_
165
166 Blip_Synth_::Blip_Synth_( short* p, int w ) :
167 impulses( p ),
168 width( w )
169 {
170 volume_unit_ = 0.0;
171 kernel_unit = 0;
172 buf = 0;
173 last_amp = 0;
174 delta_factor = 0;
175 }
176
177 static double const pi = 3.1415926535897932384626433832795029;
178
179 static void gen_sinc( float* out, int count, double oversample, double treble, double cutoff )
180 {
181 if ( cutoff >= 0.999 )
182 cutoff = 0.999;
183
184 if ( treble < -300.0 )
185 treble = -300.0;
186 if ( treble > 5.0 )
187 treble = 5.0;
188
189 double const maxh = 4096.0;
190 double const rolloff = pow( 10.0, 1.0 / (maxh * 20.0) * treble / (1.0 - cutoff) );
191 double const pow_a_n = pow( rolloff, maxh - maxh * cutoff );
192 double const to_angle = pi / 2 / maxh / oversample;
193 for ( int i = 0; i < count; i++ )
194 {
195 double angle = ((i - count) * 2 + 1) * to_angle;
196 double c = rolloff * cos( (maxh - 1.0) * angle ) - cos( maxh * angle );
197 double cos_nc_angle = cos( maxh * cutoff * angle );
198 double cos_nc1_angle = cos( (maxh * cutoff - 1.0) * angle );
199 double cos_angle = cos( angle );
200
201 c = c * pow_a_n - rolloff * cos_nc1_angle + cos_nc_angle;
202 double d = 1.0 + rolloff * (rolloff - cos_angle - cos_angle);
203 double b = 2.0 - cos_angle - cos_angle;
204 double a = 1.0 - cos_angle - cos_nc_angle + cos_nc1_angle;
205
206 out [i] = (float) ((a * d + c * b) / (b * d)); // a / b + c / d
207 }
208 }
209
210 void blip_eq_t::generate( float* out, int count ) const
211 {
212 // lower cutoff freq for narrow kernels with their wider transition band
213 // (8 points->1.49, 16 points->1.15)
214 double oversample = blip_res * 2.25 / count + 0.85;
215 double half_rate = sample_rate * 0.5;
216 if ( cutoff_freq )
217 oversample = half_rate / cutoff_freq;
218 double cutoff = rolloff_freq * oversample / half_rate;
219
220 gen_sinc( out, count, blip_res * oversample, treble, cutoff );
221
222 // apply (half of) hamming window
223 double to_fraction = pi / (count - 1);
224 for ( int i = count; i--; )
225 out [i] *= 0.54 - 0.46 * cos( i * to_fraction );
226 }
227
228 void Blip_Synth_::adjust_impulse()
229 {
230 // sum pairs for each phase and add error correction to end of first half
231 int const size = impulses_size();
232 for ( int p = blip_res; p-- >= blip_res / 2; )
233 {
234 int p2 = blip_res - 2 - p;
235 long error = kernel_unit;
236 for ( int i = 1; i < size; i += blip_res )
237 {
238 error -= impulses [i + p ];
239 error -= impulses [i + p2];
240 }
241 if ( p == p2 )
242 error /= 2; // phase = 0.5 impulse uses same half for both sides
243 impulses [size - blip_res + p] += error;
244 //printf( "error: %ld\n", error );
245 }
246
247 //for ( int i = blip_res; i--; printf( "\n" ) )
248 // for ( int j = 0; j < width / 2; j++ )
249 // printf( "%5ld,", impulses [j * blip_res + i + 1] );
250 }
251
252 void Blip_Synth_::treble_eq( blip_eq_t const& eq )
253 {
254 float fimpulse [blip_res / 2 * (blip_widest_impulse_ - 1) + blip_res * 2];
255
256 int const half_size = blip_res / 2 * (width - 1);
257 eq.generate( &fimpulse [blip_res], half_size );
258
259 int i;
260
261 // need mirror slightly past center for calculation
262 for ( i = blip_res; i--; )
263 fimpulse [blip_res + half_size + i] = fimpulse [blip_res + half_size - 1 - i];
264
265 // starts at 0
266 for ( i = 0; i < blip_res; i++ )
267 fimpulse [i] = 0.0f;
268
269 // find rescale factor
270 double total = 0.0;
271 for ( i = 0; i < half_size; i++ )
272 total += fimpulse [blip_res + i];
273
274 //double const base_unit = 44800.0 - 128 * 18; // allows treble up to +0 dB
275 //double const base_unit = 37888.0; // allows treble to +5 dB
276 double const base_unit = 32768.0; // necessary for blip_unscaled to work
277 double rescale = base_unit / 2 / total;
278 kernel_unit = (long) base_unit;
279
280 // integrate, first difference, rescale, convert to int
281 double sum = 0.0;
282 double next = 0.0;
283 int const impulses_size = this->impulses_size();
284 for ( i = 0; i < impulses_size; i++ )
285 {
286 impulses [i] = (short) floor( (next - sum) * rescale + 0.5 );
287 sum += fimpulse [i];
288 next += fimpulse [i + blip_res];
289 }
290 adjust_impulse();
291
292 // volume might require rescaling
293 double vol = volume_unit_;
294 if ( vol )
295 {
296 volume_unit_ = 0.0;
297 volume_unit( vol );
298 }
299 }
300
301 void Blip_Synth_::volume_unit( double new_unit )
302 {
303 if ( new_unit != volume_unit_ )
304 {
305 // use default eq if it hasn't been set yet
306 if ( !kernel_unit )
307 treble_eq( -8.0 );
308
309 volume_unit_ = new_unit;
310 double factor = new_unit * (1L << blip_sample_bits) / kernel_unit;
311
312 if ( factor > 0.0 )
313 {
314 int shift = 0;
315
316 // if unit is really small, might need to attenuate kernel
317 while ( factor < 2.0 )
318 {
319 shift++;
320 factor *= 2.0;
321 }
322
323 if ( shift )
324 {
325 kernel_unit >>= shift;
326 assert( kernel_unit > 0 ); // fails if volume unit is too low
327
328 // keep values positive to avoid round-towards-zero of sign-preserving
329 // right shift for negative values
330 long offset = 0x8000 + (1 << (shift - 1));
331 long offset2 = 0x8000 >> shift;
332 for ( int i = impulses_size(); i--; )
333 impulses [i] = (short) (((impulses [i] + offset) >> shift) - offset2);
334 adjust_impulse();
335 }
336 }
337 delta_factor = (int) floor( factor + 0.5 );
338 //printf( "delta_factor: %d, kernel_unit: %d\n", delta_factor, kernel_unit );
339 }
340 }
341
342 long Blip_Buffer::read_samples( blip_sample_t* out, long max_samples, int stereo )
343 {
344 long count = samples_avail();
345 if ( count > max_samples )
346 count = max_samples;
347
348 if ( count )
349 {
350 int const sample_shift = blip_sample_bits - 16;
351 int const bass_shift = this->bass_shift;
352 long accum = reader_accum;
353 buf_t_* in = buffer_;
354
355 if ( !stereo )
356 {
357 for ( long n = count; n--; )
358 {
359 long s = accum >> sample_shift;
360 accum -= accum >> bass_shift;
361 accum += *in++;
362 *out++ = (blip_sample_t) s;
363
364 // clamp sample
365 if ( (blip_sample_t) s != s )
366 out [-1] = (blip_sample_t) (0x7FFF - (s >> 24));
367 }
368 }
369 else
370 {
371 for ( long n = count; n--; )
372 {
373 long s = accum >> sample_shift;
374 accum -= accum >> bass_shift;
375 accum += *in++;
376 *out = (blip_sample_t) s;
377 out += 2;
378
379 // clamp sample
380 if ( (blip_sample_t) s != s )
381 out [-2] = (blip_sample_t) (0x7FFF - (s >> 24));
382 }
383 }
384
385 reader_accum = accum;
386 remove_samples( count );
387 }
388 return count;
389 }
390
391 void Blip_Buffer::mix_samples( blip_sample_t const* in, long count )
392 {
393 buf_t_* out = buffer_ + (offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
394
395 int const sample_shift = blip_sample_bits - 16;
396 int prev = 0;
397 while ( count-- )
398 {
399 long s = (long) *in++ << sample_shift;
400 *out += s - prev;
401 prev = s;
402 ++out;
403 }
404 *out -= prev;
405 }
406