ref: 6937b61cc57d839278f6ee73bc9471eaa07c7f87
parent: a8d9baafc008bc851bce7b0aef799b74b9732a76
author: Chris Moeller <kode54@gmail.com>
date: Sat Mar 22 21:28:04 EDT 2014
Replaced built-in linear and cubic resamplers with new routines
--- a/dumb/cmake/CMakeLists.txt
+++ b/dumb/cmake/CMakeLists.txt
@@ -101,7 +101,7 @@
../src/it/loadany2.c
../src/it/loadany.c
../src/it/readany2.c
- ../src/helpers/sinc_resampler.c
+ ../src/helpers/resampler.c
../src/helpers/lpc.c
)
--- /dev/null
+++ b/dumb/include/internal/resampler.h
@@ -1,0 +1,39 @@
+#ifndef _SINC_RESAMPLER_H_
+#define _SINC_RESAMPLER_H_
+
+// Ugglay
+#ifdef SINC_DECORATE
+#define PASTE(a,b) a ## b
+#define EVALUATE(a,b) PASTE(a,b)
+#define sinc_init EVALUATE(SINC_DECORATE,_sinc_init)
+#define sinc_resampler_create EVALUATE(SINC_DECORATE,_sinc_resampler_create)
+#define sinc_resampler_delete EVALUATE(SINC_DECORATE,_sinc_resampler_delete)
+#define sinc_resampler_dup EVALUATE(SINC_DECORATE,_sinc_resampler_dup)
+#define sinc_resampler_dup_inplace EVALUATE(SINC_DECORATE,_sinc_resampler_dup_inplace)
+#define sinc_resampler_get_free_count EVALUATE(SINC_DECORATE,_sinc_resampler_get_free_count)
+#define sinc_resampler_write_sample EVALUATE(SINC_DECORATE,_sinc_resampler_write_sample)
+#define sinc_resampler_set_rate EVALUATE(SINC_DECORATE,_sinc_resampler_set_rate)
+#define sinc_resampler_ready EVALUATE(SINC_DECORATE,_sinc_resampler_ready)
+#define sinc_resampler_clear EVALUATE(SINC_DECORATE,_sinc_resampler_clear)
+#define sinc_resampler_get_sample_count EVALUATE(SINC_DECORATE,_sinc_resampler_get_sample_count)
+#define sinc_resampler_get_sample EVALUATE(SINC_DECORATE,_sinc_resampler_get_sample)
+#define sinc_resampler_remove_sample EVALUATE(SINC_DECORATE,_sinc_resampler_remove_sample)
+#endif
+
+void sinc_init(void);
+
+void * sinc_resampler_create(void);
+void sinc_resampler_delete(void *);
+void * sinc_resampler_dup(const void *);
+void sinc_resampler_dup_inplace(void *, const void *);
+
+int sinc_resampler_get_free_count(void *);
+void sinc_resampler_write_sample(void *, short sample);
+void sinc_resampler_set_rate( void *, double new_factor );
+int sinc_resampler_ready(void *);
+void sinc_resampler_clear(void *);
+int sinc_resampler_get_sample_count(void *);
+int sinc_resampler_get_sample(void *);
+void sinc_resampler_remove_sample(void *);
+
+#endif
--- a/dumb/include/internal/sinc_resampler.h
+++ /dev/null
@@ -1,39 +1,0 @@
-#ifndef _SINC_RESAMPLER_H_
-#define _SINC_RESAMPLER_H_
-
-// Ugglay
-#ifdef SINC_DECORATE
-#define PASTE(a,b) a ## b
-#define EVALUATE(a,b) PASTE(a,b)
-#define sinc_init EVALUATE(SINC_DECORATE,_sinc_init)
-#define sinc_resampler_create EVALUATE(SINC_DECORATE,_sinc_resampler_create)
-#define sinc_resampler_delete EVALUATE(SINC_DECORATE,_sinc_resampler_delete)
-#define sinc_resampler_dup EVALUATE(SINC_DECORATE,_sinc_resampler_dup)
-#define sinc_resampler_dup_inplace EVALUATE(SINC_DECORATE,_sinc_resampler_dup_inplace)
-#define sinc_resampler_get_free_count EVALUATE(SINC_DECORATE,_sinc_resampler_get_free_count)
-#define sinc_resampler_write_sample EVALUATE(SINC_DECORATE,_sinc_resampler_write_sample)
-#define sinc_resampler_set_rate EVALUATE(SINC_DECORATE,_sinc_resampler_set_rate)
-#define sinc_resampler_ready EVALUATE(SINC_DECORATE,_sinc_resampler_ready)
-#define sinc_resampler_clear EVALUATE(SINC_DECORATE,_sinc_resampler_clear)
-#define sinc_resampler_get_sample_count EVALUATE(SINC_DECORATE,_sinc_resampler_get_sample_count)
-#define sinc_resampler_get_sample EVALUATE(SINC_DECORATE,_sinc_resampler_get_sample)
-#define sinc_resampler_remove_sample EVALUATE(SINC_DECORATE,_sinc_resampler_remove_sample)
-#endif
-
-void sinc_init(void);
-
-void * sinc_resampler_create(void);
-void sinc_resampler_delete(void *);
-void * sinc_resampler_dup(const void *);
-void sinc_resampler_dup_inplace(void *, const void *);
-
-int sinc_resampler_get_free_count(void *);
-void sinc_resampler_write_sample(void *, short sample);
-void sinc_resampler_set_rate( void *, double new_factor );
-int sinc_resampler_ready(void *);
-void sinc_resampler_clear(void *);
-int sinc_resampler_get_sample_count(void *);
-int sinc_resampler_get_sample(void *);
-void sinc_resampler_remove_sample(void *);
-
-#endif
--- a/dumb/src/helpers/resamp3.inc
+++ b/dumb/src/helpers/resamp3.inc
@@ -140,71 +140,17 @@
MIX_ALIAS( todo );
done -= check;
}
- } else if (quality <= DUMB_RQ_LINEAR) {
- /* Linear interpolation, backwards */
- SRCTYPE xbuf[3*SRC_CHANNELS];
- SRCTYPE *x = &xbuf[1*SRC_CHANNELS];
- COPYSRC(xbuf, 0, resampler->X, 1);
- COPYSRC(xbuf, 1, resampler->X, 2);
- COPYSRC(xbuf, 2, src, pos);
- while (todo && x < &xbuf[3*SRC_CHANNELS]) {
- HEAVYASSERT(pos >= resampler->start);
- MIX_LINEAR(+=, 1, 0, -1);
- subpos += dt;
- pos += subpos >> 16;
- x -= (subpos >> 16) * SRC_CHANNELS;
- subpos &= 65535;
- todo--;
- }
- // TODO: use xstart for others too
- x = &src[pos*SRC_CHANNELS];
- LOOP4(todo,
- HEAVYASSERT(pos >= resampler->start);
- MIX_LINEAR(+=, 1, 1, 2);
- subpos += dt;
- pos += subpos >> 16;
- x += (subpos >> 16) * SRC_CHANNELS;
- subpos &= 65535;
- );
- } else if (quality <= DUMB_RQ_CUBIC) {
- /* Cubic interpolation, backwards */
- SRCTYPE xbuf[6*SRC_CHANNELS];
- SRCTYPE *x = &xbuf[3*SRC_CHANNELS];
- COPYSRC(xbuf, 0, resampler->X, 0);
- COPYSRC(xbuf, 1, resampler->X, 1);
- COPYSRC(xbuf, 2, resampler->X, 2);
- COPYSRC(xbuf, 3, src, pos);
- if (pos-1 >= resampler->start) COPYSRC(xbuf, 4, src, pos-1);
- if (pos-2 >= resampler->start) COPYSRC(xbuf, 5, src, pos-2);
- while (todo && x < &xbuf[6*SRC_CHANNELS]) {
- HEAVYASSERT(pos >= resampler->start);
- MIX_CUBIC(+=, 1, x, x, 0, -1, -2, -3);
- subpos += dt;
- pos += subpos >> 16;
- x -= (subpos >> 16) * SRC_CHANNELS;
- subpos &= 65535;
- todo--;
- }
- x = &src[pos*SRC_CHANNELS];
- LOOP4(todo,
- HEAVYASSERT(pos >= resampler->start);
- MIX_CUBIC(+=, 1, x, x, 0, 1, 2, 3);
- subpos += dt;
- pos += subpos >> 16;
- x += (subpos >> 16) * SRC_CHANNELS;
- subpos &= 65535;
- );
} else {
/* FIR resampling, backwards */
SRCTYPE *x;
if ( resampler->fir_resampler_ratio != delta ) {
- sinc_resampler_set_rate( resampler->fir_resampler[0], delta );
- sinc_resampler_set_rate( resampler->fir_resampler[1], delta );
+ resampler_set_rate( resampler->fir_resampler[0], delta );
+ resampler_set_rate( resampler->fir_resampler[1], delta );
resampler->fir_resampler_ratio = delta;
}
x = &src[pos*SRC_CHANNELS];
while ( todo ) {
- while ( sinc_resampler_get_free_count( resampler->fir_resampler[0] ) &&
+ while ( resampler_get_free_count( resampler->fir_resampler[0] ) &&
pos >= resampler->start )
{
POKE_FIR(0);
@@ -211,7 +157,7 @@
pos--;
x -= SRC_CHANNELS;
}
- if ( !sinc_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
+ if ( !resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
MIX_FIR;
ADVANCE_FIR;
--todo;
@@ -273,70 +219,17 @@
MIX_ALIAS( todo );
done -= check;
}
- } else if (quality <= DUMB_RQ_LINEAR) {
- /* Linear interpolation, forwards */
- SRCTYPE xbuf[3*SRC_CHANNELS];
- SRCTYPE *x = &xbuf[1*SRC_CHANNELS];
- COPYSRC(xbuf, 0, resampler->X, 1);
- COPYSRC(xbuf, 1, resampler->X, 2);
- COPYSRC(xbuf, 2, src, pos);
- while (todo && x < &xbuf[3*SRC_CHANNELS]) {
- HEAVYASSERT(pos < resampler->end);
- MIX_LINEAR(+=, 1, -1, 0);
- subpos += dt;
- pos += subpos >> 16;
- x += (subpos >> 16) * SRC_CHANNELS;
- subpos &= 65535;
- todo--;
- }
- x = &src[pos*SRC_CHANNELS];
- LOOP4(todo,
- HEAVYASSERT(pos < resampler->end);
- MIX_LINEAR(+=, 1, -2, -1);
- subpos += dt;
- pos += subpos >> 16;
- x += (subpos >> 16) * SRC_CHANNELS;
- subpos &= 65535;
- );
- } else if (quality <= DUMB_RQ_CUBIC) {
- /* Cubic interpolation, forwards */
- SRCTYPE xbuf[6*SRC_CHANNELS];
- SRCTYPE *x = &xbuf[3*SRC_CHANNELS];
- COPYSRC(xbuf, 0, resampler->X, 0);
- COPYSRC(xbuf, 1, resampler->X, 1);
- COPYSRC(xbuf, 2, resampler->X, 2);
- COPYSRC(xbuf, 3, src, pos);
- if (pos+1 < resampler->end) COPYSRC(xbuf, 4, src, pos+1);
- if (pos+2 < resampler->end) COPYSRC(xbuf, 5, src, pos+2);
- while (todo && x < &xbuf[6*SRC_CHANNELS]) {
- HEAVYASSERT(pos < resampler->end);
- MIX_CUBIC(+=, 1, x, x, -3, -2, -1, 0);
- subpos += dt;
- pos += subpos >> 16;
- x += (subpos >> 16) * SRC_CHANNELS;
- subpos &= 65535;
- todo--;
- }
- x = &src[pos*SRC_CHANNELS];
- LOOP4(todo,
- HEAVYASSERT(pos < resampler->end);
- MIX_CUBIC(+=, 1, x, x, -3, -2, -1, 0);
- subpos += dt;
- pos += subpos >> 16;
- x += (subpos >> 16) * SRC_CHANNELS;
- subpos &= 65535;
- );
} else {
/* FIR resampling, forwards */
SRCTYPE *x;
if ( resampler->fir_resampler_ratio != delta ) {
- sinc_resampler_set_rate( resampler->fir_resampler[0], delta );
- sinc_resampler_set_rate( resampler->fir_resampler[1], delta );
+ resampler_set_rate( resampler->fir_resampler[0], delta );
+ resampler_set_rate( resampler->fir_resampler[1], delta );
resampler->fir_resampler_ratio = delta;
}
x = &src[pos*SRC_CHANNELS];
while ( todo ) {
- while ( sinc_resampler_get_free_count( resampler->fir_resampler[0] ) &&
+ while ( resampler_get_free_count( resampler->fir_resampler[0] ) &&
pos < resampler->end )
{
POKE_FIR(0);
@@ -343,7 +236,7 @@
pos++;
x += SRC_CHANNELS;
}
- if ( !sinc_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
+ if ( !resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
MIX_FIR;
ADVANCE_FIR;
--todo;
--- a/dumb/src/helpers/resample.c
+++ b/dumb/src/helpers/resample.c
@@ -46,7 +46,7 @@
#include "dumb.h"
#include "internal/blip_buf.h"
-#include "internal/sinc_resampler.h"
+#include "internal/resampler.h"
@@ -158,20 +158,12 @@
* TODO: A0 and A3 stay very small indeed. Consider different scale/resolution?
*/
-static short cubicA0[1025], cubicA1[1025];
-
void _dumb_init_cubic(void)
{
- unsigned int t; /* 3*1024*1024*1024 is within range if it's unsigned */
static int done = 0;
if (done) return;
- for (t = 0; t < 1025; t++) {
- /* int casts to pacify warnings about negating unsigned values */
- cubicA0[t] = -(int)( t*t*t >> 17) + (int)( t*t >> 6) - (int)(t << 3);
- cubicA1[t] = (int)(3*t*t*t >> 17) - (int)(5*t*t >> 7) + (int)(1 << 14);
- }
- sinc_init();
+ resampler_init();
done = 1;
}
--- a/dumb/src/helpers/resample.inc
+++ b/dumb/src/helpers/resample.inc
@@ -75,8 +75,10 @@
blip_clear(resampler->blip_buffer[0]);
blip_clear(resampler->blip_buffer[1]);
resampler->fir_resampler_ratio = 0;
- sinc_resampler_clear(resampler->fir_resampler[0]);
- sinc_resampler_clear(resampler->fir_resampler[1]);
+ resampler_clear(resampler->fir_resampler[0]);
+ resampler_clear(resampler->fir_resampler[1]);
+ resampler_set_quality(resampler->fir_resampler[0], resampler->quality);
+ resampler_set_quality(resampler->fir_resampler[1], resampler->quality);
}
@@ -158,15 +160,15 @@
resampler->last_clock += inv_dt; \
}
#define POKE_FIR(offset) { \
- sinc_resampler_write_sample( resampler->fir_resampler[0], FIR(x[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( sinc_resampler_get_sample( resampler->fir_resampler[0] ), vol )
+#define MONO_DEST_PEEK_FIR *dst = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), vol )
#define MONO_DEST_MIX_FIR { \
- *dst++ += MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
+ *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
UPDATE_VOLUME( volume, vol ); \
}
-#define ADVANCE_FIR sinc_resampler_remove_sample( resampler->fir_resampler[0] )
+#define ADVANCE_FIR resampler_remove_sample( resampler->fir_resampler[0] )
#define MONO_DEST_MIX_ALIAS(count) { \
int n = 0; \
resampler->last_clock -= count * 65536; \
@@ -184,12 +186,12 @@
*dst++ = MULSC( sample, rvol ); \
}
#define STEREO_DEST_PEEK_FIR { \
- int sample = sinc_resampler_get_sample( resampler->fir_resampler[0] ); \
+ int sample = resampler_get_sample( resampler->fir_resampler[0] ); \
*dst++ = MULSC( sample, lvol ); \
*dst++ = MULSC( sample, rvol ); \
}
#define STEREO_DEST_MIX_FIR { \
- int sample = sinc_resampler_get_sample( resampler->fir_resampler[0] ); \
+ int sample = resampler_get_sample( resampler->fir_resampler[0] ); \
*dst++ += MULSC( sample, lvol ); \
*dst++ += MULSC( sample, rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \
@@ -296,8 +298,8 @@
resampler->last_clock += inv_dt; \
}
#define POKE_FIR(offset) { \
- sinc_resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \
- sinc_resampler_write_sample( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \
+ 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 ) + \
@@ -304,18 +306,18 @@
MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
}
#define MONO_DEST_PEEK_FIR { \
- *dst = MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
- MULSC( sinc_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
+ MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
}
#define MONO_DEST_MIX_FIR { \
- *dst++ += MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
- MULSC( sinc_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
+ MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \
UPDATE_VOLUME( volume_right, rvol ); \
}
#define ADVANCE_FIR { \
- sinc_resampler_remove_sample( resampler->fir_resampler[0] ); \
- sinc_resampler_remove_sample( resampler->fir_resampler[1] ); \
+ resampler_remove_sample( resampler->fir_resampler[0] ); \
+ resampler_remove_sample( resampler->fir_resampler[1] ); \
}
#define MONO_DEST_MIX_ALIAS(count) { \
int n = 0; \
@@ -336,12 +338,12 @@
*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
}
#define STEREO_DEST_PEEK_FIR { \
- *dst++ = MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
- *dst++ = MULSC( sinc_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
+ *dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
}
#define STEREO_DEST_MIX_FIR { \
- *dst++ += MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
- *dst++ += MULSC( sinc_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
+ *dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \
UPDATE_VOLUME( volume_right, rvol ); \
}
--- /dev/null
+++ b/dumb/src/helpers/resampler.c
@@ -1,0 +1,636 @@
+#include <stdlib.h>
+#include <string.h>
+#define _USE_MATH_DEFINES
+#include <math.h>
+#if (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__))
+#include <xmmintrin.h>
+#define RESAMPLER_SSE
+#endif
+
+#ifdef _MSC_VER
+#define ALIGNED _declspec(align(16))
+#else
+#define ALIGNED __attribute__((aligned(16)))
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#include "resampler.h"
+
+enum { RESAMPLER_SHIFT = 13 };
+enum { RESAMPLER_RESOLUTION = 1 << RESAMPLER_SHIFT };
+enum { SINC_WIDTH = 16 };
+enum { SINC_SAMPLES = RESAMPLER_RESOLUTION * SINC_WIDTH };
+enum { CUBIC_SAMPLES = RESAMPLER_RESOLUTION * 4 };
+
+ALIGNED static float cubic_lut[CUBIC_SAMPLES];
+
+static float sinc_lut[SINC_SAMPLES + 1];
+
+enum { resampler_buffer_size = SINC_WIDTH * 4 };
+
+static int fEqual(const float b, const float a)
+{
+ return fabs(a - b) < 1.0e-6;
+}
+
+static float sinc(float x)
+{
+ return fEqual(x, 0.0) ? 1.0 : sin(x * M_PI) / (x * M_PI);
+}
+
+#ifdef RESAMPLER_SSE
+#ifdef _MSC_VER
+#include <intrin.h>
+#elif defined(__clang__) || defined(__GNUC__)
+static inline void
+__cpuid(int *data, int selector)
+{
+ asm("cpuid"
+ : "=a" (data[0]),
+ "=b" (data[1]),
+ "=c" (data[2]),
+ "=d" (data[3])
+ : "a"(selector));
+}
+#else
+#define __cpuid(a,b) memset((a), 0, sizeof(int) * 4)
+#endif
+
+static int query_cpu_feature_sse() {
+ int buffer[4];
+ __cpuid(buffer,1);
+ if ((buffer[3]&(1<<25)) == 0) return 0;
+ return 1;
+}
+
+static int resampler_has_sse = 0;
+#endif
+
+void resampler_init(void)
+{
+ unsigned i;
+ double dx = (float)(SINC_WIDTH) / SINC_SAMPLES, x = 0.0;
+ for (i = 0; i < SINC_SAMPLES + 1; ++i, x += dx)
+ {
+ float y = x / SINC_WIDTH;
+#if 1
+ // Blackman
+ float window = 0.42659 - 0.49656 * cos(M_PI + M_PI * y) + 0.076849 * cos(2.0 * M_PI * y);
+#elif 0
+ // C.R.Helmrich's 2 term window
+ float window = 0.79445 * cos(0.5 * M_PI * y) + 0.20555 * cos(1.5 * M_PI * y);
+#elif 0
+ // Lanczos
+ float window = sinc(y);
+#endif
+ sinc_lut[i] = fabs(x) < SINC_WIDTH ? sinc(x) * window : 0.0;
+ }
+ dx = 1.0 / (float)(RESAMPLER_RESOLUTION);
+ x = 0.0;
+ for (i = 0; i < RESAMPLER_RESOLUTION; ++i, x += dx)
+ {
+ cubic_lut[i*4] = (float)(-0.5 * x * x * x + x * x - 0.5 * x);
+ cubic_lut[i*4+1] = (float)( 1.5 * x * x * x - 2.5 * x * x + 1.0);
+ cubic_lut[i*4+2] = (float)(-1.5 * x * x * x + 2.0 * x * x + 0.5 * x);
+ cubic_lut[i*4+3] = (float)( 0.5 * x * x * x - 0.5 * x * x);
+ }
+#ifdef RESAMPLER_SSE
+ resampler_has_sse = query_cpu_feature_sse();
+#endif
+}
+
+typedef struct resampler
+{
+ int write_pos, write_filled;
+ int read_pos, read_filled;
+ unsigned short phase;
+ unsigned short phase_inc;
+ unsigned char quality;
+ float buffer_in[resampler_buffer_size * 2];
+ float buffer_out[resampler_buffer_size + SINC_WIDTH * 2 - 1];
+} resampler;
+
+void * resampler_create(void)
+{
+ resampler * r = ( resampler * ) malloc( sizeof(resampler) );
+ if ( !r ) return 0;
+
+ r->write_pos = 0;
+ r->write_filled = 0;
+ r->read_pos = 0;
+ r->read_filled = 0;
+ r->phase = 0;
+ r->phase_inc = 0;
+ r->quality = RESAMPLER_QUALITY_MAX;
+ memset( r->buffer_in, 0, sizeof(r->buffer_in) );
+ memset( r->buffer_out, 0, sizeof(r->buffer_out) );
+
+ return r;
+}
+
+void resampler_delete(void * _r)
+{
+ free( _r );
+}
+
+void * resampler_dup(const void * _r)
+{
+ const resampler * r_in = ( const resampler * ) _r;
+ resampler * r_out = ( resampler * ) malloc( sizeof(resampler) );
+ if ( !r_out ) return 0;
+
+ r_out->write_pos = r_in->write_pos;
+ r_out->write_filled = r_in->write_filled;
+ r_out->read_pos = r_in->read_pos;
+ r_out->read_filled = r_in->read_filled;
+ r_out->phase = r_in->phase;
+ r_out->phase_inc = r_in->phase_inc;
+ r_out->quality = r_in->quality;
+ 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) );
+
+ return r_out;
+}
+
+void resampler_dup_inplace(void *_d, const void *_s)
+{
+ const resampler * r_in = ( const resampler * ) _s;
+ resampler * r_out = ( resampler * ) _d;
+
+ r_out->write_pos = r_in->write_pos;
+ r_out->write_filled = r_in->write_filled;
+ r_out->read_pos = r_in->read_pos;
+ r_out->read_filled = r_in->read_filled;
+ r_out->phase = r_in->phase;
+ r_out->phase_inc = r_in->phase_inc;
+ r_out->quality = r_in->quality;
+ 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) );
+}
+
+void resampler_set_quality(void *_r, int quality)
+{
+ resampler * r = ( resampler * ) _r;
+ if (quality < RESAMPLER_QUALITY_MIN)
+ quality = RESAMPLER_QUALITY_MIN;
+ else if (quality > RESAMPLER_QUALITY_MAX)
+ quality = RESAMPLER_QUALITY_MAX;
+ r->quality = (unsigned char)quality;
+}
+
+int resampler_get_free_count(void *_r)
+{
+ resampler * r = ( resampler * ) _r;
+ return resampler_buffer_size - r->write_filled;
+}
+
+static int resampler_min_filled(resampler *r)
+{
+ switch (r->quality)
+ {
+ default:
+ case RESAMPLER_QUALITY_ZOH:
+ return 1;
+
+ case RESAMPLER_QUALITY_LINEAR:
+ return 2;
+
+ case RESAMPLER_QUALITY_CUBIC:
+ return 4;
+
+ case RESAMPLER_QUALITY_SINC:
+ return SINC_WIDTH * 2;
+ }
+}
+
+int resampler_ready(void *_r)
+{
+ resampler * r = ( resampler * ) _r;
+ return r->write_filled > resampler_min_filled(r);
+}
+
+void resampler_clear(void *_r)
+{
+ resampler * r = ( resampler * ) _r;
+ r->write_pos = 0;
+ r->write_filled = 0;
+ r->read_pos = 0;
+ r->read_filled = 0;
+ r->phase = 0;
+}
+
+void resampler_set_rate(void *_r, double new_factor)
+{
+ resampler * r = ( resampler * ) _r;
+ r->phase_inc = (int)( new_factor * RESAMPLER_RESOLUTION );
+}
+
+void resampler_write_sample(void *_r, short s)
+{
+ resampler * r = ( resampler * ) _r;
+
+ if ( r->write_filled < resampler_buffer_size )
+ {
+ float s32 = s;
+ s32 *= (1.0 / 32768.0);
+
+ r->buffer_in[ r->write_pos ] = s32;
+ r->buffer_in[ r->write_pos + resampler_buffer_size ] = s32;
+
+ ++r->write_filled;
+
+ r->write_pos = ( r->write_pos + 1 ) % resampler_buffer_size;
+ }
+}
+
+static int resampler_run_zoh(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;
+ int phase = r->phase;
+ int phase_inc = r->phase_inc;
+
+ do
+ {
+ float sample;
+
+ if ( out >= out_end )
+ break;
+
+ sample = *in;
+ *out++ = sample;
+
+ phase += phase_inc;
+
+ in += phase >> RESAMPLER_SHIFT;
+
+ phase &= RESAMPLER_RESOLUTION-1;
+ }
+ while ( in < in_end );
+
+ r->phase = (unsigned short) phase;
+ *out_ = out;
+
+ used = (int)(in - in_);
+
+ r->write_filled -= used;
+ }
+
+ return used;
+}
+
+static int resampler_run_linear(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 -= 2;
+ if ( in_size > 0 )
+ {
+ float* out = *out_;
+ float const* in = in_;
+ float const* const in_end = in + in_size;
+ int phase = r->phase;
+ int phase_inc = r->phase_inc;
+
+ do
+ {
+ float sample;
+
+ if ( out >= out_end )
+ break;
+
+ sample = in[0] + (in[1] - in[0]) * ((float)phase / RESAMPLER_RESOLUTION);
+ *out++ = sample;
+
+ phase += phase_inc;
+
+ in += phase >> RESAMPLER_SHIFT;
+
+ phase &= RESAMPLER_RESOLUTION-1;
+ }
+ while ( in < in_end );
+
+ r->phase = (unsigned short) phase;
+ *out_ = out;
+
+ used = (int)(in - in_);
+
+ r->write_filled -= used;
+ }
+
+ return used;
+}
+
+static int resampler_run_cubic(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 -= 4;
+ if ( in_size > 0 )
+ {
+ float* out = *out_;
+ float const* in = in_;
+ float const* const in_end = in + in_size;
+ int phase = r->phase;
+ int phase_inc = r->phase_inc;
+
+ do
+ {
+ float * kernel;
+ int i;
+ float sample;
+
+ if ( out >= out_end )
+ break;
+
+ kernel = cubic_lut + phase * 4;
+
+ for (sample = 0, i = 0; i < 4; ++i)
+ sample += in[i] * kernel[i];
+ *out++ = sample;
+
+ phase += phase_inc;
+
+ in += phase >> RESAMPLER_SHIFT;
+
+ phase &= RESAMPLER_RESOLUTION-1;
+ }
+ while ( in < in_end );
+
+ r->phase = (unsigned short) phase;
+ *out_ = out;
+
+ used = (int)(in - in_);
+
+ r->write_filled -= used;
+ }
+
+ return used;
+}
+
+#ifdef RESAMPLER_SSE
+static int resampler_run_cubic_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 -= 4;
+ if ( in_size > 0 )
+ {
+ float* out = *out_;
+ float const* in = in_;
+ float const* const in_end = in + in_size;
+ int phase = r->phase;
+ int phase_inc = r->phase_inc;
+
+ do
+ {
+ __m128 temp1, temp2;
+ __m128 samplex = _mm_setzero_ps();
+
+ if ( out >= out_end )
+ break;
+
+ temp1 = _mm_loadu_ps( (const float *)( in ) );
+ temp2 = _mm_load_ps( (const float *)( cubic_lut + phase * 4 ) );
+ temp1 = _mm_mul_ps( temp1, temp2 );
+ samplex = _mm_add_ps( samplex, temp1 );
+ temp1 = _mm_movehl_ps( temp1, samplex );
+ samplex = _mm_add_ps( samplex, temp1 );
+ temp1 = samplex;
+ temp1 = _mm_shuffle_ps( temp1, samplex, _MM_SHUFFLE(0, 0, 0, 1) );
+ samplex = _mm_add_ps( samplex, temp1 );
+ _mm_store_ss( out, samplex );
+ ++out;
+
+ phase += phase_inc;
+
+ in += phase >> RESAMPLER_SHIFT;
+
+ phase &= RESAMPLER_RESOLUTION - 1;
+ }
+ while ( in < in_end );
+
+ r->phase = (unsigned short) phase;
+ *out_ = out;
+
+ used = (int)(in - in_);
+
+ r->write_filled -= used;
+ }
+
+ return used;
+}
+#endif
+
+static int resampler_run_sinc(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 -= SINC_WIDTH * 2;
+ if ( in_size > 0 )
+ {
+ float* out = *out_;
+ float const* in = in_;
+ float const* const in_end = in + in_size;
+ int phase = r->phase;
+ int phase_inc = r->phase_inc;
+
+ int step = phase_inc > RESAMPLER_RESOLUTION ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION / phase_inc : RESAMPLER_RESOLUTION;
+
+ do
+ {
+ float kernel[SINC_WIDTH * 2], kernel_sum = 0.0;
+ int i = SINC_WIDTH;
+ int phase_adj = phase * step / RESAMPLER_RESOLUTION;
+ float sample;
+
+ if ( out >= out_end )
+ break;
+
+ for (; i >= -SINC_WIDTH + 1; --i)
+ {
+ int pos = i * step;
+ kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)];
+ }
+ for (sample = 0, i = 0; i < SINC_WIDTH * 2; ++i)
+ sample += in[i] * kernel[i];
+ *out++ = (float)(sample / kernel_sum);
+
+ phase += phase_inc;
+
+ in += phase >> RESAMPLER_SHIFT;
+
+ phase &= RESAMPLER_RESOLUTION-1;
+ }
+ while ( in < in_end );
+
+ r->phase = (unsigned short) phase;
+ *out_ = out;
+
+ used = (int)(in - in_);
+
+ r->write_filled -= used;
+ }
+
+ return used;
+}
+
+#ifdef RESAMPLER_SSE
+static int resampler_run_sinc_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 -= SINC_WIDTH * 2;
+ if ( in_size > 0 )
+ {
+ float* out = *out_;
+ float const* in = in_;
+ float const* const in_end = in + in_size;
+ int phase = r->phase;
+ int phase_inc = r->phase_inc;
+
+ int step = phase_inc > RESAMPLER_RESOLUTION ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION / phase_inc : RESAMPLER_RESOLUTION;
+
+ do
+ {
+ // accumulate in extended precision
+ float kernel_sum = 0.0;
+ __m128 kernel[SINC_WIDTH / 2];
+ __m128 temp1, temp2;
+ __m128 samplex = _mm_setzero_ps();
+ float *kernelf = (float*)(&kernel);
+ int i = SINC_WIDTH;
+ int phase_adj = phase * step / RESAMPLER_RESOLUTION;
+
+ if ( out >= out_end )
+ break;
+
+ for (; i >= -SINC_WIDTH + 1; --i)
+ {
+ int pos = i * step;
+ kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)];
+ }
+ for (i = 0; i < SINC_WIDTH / 2; ++i)
+ {
+ temp1 = _mm_loadu_ps( (const float *)( in + i * 4 ) );
+ temp2 = _mm_load_ps( (const float *)( kernel + i ) );
+ temp1 = _mm_mul_ps( temp1, temp2 );
+ samplex = _mm_add_ps( samplex, temp1 );
+ }
+ kernel_sum = 1.0 / kernel_sum;
+ temp1 = _mm_movehl_ps( temp1, samplex );
+ samplex = _mm_add_ps( samplex, temp1 );
+ temp1 = samplex;
+ temp1 = _mm_shuffle_ps( temp1, samplex, _MM_SHUFFLE(0, 0, 0, 1) );
+ samplex = _mm_add_ps( samplex, temp1 );
+ temp1 = _mm_set_ss( kernel_sum );
+ samplex = _mm_mul_ps( samplex, temp1 );
+ _mm_store_ss( out, samplex );
+ ++out;
+
+ phase += phase_inc;
+
+ in += phase >> RESAMPLER_SHIFT;
+
+ phase &= RESAMPLER_RESOLUTION - 1;
+ }
+ while ( in < in_end );
+
+ r->phase = (unsigned short) phase;
+ *out_ = out;
+
+ used = (int)(in - in_);
+
+ r->write_filled -= used;
+ }
+
+ return used;
+}
+#endif
+
+static void resampler_fill(resampler * r)
+{
+ int min_filled = resampler_min_filled(r);
+ int quality = r->quality;
+ while ( r->write_filled > min_filled &&
+ r->read_filled < resampler_buffer_size )
+ {
+ int write_pos = ( r->read_pos + r->read_filled ) % resampler_buffer_size;
+ int write_size = resampler_buffer_size - write_pos;
+ float * out = r->buffer_out + write_pos;
+ if ( write_size > ( resampler_buffer_size - r->read_filled ) )
+ write_size = resampler_buffer_size - r->read_filled;
+ switch (quality)
+ {
+ case RESAMPLER_QUALITY_ZOH:
+ resampler_run_zoh( r, &out, out + write_size );
+ break;
+
+ case RESAMPLER_QUALITY_LINEAR:
+ resampler_run_linear( r, &out, out + write_size );
+ break;
+
+ case RESAMPLER_QUALITY_CUBIC:
+#ifdef RESAMPLER_SSE
+ if ( resampler_has_sse )
+ resampler_run_cubic_sse( r, &out, out + write_size );
+ else
+#endif
+ resampler_run_cubic( r, &out, out + write_size );
+ break;
+
+ case RESAMPLER_QUALITY_SINC:
+#ifdef RESAMPLER_SSE
+ if ( resampler_has_sse )
+ resampler_run_sinc_sse( r, &out, out + write_size );
+ else
+#endif
+ resampler_run_sinc( r, &out, out + write_size );
+ break;
+ }
+ r->read_filled += out - r->buffer_out - write_pos;
+ }
+}
+
+int resampler_get_sample_count(void *_r)
+{
+ resampler * r = ( resampler * ) _r;
+ if ( r->read_filled < 1 )
+ resampler_fill( r );
+ return r->read_filled;
+}
+
+int resampler_get_sample(void *_r)
+{
+ resampler * r = ( resampler * ) _r;
+ if ( r->read_filled < 1 )
+ resampler_fill( r );
+ if ( r->read_filled < 1 )
+ return 0;
+ return (int)(r->buffer_out[ r->read_pos ] * 16777216.0);
+}
+
+void resampler_remove_sample(void *_r)
+{
+ resampler * r = ( resampler * ) _r;
+ if ( r->read_filled > 0 )
+ {
+ --r->read_filled;
+ r->read_pos = ( r->read_pos + 1 ) % resampler_buffer_size;
+ }
+}
--- a/dumb/src/helpers/sinc_resampler.c
+++ /dev/null
@@ -1,361 +1,0 @@
-#include <stdlib.h>
-#include <string.h>
-#define _USE_MATH_DEFINES
-#include <math.h>
-#if (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__))
-#include <xmmintrin.h>
-#define SINC_SSE
-#endif
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-#include "sinc_resampler.h"
-
-enum { SINC_RESOLUTION = 8192 };
-enum { SINC_WIDTH = 16 };
-enum { SINC_SAMPLES = SINC_RESOLUTION * SINC_WIDTH };
-
-static float sinc_lut[SINC_SAMPLES + 1];
-
-enum { sinc_buffer_size = SINC_WIDTH * 4 };
-
-static int fEqual(const float b, const float a)
-{
- return fabs(a - b) < 1.0e-6;
-}
-
-static float sinc(float x)
-{
- return fEqual(x, 0.0) ? 1.0 : sin(x * M_PI) / (x * M_PI);
-}
-
-#ifdef SINC_SSE
-#ifdef _MSC_VER
-#include <intrin.h>
-#elif defined(__clang__) || defined(__GNUC__)
-static inline void
-__cpuid(int *data, int selector)
-{
- asm("cpuid"
- : "=a" (data[0]),
- "=b" (data[1]),
- "=c" (data[2]),
- "=d" (data[3])
- : "a"(selector));
-}
-#else
-#define __cpuid(a,b) memset((a), 0, sizeof(int) * 4)
-#endif
-
-static int query_cpu_feature_sse() {
- int buffer[4];
- __cpuid(buffer,1);
- if ((buffer[3]&(1<<25)) == 0) return 0;
- return 1;
-}
-
-static int sinc_has_sse = 0;
-#endif
-
-void sinc_init(void)
-{
- unsigned i;
- float dx = (float)(SINC_WIDTH) / SINC_SAMPLES, x = 0.0;
- for (i = 0; i < SINC_SAMPLES + 1; ++i, x += dx)
- {
- float y = x / SINC_WIDTH;
- float window = 0.42659 - 0.49656 * cos(M_PI + M_PI * y) + 0.076849 * cos(2.0 * M_PI * y);
- sinc_lut[i] = fabs(x) < SINC_WIDTH ? sinc(x) * window : 0.0;
- }
-#ifdef SINC_SSE
- sinc_has_sse = query_cpu_feature_sse();
-#endif
-}
-
-typedef struct sinc_resampler
-{
- int write_pos, write_filled;
- int read_pos, read_filled;
- unsigned short phase;
- unsigned int phase_inc;
- float buffer_in[sinc_buffer_size * 2];
- int buffer_out[sinc_buffer_size];
-} sinc_resampler;
-
-void * sinc_resampler_create(void)
-{
- sinc_resampler * r = ( sinc_resampler * ) malloc( sizeof(sinc_resampler) );
- if ( !r ) return 0;
-
- r->write_pos = 0;
- r->write_filled = 0;
- r->read_pos = 0;
- r->read_filled = 0;
- r->phase = 0;
- r->phase_inc = 0;
- memset( r->buffer_in, 0, sizeof(r->buffer_in) );
- memset( r->buffer_out, 0, sizeof(r->buffer_out) );
-
- return r;
-}
-
-void sinc_resampler_delete(void * _r)
-{
- free( _r );
-}
-
-void * sinc_resampler_dup(const void * _r)
-{
- const sinc_resampler * r_in = ( const sinc_resampler * ) _r;
- sinc_resampler * r_out = ( sinc_resampler * ) malloc( sizeof(sinc_resampler) );
- if ( !r_out ) return 0;
-
- r_out->write_pos = r_in->write_pos;
- r_out->write_filled = r_in->write_filled;
- r_out->read_pos = r_in->read_pos;
- r_out->read_filled = r_in->read_filled;
- r_out->phase = r_in->phase;
- r_out->phase_inc = r_in->phase_inc;
- 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) );
-
- return r_out;
-}
-
-void sinc_resampler_dup_inplace(void *_d, const void *_s)
-{
- const sinc_resampler * r_in = ( const sinc_resampler * ) _s;
- sinc_resampler * r_out = ( sinc_resampler * ) _d;
-
- r_out->write_pos = r_in->write_pos;
- r_out->write_filled = r_in->write_filled;
- r_out->read_pos = r_in->read_pos;
- r_out->read_filled = r_in->read_filled;
- r_out->phase = r_in->phase;
- r_out->phase_inc = r_in->phase_inc;
- 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) );
-}
-
-int sinc_resampler_get_free_count(void *_r)
-{
- sinc_resampler * r = ( sinc_resampler * ) _r;
- return sinc_buffer_size - r->write_filled;
-}
-
-int sinc_resampler_ready(void *_r)
-{
- sinc_resampler * r = ( sinc_resampler * ) _r;
- return r->write_filled > (SINC_WIDTH * 2);
-}
-
-void sinc_resampler_clear(void *_r)
-{
- sinc_resampler * r = ( sinc_resampler * ) _r;
- r->write_pos = 0;
- r->write_filled = 0;
- r->read_pos = 0;
- r->read_filled = 0;
- r->phase = 0;
-}
-
-void sinc_resampler_set_rate(void *_r, double new_factor)
-{
- sinc_resampler * r = ( sinc_resampler * ) _r;
- r->phase_inc = (int)( new_factor * SINC_RESOLUTION );
-}
-
-void sinc_resampler_write_sample(void *_r, short s)
-{
- sinc_resampler * r = ( sinc_resampler * ) _r;
-
- if ( r->write_filled < sinc_buffer_size )
- {
- float s32 = s;
-
- r->buffer_in[ r->write_pos ] = s32;
- r->buffer_in[ r->write_pos + sinc_buffer_size ] = s32;
-
- ++r->write_filled;
-
- r->write_pos = ( r->write_pos + 1 ) % sinc_buffer_size;
- }
-}
-
-static int sinc_resampler_run(sinc_resampler * r, int ** out_, int * out_end)
-{
- int in_size = r->write_filled;
- float const* in_ = r->buffer_in + sinc_buffer_size + r->write_pos - r->write_filled;
- int used = 0;
- in_size -= SINC_WIDTH * 2;
- if ( in_size > 0 )
- {
- int* out = *out_;
- float const* in = in_;
- float const* const in_end = in + in_size;
- int phase = r->phase;
- int phase_inc = r->phase_inc;
-
- int step = phase_inc > SINC_RESOLUTION ? SINC_RESOLUTION * SINC_RESOLUTION / phase_inc : SINC_RESOLUTION;
-
- do
- {
- // accumulate in extended precision
- float kernel[SINC_WIDTH * 2], kernel_sum = 0.0;
- int i = SINC_WIDTH;
- int phase_adj = phase * step / SINC_RESOLUTION;
- float sample;
-
- if ( out >= out_end )
- break;
-
- for (; i >= -SINC_WIDTH + 1; --i)
- {
- int pos = i * step;
- kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)];
- }
- for (sample = 0, i = 0; i < SINC_WIDTH * 2; ++i)
- sample += in[i] * kernel[i];
- *out++ = (int)(sample / kernel_sum * 256.0);
-
- phase += phase_inc;
-
- in += phase >> 13;
-
- phase &= 8191;
- }
- while ( in < in_end );
-
- r->phase = (unsigned short) phase;
- *out_ = out;
-
- used = (int)(in - in_);
-
- r->write_filled -= used;
- }
-
- return used;
-}
-
-#ifdef SINC_SSE
-static int sinc_resampler_run_sse(sinc_resampler * r, int ** out_, int * out_end)
-{
- int in_size = r->write_filled;
- float const* in_ = r->buffer_in + sinc_buffer_size + r->write_pos - r->write_filled;
- int used = 0;
- in_size -= SINC_WIDTH * 2;
- if ( in_size > 0 )
- {
- int* out = *out_;
- float const* in = in_;
- float const* const in_end = in + in_size;
- int phase = r->phase;
- int phase_inc = r->phase_inc;
-
- int step = phase_inc > SINC_RESOLUTION ? SINC_RESOLUTION * SINC_RESOLUTION / phase_inc : SINC_RESOLUTION;
-
- do
- {
- // accumulate in extended precision
- float kernel_sum = 0.0;
- __m128 kernel[SINC_WIDTH / 2];
- __m128 temp1, temp2;
- __m128 samplex = _mm_setzero_ps();
- float *kernelf = (float*)(&kernel);
- int i = SINC_WIDTH;
- int phase_adj = phase * step / SINC_RESOLUTION;
-
- if ( out >= out_end )
- break;
-
- for (; i >= -SINC_WIDTH + 1; --i)
- {
- int pos = i * step;
- kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)];
- }
- for (i = 0; i < SINC_WIDTH / 2; ++i)
- {
- temp1 = _mm_loadu_ps( (const float *)( in + i * 4 ) );
- temp2 = _mm_load_ps( (const float *)( kernel + i ) );
- temp1 = _mm_mul_ps( temp1, temp2 );
- samplex = _mm_add_ps( samplex, temp1 );
- }
- kernel_sum = 1.0 / kernel_sum * 256.0;
- temp1 = _mm_movehl_ps( temp1, samplex );
- samplex = _mm_add_ps( samplex, temp1 );
- temp1 = samplex;
- temp1 = _mm_shuffle_ps( temp1, samplex, _MM_SHUFFLE(0, 0, 0, 1) );
- samplex = _mm_add_ps( samplex, temp1 );
- temp1 = _mm_set_ss( kernel_sum );
- samplex = _mm_mul_ps( samplex, temp1 );
- *out++ = _mm_cvtss_si32( samplex );
-
- phase += phase_inc;
-
- in += phase >> 13;
-
- phase &= 8191;
- }
- while ( in < in_end );
-
- r->phase = (unsigned short) phase;
- *out_ = out;
-
- used = (int)(in - in_);
-
- r->write_filled -= used;
- }
-
- return used;
-}
-#endif
-
-static void sinc_resampler_fill(sinc_resampler * r)
-{
- while ( r->write_filled > (SINC_WIDTH * 2) &&
- r->read_filled < sinc_buffer_size )
- {
- int write_pos = ( r->read_pos + r->read_filled ) % sinc_buffer_size;
- int write_size = sinc_buffer_size - write_pos;
- int * out = r->buffer_out + write_pos;
- if ( write_size > ( sinc_buffer_size - r->read_filled ) )
- write_size = sinc_buffer_size - r->read_filled;
-#ifdef SINC_SSE
- if ( sinc_has_sse )
- sinc_resampler_run_sse( r, &out, out + write_size );
- else
-#endif
- sinc_resampler_run( r, &out, out + write_size );
- r->read_filled += out - r->buffer_out - write_pos;
- }
-}
-
-int sinc_resampler_get_sample_count(void *_r)
-{
- sinc_resampler * r = ( sinc_resampler * ) _r;
- if ( r->read_filled < 1 )
- sinc_resampler_fill( r );
- return r->read_filled;
-}
-
-int sinc_resampler_get_sample(void *_r)
-{
- sinc_resampler * r = ( sinc_resampler * ) _r;
- if ( r->read_filled < 1 )
- sinc_resampler_fill( r );
- if ( r->read_filled < 1 )
- return 0;
- return r->buffer_out[ r->read_pos ];
-}
-
-void sinc_resampler_remove_sample(void *_r)
-{
- sinc_resampler * r = ( sinc_resampler * ) _r;
- if ( r->read_filled > 0 )
- {
- --r->read_filled;
- r->read_pos = ( r->read_pos + 1 ) % sinc_buffer_size;
- }
-}
--- a/dumb/src/it/itrender.c
+++ b/dumb/src/it/itrender.c
@@ -27,7 +27,7 @@
#include "internal/lpc.h"
#include "internal/blip_buf.h"
-#include "internal/sinc_resampler.h"
+#include "internal/resampler.h"
// #define BIT_ARRAY_BULLSHIT
@@ -52,7 +52,7 @@
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] = sinc_resampler_create();
+ 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] );
@@ -59,9 +59,9 @@
free( r );
return NULL;
}
- r->resampler.fir_resampler[1] = sinc_resampler_create();
+ r->resampler.fir_resampler[1] = resampler_create();
if ( !r->resampler.fir_resampler[1] ) {
- sinc_resampler_delete( r->resampler.fir_resampler[0] );
+ resampler_delete( r->resampler.fir_resampler[0] );
free( r->resampler.blip_buffer[1] );
free( r->resampler.blip_buffer[0] );
free( r );
@@ -73,8 +73,8 @@
static void free_playing(IT_PLAYING * r)
{
- sinc_resampler_delete( r->resampler.fir_resampler[1] );
- sinc_resampler_delete( r->resampler.fir_resampler[0] );
+ 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 );
@@ -180,7 +180,7 @@
return NULL;
}
dst->resampler.fir_resampler_ratio = src->resampler.fir_resampler_ratio;
- dst->resampler.fir_resampler[0] = sinc_resampler_dup( src->resampler.fir_resampler[0] );
+ 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] );
@@ -187,9 +187,9 @@
free( dst );
return NULL;
}
- dst->resampler.fir_resampler[1] = sinc_resampler_dup( src->resampler.fir_resampler[1] );
+ dst->resampler.fir_resampler[1] = resampler_dup( src->resampler.fir_resampler[1] );
if ( !dst->resampler.fir_resampler[1] ) {
- sinc_resampler_delete( dst->resampler.fir_resampler[0] );
+ resampler_delete( dst->resampler.fir_resampler[0] );
blip_delete( dst->resampler.blip_buffer[1] );
blip_delete( dst->resampler.blip_buffer[0] );
free( dst );
@@ -4660,6 +4660,8 @@
if (playing->sample->max_resampling_quality >= 0 && quality > playing->sample->max_resampling_quality)
quality = playing->sample->max_resampling_quality;
playing->resampler.quality = quality;
+ resampler_set_quality(playing->resampler.fir_resampler[0], quality);
+ resampler_set_quality(playing->resampler.fir_resampler[1], quality);
}
bits = playing->sample->flags & IT_SAMPLE_16BIT ? 16 : 8;
@@ -5335,6 +5337,8 @@
IT_PLAYING * playing = sigrenderer->channel[i].playing;
playing->resampling_quality = quality;
playing->resampler.quality = quality;
+ resampler_set_quality(playing->resampler.fir_resampler[0], quality);
+ resampler_set_quality(playing->resampler.fir_resampler[1], quality);
}
}
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
@@ -5342,6 +5346,8 @@
IT_PLAYING * playing = sigrenderer->playing[i];
playing->resampling_quality = quality;
playing->resampler.quality = quality;
+ resampler_set_quality(playing->resampler.fir_resampler[0], quality);
+ resampler_set_quality(playing->resampler.fir_resampler[1], quality);
}
}
}
--- a/dumb/vc6/dumb/dumb.vcxproj
+++ b/dumb/vc6/dumb/dumb.vcxproj
@@ -112,7 +112,7 @@
<ClCompile Include="..\..\src\helpers\blip_buf.c" />
<ClCompile Include="..\..\src\helpers\clickrem.c" />
<ClCompile Include="..\..\src\helpers\fir_resampler.c" />
- <ClCompile Include="..\..\src\helpers\sinc_resampler.c" />
+ <ClCompile Include="..\..\src\helpers\resampler.c" />
<ClCompile Include="..\..\src\helpers\lpc.c" />
<ClCompile Include="..\..\src\helpers\memfile.c" />
<ClCompile Include="..\..\src\helpers\resample.c" />
@@ -209,7 +209,7 @@
<ClInclude Include="..\..\include\internal\dumbfile.h" />
<ClInclude Include="..\..\include\internal\fir_resampler.h" />
<ClInclude Include="..\..\include\internal\it.h" />
- <ClInclude Include="..\..\include\internal\sinc_resampler.h" />
+ <ClInclude Include="..\..\include\internal\resampler.h" />
<ClInclude Include="..\..\include\internal\lpc.h" />
<ClInclude Include="..\..\include\internal\riff.h" />
<ClInclude Include="..\..\include\internal\stack_alloc.h" />
--- a/dumb/vc6/dumb/dumb.vcxproj.filters
+++ b/dumb/vc6/dumb/dumb.vcxproj.filters
@@ -282,7 +282,7 @@
<ClCompile Include="..\..\src\it\readany2.c">
<Filter>src\it\readers</Filter>
</ClCompile>
- <ClCompile Include="..\..\src\helpers\sinc_resampler.c">
+ <ClCompile Include="..\..\src\helpers\resampler.c">
<Filter>src\helpers</Filter>
</ClCompile>
<ClCompile Include="..\..\src\helpers\tarray.c">
@@ -320,7 +320,7 @@
<ClInclude Include="..\..\include\internal\blip_buf.h">
<Filter>include\internal</Filter>
</ClInclude>
- <ClInclude Include="..\..\include\internal\sinc_resampler.h">
+ <ClInclude Include="..\..\include\internal\resampler.h">
<Filter>include\internal</Filter>
</ClInclude>
<ClInclude Include="..\..\include\internal\tarray.h">