#ifndef BLIP_BUFFER_H
#define BLIP_BUFFER_H
typedef long blip_time_t;
typedef short blip_sample_t;
enum { blip_sample_max = 32767 };
class Blip_Buffer {
public:
typedef const char* blargg_err_t;
blargg_err_t set_sample_rate( long samples_per_sec, int msec_length = 1000 / 4 );
void clock_rate( long );
void end_frame( blip_time_t time );
long read_samples( blip_sample_t* dest, long max_samples, int stereo = 0 );
long sample_rate() const;
int length() const;
long clock_rate() const;
void bass_freq( int frequency );
int output_latency() const;
void clear( int entire_buffer = 1 );
long samples_avail() const;
void remove_samples( long count );
long count_samples( blip_time_t duration ) const;
void mix_samples( blip_sample_t const* buf, long count );
blip_time_t count_clocks( long count ) const;
typedef unsigned long blip_resampled_time_t;
void remove_silence( long count );
blip_resampled_time_t resampled_duration( int t ) const { return t * factor_; }
blip_resampled_time_t resampled_time( blip_time_t t ) const { return t * factor_ + offset_; }
blip_resampled_time_t clock_rate_factor( long clock_rate ) const;
public:
Blip_Buffer();
~Blip_Buffer();
typedef blip_resampled_time_t resampled_time_t;
blargg_err_t sample_rate( long r ) { return set_sample_rate( r ); }
blargg_err_t sample_rate( long r, int msec ) { return set_sample_rate( r, msec ); }
private:
Blip_Buffer( const Blip_Buffer& );
Blip_Buffer& operator = ( const Blip_Buffer& );
public:
typedef long buf_t_;
unsigned long factor_;
blip_resampled_time_t offset_;
buf_t_* buffer_;
long buffer_size_;
private:
long reader_accum;
int bass_shift;
long sample_rate_;
long clock_rate_;
int bass_freq_;
int length_;
friend class Blip_Reader;
};
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef BLIP_BUFFER_ACCURACY
#define BLIP_BUFFER_ACCURACY 16
#endif
#ifndef BLIP_PHASE_BITS
#define BLIP_PHASE_BITS 6
#endif
typedef unsigned long blip_resampled_time_t;
int const blip_widest_impulse_ = 16;
int const blip_res = 1 << BLIP_PHASE_BITS;
class blip_eq_t;
class Blip_Synth_ {
double volume_unit_;
short* const impulses;
int const width;
long kernel_unit;
int impulses_size() const { return blip_res / 2 * width + 1; }
void adjust_impulse();
public:
Blip_Buffer* buf;
int last_amp;
int delta_factor;
Blip_Synth_( short* impulses, int width );
void treble_eq( blip_eq_t const& );
void volume_unit( double );
};
const int blip_med_quality = 8;
const int blip_good_quality = 12;
const int blip_high_quality = 16;
template<int quality,int range>
class Blip_Synth {
public:
void volume( double v ) { impl.volume_unit( v * (1.0 / (range < 0 ? -range : range)) ); }
void treble_eq( blip_eq_t const& eq ) { impl.treble_eq( eq ); }
Blip_Buffer* output() const { return impl.buf; }
void output( Blip_Buffer* b ) { impl.buf = b; impl.last_amp = 0; }
void update( blip_time_t time, int amplitude );
void offset( blip_time_t, int delta, Blip_Buffer* ) const;
void offset( blip_time_t t, int delta ) const { offset( t, delta, impl.buf ); }
void offset_resampled( blip_resampled_time_t, int delta, Blip_Buffer* ) const;
void offset_inline( blip_time_t t, int delta, Blip_Buffer* buf ) const {
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
}
void offset_inline( blip_time_t t, int delta ) const {
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
}
public:
Blip_Synth() : impl( impulses, quality ) { }
private:
typedef short imp_t;
imp_t impulses [blip_res * (quality / 2) + 1];
Blip_Synth_ impl;
};
class blip_eq_t {
public:
blip_eq_t( double treble_db = 0 );
blip_eq_t( double treble, long rolloff_freq, long sample_rate, long cutoff_freq = 0 );
private:
double treble;
long rolloff_freq;
long sample_rate;
long cutoff_freq;
void generate( float* out, int count ) const;
friend class Blip_Synth_;
};
int const blip_sample_bits = 30;
class Blip_Reader {
public:
int begin( Blip_Buffer& );
long read() const { return accum >> (blip_sample_bits - 16); }
long read_raw() const { return accum; }
void next( int bass_shift = 9 ) { accum += *buf++ - (accum >> bass_shift); }
void end( Blip_Buffer& b ) { b.reader_accum = accum; }
private:
const Blip_Buffer::buf_t_* buf;
long accum;
};
#include <assert.h>
const long blip_unscaled = 65535;
const int blip_low_quality = blip_med_quality;
const int blip_best_quality = blip_high_quality;
#define BLIP_FWD( i ) { \
long t0 = i0 * delta + buf [fwd + i]; \
long t1 = imp [blip_res * (i + 1)] * delta + buf [fwd + 1 + i]; \
i0 = imp [blip_res * (i + 2)]; \
buf [fwd + i] = t0; \
buf [fwd + 1 + i] = t1; }
#define BLIP_REV( r ) { \
long t0 = i0 * delta + buf [rev - r]; \
long t1 = imp [blip_res * r] * delta + buf [rev + 1 - r]; \
i0 = imp [blip_res * (r - 1)]; \
buf [rev - r] = t0; \
buf [rev + 1 - r] = t1; }
template<int quality,int range>
inline void Blip_Synth<quality,range>::offset_resampled( blip_resampled_time_t time,
int delta, Blip_Buffer* blip_buf ) const
{
assert( (long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
delta *= impl.delta_factor;
int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
imp_t const* imp = impulses + blip_res - phase;
long* buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
long i0 = *imp;
int const fwd = (blip_widest_impulse_ - quality) / 2;
int const rev = fwd + quality - 2;
BLIP_FWD( 0 )
if ( quality > 8 ) BLIP_FWD( 2 )
if ( quality > 12 ) BLIP_FWD( 4 )
{
int const mid = quality / 2 - 1;
long t0 = i0 * delta + buf [fwd + mid - 1];
long t1 = imp [blip_res * mid] * delta + buf [fwd + mid];
imp = impulses + phase;
i0 = imp [blip_res * mid];
buf [fwd + mid - 1] = t0;
buf [fwd + mid] = t1;
}
if ( quality > 12 ) BLIP_REV( 6 )
if ( quality > 8 ) BLIP_REV( 4 )
BLIP_REV( 2 )
long t0 = i0 * delta + buf [rev];
long t1 = *imp * delta + buf [rev + 1];
buf [rev] = t0;
buf [rev + 1] = t1;
}
#undef BLIP_FWD
#undef BLIP_REV
template<int quality,int range>
void Blip_Synth<quality,range>::offset( blip_time_t t, int delta, Blip_Buffer* buf ) const
{
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
}
template<int quality,int range>
void Blip_Synth<quality,range>::update( blip_time_t t, int amp )
{
int delta = amp - impl.last_amp;
impl.last_amp = amp;
offset_resampled( t * impl.buf->factor_ + impl.buf->offset_, delta, impl.buf );
}
inline blip_eq_t::blip_eq_t( double t ) :
treble( t ), rolloff_freq( 0 ), sample_rate( 44100 ), cutoff_freq( 0 ) { }
inline blip_eq_t::blip_eq_t( double t, long rf, long sr, long cf ) :
treble( t ), rolloff_freq( rf ), sample_rate( sr ), cutoff_freq( cf ) { }
inline int Blip_Buffer::length() const { return length_; }
inline long Blip_Buffer::samples_avail() const { return (long) (offset_ >> BLIP_BUFFER_ACCURACY); }
inline long Blip_Buffer::sample_rate() const { return sample_rate_; }
inline int Blip_Buffer::output_latency() const { return blip_widest_impulse_ / 2; }
inline long Blip_Buffer::clock_rate() const { return clock_rate_; }
inline void Blip_Buffer::clock_rate( long cps ) { factor_ = clock_rate_factor( clock_rate_ = cps ); }
inline int Blip_Reader::begin( Blip_Buffer& blip_buf )
{
buf = blip_buf.buffer_;
accum = blip_buf.reader_accum;
return blip_buf.bass_shift;
}
int const blip_max_length = 0;
int const blip_default_length = 250;
#endif