shithub: dumb

Download patch

ref: 74390bd111b0496a25967cd1418e6f7ec0a4a868
parent: cb8ab8c6f6ddef8a0938f771e3fad9d0ca6b2735
author: Chris Moeller <kode54@gmail.com>
date: Wed Mar 26 16:51:43 EDT 2014

Implemented blep synthesis into resampler.c, and removed blip_buf.c and code which referenced the old resamplers

--- a/dumb/include/dumb.h
+++ b/dumb/include/dumb.h
@@ -377,8 +377,6 @@
 
 DUH_SIGRENDERER *dumb_it_start_at_order(DUH *duh, int n_channels, int startorder);
 
-void dumb_it_set_resampling_quality(DUMB_IT_SIGRENDERER * sigrenderer, int quality);
-
 enum
 {
     DUMB_IT_RAMP_NONE = 0,
@@ -674,12 +672,15 @@
 /* Resampling Helpers */
 
 #define DUMB_RQ_ALIASING 0
-#define DUMB_RQ_LINEAR   1
-#define DUMB_RQ_CUBIC    2
-#define DUMB_RQ_FIR      3
-#define DUMB_RQ_N_LEVELS 4
-extern int dumb_resampling_quality;
+#define DUMB_RQ_BLEP     1
+#define DUMB_RQ_LINEAR   2
+#define DUMB_RQ_CUBIC    3
+#define DUMB_RQ_FIR      4
+#define DUMB_RQ_N_LEVELS 5
 
+extern int dumb_resampling_quality; /* This specifies the default */
+void dumb_it_set_resampling_quality(DUMB_IT_SIGRENDERER * sigrenderer, int quality); /* This overrides it */
+
 typedef struct DUMB_RESAMPLER DUMB_RESAMPLER;
 
 typedef struct DUMB_VOLUME_RAMP_INFO DUMB_VOLUME_RAMP_INFO;
@@ -686,11 +687,6 @@
 
 typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data);
 
-#ifndef BLIP_T_DEFINED
-#define BLIP_T_DEFINED
-typedef struct blip_t blip_t;
-#endif
-
 struct DUMB_RESAMPLER
 {
 	void *src;
@@ -708,9 +704,6 @@
 		signed char x8[3*2];
 	} x;
 	int overshot;
-	int last_clock;
-	int last_amp[2];
-	blip_t* blip_buffer[2];
     double fir_resampler_ratio;
     void* fir_resampler[2];
 };
--- a/dumb/include/internal/blip_buf.h
+++ /dev/null
@@ -1,80 +1,0 @@
-/** \file
-Sample buffer that resamples from input clock rate to output sample rate */
-
-/* blip_buf 1.1.0 */
-#ifndef BLIP_BUF_H 
-#define BLIP_BUF_H
-
-#ifdef __cplusplus
-	extern "C" {
-#endif
-
-/** First parameter of most functions is blip_t*, or const blip_t* if nothing
-is changed. */
-#ifndef BLIP_T_DEFINED
-#define BLIP_T_DEFINED
-typedef struct blip_t blip_t;
-#endif
-
-/** Creates new buffer that can hold at most sample_count samples. Sets rates
-so that there are blip_max_ratio clocks per sample. Returns pointer to new
-buffer, or NULL if insufficient memory. */
-blip_t* blip_new( int sample_count );
-
-blip_t* blip_dup( blip_t* );
-
-/** Sets approximate input clock rate and output sample rate. For every
-clock_rate input clocks, approximately sample_rate samples are generated. */
-void blip_set_rates( blip_t*, double clock_rate, double sample_rate );
-
-enum { /** Maximum clock_rate/sample_rate ratio. For a given sample_rate,
-clock_rate must not be greater than sample_rate*blip_max_ratio. */
-blip_max_ratio = 1 << 20 };
-
-/** Clears entire buffer. Afterwards, blip_samples_avail() == 0. */
-void blip_clear( blip_t* );
-
-/** Adds positive/negative delta into buffer at specified clock time. */
-void blip_add_delta( blip_t*, unsigned int clock_time, int delta );
-
-/** Same as blip_add_delta(), but uses faster, lower-quality synthesis. */
-void blip_add_delta_fast( blip_t*, unsigned int clock_time, int delta );
-
-/** Length of time frame, in clocks, needed to make sample_count additional
-samples available. */
-int blip_clocks_needed( const blip_t*, int sample_count );
-
-enum { /** Maximum number of samples that can be generated from one time frame. */
-blip_max_frame = 4000 };
-
-/** Makes input clocks before clock_duration available for reading as output
-samples. Also begins new time frame at clock_duration, so that clock time 0 in
-the new time frame specifies the same clock as clock_duration in the old time
-frame specified. Deltas can have been added slightly past clock_duration (up to
-however many clocks there are in two output samples). */
-void blip_end_frame( blip_t*, unsigned int clock_duration );
-
-/** Number of buffered samples available for reading. */
-int blip_samples_avail( const blip_t* );
-
-/** Reads and removes at most 'count' samples and writes them to 'out'. If
-'stereo' is true, writes output to every other element of 'out', allowing easy
-interleaving of two buffers into a stereo sample stream. Outputs 16-bit signed
-samples. Returns number of samples actually read.  */
-int blip_read_samples( blip_t*, int out [], int count );
-
-/** Reads the current integrator and returns it */
-int blip_peek_sample( blip_t* );
-
-/** Frees buffer. No effect if NULL is passed. */
-void blip_delete( blip_t* );
-
-
-/* Deprecated */
-typedef blip_t blip_buffer_t;
-
-#ifdef __cplusplus
-	}
-#endif
-
-#endif
--- a/dumb/include/internal/resampler.h
+++ b/dumb/include/internal/resampler.h
@@ -32,10 +32,11 @@
 {
     RESAMPLER_QUALITY_MIN = 0,
     RESAMPLER_QUALITY_ZOH = 0,
-    RESAMPLER_QUALITY_LINEAR = 1,
-    RESAMPLER_QUALITY_CUBIC = 2,
-    RESAMPLER_QUALITY_SINC = 3,
-    RESAMPLER_QUALITY_MAX = 3
+    RESAMPLER_QUALITY_BLEP = 1,
+    RESAMPLER_QUALITY_LINEAR = 2,
+    RESAMPLER_QUALITY_CUBIC = 3,
+    RESAMPLER_QUALITY_SINC = 4,
+    RESAMPLER_QUALITY_MAX = 4
 };
 
 void resampler_set_quality(void *, int quality);
--- a/dumb/src/helpers/blip_buf.c
+++ /dev/null
@@ -1,354 +1,0 @@
-/* blip_buf 1.1.0. http://www.slack.net/~ant/ */
-
-#include "internal/blip_buf.h"
-
-#include <assert.h>
-#include <limits.h>
-#include <string.h>
-#include <stdlib.h>
-
-/* Library Copyright (C) 2003-2009 Shay Green. This library is free software;
-you can redistribute it and/or modify it under the terms of the GNU Lesser
-General Public License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version. This
-library is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
-details. You should have received a copy of the GNU Lesser General Public
-License along with this module; if not, write to the Free Software Foundation,
-Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
-
-#if defined (BLARGG_TEST) && BLARGG_TEST
-	#include "blargg_test.h"
-#endif
-
-/* Equivalent to ULONG_MAX >= 0xFFFFFFFF00000000.
-Avoids constants that don't fit in 32 bits. */
-#if ULONG_MAX/0xFFFFFFFF > 0xFFFFFFFF
-	typedef unsigned long fixed_t;
-	enum { pre_shift = 32 };
-
-#elif defined(ULLONG_MAX)
-	typedef unsigned long long fixed_t;
-	enum { pre_shift = 32 };
-
-#else
-	typedef unsigned fixed_t;
-	enum { pre_shift = 0 };
-
-#endif
-
-enum { time_bits = pre_shift + 20 };
-
-static fixed_t const time_unit = (fixed_t) 1 << time_bits;
-
-enum { bass_shift  = 9 }; /* affects high-pass filter breakpoint frequency */
-enum { end_frame_extra = 2 }; /* allows deltas slightly after frame length */
-
-enum { half_width  = 8 };
-enum { buf_extra   = half_width*2 + end_frame_extra };
-enum { phase_bits  = 5 };
-enum { phase_count = 1 << phase_bits };
-enum { delta_bits  = 15 };
-enum { delta_unit  = 1 << delta_bits };
-enum { frac_bits = time_bits - pre_shift };
-
-/* We could eliminate avail and encode whole samples in offset, but that would
-limit the total buffered samples to blip_max_frame. That could only be
-increased by decreasing time_bits, which would reduce resample ratio accuracy.
-*/
-
-/** Sample buffer that resamples to output rate and accumulates samples
-until they're read out */
-struct blip_t
-{
-	fixed_t factor;
-	fixed_t offset;
-	int avail;
-	int size;
-	int integrator;
-};
-
-typedef int buf_t;
-
-/* probably not totally portable */
-#define SAMPLES( buf ) ((buf_t*) ((buf) + 1))
-
-/* Arithmetic (sign-preserving) right shift */
-#define ARITH_SHIFT( n, shift ) \
-	((n) >> (shift))
-
-enum { max_sample = +32767 };
-enum { min_sample = -32768 };
-
-#define CLAMP( n ) \
-	{\
-		if ( (short) n != n )\
-			n = ARITH_SHIFT( n, 16 ) ^ max_sample;\
-	}
-
-static void check_assumptions( void )
-{
-	int n;
-	
-	#if INT_MAX < 0x7FFFFFFF || UINT_MAX < 0xFFFFFFFF
-		#error "int must be at least 32 bits"
-	#endif
-	
-	assert( (-3 >> 1) == -2 ); /* right shift must preserve sign */
-	
-	n = max_sample * 2;
-	CLAMP( n );
-	assert( n == max_sample );
-	
-	n = min_sample * 2;
-	CLAMP( n );
-	assert( n == min_sample );
-	
-	assert( blip_max_ratio <= time_unit );
-	assert( blip_max_frame <= (fixed_t) -1 >> time_bits );
-}
-
-blip_t* blip_new( int size )
-{
-	blip_t* m;
-	assert( size >= 0 );
-	
-	m = (blip_t*) malloc( sizeof *m + (size + buf_extra) * sizeof (buf_t) );
-	if ( m )
-	{
-		m->factor = time_unit / blip_max_ratio;
-		m->size   = size;
-		blip_clear( m );
-		check_assumptions();
-	}
-	return m;
-}
-
-blip_t* blip_dup( blip_t* m )
-{
-	size_t size = sizeof *m + (m->size + buf_extra) * sizeof(buf_t);
-	blip_t* r = (blip_t*) malloc( size );
-	if ( r ) memcpy( r, m, size );
-	return r;
-}
-
-void blip_delete( blip_t* m )
-{
-	if ( m != NULL )
-	{
-		/* Clear fields in case user tries to use after freeing */
-		memset( m, 0, sizeof *m );
-		free( m );
-	}
-}
-
-void blip_set_rates( blip_t* m, double clock_rate, double sample_rate )
-{
-	double factor = time_unit * sample_rate / clock_rate;
-	m->factor = (fixed_t) factor;
-	
-	/* Fails if clock_rate exceeds maximum, relative to sample_rate */
-	assert( 0 <= factor - m->factor && factor - m->factor < 1 );
-	
-	/* Avoid requiring math.h. Equivalent to
-	m->factor = (int) ceil( factor ) */
-	if ( m->factor < factor )
-		m->factor++;
-	
-	/* At this point, factor is most likely rounded up, but could still
-	have been rounded down in the floating-point calculation. */
-}
-
-void blip_clear( blip_t* m )
-{
-	/* We could set offset to 0, factor/2, or factor-1. 0 is suitable if
-	factor is rounded up. factor-1 is suitable if factor is rounded down.
-	Since we don't know rounding direction, factor/2 accommodates either,
-	with the slight loss of showing an error in half the time. Since for
-	a 64-bit factor this is years, the halving isn't a problem. */
-	
-	m->offset     = m->factor / 2;
-	m->avail      = 0;
-	m->integrator = 0;
-	memset( SAMPLES( m ), 0, (m->size + buf_extra) * sizeof (buf_t) );
-}
-
-int blip_clocks_needed( const blip_t* m, int samples )
-{
-	fixed_t needed;
-	
-	/* Fails if buffer can't hold that many more samples */
-	assert( samples >= 0 && m->avail + samples <= m->size );
-	
-	needed = (fixed_t) samples * time_unit;
-	if ( needed < m->offset )
-		return 0;
-	
-	return (needed - m->offset + m->factor - 1) / m->factor;
-}
-
-void blip_end_frame( blip_t* m, unsigned t )
-{
-	fixed_t off = t * m->factor + m->offset;
-	m->avail += off >> time_bits;
-	m->offset = off & (time_unit - 1);
-	
-	/* Fails if buffer size was exceeded */
-	assert( m->avail <= m->size );
-}
-
-int blip_samples_avail( const blip_t* m )
-{
-	return m->avail;
-}
-
-static void remove_samples( blip_t* m, int count )
-{
-	buf_t* buf = SAMPLES( m );
-	int remain = m->avail + buf_extra - count;
-	m->avail -= count;
-	
-	memmove( &buf [0], &buf [count], remain * sizeof buf [0] );
-	memset( &buf [remain], 0, count * sizeof buf [0] );
-}
-
-int blip_read_samples( blip_t* m, int out [], int count )
-{
-	assert( count >= 0 );
-	
-	if ( count > m->avail )
-		count = m->avail;
-	
-	if ( count )
-	{
-		buf_t const* in  = SAMPLES( m );
-		buf_t const* end = in + count;
-		int sum = m->integrator;
-		do
-		{
-			/* Eliminate fraction */
-			int s = ARITH_SHIFT( sum, delta_bits - 8 );
-			
-			sum += *in++;
-			
-			*out = s;
-			out++;
-			
-			/* High-pass filter */
-			sum -= s >> (8 - (delta_bits - bass_shift)); //<< (delta_bits - bass_shift - 8);
-		}
-		while ( in != end );
-		m->integrator = sum;
-		
-		remove_samples( m, count );
-	}
-	
-	return count;
-}
-
-int blip_peek_sample( blip_t* m )
-{
-	return ARITH_SHIFT( m->integrator, delta_bits - 8 );
-}
-
-/* Things that didn't help performance on x86:
-	__attribute__((aligned(128)))
-	#define short int
-	restrict
-*/
-
-/* Sinc_Generator( 0.9, 0.55, 4.5 ) */
-static short const bl_step [phase_count + 1] [half_width] =
-{
-{   43, -115,  350, -488, 1136, -914, 5861,21022},
-{   44, -118,  348, -473, 1076, -799, 5274,21001},
-{   45, -121,  344, -454, 1011, -677, 4706,20936},
-{   46, -122,  336, -431,  942, -549, 4156,20829},
-{   47, -123,  327, -404,  868, -418, 3629,20679},
-{   47, -122,  316, -375,  792, -285, 3124,20488},
-{   47, -120,  303, -344,  714, -151, 2644,20256},
-{   46, -117,  289, -310,  634,  -17, 2188,19985},
-{   46, -114,  273, -275,  553,  117, 1758,19675},
-{   44, -108,  255, -237,  471,  247, 1356,19327},
-{   43, -103,  237, -199,  390,  373,  981,18944},
-{   42,  -98,  218, -160,  310,  495,  633,18527},
-{   40,  -91,  198, -121,  231,  611,  314,18078},
-{   38,  -84,  178,  -81,  153,  722,   22,17599},
-{   36,  -76,  157,  -43,   80,  824, -241,17092},
-{   34,  -68,  135,   -3,    8,  919, -476,16558},
-{   32,  -61,  115,   34,  -60, 1006, -683,16001},
-{   29,  -52,   94,   70, -123, 1083, -862,15422},
-{   27,  -44,   73,  106, -184, 1152,-1015,14824},
-{   25,  -36,   53,  139, -239, 1211,-1142,14210},
-{   22,  -27,   34,  170, -290, 1261,-1244,13582},
-{   20,  -20,   16,  199, -335, 1301,-1322,12942},
-{   18,  -12,   -3,  226, -375, 1331,-1376,12293},
-{   15,   -4,  -19,  250, -410, 1351,-1408,11638},
-{   13,    3,  -35,  272, -439, 1361,-1419,10979},
-{   11,    9,  -49,  292, -464, 1362,-1410,10319},
-{    9,   16,  -63,  309, -483, 1354,-1383, 9660},
-{    7,   22,  -75,  322, -496, 1337,-1339, 9005},
-{    6,   26,  -85,  333, -504, 1312,-1280, 8355},
-{    4,   31,  -94,  341, -507, 1278,-1205, 7713},
-{    3,   35, -102,  347, -506, 1238,-1119, 7082},
-{    1,   40, -110,  350, -499, 1190,-1021, 6464},
-{    0,   43, -115,  350, -488, 1136, -914, 5861}
-};
-
-/* Shifting by pre_shift allows calculation using unsigned int rather than
-possibly-wider fixed_t. On 32-bit platforms, this is likely more efficient.
-And by having pre_shift 32, a 32-bit platform can easily do the shift by
-simply ignoring the low half. */
-
-void blip_add_delta( blip_t* m, unsigned time, int delta )
-{
-	unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift);
-	buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits);
-	
-	int const phase_shift = frac_bits - phase_bits;
-	int phase = fixed >> phase_shift & (phase_count - 1);
-	short const* in  = bl_step [phase];
-	short const* rev = bl_step [phase_count - phase];
-	
-	int interp = fixed >> (phase_shift - delta_bits) & (delta_unit - 1);
-	int delta2 = (delta * interp) >> delta_bits;
-	delta -= delta2;
-	
-	/* Fails if buffer size was exceeded */
-	assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] );
-	
-	out [0] += in[0]*delta + in[half_width+0]*delta2;
-	out [1] += in[1]*delta + in[half_width+1]*delta2;
-	out [2] += in[2]*delta + in[half_width+2]*delta2;
-	out [3] += in[3]*delta + in[half_width+3]*delta2;
-	out [4] += in[4]*delta + in[half_width+4]*delta2;
-	out [5] += in[5]*delta + in[half_width+5]*delta2;
-	out [6] += in[6]*delta + in[half_width+6]*delta2;
-	out [7] += in[7]*delta + in[half_width+7]*delta2;
-	
-	in = rev;
-	out [ 8] += in[7]*delta + in[7-half_width]*delta2;
-	out [ 9] += in[6]*delta + in[6-half_width]*delta2;
-	out [10] += in[5]*delta + in[5-half_width]*delta2;
-	out [11] += in[4]*delta + in[4-half_width]*delta2;
-	out [12] += in[3]*delta + in[3-half_width]*delta2;
-	out [13] += in[2]*delta + in[2-half_width]*delta2;
-	out [14] += in[1]*delta + in[1-half_width]*delta2;
-	out [15] += in[0]*delta + in[0-half_width]*delta2;
-}
-
-void blip_add_delta_fast( blip_t* m, unsigned time, int delta )
-{
-	unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift);
-	buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits);
-	
-	int interp = fixed >> (frac_bits - delta_bits) & (delta_unit - 1);
-	int delta2 = delta * interp;
-	
-	/* Fails if buffer size was exceeded */
-	assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] );
-	
-	out [7] += delta * delta_unit - delta2;
-	out [8] += delta2;
-}
--- a/dumb/src/helpers/resamp2.inc
+++ b/dumb/src/helpers/resamp2.inc
@@ -94,12 +94,8 @@
 #define SET_VOLUME_VARIABLES SET_MONO_DEST_VOLUME_VARIABLES
 #define RETURN_VOLUME_VARIABLES RETURN_MONO_DEST_VOLUME_VARIABLES
 #define VOLUMES_ARE_ZERO MONO_DEST_VOLUMES_ARE_ZERO
-#define MIX_ALIAS(count) MONO_DEST_MIX_ALIAS(count)
-#define PEEK_ALIAS MONO_DEST_PEEK_ALIAS
 #define PEEK_FIR MONO_DEST_PEEK_FIR
 #define MIX_FIR MONO_DEST_MIX_FIR
-#define MIX_LINEAR(op, upd, o0, o1) MONO_DEST_MIX_LINEAR(op, upd, o0, o1)
-#define MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) MONO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3)
 #define MIX_ZEROS(op) *dst++ op 0
 #include "resamp3.inc"
 
@@ -140,23 +136,13 @@
 	if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
 }
 #define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
-#define MIX_ALIAS(count) STEREO_DEST_MIX_ALIAS(count)
-#define PEEK_ALIAS STEREO_DEST_PEEK_ALIAS
 #define PEEK_FIR STEREO_DEST_PEEK_FIR
 #define MIX_FIR STEREO_DEST_MIX_FIR
-#define MIX_LINEAR(op, upd, o0, o1) STEREO_DEST_MIX_LINEAR(op, upd, o0, o1)
-#define MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) STEREO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3)
 #define MIX_ZEROS(op) { *dst++ op 0; *dst++ op 0; }
 #include "resamp3.inc"
 
 
 
-#undef STEREO_DEST_MIX_CUBIC
-#undef MONO_DEST_MIX_CUBIC
-#undef STEREO_DEST_MIX_LINEAR
-#undef MONO_DEST_MIX_LINEAR
-#undef STEREO_DEST_MIX_ALIAS
-#undef MONO_DEST_MIX_ALIAS
 #undef MONO_DEST_VOLUMES_ARE_ZERO
 #undef SET_MONO_DEST_VOLUME_VARIABLES
 #undef RETURN_MONO_DEST_VOLUME_VARIABLES
@@ -163,9 +149,6 @@
 #undef MONO_DEST_VOLUME_ZEROS
 #undef MONO_DEST_VOLUME_VARIABLES
 #undef MONO_DEST_VOLUME_PARAMETERS
-#undef STEREO_DEST_PEEK_ALIAS
-#undef MONO_DEST_PEEK_ALIAS
-#undef POKE_ALIAS
 #undef MONO_DEST_PEEK_FIR
 #undef STEREO_DEST_PEEK_FIR
 #undef MONO_DEST_MIX_FIR
--- a/dumb/src/helpers/resamp3.inc
+++ b/dumb/src/helpers/resamp3.inc
@@ -52,7 +52,6 @@
 	long todo;
 	LONG_LONG todo64;
 	int quality;
-	int blip_samples[256*SRC_CHANNELS];
 	int check;
 
 	if (!resampler || resampler->dir == 0) return 0;
@@ -105,41 +104,6 @@
 					LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo;
 					pos += (long)(new_subpos >> 16);
 					subpos = (long)new_subpos & 65535;
-				} else if (quality <= DUMB_RQ_ALIASING) {
-					/* Aliasing, backwards */
-					int todo_clocks = todo << 16, todo_clocks_set = todo_clocks;
-					SRCTYPE xbuf[2*SRC_CHANNELS];
-					SRCTYPE *x = &xbuf[0];
-					check = resampler->start;
-					COPYSRC(xbuf, 0, resampler->X, 1);
-					COPYSRC(xbuf, 1, resampler->X, 2);
-					if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
-					while (resampler->last_clock < todo_clocks_set && x < &xbuf[2*SRC_CHANNELS]) {
-						// TODO: check what happens when multiple tempo slides occur per row
-						HEAVYASSERT(pos >= resampler->start);
-						POKE_ALIAS(0);
-						pos--;
-						x += SRC_CHANNELS;
-					}
-					x = &src[pos*SRC_CHANNELS];
-					while ( todo_clocks ) {
-						todo_clocks_set = todo_clocks;
-						if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
-						todo_clocks -= todo_clocks_set;
-						while ( resampler->last_clock < todo_clocks_set && pos >= check ) {
-							POKE_ALIAS(2);
-							pos--;
-							x -= SRC_CHANNELS;
-						}
-						todo = todo_clocks_set >> 16;
-						check = 0;
-						if ( resampler->last_clock < todo_clocks_set ) {
-							check = ( todo_clocks_set - resampler->last_clock + 65535 ) >> 16;
-						}
-						todo -= check;
-						MIX_ALIAS( todo );
-						done -= check;
-					}
                                 } else {
                                     /* FIR resampling, backwards */
                                     SRCTYPE *x;
@@ -185,40 +149,6 @@
 					LONG_LONG new_subpos = subpos + (LONG_LONG)dt * todo;
 					pos += (long)(new_subpos >> 16);
 					subpos = (long)new_subpos & 65535;
-				} else if (quality <= DUMB_RQ_ALIASING) {
-					/* Aliasing, forwards */
-					int todo_clocks = todo << 16, todo_clocks_set = todo_clocks;
-					SRCTYPE xbuf[2*SRC_CHANNELS];
-					SRCTYPE *x = &xbuf[0];
-					check = resampler->end;
-					COPYSRC(xbuf, 0, resampler->X, 1);
-					COPYSRC(xbuf, 1, resampler->X, 2);
-					if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
-					while (resampler->last_clock < todo_clocks_set && x < &xbuf[2*SRC_CHANNELS]) {
-						HEAVYASSERT(pos < resampler->end);
-						POKE_ALIAS(0);
-						pos++;
-						x += SRC_CHANNELS;
-					}
-					x = &src[pos*SRC_CHANNELS];
-					while ( todo_clocks ) {
-						todo_clocks_set = todo_clocks;
-						if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
-						todo_clocks -= todo_clocks_set;
-						while ( resampler->last_clock < todo_clocks_set && pos < check ) {
-							POKE_ALIAS(-2);
-							pos++;
-							x += SRC_CHANNELS;
-						}
-						todo = todo_clocks_set >> 16;
-						check = 0;
-						if ( resampler->last_clock < todo_clocks_set ) {
-							check = ( todo_clocks_set - resampler->last_clock + 65535 ) >> 16;
-						}
-						todo -= check;
-						MIX_ALIAS( todo );
-						done -= check;
-					}
                                 } else {
                                     /* FIR resampling, forwards */
                                     SRCTYPE *x;
@@ -299,22 +229,12 @@
 
 	if (resampler->dir < 0) {
 		HEAVYASSERT(pos >= resampler->start);
-		if (quality <= DUMB_RQ_ALIASING) {
-			/* Aliasing, backwards */
-			PEEK_ALIAS;
-                } else {
                         /* FIR resampling, backwards */
                         PEEK_FIR;
-                }
 	} else {
 		HEAVYASSERT(pos < resampler->end);
-		if (quality <= DUMB_RQ_ALIASING) {
-			/* Aliasing */
-			PEEK_ALIAS;
-                } else {
                         /* FIR resampling, forwards */
                         PEEK_FIR;
-                }
 	}
 }
 
@@ -321,11 +241,7 @@
 
 
 #undef MIX_ZEROS
-#undef MIX_CUBIC
-#undef MIX_LINEAR
-#undef MIX_ALIAS
 #undef MIX_FIR
-#undef PEEK_ALIAS
 #undef PEEK_FIR
 #undef VOLUMES_ARE_ZERO
 #undef SET_VOLUME_VARIABLES
--- a/dumb/src/helpers/resample.c
+++ b/dumb/src/helpers/resample.c
@@ -45,7 +45,6 @@
 #include <math.h>
 #include "dumb.h"
 
-#include "internal/blip_buf.h"
 #include "internal/resampler.h"
 
 
@@ -73,11 +72,12 @@
  * specification doesn't override it. The following values are valid:
  *
  *  0 - DUMB_RQ_ALIASING - fastest
- *  1 - DUMB_RQ_LINEAR
- *  2 - DUMB_RQ_CUBIC
- *  3 - DUMB_RQ_FIR      - nicest
+ *  1 - DUMB_RQ_BLEP     - nicer than aliasing, but slower
+ *  2 - DUMB_RQ_LINEAR
+ *  3 - DUMB_RQ_CUBIC
+ *  4 - DUMB_RQ_FIR      - nicest
  *
- * Values outside the range 0-3 will behave the same as the nearest
+ * Values outside the range 0-4 will behave the same as the nearest
  * value within the range.
  */
 int dumb_resampling_quality = DUMB_RQ_CUBIC;
@@ -157,23 +157,7 @@
 
 #define SRCTYPE sample_t
 #define SRCBITS 24
-#define ALIAS(x) (x >> 8)
 #define FIR(x) (x >> 8)
-#define LINEAR(x0, x1) (x0 + MULSC(x1 - x0, subpos))
-/*
-#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
-	a = (3 * (x1 - x2) + (x3 - x0)) >> 1; \
-	b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) >> 1; \
-	c = (x2 - x0) >> 1; \
-}
-#define CUBIC(d) MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + d, vol)
-*/
-#define CUBIC(x0, x1, x2, x3) ( \
-	MULSC(x0, cubicA0[subpos >> 6] << 2) + \
-	MULSC(x1, cubicA1[subpos >> 6] << 2) + \
-	MULSC(x2, cubicA1[1 + (subpos >> 6 ^ 1023)] << 2) + \
-	MULSC(x3, cubicA0[1 + (subpos >> 6 ^ 1023)] << 2))
-#define CUBICVOL(x, vol) MULSC(x, vol)
 #include "resample.inc"
 
 /* Undefine the simplified macros. */
@@ -194,23 +178,7 @@
 #define SUFFIX _16
 #define SRCTYPE short
 #define SRCBITS 16
-#define ALIAS(x) (x)
 #define FIR(x) (x)
-#define LINEAR(x0, x1) ((x0 << 8) + MULSC16(x1 - x0, subpos))
-/*
-#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
-	a = (3 * (x1 - x2) + (x3 - x0)) << 7; \
-	b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) << 7; \
-	c = (x2 - x0) << 7; \
-}
-#define CUBIC(d) MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + (d << 8), vol)
-*/
-#define CUBIC(x0, x1, x2, x3) ( \
-	x0 * cubicA0[subpos >> 6] + \
-	x1 * cubicA1[subpos >> 6] + \
-	x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \
-	x3 * cubicA0[1 + (subpos >> 6 ^ 1023)])
-#define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 10) >> 32)
 #include "resample.inc"
 
 /* Create resamplers for 8-bit source samples. */
@@ -217,23 +185,7 @@
 #define SUFFIX _8
 #define SRCTYPE signed char
 #define SRCBITS 8
-#define ALIAS(x) (x << 8)
 #define FIR(x) (x << 8)
-#define LINEAR(x0, x1) ((x0 << 16) + (x1 - x0) * subpos)
-/*
-#define SET_CUBIC_COEFFICIENTS(x0, x1, x2, x3) { \
-	a = 3 * (x1 - x2) + (x3 - x0); \
-	b = ((x2 << 2) + (x0 << 1) - (5 * x1 + x3)) << 15; \
-	c = (x2 - x0) << 15; \
-}
-#define CUBIC(d) MULSC(MULSC(MULSC((a * subpos >> 1) + b, subpos) + c, subpos) + (d << 16), vol)
-*/
-#define CUBIC(x0, x1, x2, x3) (( \
-	x0 * cubicA0[subpos >> 6] + \
-	x1 * cubicA1[subpos >> 6] + \
-	x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \
-	x3 * cubicA0[1 + (subpos >> 6 ^ 1023)]) << 6)
-#define CUBICVOL(x, vol) (int)((LONG_LONG)(x) * (vol << 12) >> 32)
 #include "resample.inc"
 
 
--- a/dumb/src/helpers/resample.inc
+++ b/dumb/src/helpers/resample.inc
@@ -69,11 +69,6 @@
 	}
 	for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0;
 	resampler->overshot = -1;
-	resampler->last_clock = 0;
-	resampler->last_amp[0] = 0;
-	resampler->last_amp[1] = 0;
-	blip_clear(resampler->blip_buffer[0]);
-	blip_clear(resampler->blip_buffer[1]);
         resampler->fir_resampler_ratio = 0;
         resampler_clear(resampler->fir_resampler[0]);
         resampler_clear(resampler->fir_resampler[1]);
@@ -87,21 +82,6 @@
 {
 	DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
 	if (!resampler) return NULL;
-	resampler->blip_buffer[0] = blip_new( 256 );
-	if (!resampler->blip_buffer[0])
-	{
-		free(resampler);
-		return NULL;
-	}
-	resampler->blip_buffer[1] = blip_new( 256 );
-	if (!resampler->blip_buffer[1])
-	{
-		free(resampler->blip_buffer[0]);
-		free(resampler);
-		return NULL;
-	}
-	blip_set_rates(resampler->blip_buffer[0], 65536, 1);
-	blip_set_rates(resampler->blip_buffer[1], 65536, 1);
 	dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
 	return resampler;
 }
@@ -153,16 +133,9 @@
 }
 #define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = (float)volr / 16777216.0f
 #define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0)
-#define POKE_ALIAS(offset) { \
-	int delta = ALIAS(x[offset]) - resampler->last_amp[0]; \
-	resampler->last_amp[0] += delta; \
-	if ( delta ) blip_add_delta( resampler->blip_buffer[0], resampler->last_clock, delta ); \
-	resampler->last_clock += inv_dt; \
-}
 #define POKE_FIR(offset) { \
         resampler_write_sample( resampler->fir_resampler[0], FIR(x[offset]) ); \
 }
-#define MONO_DEST_PEEK_ALIAS *dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), vol )
 #define MONO_DEST_PEEK_FIR *dst = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), vol )
 #define MONO_DEST_MIX_FIR { \
         *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
@@ -169,22 +142,6 @@
         UPDATE_VOLUME( volume, vol ); \
 }
 #define ADVANCE_FIR resampler_remove_sample( resampler->fir_resampler[0] )
-#define MONO_DEST_MIX_ALIAS(count) { \
-	int n = 0; \
-	resampler->last_clock -= count * 65536; \
-	blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
-	blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
-	LOOP4( count, \
-		*dst++ += MULSC( blip_samples[n], vol ); \
-		n++; \
-		UPDATE_VOLUME( volume, vol ); \
-	); \
-}
-#define STEREO_DEST_PEEK_ALIAS { \
-	int sample = blip_peek_sample( resampler->blip_buffer[0] ); \
-	*dst++ = MULSC( sample, lvol ); \
-	*dst++ = MULSC( sample, rvol ); \
-}
 #define STEREO_DEST_PEEK_FIR { \
         int sample = resampler_get_sample( resampler->fir_resampler[0] ); \
         *dst++ = MULSC( sample, lvol ); \
@@ -197,41 +154,6 @@
         UPDATE_VOLUME( volume_left, lvol ); \
         UPDATE_VOLUME( volume_right, rvol ); \
 }
-#define STEREO_DEST_MIX_ALIAS(count) { \
-	int sample, n = 0; \
-	resampler->last_clock -= count * 65536; \
-	blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
-	blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
-	LOOP4( count, \
-		sample = blip_samples[n++]; \
-		*dst++ += MULSC( sample, lvol ); \
-		*dst++ += MULSC( sample, rvol ); \
-		UPDATE_VOLUME( volume_left, lvol ); \
-		UPDATE_VOLUME( volume_right, rvol ); \
-	); \
-}
-#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
-	*dst++ op MULSC(LINEAR(x[o0], x[o1]), vol); \
-	if ( upd ) UPDATE_VOLUME( volume, vol ); \
-}
-#define STEREO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
-	int xm = LINEAR(x[o0], x[o1]); \
-	*dst++ op MULSC(xm, lvol); \
-	*dst++ op MULSC(xm, rvol); \
-	if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
-	if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
-}
-#define MONO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) { \
-	*dst++ op CUBICVOL(CUBIC(x0[o0], x[o1], x[o2], x3[o3]), vol); \
-	if ( upd ) UPDATE_VOLUME( volume, vol ); \
-}
-#define STEREO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) { \
-	int xm = CUBIC(x0[o0], x[o1], x[o2], x3[o3]); \
-	*dst++ op CUBICVOL(xm, lvol); \
-	*dst++ op CUBICVOL(xm, rvol); \
-	if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
-	if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
-}
 #include "resamp2.inc"
 
 /* Create stereo source resampler. */
@@ -288,23 +210,10 @@
 	if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
 }
 #define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
-#define POKE_ALIAS(offset) { \
-	int deltal = ALIAS(x[(offset)*2+0]) - resampler->last_amp[0]; \
-	int deltar = ALIAS(x[(offset)*2+1]) - resampler->last_amp[1]; \
-	resampler->last_amp[0] += deltal; \
-	resampler->last_amp[1] += deltar; \
-	if ( deltal ) blip_add_delta( resampler->blip_buffer[0], resampler->last_clock, deltal ); \
-	if ( deltar ) blip_add_delta( resampler->blip_buffer[1], resampler->last_clock, deltar ); \
-	resampler->last_clock += inv_dt; \
-}
 #define POKE_FIR(offset) { \
         resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \
         resampler_write_sample( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \
 }
-#define MONO_DEST_PEEK_ALIAS { \
-	*dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ) + \
-		MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
-}
 #define MONO_DEST_PEEK_FIR { \
         *dst = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
                 MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
@@ -319,24 +228,6 @@
         resampler_remove_sample( resampler->fir_resampler[0] ); \
         resampler_remove_sample( resampler->fir_resampler[1] ); \
 }
-#define MONO_DEST_MIX_ALIAS(count) { \
-	int n = 0; \
-	resampler->last_clock -= count * 65536; \
-	blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
-	blip_end_frame( resampler->blip_buffer[1], count * 65536 ); \
-	blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
-	blip_read_samples( resampler->blip_buffer[1], blip_samples + 256, count ); \
-	LOOP4( count, \
-		*dst++ += MULSC( blip_samples[n], lvol ) + MULSC( blip_samples[256+n], rvol ); \
-		n++; \
-		UPDATE_VOLUME( volume_left, lvol ); \
-		UPDATE_VOLUME( volume_right, rvol ); \
-	); \
-}
-#define STEREO_DEST_PEEK_ALIAS { \
-	*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ); \
-	*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
-}
 #define STEREO_DEST_PEEK_FIR { \
         *dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
         *dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
@@ -347,45 +238,6 @@
         UPDATE_VOLUME( volume_left, lvol ); \
         UPDATE_VOLUME( volume_right, rvol ); \
 }
-#define STEREO_DEST_MIX_ALIAS(count) { \
-	int n = 0; \
-	resampler->last_clock -= count * 65536; \
-	blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
-	blip_end_frame( resampler->blip_buffer[1], count * 65536 ); \
-	blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
-	blip_read_samples( resampler->blip_buffer[1], blip_samples + 256, count ); \
-	LOOP4( count, \
-		*dst++ += MULSC( blip_samples[n], lvol); \
-		*dst++ += MULSC( blip_samples[256+n], rvol); \
-		n++; \
-		UPDATE_VOLUME( volume_left, lvol ); \
-		UPDATE_VOLUME( volume_right, rvol ); \
-	); \
-}
-#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
-	*dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol) + MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol); \
-	if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
-	if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
-}
-#define STEREO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
-	*dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol); \
-	*dst++ op MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol); \
-	if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
-	if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
-}
-#define MONO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) { \
-	*dst++ op \
-		CUBICVOL(CUBIC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x3[(o3)*2]), lvol) + \
-		CUBICVOL(CUBIC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x3[(o3)*2+1]), rvol); \
-	if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
-	if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
-}
-#define STEREO_DEST_MIX_CUBIC(op, upd, x0, x3, o0, o1, o2, o3) { \
-	*dst++ op CUBICVOL(CUBIC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x3[(o3)*2]), lvol); \
-	*dst++ op CUBICVOL(CUBIC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x3[(o3)*2+1]), rvol); \
-	if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
-	if ( upd ) UPDATE_VOLUME( volume_right, rvol ); \
-}
 #include "resamp2.inc"
 
 
@@ -398,10 +250,6 @@
 
 
 
-#undef CUBICVOL
-#undef CUBIC
-#undef LINEAR
-#undef ALIAS
 #undef FIR
 #undef SRCBITS
 #undef SRCTYPE
--- a/dumb/src/helpers/resampler.c
+++ b/dumb/src/helpers/resampler.c
@@ -60,10 +60,10 @@
 #endif
 
 static int query_cpu_feature_sse() {
-	int buffer[4];
-	__cpuid(buffer,1);
-	if ((buffer[3]&(1<<25)) == 0) return 0;
-	return 1;
+    int buffer[4];
+    __cpuid(buffer,1);
+    if ((buffer[3]&(1<<25)) == 0) return 0;
+    return 1;
 }
 
 static int resampler_has_sse = 0;
@@ -109,9 +109,13 @@
 {
     int write_pos, write_filled;
     int read_pos, read_filled;
-    unsigned short phase;
+    unsigned int phase;
     unsigned int phase_inc;
+    unsigned int inv_phase;
+    unsigned int inv_phase_inc;
     unsigned char quality;
+    float last_amp;
+    float accumulator;
     float buffer_in[resampler_buffer_size * 2];
     float buffer_out[resampler_buffer_size + SINC_WIDTH * 2 - 1];
 } resampler;
@@ -127,7 +131,11 @@
     r->read_filled = 0;
     r->phase = 0;
     r->phase_inc = 0;
+    r->inv_phase = 0;
+    r->inv_phase_inc = 0;
     r->quality = RESAMPLER_QUALITY_MAX;
+    r->last_amp = 0;
+    r->accumulator = 0;
     memset( r->buffer_in, 0, sizeof(r->buffer_in) );
     memset( r->buffer_out, 0, sizeof(r->buffer_out) );
 
@@ -151,7 +159,11 @@
     r_out->read_filled = r_in->read_filled;
     r_out->phase = r_in->phase;
     r_out->phase_inc = r_in->phase_inc;
+    r_out->inv_phase = r_in->inv_phase;
+    r_out->inv_phase_inc = r_in->inv_phase_inc;
     r_out->quality = r_in->quality;
+    r_out->last_amp = r_in->last_amp;
+    r_out->accumulator = r_in->accumulator;
     memcpy( r_out->buffer_in, r_in->buffer_in, sizeof(r_in->buffer_in) );
     memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) );
 
@@ -169,7 +181,11 @@
     r_out->read_filled = r_in->read_filled;
     r_out->phase = r_in->phase;
     r_out->phase_inc = r_in->phase_inc;
+    r_out->inv_phase = r_in->inv_phase;
+    r_out->inv_phase_inc = r_in->inv_phase_inc;
     r_out->quality = r_in->quality;
+    r_out->last_amp = r_in->last_amp;
+    r_out->accumulator = r_in->accumulator;
     memcpy( r_out->buffer_in, r_in->buffer_in, sizeof(r_in->buffer_in) );
     memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) );
 }
@@ -181,6 +197,17 @@
         quality = RESAMPLER_QUALITY_MIN;
     else if (quality > RESAMPLER_QUALITY_MAX)
         quality = RESAMPLER_QUALITY_MAX;
+    if ( r->quality != quality )
+    {
+        if ( quality == RESAMPLER_QUALITY_BLEP || r->quality == RESAMPLER_QUALITY_BLEP )
+        {
+            r->read_pos = 0;
+            r->read_filled = 0;
+            r->last_amp = 0;
+            r->accumulator = 0;
+            memset( r->buffer_out, 0, sizeof(r->buffer_out) );
+        }
+    }
     r->quality = (unsigned char)quality;
 }
 
@@ -196,6 +223,7 @@
     {
     default:
     case RESAMPLER_QUALITY_ZOH:
+    case RESAMPLER_QUALITY_BLEP:
         return 1;
             
     case RESAMPLER_QUALITY_LINEAR:
@@ -223,8 +251,10 @@
     r->read_pos = 0;
     r->read_filled = 0;
     r->phase = 0;
-	memset(r->buffer_in, 0, (SINC_WIDTH - 1) * sizeof(r->buffer_in[0]));
-	memset(r->buffer_in + resampler_buffer_size, 0, (SINC_WIDTH - 1) * sizeof(r->buffer_in[0]));
+    memset(r->buffer_in, 0, (SINC_WIDTH - 1) * sizeof(r->buffer_in[0]));
+    memset(r->buffer_in + resampler_buffer_size, 0, (SINC_WIDTH - 1) * sizeof(r->buffer_in[0]));
+    if (r->quality == RESAMPLER_QUALITY_BLEP)
+        memset(r->buffer_out, 0, sizeof(r->buffer_out));
 }
 
 void resampler_set_rate(void *_r, double new_factor)
@@ -231,6 +261,8 @@
 {
     resampler * r = ( resampler * ) _r;
     r->phase_inc = (int)( new_factor * RESAMPLER_RESOLUTION );
+    new_factor = 1.0 / new_factor;
+    r->inv_phase_inc = (int)( new_factor * RESAMPLER_RESOLUTION );
 }
 
 void resampler_write_sample(void *_r, short s)
@@ -294,6 +326,134 @@
     return used;
 }
 
+static int resampler_run_blep(resampler * r, float ** out_, float * out_end)
+{
+    int in_size = r->write_filled;
+    float const* in_ = r->buffer_in + resampler_buffer_size + r->write_pos - r->write_filled;
+    int used = 0;
+    in_size -= 1;
+    if ( in_size > 0 )
+    {
+        float* out = *out_;
+        float const* in = in_;
+        float const* const in_end = in + in_size;
+        float last_amp = r->last_amp;
+        int inv_phase = r->inv_phase;
+        int inv_phase_inc = r->inv_phase_inc;
+        
+        const int step = RESAMPLER_RESOLUTION;
+        
+        do
+        {
+            float kernel[SINC_WIDTH * 2], kernel_sum = 0.0;
+            int i = SINC_WIDTH;
+            float sample;
+            
+            if ( out + SINC_WIDTH * 2 > out_end )
+                break;
+            
+            for (; i >= -SINC_WIDTH + 1; --i)
+            {
+                int pos = i * step;
+                kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(inv_phase - pos)];
+            }
+            sample = *in++ - last_amp;
+            last_amp += sample;
+            sample /= kernel_sum;
+            for (sample = 0, i = 0; i < SINC_WIDTH * 2; ++i)
+                out[i] += sample * kernel[i];
+            
+            inv_phase += inv_phase_inc;
+            
+            out += inv_phase >> RESAMPLER_SHIFT;
+            
+            inv_phase &= RESAMPLER_RESOLUTION-1;
+        }
+        while ( in < in_end );
+        
+        r->inv_phase = inv_phase;
+        r->last_amp = last_amp;
+        *out_ = out;
+        
+        used = (int)(in - in_);
+        
+        r->write_filled -= used;
+    }
+    
+    return used;
+}
+
+#ifdef RESAMPLER_SSE
+static int resampler_run_blep_sse(resampler * r, float ** out_, float * out_end)
+{
+    int in_size = r->write_filled;
+    float const* in_ = r->buffer_in + resampler_buffer_size + r->write_pos - r->write_filled;
+    int used = 0;
+    in_size -= 1;
+    if ( in_size > 0 )
+    {
+        float* out = *out_;
+        float const* in = in_;
+        float const* const in_end = in + in_size;
+        float last_amp = r->last_amp;
+        int inv_phase = r->inv_phase;
+        int inv_phase_inc = r->inv_phase_inc;
+        
+        const int step = RESAMPLER_RESOLUTION;
+        
+        do
+        {
+            // accumulate in extended precision
+            float kernel_sum = 0.0;
+            __m128 kernel[SINC_WIDTH / 2];
+            __m128 temp1, temp2;
+            __m128 samplex;
+            float sample;
+            float *kernelf = (float*)(&kernel);
+            int i = SINC_WIDTH;
+            
+            if ( out + SINC_WIDTH * 2 > out_end )
+                break;
+            
+            for (; i >= -SINC_WIDTH + 1; --i)
+            {
+                int pos = i * step;
+                kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(inv_phase - pos)];
+            }
+            sample = *in++ - last_amp;
+            last_amp += sample;
+            sample /= kernel_sum;
+            samplex = _mm_set1_ps( sample );
+            for (i = 0; i < SINC_WIDTH / 2; ++i)
+            {
+                temp1 = _mm_load_ps( (const float *)( kernel + i ) );
+                temp1 = _mm_mul_ps( temp1, samplex );
+                temp2 = _mm_loadu_ps( (const float *) out + i * 4 );
+                temp1 = _mm_add_ps( temp1, temp2 );
+                _mm_storeu_ps( (float *) out + i * 4, temp1 );
+            }
+            
+            inv_phase += inv_phase_inc;
+            
+            out += inv_phase >> RESAMPLER_SHIFT;
+            
+            inv_phase &= RESAMPLER_RESOLUTION - 1;
+        }
+        while ( in < in_end );
+        
+        r->inv_phase = inv_phase;
+        r->last_amp = last_amp;
+        *out_ = out;
+        
+        used = (int)(in - in_);
+        
+        r->write_filled -= used;
+    }
+    
+    return used;
+}
+#endif
+
 static int resampler_run_linear(resampler * r, float ** out_, float * out_end)
 {
     int in_size = r->write_filled;
@@ -326,7 +486,7 @@
         }
         while ( in < in_end );
         
-        r->phase = (unsigned short) phase;
+        r->phase = phase;
         *out_ = out;
         
         used = (int)(in - in_);
@@ -374,7 +534,7 @@
         }
         while ( in < in_end );
         
-        r->phase = (unsigned short) phase;
+        r->phase = phase;
         *out_ = out;
         
         used = (int)(in - in_);
@@ -428,7 +588,7 @@
         }
         while ( in < in_end );
         
-        r->phase = (unsigned short) phase;
+        r->phase = phase;
         *out_ = out;
         
         used = (int)(in - in_);
@@ -483,7 +643,7 @@
         }
         while ( in < in_end );
 
-        r->phase = (unsigned short) phase;
+        r->phase = phase;
         *out_ = out;
 
         used = (int)(in - in_);
@@ -556,7 +716,7 @@
         }
         while ( in < in_end );
         
-        r->phase = (unsigned short) phase;
+        r->phase = phase;
         *out_ = out;
         
         used = (int)(in - in_);
@@ -586,6 +746,25 @@
             resampler_run_zoh( r, &out, out + write_size );
             break;
                 
+        case RESAMPLER_QUALITY_BLEP:
+        {
+            int used;
+            int write_extra = 0;
+            if ( write_pos >= r->read_pos )
+                write_extra = r->read_pos;
+            if ( write_extra > SINC_WIDTH * 2 - 1 )
+                write_extra = SINC_WIDTH * 2 - 1;
+            memcpy( r->buffer_out + resampler_buffer_size, r->buffer_out, write_extra * sizeof(r->buffer_out[0]) );
+            if ( resampler_has_sse )
+                used = resampler_run_blep_sse( r, &out, out + write_size + write_extra );
+            else
+                used = resampler_run_blep( r, &out, out + write_size + write_extra );
+            memcpy( r->buffer_out, r->buffer_out + resampler_buffer_size, write_extra * sizeof(r->buffer_out[0]) );
+            if (!used)
+                return;
+            break;
+        }
+                
         case RESAMPLER_QUALITY_LINEAR:
             resampler_run_linear( r, &out, out + write_size );
             break;
@@ -623,11 +802,14 @@
 int resampler_get_sample(void *_r)
 {
     resampler * r = ( resampler * ) _r;
-    if ( r->read_filled < 1 )
+    if ( r->read_filled < 1 && r->phase_inc)
         resampler_fill( r );
     if ( r->read_filled < 1 )
         return 0;
-    return (int)(r->buffer_out[ r->read_pos ] * 8388608.0);
+    if ( r->quality == RESAMPLER_QUALITY_BLEP )
+        return (r->buffer_out[ r->read_pos ] + r->accumulator) * 8388608.0;
+    else
+        return r->buffer_out[ r->read_pos ] * 8388608.0;
 }
 
 void resampler_remove_sample(void *_r)
@@ -635,6 +817,12 @@
     resampler * r = ( resampler * ) _r;
     if ( r->read_filled > 0 )
     {
+        if ( r->quality == RESAMPLER_QUALITY_BLEP )
+        {
+            r->accumulator += r->buffer_out[ r->read_pos ];
+            r->buffer_out[ r->read_pos ] = 0;
+            r->accumulator -= r->accumulator * (1.0 / 8192.0);
+        }
         --r->read_filled;
         r->read_pos = ( r->read_pos + 1 ) % resampler_buffer_size;
     }
--- a/dumb/src/it/itrender.c
+++ b/dumb/src/it/itrender.c
@@ -26,7 +26,6 @@
 #include "internal/it.h"
 #include "internal/lpc.h"
 
-#include "internal/blip_buf.h"
 #include "internal/resampler.h"
 
 // #define BIT_ARRAY_BULLSHIT
@@ -36,26 +35,9 @@
 	IT_PLAYING * r = (IT_PLAYING*) malloc(sizeof(*r));
 	if (r)
 	{
-		r->resampler.blip_buffer[0] = blip_new( 256 );
-		if ( !r->resampler.blip_buffer[0] )
-		{
-			free( r );
-			return NULL;
-		}
-		r->resampler.blip_buffer[1] = blip_new( 256 );
-		if ( !r->resampler.blip_buffer[1] )
-		{
-			free( r->resampler.blip_buffer[0] );
-			free( r );
-			return NULL;
-		}
-		blip_set_rates(r->resampler.blip_buffer[0], 65536, 1);
-		blip_set_rates(r->resampler.blip_buffer[1], 65536, 1);
 		r->resampler.fir_resampler_ratio = 0.0;
 		r->resampler.fir_resampler[0] = resampler_create();
 		if ( !r->resampler.fir_resampler[0] ) {
-			free( r->resampler.blip_buffer[1] );
-			free( r->resampler.blip_buffer[0] );
 			free( r );
 			return NULL;
 		}
@@ -62,8 +44,6 @@
 		r->resampler.fir_resampler[1] = resampler_create();
 		if ( !r->resampler.fir_resampler[1] ) {
 			resampler_delete( r->resampler.fir_resampler[0] );
-			free( r->resampler.blip_buffer[1] );
-			free( r->resampler.blip_buffer[0] );
 			free( r );
 			return NULL;
 		}
@@ -75,8 +55,6 @@
 {
 	resampler_delete( r->resampler.fir_resampler[1] );
 	resampler_delete( r->resampler.fir_resampler[0] );
-	blip_delete( r->resampler.blip_buffer[1] );
-	blip_delete( r->resampler.blip_buffer[0] );
 	free( r );
 }
 
@@ -166,24 +144,9 @@
 
 	dst->resampler = src->resampler;
 	dst->resampler.pickup_data = dst;
-	dst->resampler.blip_buffer[0] = blip_dup( src->resampler.blip_buffer[0] );
-	if ( !dst->resampler.blip_buffer[0] )
-	{
-		free( dst );
-		return NULL;
-	}
-	dst->resampler.blip_buffer[1] = blip_dup( src->resampler.blip_buffer[1] );
-	if ( !dst->resampler.blip_buffer[1] )
-	{
-		blip_delete( dst->resampler.blip_buffer[0] );
-		free( dst );
-		return NULL;
-	}
 	dst->resampler.fir_resampler_ratio = src->resampler.fir_resampler_ratio;
 	dst->resampler.fir_resampler[0] = resampler_dup( src->resampler.fir_resampler[0] );
 	if ( !dst->resampler.fir_resampler[0] ) {
-		blip_delete( dst->resampler.blip_buffer[1] );
-		blip_delete( dst->resampler.blip_buffer[0] );
 		free( dst );
 		return NULL;
 	}
@@ -190,8 +153,6 @@
 	dst->resampler.fir_resampler[1] = resampler_dup( src->resampler.fir_resampler[1] );
 	if ( !dst->resampler.fir_resampler[1] ) {
 		resampler_delete( dst->resampler.fir_resampler[0] );
-		blip_delete( dst->resampler.blip_buffer[1] );
-		blip_delete( dst->resampler.blip_buffer[0] );
 		free( dst );
 		return NULL;
 	}
--- a/dumb/vc6/dumb/dumb.vcxproj
+++ b/dumb/vc6/dumb/dumb.vcxproj
@@ -109,7 +109,6 @@
     <ClCompile Include="..\..\src\core\rendsig.c" />
     <ClCompile Include="..\..\src\core\unload.c" />
     <ClCompile Include="..\..\src\helpers\barray.c" />
-    <ClCompile Include="..\..\src\helpers\blip_buf.c" />
     <ClCompile Include="..\..\src\helpers\clickrem.c" />
     <ClCompile Include="..\..\src\helpers\resampler.c" />
     <ClCompile Include="..\..\src\helpers\lpc.c" />
@@ -203,7 +202,6 @@
   <ItemGroup>
     <ClInclude Include="..\..\include\dumb.h" />
     <ClInclude Include="..\..\include\internal\barray.h" />
-    <ClInclude Include="..\..\include\internal\blip_buf.h" />
     <ClInclude Include="..\..\include\internal\dumb.h" />
     <ClInclude Include="..\..\include\internal\dumbfile.h" />
     <ClInclude Include="..\..\include\internal\fir_resampler.h" />
--- a/dumb/vc6/dumb/dumb.vcxproj.filters
+++ b/dumb/vc6/dumb/dumb.vcxproj.filters
@@ -252,9 +252,6 @@
     <ClCompile Include="..\..\src\it\xmeffect.c">
       <Filter>src\it</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\src\helpers\blip_buf.c">
-      <Filter>src\helpers</Filter>
-    </ClCompile>
     <ClCompile Include="..\..\src\it\readokt.c">
       <Filter>src\it\readers</Filter>
     </ClCompile>
@@ -312,9 +309,6 @@
       <Filter>include\internal</Filter>
     </ClInclude>
     <ClInclude Include="..\..\include\internal\stack_alloc.h">
-      <Filter>include\internal</Filter>
-    </ClInclude>
-    <ClInclude Include="..\..\include\internal\blip_buf.h">
       <Filter>include\internal</Filter>
     </ClInclude>
     <ClInclude Include="..\..\include\internal\resampler.h">