Submit initial patch from FS#12176. Adds support for several new game music formats...
[kugel-rb.git] / apps / codecs / libgme / blip_buffer.c
blob3061f68573fa2bc8428a935ea8417d3109f92f70
1 // Blip_Buffer 0.4.1. http://www.slack.net/~ant/
3 #include "blip_buffer.h"
5 #include <assert.h>
6 #include <limits.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <math.h>
11 /* Copyright (C) 2003-2006 Shay Green. This module is free software; you
12 can redistribute it and/or modify it under the terms of the GNU Lesser
13 General Public License as published by the Free Software Foundation; either
14 version 2.1 of the License, or (at your option) any later version. This
15 module is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 details. You should have received a copy of the GNU Lesser General Public
19 License along with this module; if not, write to the Free Software Foundation,
20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
22 #ifdef BLARGG_ENABLE_OPTIMIZER
23 #include BLARGG_ENABLE_OPTIMIZER
24 #endif
26 int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
28 void Blip_init( struct Blip_Buffer* this )
30 this->factor_ = LONG_MAX;
31 this->offset_ = 0;
32 this->buffer_size_ = 0;
33 this->sample_rate_ = 0;
34 this->reader_accum_ = 0;
35 this->bass_shift_ = 0;
36 this->clock_rate_ = 0;
37 this->bass_freq_ = 16;
38 this->length_ = 0;
40 // assumptions code makes about implementation-defined features
41 #ifndef NDEBUG
42 // right shift of negative value preserves sign
43 buf_t_ i = -0x7FFFFFFE;
44 assert( (i >> 1) == -0x3FFFFFFF );
46 // casting to short truncates to 16 bits and sign-extends
47 i = 0x18000;
48 assert( (short) i == -0x8000 );
49 #endif
52 void Blip_stop( struct Blip_Buffer* this )
54 if ( this->buffer_size_ != silent_buf_size )
55 free( this->buffer_ );
58 void Blip_clear( struct Blip_Buffer* this, int entire_buffer )
60 this->offset_ = 0;
61 this->reader_accum_ = 0;
62 this->modified_ = 0;
63 if ( this->buffer_ )
65 long count = (entire_buffer ? this->buffer_size_ : Blip_samples_avail( this ));
66 memset( this->buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) );
70 blargg_err_t Blip_set_sample_rate( struct Blip_Buffer* this, long new_rate, int msec )
72 if ( this->buffer_size_ == silent_buf_size )
74 assert( 0 );
75 return "Internal (tried to resize Silent_Blip_Buffer)";
78 // start with maximum length that resampled time can represent
79 long new_size = (ULONG_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64;
80 if ( msec != blip_max_length )
82 long s = (new_rate * (msec + 1) + 999) / 1000;
83 if ( s < new_size )
84 new_size = s;
85 else
86 assert( 0 ); // fails if requested buffer length exceeds limit
89 if ( new_size > blip_buffer_max )
90 return "Out of memory";
92 this->buffer_size_ = new_size;
93 assert( this->buffer_size_ != silent_buf_size );
95 // update things based on the sample rate
96 this->sample_rate_ = new_rate;
97 this->length_ = new_size * 1000 / new_rate - 1;
98 if ( msec )
99 assert( this->length_ == msec ); // ensure length is same as that passed in
100 if ( this->clock_rate_ )
101 Blip_set_clock_rate( this, this->clock_rate_ );
102 Blip_bass_freq( this, this->bass_freq_ );
104 Blip_clear( this, 1 );
106 return 0; // success
109 /* Not sure if this affects sound quality */
110 #if defined(ROCKBOX)
111 double floor(double x) {
112 if ( x > 0 ) return (int)x;
113 return (int)(x-0.9999999999999999);
115 #endif
117 blip_resampled_time_t Blip_clock_rate_factor( struct Blip_Buffer* this, long rate )
119 double ratio = (double) this->sample_rate_ / rate;
120 blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
121 assert( factor > 0 || !this->sample_rate_ ); // fails if clock/output ratio is too large
122 return (blip_resampled_time_t) factor;
125 void Blip_bass_freq( struct Blip_Buffer* this, int freq )
127 this->bass_freq_ = freq;
128 int shift = 31;
129 if ( freq > 0 )
131 shift = 13;
132 long f = (freq << 16) / this->sample_rate_;
133 while ( (f >>= 1) && --shift ) { }
135 this->bass_shift_ = shift;
138 void Blip_end_frame( struct Blip_Buffer* this, blip_time_t t )
140 this->offset_ += t * this->factor_;
141 assert( Blip_samples_avail( this ) <= (long) this->buffer_size_ ); // time outside buffer length
144 void Blip_remove_silence( struct Blip_Buffer* this, long count )
146 assert( count <= Blip_samples_avail( this ) ); // tried to remove more samples than available
147 this->offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
150 long Blip_count_samples( struct Blip_Buffer* this, blip_time_t t )
152 unsigned long last_sample = Blip_resampled_time( this, t ) >> BLIP_BUFFER_ACCURACY;
153 unsigned long first_sample = this->offset_ >> BLIP_BUFFER_ACCURACY;
154 return (long) (last_sample - first_sample);
157 blip_time_t Blip_count_clocks( struct Blip_Buffer* this, long count )
159 if ( !this->factor_ )
161 assert( 0 ); // sample rate and clock rates must be set first
162 return 0;
165 if ( count > this->buffer_size_ )
166 count = this->buffer_size_;
167 blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
168 return (blip_time_t) ((time - this->offset_ + this->factor_ - 1) / this->factor_);
171 void Blip_remove_samples( struct Blip_Buffer* this, long count )
173 if ( count )
175 Blip_remove_silence( this, count );
177 // copy remaining samples to beginning and clear old samples
178 long remain = Blip_samples_avail( this ) + blip_buffer_extra_;
179 memmove( this->buffer_, this->buffer_ + count, remain * sizeof *this->buffer_ );
180 memset( this->buffer_ + remain, 0, count * sizeof *this->buffer_ );
184 long Blip_read_samples( struct Blip_Buffer* this, blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo )
186 long count = Blip_samples_avail( this );
187 if ( count > max_samples )
188 count = max_samples;
190 if ( count )
192 int const bass = BLIP_READER_BASS( *this );
193 BLIP_READER_BEGIN( reader, *this );
195 if ( !stereo )
197 blip_long n;
198 for ( n = count; n; --n )
200 blip_long s = BLIP_READER_READ( reader );
201 if ( (blip_sample_t) s != s )
202 s = 0x7FFF - (s >> 24);
203 *out++ = (blip_sample_t) s;
204 BLIP_READER_NEXT( reader, bass );
207 else
209 blip_long n;
210 for ( n = count; n; --n )
212 blip_long s = BLIP_READER_READ( reader );
213 if ( (blip_sample_t) s != s )
214 s = 0x7FFF - (s >> 24);
215 *out = (blip_sample_t) s;
216 out += 2;
217 BLIP_READER_NEXT( reader, bass );
220 BLIP_READER_END( reader, *this );
222 Blip_remove_samples( this, count );
224 return count;
227 void Blip_mix_samples( struct Blip_Buffer* this, blip_sample_t const* in, long count )
229 if ( this->buffer_size_ == silent_buf_size )
231 assert( 0 );
232 return;
235 buf_t_* out = this->buffer_ + (this->offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
237 int const sample_shift = blip_sample_bits - 16;
238 int prev = 0;
239 while ( count-- )
241 blip_long s = (blip_long) *in++ << sample_shift;
242 *out += s - prev;
243 prev = s;
244 ++out;
246 *out -= prev;
249 void Blip_set_modified( struct Blip_Buffer* this )
251 this->modified_ = 1;
254 int Blip_clear_modified( struct Blip_Buffer* this )
256 int b = this->modified_;
257 this->modified_ = 0;
258 return b;
261 blip_resampled_time_t Blip_resampled_duration( struct Blip_Buffer* this, int t )
263 return t * this->factor_;
266 blip_resampled_time_t Blip_resampled_time( struct Blip_Buffer* this, blip_time_t t )
268 return t * this->factor_ + this->offset_;
272 // Blip_Synth
274 void Synth_init( struct Blip_Synth* this )
276 this->buf = 0;
277 this->last_amp = 0;
278 this->delta_factor = 0;
281 // Set overall volume of waveform
282 void Synth_volume( struct Blip_Synth* this, double v )
284 this->delta_factor = (int) (v * (1L << blip_sample_bits) + 0.5);