rlm@1: // Band-limited sound synthesis buffer rlm@1: rlm@1: // Blip_Buffer 0.4.1 rlm@1: #ifndef BLIP_BUFFER_H rlm@1: #define BLIP_BUFFER_H rlm@1: rlm@1: // internal rlm@1: #include rlm@1: #if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF rlm@1: typedef long blip_long; rlm@1: typedef unsigned long blip_ulong; rlm@1: #else rlm@1: typedef int blip_long; rlm@1: typedef unsigned blip_ulong; rlm@1: #endif rlm@1: rlm@1: // Time unit at source clock rate rlm@1: typedef blip_long blip_time_t; rlm@1: rlm@1: // Output samples are 16-bit signed, with a range of -32768 to 32767 rlm@1: typedef short blip_sample_t; rlm@1: enum { blip_sample_max = 32767 }; rlm@1: rlm@1: struct blip_buffer_state_t; rlm@1: rlm@1: class Blip_Buffer { rlm@1: public: rlm@1: typedef const char* blargg_err_t; rlm@1: rlm@1: // Sets output sample rate and buffer length in milliseconds (1/1000 sec, defaults rlm@1: // to 1/4 second) and clears buffer. If there isn't enough memory, leaves buffer rlm@1: // untouched and returns "Out of memory", otherwise returns NULL. rlm@1: blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 ); rlm@1: rlm@1: // Sets number of source time units per second rlm@1: void clock_rate( long clocks_per_sec ); rlm@1: rlm@1: // Ends current time frame of specified duration and makes its samples available rlm@1: // (along with any still-unread samples) for reading with read_samples(). Begins rlm@1: // a new time frame at the end of the current frame. rlm@1: void end_frame( blip_time_t time ); rlm@1: rlm@1: // Reads at most 'max_samples' out of buffer into 'dest', removing them from from rlm@1: // the buffer. Returns number of samples actually read and removed. If stereo is rlm@1: // true, increments 'dest' one extra time after writing each sample, to allow rlm@1: // easy interleving of two channels into a stereo output buffer. rlm@1: long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 ); rlm@1: rlm@1: // Additional features rlm@1: rlm@1: // Removes all available samples and clear buffer to silence. If 'entire_buffer' is rlm@1: // false, just clears out any samples waiting rather than the entire buffer. rlm@1: void clear( int entire_buffer = 1 ); rlm@1: rlm@1: // Number of samples available for reading with read_samples() rlm@1: long samples_avail() const; rlm@1: rlm@1: // Removes 'count' samples from those waiting to be read rlm@1: void remove_samples( long count ); rlm@1: rlm@1: // Sets frequency high-pass filter frequency, where higher values reduce bass more rlm@1: void bass_freq( int frequency ); rlm@1: rlm@1: // Current output sample rate rlm@1: long sample_rate() const; rlm@1: rlm@1: // Length of buffer in milliseconds rlm@1: int length() const; rlm@1: rlm@1: // Number of source time units per second rlm@1: long clock_rate() const; rlm@1: rlm@1: // Experimental features rlm@1: rlm@1: // Saves state, including high-pass filter and tails of last deltas. rlm@1: // All samples must have been read from buffer before calling this. rlm@1: void save_state( blip_buffer_state_t* out ); rlm@1: rlm@1: // Loads state. State must have been saved from Blip_Buffer with same rlm@1: // settings during same run of program. States can NOT be stored on disk. rlm@1: // Clears buffer before loading state. rlm@1: void load_state( blip_buffer_state_t const& in ); rlm@1: rlm@1: // Number of samples delay from synthesis to samples read out rlm@1: int output_latency() const; rlm@1: rlm@1: // Counts number of clocks needed until 'count' samples will be available. rlm@1: // If buffer can't even hold 'count' samples, returns number of clocks until rlm@1: // buffer becomes full. rlm@1: blip_time_t count_clocks( long count ) const; rlm@1: rlm@1: // Number of raw samples that can be mixed within frame of specified duration. rlm@1: long count_samples( blip_time_t duration ) const; rlm@1: rlm@1: // Mixes in 'count' samples from 'buf_in' rlm@1: void mix_samples( blip_sample_t const* buf_in, long count ); rlm@1: rlm@1: rlm@1: // Signals that sound has been added to buffer. Could be done automatically in rlm@1: // Blip_Synth, but that would affect performance more, as you can arrange that rlm@1: // this is called only once per time frame rather than for every delta. rlm@1: void set_modified() { modified_ = this; } rlm@1: rlm@1: // not documented yet rlm@1: blip_ulong unsettled() const; rlm@1: Blip_Buffer* clear_modified() { Blip_Buffer* b = modified_; modified_ = 0; return b; } rlm@1: void remove_silence( long count ); rlm@1: typedef blip_ulong blip_resampled_time_t; rlm@1: blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; } rlm@1: blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; } rlm@1: blip_resampled_time_t clock_rate_factor( long clock_rate ) const; rlm@1: public: rlm@1: Blip_Buffer(); rlm@1: ~Blip_Buffer(); rlm@1: rlm@1: // Deprecated rlm@1: typedef blip_resampled_time_t resampled_time_t; rlm@1: blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); } rlm@1: blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); } rlm@1: private: rlm@1: // noncopyable rlm@1: Blip_Buffer( const Blip_Buffer& ); rlm@1: Blip_Buffer& operator = ( const Blip_Buffer& ); rlm@1: public: rlm@1: typedef blip_long buf_t_; rlm@1: blip_ulong factor_; rlm@1: blip_resampled_time_t offset_; rlm@1: buf_t_* buffer_; rlm@1: blip_long buffer_size_; rlm@1: blip_long reader_accum_; rlm@1: int bass_shift_; rlm@1: private: rlm@1: long sample_rate_; rlm@1: long clock_rate_; rlm@1: int bass_freq_; rlm@1: int length_; rlm@1: Blip_Buffer* modified_; // non-zero = true (more optimal than using bool, heh) rlm@1: friend class Blip_Reader; rlm@1: }; rlm@1: rlm@1: #ifdef HAVE_CONFIG_H rlm@1: #include "config.h" rlm@1: #endif rlm@1: rlm@1: // Number of bits in resample ratio fraction. Higher values give a more accurate ratio rlm@1: // but reduce maximum buffer size. rlm@1: #ifndef BLIP_BUFFER_ACCURACY rlm@1: #define BLIP_BUFFER_ACCURACY 16 rlm@1: #endif rlm@1: rlm@1: // Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in rlm@1: // noticeable broadband noise when synthesizing high frequency square waves. rlm@1: // Affects size of Blip_Synth objects since they store the waveform directly. rlm@1: #ifndef BLIP_PHASE_BITS rlm@1: #if BLIP_BUFFER_FAST rlm@1: #define BLIP_PHASE_BITS 8 rlm@1: #else rlm@1: #define BLIP_PHASE_BITS 6 rlm@1: #endif rlm@1: #endif rlm@1: rlm@1: // Internal rlm@1: typedef blip_ulong blip_resampled_time_t; rlm@1: int const blip_widest_impulse_ = 16; rlm@1: int const blip_buffer_extra_ = blip_widest_impulse_ + 2; rlm@1: int const blip_res = 1 << BLIP_PHASE_BITS; rlm@1: class blip_eq_t; rlm@1: rlm@1: class Blip_Synth_Fast_ { rlm@1: public: rlm@1: Blip_Buffer* buf; rlm@1: int last_amp; rlm@1: int delta_factor; rlm@1: rlm@1: void volume_unit( double ); rlm@1: Blip_Synth_Fast_(); rlm@1: void treble_eq( blip_eq_t const& ) { } rlm@1: }; rlm@1: rlm@1: class Blip_Synth_ { rlm@1: public: rlm@1: Blip_Buffer* buf; rlm@1: int last_amp; rlm@1: int delta_factor; rlm@1: rlm@1: void volume_unit( double ); rlm@1: Blip_Synth_( short* impulses, int width ); rlm@1: void treble_eq( blip_eq_t const& ); rlm@1: private: rlm@1: double volume_unit_; rlm@1: short* const impulses; rlm@1: int const width; rlm@1: blip_long kernel_unit; rlm@1: int impulses_size() const { return blip_res / 2 * width + 1; } rlm@1: void adjust_impulse(); rlm@1: }; rlm@1: rlm@1: // Quality level, better = slower. In general, use blip_good_quality. rlm@1: const int blip_med_quality = 8; rlm@1: const int blip_good_quality = 12; rlm@1: const int blip_high_quality = 16; rlm@1: rlm@1: // Range specifies the greatest expected change in amplitude. Calculate it rlm@1: // by finding the difference between the maximum and minimum expected rlm@1: // amplitudes (max - min). rlm@1: template rlm@1: class Blip_Synth { rlm@1: public: rlm@1: // Sets overall volume of waveform rlm@1: void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); } rlm@1: rlm@1: // Configures low-pass filter (see blip_buffer.txt) rlm@1: void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); } rlm@1: rlm@1: // Gets/sets Blip_Buffer used for output rlm@1: Blip_Buffer* output() const { return impl.buf; } rlm@1: void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; } rlm@1: rlm@1: // Updates amplitude of waveform at given time. Using this requires a separate rlm@1: // Blip_Synth for each waveform. rlm@1: void update( blip_time_t time, int amplitude ); rlm@1: rlm@1: // Low-level interface rlm@1: rlm@1: // Adds an amplitude transition of specified delta, optionally into specified buffer rlm@1: // rather than the one set with output(). Delta can be positive or negative. rlm@1: // The actual change in amplitude is delta * (volume / range) rlm@1: void offset( blip_time_t, int delta, Blip_Buffer* ) const; rlm@1: void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); } rlm@1: rlm@1: // Works directly in terms of fractional output samples. Contact author for more info. rlm@1: void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const; rlm@1: rlm@1: // Same as offset(), except code is inlined for higher performance rlm@1: void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const { rlm@1: offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); rlm@1: } rlm@1: void offset_inline( blip_time_t t, int delta ) const { rlm@1: offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf ); rlm@1: } rlm@1: rlm@1: private: rlm@1: #if BLIP_BUFFER_FAST rlm@1: Blip_Synth_Fast_ impl; rlm@1: #else rlm@1: Blip_Synth_ impl; rlm@1: typedef short imp_t; rlm@1: imp_t impulses [blip_res * (quality / 2) + 1]; rlm@1: public: rlm@1: Blip_Synth() : impl( impulses, quality ) { } rlm@1: #endif rlm@1: }; rlm@1: rlm@1: // Low-pass equalization parameters rlm@1: class blip_eq_t { rlm@1: public: rlm@1: // Logarithmic rolloff to treble dB at half sampling rate. Negative values reduce rlm@1: // treble, small positive values (0 to 5.0) increase treble. rlm@1: blip_eq_t( double treble_db = 0 ); rlm@1: rlm@1: // See blip_buffer.txt rlm@1: blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 ); rlm@1: rlm@1: private: rlm@1: double treble; rlm@1: long rolloff_freq; rlm@1: long sample_rate; rlm@1: long cutoff_freq; rlm@1: void generate( float* out, int count ) const; rlm@1: friend class Blip_Synth_; rlm@1: }; rlm@1: rlm@1: int const blip_sample_bits = 30; rlm@1: rlm@1: // Dummy Blip_Buffer to direct sound output to, for easy muting without rlm@1: // having to stop sound code. rlm@1: class Silent_Blip_Buffer : public Blip_Buffer { rlm@1: buf_t_ buf [blip_buffer_extra_ + 1]; rlm@1: public: rlm@1: // The following cannot be used (an assertion will fail if attempted): rlm@1: blargg_err_t set_sample_rate( long samples_per_sec, int msec_length ); rlm@1: blip_time_t count_clocks( long count ) const; rlm@1: void mix_samples( blip_sample_t const* buf, long count ); rlm@1: rlm@1: Silent_Blip_Buffer(); rlm@1: }; rlm@1: rlm@1: #if __GNUC__ >= 3 || _MSC_VER >= 1400 rlm@1: #define BLIP_RESTRICT __restrict rlm@1: #else rlm@1: #define BLIP_RESTRICT rlm@1: #endif rlm@1: rlm@1: // Optimized reading from Blip_Buffer, for use in custom sample output rlm@1: rlm@1: // Begins reading from buffer. Name should be unique to the current block. rlm@1: #define BLIP_READER_BEGIN( name, blip_buffer ) \ rlm@1: const Blip_Buffer::buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\ rlm@1: blip_long name##_reader_accum = (blip_buffer).reader_accum_ rlm@1: rlm@1: // Gets value to pass to BLIP_READER_NEXT() rlm@1: #define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_) rlm@1: rlm@1: // Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal rlm@1: // code at the cost of having no bass control rlm@1: int const blip_reader_default_bass = 9; rlm@1: rlm@1: // Current sample rlm@1: #define BLIP_READER_READ( name ) (name##_reader_accum >> (blip_sample_bits - 16)) rlm@1: rlm@1: // Current raw sample in full internal resolution rlm@1: #define BLIP_READER_READ_RAW( name ) (name##_reader_accum) rlm@1: rlm@1: // Advances to next sample rlm@1: #define BLIP_READER_NEXT( name, bass ) \ rlm@1: (void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass))) rlm@1: rlm@1: // Ends reading samples from buffer. The number of samples read must now be removed rlm@1: // using Blip_Buffer::remove_samples(). rlm@1: #define BLIP_READER_END( name, blip_buffer ) \ rlm@1: (void) ((blip_buffer).reader_accum_ = name##_reader_accum) rlm@1: rlm@1: rlm@1: // experimental rlm@1: #define BLIP_READER_ADJ_( name, offset ) (name##_reader_buf += offset) rlm@1: rlm@1: blip_long const blip_reader_idx_factor = sizeof (Blip_Buffer::buf_t_); rlm@1: rlm@1: #define BLIP_READER_NEXT_IDX_( name, bass, idx ) {\ rlm@1: name##_reader_accum -= name##_reader_accum >> (bass);\ rlm@1: name##_reader_accum += name##_reader_buf [(idx)];\ rlm@1: } rlm@1: rlm@1: #define BLIP_READER_NEXT_RAW_IDX_( name, bass, idx ) {\ rlm@1: name##_reader_accum -= name##_reader_accum >> (bass);\ rlm@1: name##_reader_accum +=\ rlm@1: *(Blip_Buffer::buf_t_ const*) ((char const*) name##_reader_buf + (idx));\ rlm@1: } rlm@1: rlm@1: // Compatibility with older version rlm@1: const long blip_unscaled = 65535; rlm@1: const int blip_low_quality = blip_med_quality; rlm@1: const int blip_best_quality = blip_high_quality; rlm@1: rlm@1: // Deprecated; use BLIP_READER macros as follows: rlm@1: // Blip_Reader r; r.begin( buf ); -> BLIP_READER_BEGIN( r, buf ); rlm@1: // int bass = r.begin( buf ) -> BLIP_READER_BEGIN( r, buf ); int bass = BLIP_READER_BASS( buf ); rlm@1: // r.read() -> BLIP_READER_READ( r ) rlm@1: // r.read_raw() -> BLIP_READER_READ_RAW( r ) rlm@1: // r.next( bass ) -> BLIP_READER_NEXT( r, bass ) rlm@1: // r.next() -> BLIP_READER_NEXT( r, blip_reader_default_bass ) rlm@1: // r.end( buf ) -> BLIP_READER_END( r, buf ) rlm@1: class Blip_Reader { rlm@1: public: rlm@1: int begin( Blip_Buffer& ); rlm@1: blip_long read() const { return accum >> (blip_sample_bits - 16); } rlm@1: blip_long read_raw() const { return accum; } rlm@1: void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); } rlm@1: void end( Blip_Buffer& b ) { b.reader_accum_ = accum; } rlm@1: private: rlm@1: const Blip_Buffer::buf_t_* buf; rlm@1: blip_long accum; rlm@1: }; rlm@1: rlm@1: #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ rlm@1: defined (__x86_64__) || defined (__ia64__) || defined (__i386__) rlm@1: #define BLIP_CLAMP_( in ) in < -0x8000 || 0x7FFF < in rlm@1: #else rlm@1: #define BLIP_CLAMP_( in ) (blip_sample_t) in != in rlm@1: #endif rlm@1: rlm@1: // Clamp sample to blip_sample_t range rlm@1: #define BLIP_CLAMP( sample, out )\ rlm@1: { if ( BLIP_CLAMP_( (sample) ) ) (out) = ((sample) >> 24) ^ 0x7FFF; } rlm@1: rlm@1: struct blip_buffer_state_t rlm@1: { rlm@1: blip_resampled_time_t offset_; rlm@1: blip_long reader_accum_; rlm@1: blip_long buf [blip_buffer_extra_]; rlm@1: }; rlm@1: rlm@1: // End of public interface rlm@1: rlm@1: #ifndef assert rlm@1: #include rlm@1: #endif rlm@1: rlm@1: template rlm@1: inline void Blip_Synth::offset_resampled( blip_resampled_time_t time, rlm@1: int delta, Blip_Buffer* blip_buf ) const rlm@1: { rlm@1: // If this assertion fails, it means that an attempt was made to add a delta rlm@1: // at a negative time or past the end of the buffer. rlm@1: assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ ); rlm@1: rlm@1: delta *= impl.delta_factor; rlm@1: blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY); rlm@1: int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1)); rlm@1: rlm@1: #if BLIP_BUFFER_FAST rlm@1: blip_long left = buf [0] + delta; rlm@1: rlm@1: // Kind of crappy, but doing shift after multiply results in overflow. rlm@1: // Alternate way of delaying multiply by delta_factor results in worse rlm@1: // sub-sample resolution. rlm@1: blip_long right = (delta >> BLIP_PHASE_BITS) * phase; rlm@1: left -= right; rlm@1: right += buf [1]; rlm@1: rlm@1: buf [0] = left; rlm@1: buf [1] = right; rlm@1: #else rlm@1: rlm@1: int const fwd = (blip_widest_impulse_ - quality) / 2; rlm@1: int const rev = fwd + quality - 2; rlm@1: int const mid = quality / 2 - 1; rlm@1: rlm@1: imp_t const* BLIP_RESTRICT imp = impulses + blip_res - phase; rlm@1: rlm@1: #if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \ rlm@1: defined (__x86_64__) || defined (__ia64__) || defined (__i386__) rlm@1: rlm@1: // this straight forward version gave in better code on GCC for x86 rlm@1: rlm@1: #define ADD_IMP( out, in ) \ rlm@1: buf [out] += (blip_long) imp [blip_res * (in)] * delta rlm@1: rlm@1: #define BLIP_FWD( i ) {\ rlm@1: ADD_IMP( fwd + i, i );\ rlm@1: ADD_IMP( fwd + 1 + i, i + 1 );\ rlm@1: } rlm@1: #define BLIP_REV( r ) {\ rlm@1: ADD_IMP( rev - r, r + 1 );\ rlm@1: ADD_IMP( rev + 1 - r, r );\ rlm@1: } rlm@1: rlm@1: BLIP_FWD( 0 ) rlm@1: if ( quality > 8 ) BLIP_FWD( 2 ) rlm@1: if ( quality > 12 ) BLIP_FWD( 4 ) rlm@1: { rlm@1: ADD_IMP( fwd + mid - 1, mid - 1 ); rlm@1: ADD_IMP( fwd + mid , mid ); rlm@1: imp = impulses + phase; rlm@1: } rlm@1: if ( quality > 12 ) BLIP_REV( 6 ) rlm@1: if ( quality > 8 ) BLIP_REV( 4 ) rlm@1: BLIP_REV( 2 ) rlm@1: rlm@1: ADD_IMP( rev , 1 ); rlm@1: ADD_IMP( rev + 1, 0 ); rlm@1: rlm@1: #undef ADD_IMP rlm@1: rlm@1: #else rlm@1: rlm@1: // for RISC processors, help compiler by reading ahead of writes rlm@1: rlm@1: #define BLIP_FWD( i ) {\ rlm@1: blip_long t0 = i0 * delta + buf [fwd + i];\ rlm@1: blip_long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i];\ rlm@1: i0 = imp [blip_res * (i + 2)];\ rlm@1: buf [fwd + i] = t0;\ rlm@1: buf [fwd + 1 + i] = t1;\ rlm@1: } rlm@1: #define BLIP_REV( r ) {\ rlm@1: blip_long t0 = i0 * delta + buf [rev - r];\ rlm@1: blip_long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r];\ rlm@1: i0 = imp [blip_res * (r - 1)];\ rlm@1: buf [rev - r] = t0;\ rlm@1: buf [rev + 1 - r] = t1;\ rlm@1: } rlm@1: rlm@1: blip_long i0 = *imp; rlm@1: BLIP_FWD( 0 ) rlm@1: if ( quality > 8 ) BLIP_FWD( 2 ) rlm@1: if ( quality > 12 ) BLIP_FWD( 4 ) rlm@1: { rlm@1: blip_long t0 = i0 * delta + buf [fwd + mid - 1]; rlm@1: blip_long t1 = imp [blip_res * mid] * delta + buf [fwd + mid ]; rlm@1: imp = impulses + phase; rlm@1: i0 = imp [blip_res * mid]; rlm@1: buf [fwd + mid - 1] = t0; rlm@1: buf [fwd + mid ] = t1; rlm@1: } rlm@1: if ( quality > 12 ) BLIP_REV( 6 ) rlm@1: if ( quality > 8 ) BLIP_REV( 4 ) rlm@1: BLIP_REV( 2 ) rlm@1: rlm@1: blip_long t0 = i0 * delta + buf [rev ]; rlm@1: blip_long t1 = *imp * delta + buf [rev + 1]; rlm@1: buf [rev ] = t0; rlm@1: buf [rev + 1] = t1; rlm@1: #endif rlm@1: rlm@1: #endif rlm@1: } rlm@1: rlm@1: #undef BLIP_FWD rlm@1: #undef BLIP_REV rlm@1: rlm@1: template rlm@1: #if BLIP_BUFFER_FAST rlm@1: inline rlm@1: #endif rlm@1: void Blip_Synth::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const rlm@1: { rlm@1: offset_resampled( t * buf->factor_ + buf->offset_, delta, buf ); rlm@1: } rlm@1: rlm@1: template rlm@1: #if BLIP_BUFFER_FAST rlm@1: inline rlm@1: #endif rlm@1: void Blip_Synth::update( blip_time_t t, int amp ) rlm@1: { rlm@1: int delta = amp - impl.last_amp; rlm@1: impl.last_amp = amp; rlm@1: offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf ); rlm@1: } rlm@1: rlm@1: inline blip_eq_t::blip_eq_t( double t ) : rlm@1: treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { } rlm@1: inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) : rlm@1: treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { } rlm@1: rlm@1: inline int Blip_Buffer::length() const { return length_; } rlm@1: inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); } rlm@1: inline long Blip_Buffer::sample_rate() const { return sample_rate_; } rlm@1: inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; } rlm@1: inline long Blip_Buffer::clock_rate() const { return clock_rate_; } rlm@1: inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); } rlm@1: rlm@1: inline int Blip_Reader::begin( Blip_Buffer& blip_buf ) rlm@1: { rlm@1: buf = blip_buf.buffer_; rlm@1: accum = blip_buf.reader_accum_; rlm@1: return blip_buf.bass_shift_; rlm@1: } rlm@1: rlm@1: inline void Blip_Buffer::remove_silence( long count ) rlm@1: { rlm@1: // fails if you try to remove more samples than available rlm@1: assert( count <= samples_avail() ); rlm@1: offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY; rlm@1: } rlm@1: rlm@1: inline blip_ulong Blip_Buffer::unsettled() const rlm@1: { rlm@1: return reader_accum_ >> (blip_sample_bits - 16); rlm@1: } rlm@1: rlm@1: int const blip_max_length = 0; rlm@1: int const blip_default_length = 250; // 1/4 second rlm@1: rlm@1: #endif