| 1 | |
| 2 | // Buffer of sound samples into which band-limited waveforms can be synthesized |
| 3 | // using Blip_Wave or Blip_Synth. |
| 4 | |
| 5 | // Blip_Buffer 0.3.3. Copyright (C) 2003-2005 Shay Green. GNU LGPL license. |
| 6 | |
| 7 | #ifndef BLIP_BUFFER_H |
| 8 | #define BLIP_BUFFER_H |
| 9 | |
| 10 | #include "blargg_common.h" |
| 11 | |
| 12 | class Blip_Reader; |
| 13 | |
| 14 | // Source time unit. |
| 15 | typedef long blip_time_t; |
| 16 | |
| 17 | // Type of sample produced. Signed 16-bit format. |
| 18 | typedef BOOST::int16_t blip_sample_t; |
| 19 | |
| 20 | // Make buffer as large as possible (currently about 65000 samples) |
| 21 | const int blip_default_length = 0; |
| 22 | |
| 23 | class Blip_Buffer { |
| 24 | public: |
| 25 | // Construct an empty buffer. |
| 26 | Blip_Buffer(); |
| 27 | ~Blip_Buffer(); |
| 28 | |
| 29 | // Set output sample rate and buffer length in milliseconds (1/1000 sec), |
| 30 | // then clear buffer. If length is not specified, make as large as possible. |
| 31 | // If there is insufficient memory for the buffer, sets the buffer length |
| 32 | // to 0 and returns error string (or propagates exception if compiler supports it). |
| 33 | blargg_err_t sample_rate( long samples_per_sec, int msec_length = blip_default_length ); |
| 34 | // to do: rename to set_sample_rate |
| 35 | |
| 36 | // Length of buffer, in milliseconds |
| 37 | int length() const; |
| 38 | |
| 39 | // Current output sample rate |
| 40 | long sample_rate() const; |
| 41 | |
| 42 | // Number of source time units per second |
| 43 | void clock_rate( long ); |
| 44 | long clock_rate() const; |
| 45 | |
| 46 | // Set frequency at which high-pass filter attenuation passes -3dB |
| 47 | void bass_freq( int frequency ); |
| 48 | |
| 49 | // Remove all available samples and clear buffer to silence. If 'entire_buffer' is |
| 50 | // false, just clear out any samples waiting rather than the entire buffer. |
| 51 | void clear( bool entire_buffer = true ); |
| 52 | |
| 53 | // to do: |
| 54 | // Notify Blip_Buffer that synthesis has been performed until specified time |
| 55 | //void run_until( blip_time_t ); |
| 56 | |
| 57 | // End current time frame of specified duration and make its samples available |
| 58 | // (along with any still-unread samples) for reading with read_samples(). Begin |
| 59 | // a new time frame at the end of the current frame. All transitions must have |
| 60 | // been added before 'time'. |
| 61 | void end_frame( blip_time_t time ); |
| 62 | |
| 63 | // Number of samples available for reading with read_samples() |
| 64 | long samples_avail() const; |
| 65 | |
| 66 | // Read at most 'max_samples' out of buffer into 'dest', removing them from from |
| 67 | // the buffer. Return number of samples actually read and removed. If stereo is |
| 68 | // true, increment 'dest' one extra time after writing each sample, to allow |
| 69 | // easy interleving of two channels into a stereo output buffer. |
| 70 | long read_samples( blip_sample_t* dest, long max_samples, bool stereo = false ); |
| 71 | |
| 72 | // Remove 'count' samples from those waiting to be read |
| 73 | void remove_samples( long count ); |
| 74 | |
| 75 | // Number of samples delay from synthesis to samples read out |
| 76 | int output_latency() const; |
| 77 | |
| 78 | |
| 79 | // Experimental external buffer mixing support |
| 80 | |
| 81 | // Number of raw samples that can be mixed within frame of specified duration |
| 82 | long count_samples( blip_time_t duration ) const; |
| 83 | |
| 84 | // Mix 'count' samples from 'buf' into buffer. |
| 85 | void mix_samples( const blip_sample_t* buf, long count ); |
| 86 | |
| 87 | |
| 88 | // not documented yet |
| 89 | |
| 90 | void remove_silence( long count ); |
| 91 | |
| 92 | typedef unsigned long resampled_time_t; |
| 93 | |
| 94 | resampled_time_t resampled_time( blip_time_t t ) const { |
| 95 | return t * resampled_time_t (factor_) + offset_; |
| 96 | } |
| 97 | |
| 98 | resampled_time_t resampled_duration( int t ) const { |
| 99 | return t * resampled_time_t (factor_); |
| 100 | } |
| 101 | |
| 102 | private: |
| 103 | // noncopyable |
| 104 | Blip_Buffer( const Blip_Buffer& ); |
| 105 | Blip_Buffer& operator = ( const Blip_Buffer& ); |
| 106 | |
| 107 | // Don't use the following members. They are public only for technical reasons. |
| 108 | public: |
| 109 | enum { widest_impulse_ = 24 }; |
| 110 | typedef BOOST::uint16_t buf_t_; |
| 111 | |
| 112 | unsigned long factor_; |
| 113 | resampled_time_t offset_; |
| 114 | buf_t_* buffer_; |
| 115 | unsigned buffer_size_; |
| 116 | private: |
| 117 | long reader_accum; |
| 118 | int bass_shift; |
| 119 | long samples_per_sec; |
| 120 | long clocks_per_sec; |
| 121 | int bass_freq_; |
| 122 | int length_; |
| 123 | |
| 124 | enum { accum_fract = 15 }; // less than 16 to give extra sample range |
| 125 | enum { sample_offset = 0x7F7F }; // repeated byte allows memset to clear buffer |
| 126 | |
| 127 | friend class Blip_Reader; |
| 128 | }; |
| 129 | |
| 130 | // Low-pass equalization parameters (see notes.txt) |
| 131 | class blip_eq_t { |
| 132 | public: |
| 133 | blip_eq_t( double treble = 0 ); |
| 134 | blip_eq_t( double treble, long cutoff, long sample_rate ); |
| 135 | private: |
| 136 | double treble; |
| 137 | long cutoff; |
| 138 | long sample_rate; |
| 139 | friend class Blip_Impulse_; |
| 140 | }; |
| 141 | |
| 142 | // not documented yet (see Multi_Buffer.cpp for an example of use) |
| 143 | class Blip_Reader { |
| 144 | const Blip_Buffer::buf_t_* buf; |
| 145 | long accum; |
| 146 | #ifdef __MWERKS__ |
| 147 | void operator = ( struct foobar ); // helps optimizer |
| 148 | #endif |
| 149 | public: |
| 150 | // avoid anything which might cause optimizer to put object in memory |
| 151 | |
| 152 | int begin( Blip_Buffer& blip_buf ) { |
| 153 | buf = blip_buf.buffer_; |
| 154 | accum = blip_buf.reader_accum; |
| 155 | return blip_buf.bass_shift; |
| 156 | } |
| 157 | |
| 158 | int read() const { |
| 159 | return accum >> Blip_Buffer::accum_fract; |
| 160 | } |
| 161 | |
| 162 | void next( int bass_shift = 9 ) { |
| 163 | accum -= accum >> bass_shift; |
| 164 | accum += ((long) *buf++ - Blip_Buffer::sample_offset) << Blip_Buffer::accum_fract; |
| 165 | } |
| 166 | |
| 167 | void end( Blip_Buffer& blip_buf ) { |
| 168 | blip_buf.reader_accum = accum; |
| 169 | } |
| 170 | }; |
| 171 | |
| 172 | |
| 173 | |
| 174 | // End of public interface |
| 175 | |
| 176 | #ifndef BLIP_BUFFER_ACCURACY |
| 177 | #define BLIP_BUFFER_ACCURACY 16 |
| 178 | #endif |
| 179 | |
| 180 | const int blip_res_bits_ = 5; |
| 181 | |
| 182 | typedef BOOST::uint32_t blip_pair_t_; |
| 183 | |
| 184 | class Blip_Impulse_ { |
| 185 | typedef BOOST::uint16_t imp_t; |
| 186 | |
| 187 | blip_eq_t eq; |
| 188 | double volume_unit_; |
| 189 | imp_t* impulses; |
| 190 | imp_t* impulse; |
| 191 | int width; |
| 192 | int fine_bits; |
| 193 | int res; |
| 194 | bool generate; |
| 195 | |
| 196 | void fine_volume_unit(); |
| 197 | void scale_impulse( int unit, imp_t* ) const; |
| 198 | public: |
| 199 | Blip_Buffer* buf; |
| 200 | BOOST::uint32_t offset; |
| 201 | |
| 202 | void init( blip_pair_t_* impulses, int width, int res, int fine_bits = 0 ); |
| 203 | void volume_unit( double ); |
| 204 | void treble_eq( const blip_eq_t& ); |
| 205 | }; |
| 206 | |
| 207 | inline blip_eq_t::blip_eq_t( double t ) : |
| 208 | treble( t ), cutoff( 0 ), sample_rate( 44100 ) { |
| 209 | } |
| 210 | |
| 211 | inline blip_eq_t::blip_eq_t( double t, long c, long sr ) : |
| 212 | treble( t ), cutoff( c ), sample_rate( sr ) { |
| 213 | } |
| 214 | |
| 215 | inline int Blip_Buffer::length() const { |
| 216 | return length_; |
| 217 | } |
| 218 | |
| 219 | inline long Blip_Buffer::samples_avail() const { |
| 220 | return long (offset_ >> BLIP_BUFFER_ACCURACY); |
| 221 | } |
| 222 | |
| 223 | inline long Blip_Buffer::sample_rate() const { |
| 224 | return samples_per_sec; |
| 225 | } |
| 226 | |
| 227 | inline void Blip_Buffer::end_frame( blip_time_t t ) { |
| 228 | offset_ += t * factor_; |
| 229 | assert(( "Blip_Buffer::end_frame(): Frame went past end of buffer" , |
| 230 | samples_avail() <= (long) buffer_size_ )); |
| 231 | } |
| 232 | |
| 233 | inline void Blip_Buffer::remove_silence( long count ) { |
| 234 | assert(( "Blip_Buffer::remove_silence(): Tried to remove more samples than available" , |
| 235 | count <= samples_avail() )); |
| 236 | offset_ -= resampled_time_t (count) << BLIP_BUFFER_ACCURACY; |
| 237 | } |
| 238 | |
| 239 | inline int Blip_Buffer::output_latency() const { |
| 240 | return widest_impulse_ / 2; |
| 241 | } |
| 242 | |
| 243 | inline long Blip_Buffer::clock_rate() const { |
| 244 | return clocks_per_sec; |
| 245 | } |
| 246 | |
| 247 | // MSVC6 fix |
| 248 | typedef Blip_Buffer::resampled_time_t blip_resampled_time_t; |
| 249 | |
| 250 | #include "Blip_Synth.h" |
| 251 | |
| 252 | #endif |
| 253 | |
| 254 | |