ref: a8d9baafc008bc851bce7b0aef799b74b9732a76
parent: 0d21e1317cb204c4975cb98f7ab3ca5685aca910
author: Chris Moeller <kode54@gmail.com>
date: Sat Mar 22 12:29:27 EDT 2014
Renamed lanczos_resampler to sinc_resampler, changed to Blackman window
--- 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/lanczos_resampler.c
+ ../src/helpers/sinc_resampler.c
../src/helpers/lpc.c
)
--- a/dumb/include/internal/lanczos_resampler.h
+++ /dev/null
@@ -1,39 +1,0 @@
-#ifndef _LANCZOS_RESAMPLER_H_
-#define _LANCZOS_RESAMPLER_H_
-
-// Ugglay
-#ifdef LANCZOS_DECORATE
-#define PASTE(a,b) a ## b
-#define EVALUATE(a,b) PASTE(a,b)
-#define lanczos_init EVALUATE(LANCZOS_DECORATE,_lanczos_init)
-#define lanczos_resampler_create EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_create)
-#define lanczos_resampler_delete EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_delete)
-#define lanczos_resampler_dup EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_dup)
-#define lanczos_resampler_dup_inplace EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_dup_inplace)
-#define lanczos_resampler_get_free_count EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_get_free_count)
-#define lanczos_resampler_write_sample EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_write_sample)
-#define lanczos_resampler_set_rate EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_set_rate)
-#define lanczos_resampler_ready EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_ready)
-#define lanczos_resampler_clear EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_clear)
-#define lanczos_resampler_get_sample_count EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_get_sample_count)
-#define lanczos_resampler_get_sample EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_get_sample)
-#define lanczos_resampler_remove_sample EVALUATE(LANCZOS_DECORATE,_lanczos_resampler_remove_sample)
-#endif
-
-void lanczos_init(void);
-
-void * lanczos_resampler_create(void);
-void lanczos_resampler_delete(void *);
-void * lanczos_resampler_dup(const void *);
-void lanczos_resampler_dup_inplace(void *, const void *);
-
-int lanczos_resampler_get_free_count(void *);
-void lanczos_resampler_write_sample(void *, short sample);
-void lanczos_resampler_set_rate( void *, double new_factor );
-int lanczos_resampler_ready(void *);
-void lanczos_resampler_clear(void *);
-int lanczos_resampler_get_sample_count(void *);
-int lanczos_resampler_get_sample(void *);
-void lanczos_resampler_remove_sample(void *);
-
-#endif
--- /dev/null
+++ b/dumb/include/internal/sinc_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/prj/dumb/dumb.pro
+++ b/dumb/prj/dumb/dumb.pro
@@ -101,7 +101,7 @@
../../src/it/loadany2.c \
../../src/it/loadany.c \
../../src/it/readany2.c \
- ../../src/helpers/lanczos_resampler.c \
+ ../../src/helpers/sinc_resampler.c \
../../src/helpers/lpc.c
HEADERS += \
@@ -113,7 +113,7 @@
../../include/internal/barray.h \
../../include/internal/tarray.h \
../../include/internal/aldumb.h \
- ../../include/internal/lanczos_resampler.h \
+ ../../include/internal/sinc_resampler.h \
../../include/internal/stack_alloc.h \
../../include/internal/lpc.h \
../../include/internal/dumbfile.h
--- a/dumb/src/helpers/lanczos_resampler.c
+++ /dev/null
@@ -1,355 +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 LANCZOS_SSE
-#endif
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
-#include "internal/lanczos_resampler.h"
-
-enum { LANCZOS_RESOLUTION = 8192 };
-enum { LANCZOS_WIDTH = 16 };
-enum { LANCZOS_SAMPLES = LANCZOS_RESOLUTION * LANCZOS_WIDTH };
-
-static float lanczos_lut[LANCZOS_SAMPLES + 1];
-
-enum { lanczos_buffer_size = LANCZOS_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 LANCZOS_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 lanczos_has_sse = 0;
-#endif
-
-void lanczos_init(void)
-{
- unsigned i;
- float dx = (float)(LANCZOS_WIDTH) / LANCZOS_SAMPLES, x = 0.0;
- for (i = 0; i < LANCZOS_SAMPLES + 1; ++i, x += dx)
- lanczos_lut[i] = fabs(x) < LANCZOS_WIDTH ? sinc(x) * sinc(x / LANCZOS_WIDTH) : 0.0;
-#ifdef LANCZOS_SSE
- lanczos_has_sse = query_cpu_feature_sse();
-#endif
-}
-
-typedef struct lanczos_resampler
-{
- int write_pos, write_filled;
- int read_pos, read_filled;
- unsigned short phase;
- unsigned int phase_inc;
- float buffer_in[lanczos_buffer_size * 2];
- int buffer_out[lanczos_buffer_size];
-} lanczos_resampler;
-
-void * lanczos_resampler_create(void)
-{
- lanczos_resampler * r = ( lanczos_resampler * ) malloc( sizeof(lanczos_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 lanczos_resampler_delete(void * _r)
-{
- free( _r );
-}
-
-void * lanczos_resampler_dup(const void * _r)
-{
- const lanczos_resampler * r_in = ( const lanczos_resampler * ) _r;
- lanczos_resampler * r_out = ( lanczos_resampler * ) malloc( sizeof(lanczos_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 lanczos_resampler_dup_inplace(void *_d, const void *_s)
-{
- const lanczos_resampler * r_in = ( const lanczos_resampler * ) _s;
- lanczos_resampler * r_out = ( lanczos_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 lanczos_resampler_get_free_count(void *_r)
-{
- lanczos_resampler * r = ( lanczos_resampler * ) _r;
- return lanczos_buffer_size - r->write_filled;
-}
-
-int lanczos_resampler_ready(void *_r)
-{
- lanczos_resampler * r = ( lanczos_resampler * ) _r;
- return r->write_filled > (LANCZOS_WIDTH * 2);
-}
-
-void lanczos_resampler_clear(void *_r)
-{
- lanczos_resampler * r = ( lanczos_resampler * ) _r;
- r->write_pos = 0;
- r->write_filled = 0;
- r->read_pos = 0;
- r->read_filled = 0;
- r->phase = 0;
-}
-
-void lanczos_resampler_set_rate(void *_r, double new_factor)
-{
- lanczos_resampler * r = ( lanczos_resampler * ) _r;
- r->phase_inc = (int)( new_factor * LANCZOS_RESOLUTION );
-}
-
-void lanczos_resampler_write_sample(void *_r, short s)
-{
- lanczos_resampler * r = ( lanczos_resampler * ) _r;
-
- if ( r->write_filled < lanczos_buffer_size )
- {
- float s32 = s;
-
- r->buffer_in[ r->write_pos ] = s32;
- r->buffer_in[ r->write_pos + lanczos_buffer_size ] = s32;
-
- ++r->write_filled;
-
- r->write_pos = ( r->write_pos + 1 ) % lanczos_buffer_size;
- }
-}
-
-static int lanczos_resampler_run(lanczos_resampler * r, int ** out_, int * out_end)
-{
- int in_size = r->write_filled;
- float const* in_ = r->buffer_in + lanczos_buffer_size + r->write_pos - r->write_filled;
- int used = 0;
- in_size -= LANCZOS_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 > LANCZOS_RESOLUTION ? LANCZOS_RESOLUTION * LANCZOS_RESOLUTION / phase_inc : LANCZOS_RESOLUTION;
-
- do
- {
- float kernel[LANCZOS_WIDTH * 2], kernel_sum = 0.0;
- int i = LANCZOS_WIDTH;
- int phase_adj = phase * step / LANCZOS_RESOLUTION;
- float sample;
-
- if ( out >= out_end )
- break;
-
- for (; i >= -LANCZOS_WIDTH + 1; --i)
- {
- int pos = i * step;
- kernel_sum += kernel[i + LANCZOS_WIDTH - 1] = lanczos_lut[abs(phase_adj - pos)];
- }
- for (sample = 0, i = 0; i < LANCZOS_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 LANCZOS_SSE
-static int lanczos_resampler_run_sse(lanczos_resampler * r, int ** out_, int * out_end)
-{
- int in_size = r->write_filled;
- float const* in_ = r->buffer_in + lanczos_buffer_size + r->write_pos - r->write_filled;
- int used = 0;
- in_size -= LANCZOS_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 > LANCZOS_RESOLUTION ? LANCZOS_RESOLUTION * LANCZOS_RESOLUTION / phase_inc : LANCZOS_RESOLUTION;
-
- do
- {
- float kernel_sum = 0.0;
- __m128 kernel[LANCZOS_WIDTH / 2];
- __m128 temp1, temp2;
- __m128 samplex = _mm_setzero_ps();
- float *kernelf = (float*)(&kernel);
- int i = LANCZOS_WIDTH;
- int phase_adj = phase * step / LANCZOS_RESOLUTION;
-
- if ( out >= out_end )
- break;
-
- for (; i >= -LANCZOS_WIDTH + 1; --i)
- {
- int pos = i * step;
- kernel_sum += kernelf[i + LANCZOS_WIDTH - 1] = lanczos_lut[abs(phase_adj - pos)];
- }
- for (i = 0; i < LANCZOS_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 lanczos_resampler_fill(lanczos_resampler * r)
-{
- while ( r->write_filled > (LANCZOS_WIDTH * 2) &&
- r->read_filled < lanczos_buffer_size )
- {
- int write_pos = ( r->read_pos + r->read_filled ) % lanczos_buffer_size;
- int write_size = lanczos_buffer_size - write_pos;
- int * out = r->buffer_out + write_pos;
- if ( write_size > ( lanczos_buffer_size - r->read_filled ) )
- write_size = lanczos_buffer_size - r->read_filled;
-#ifdef LANCZOS_SSE
- if ( lanczos_has_sse )
- lanczos_resampler_run_sse( r, &out, out + write_size );
- else
-#endif
- lanczos_resampler_run( r, &out, out + write_size );
- r->read_filled += out - r->buffer_out - write_pos;
- }
-}
-
-int lanczos_resampler_get_sample_count(void *_r)
-{
- lanczos_resampler * r = ( lanczos_resampler * ) _r;
- if ( r->read_filled < 1 )
- lanczos_resampler_fill( r );
- return r->read_filled;
-}
-
-int lanczos_resampler_get_sample(void *_r)
-{
- lanczos_resampler * r = ( lanczos_resampler * ) _r;
- if ( r->read_filled < 1 )
- lanczos_resampler_fill( r );
- if ( r->read_filled < 1 )
- return 0;
- return r->buffer_out[ r->read_pos ];
-}
-
-void lanczos_resampler_remove_sample(void *_r)
-{
- lanczos_resampler * r = ( lanczos_resampler * ) _r;
- if ( r->read_filled > 0 )
- {
- --r->read_filled;
- r->read_pos = ( r->read_pos + 1 ) % lanczos_buffer_size;
- }
-}
--- a/dumb/src/helpers/resamp3.inc
+++ b/dumb/src/helpers/resamp3.inc
@@ -198,13 +198,13 @@
/* FIR resampling, backwards */
SRCTYPE *x;
if ( resampler->fir_resampler_ratio != delta ) {
- lanczos_resampler_set_rate( resampler->fir_resampler[0], delta );
- lanczos_resampler_set_rate( resampler->fir_resampler[1], delta );
+ sinc_resampler_set_rate( resampler->fir_resampler[0], delta );
+ sinc_resampler_set_rate( resampler->fir_resampler[1], delta );
resampler->fir_resampler_ratio = delta;
}
x = &src[pos*SRC_CHANNELS];
while ( todo ) {
- while ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
+ while ( sinc_resampler_get_free_count( resampler->fir_resampler[0] ) &&
pos >= resampler->start )
{
POKE_FIR(0);
@@ -211,7 +211,7 @@
pos--;
x -= SRC_CHANNELS;
}
- if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
+ if ( !sinc_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
MIX_FIR;
ADVANCE_FIR;
--todo;
@@ -330,13 +330,13 @@
/* FIR resampling, forwards */
SRCTYPE *x;
if ( resampler->fir_resampler_ratio != delta ) {
- lanczos_resampler_set_rate( resampler->fir_resampler[0], delta );
- lanczos_resampler_set_rate( resampler->fir_resampler[1], delta );
+ sinc_resampler_set_rate( resampler->fir_resampler[0], delta );
+ sinc_resampler_set_rate( resampler->fir_resampler[1], delta );
resampler->fir_resampler_ratio = delta;
}
x = &src[pos*SRC_CHANNELS];
while ( todo ) {
- while ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
+ while ( sinc_resampler_get_free_count( resampler->fir_resampler[0] ) &&
pos < resampler->end )
{
POKE_FIR(0);
@@ -343,7 +343,7 @@
pos++;
x += SRC_CHANNELS;
}
- if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
+ if ( !sinc_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/lanczos_resampler.h"
+#include "internal/sinc_resampler.h"
@@ -171,7 +171,7 @@
cubicA1[t] = (int)(3*t*t*t >> 17) - (int)(5*t*t >> 7) + (int)(1 << 14);
}
- lanczos_init();
+ sinc_init();
done = 1;
}
--- a/dumb/src/helpers/resample.inc
+++ b/dumb/src/helpers/resample.inc
@@ -75,8 +75,8 @@
blip_clear(resampler->blip_buffer[0]);
blip_clear(resampler->blip_buffer[1]);
resampler->fir_resampler_ratio = 0;
- lanczos_resampler_clear(resampler->fir_resampler[0]);
- lanczos_resampler_clear(resampler->fir_resampler[1]);
+ sinc_resampler_clear(resampler->fir_resampler[0]);
+ sinc_resampler_clear(resampler->fir_resampler[1]);
}
@@ -158,15 +158,15 @@
resampler->last_clock += inv_dt; \
}
#define POKE_FIR(offset) { \
- lanczos_resampler_write_sample( resampler->fir_resampler[0], FIR(x[offset]) ); \
+ sinc_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( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), vol )
+#define MONO_DEST_PEEK_FIR *dst = MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), vol )
#define MONO_DEST_MIX_FIR { \
- *dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
+ *dst++ += MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
UPDATE_VOLUME( volume, vol ); \
}
-#define ADVANCE_FIR lanczos_resampler_remove_sample( resampler->fir_resampler[0] )
+#define ADVANCE_FIR sinc_resampler_remove_sample( resampler->fir_resampler[0] )
#define MONO_DEST_MIX_ALIAS(count) { \
int n = 0; \
resampler->last_clock -= count * 65536; \
@@ -184,12 +184,12 @@
*dst++ = MULSC( sample, rvol ); \
}
#define STEREO_DEST_PEEK_FIR { \
- int sample = lanczos_resampler_get_sample( resampler->fir_resampler[0] ); \
+ int sample = sinc_resampler_get_sample( resampler->fir_resampler[0] ); \
*dst++ = MULSC( sample, lvol ); \
*dst++ = MULSC( sample, rvol ); \
}
#define STEREO_DEST_MIX_FIR { \
- int sample = lanczos_resampler_get_sample( resampler->fir_resampler[0] ); \
+ int sample = sinc_resampler_get_sample( resampler->fir_resampler[0] ); \
*dst++ += MULSC( sample, lvol ); \
*dst++ += MULSC( sample, rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \
@@ -296,8 +296,8 @@
resampler->last_clock += inv_dt; \
}
#define POKE_FIR(offset) { \
- lanczos_resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \
- lanczos_resampler_write_sample( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \
+ 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]) ); \
}
#define MONO_DEST_PEEK_ALIAS { \
*dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ) + \
@@ -304,18 +304,18 @@
MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
}
#define MONO_DEST_PEEK_FIR { \
- *dst = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
- MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst = MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
+ MULSC( sinc_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
}
#define MONO_DEST_MIX_FIR { \
- *dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
- MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst++ += MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
+ MULSC( sinc_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \
UPDATE_VOLUME( volume_right, rvol ); \
}
#define ADVANCE_FIR { \
- lanczos_resampler_remove_sample( resampler->fir_resampler[0] ); \
- lanczos_resampler_remove_sample( resampler->fir_resampler[1] ); \
+ sinc_resampler_remove_sample( resampler->fir_resampler[0] ); \
+ sinc_resampler_remove_sample( resampler->fir_resampler[1] ); \
}
#define MONO_DEST_MIX_ALIAS(count) { \
int n = 0; \
@@ -336,12 +336,12 @@
*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
}
#define STEREO_DEST_PEEK_FIR { \
- *dst++ = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
- *dst++ = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst++ = MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
+ *dst++ = MULSC( sinc_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
}
#define STEREO_DEST_MIX_FIR { \
- *dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
- *dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst++ += MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
+ *dst++ += MULSC( sinc_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \
UPDATE_VOLUME( volume_right, rvol ); \
}
--- /dev/null
+++ b/dumb/src/helpers/sinc_resampler.c
@@ -1,0 +1,361 @@
+#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/lanczos_resampler.h"
+#include "internal/sinc_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] = lanczos_resampler_create();
+ r->resampler.fir_resampler[0] = sinc_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] = lanczos_resampler_create();
+ r->resampler.fir_resampler[1] = sinc_resampler_create();
if ( !r->resampler.fir_resampler[1] ) {
- lanczos_resampler_delete( r->resampler.fir_resampler[0] );
+ sinc_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)
{
- lanczos_resampler_delete( r->resampler.fir_resampler[1] );
- lanczos_resampler_delete( r->resampler.fir_resampler[0] );
+ sinc_resampler_delete( r->resampler.fir_resampler[1] );
+ sinc_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] = lanczos_resampler_dup( src->resampler.fir_resampler[0] );
+ dst->resampler.fir_resampler[0] = sinc_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] = lanczos_resampler_dup( src->resampler.fir_resampler[1] );
+ dst->resampler.fir_resampler[1] = sinc_resampler_dup( src->resampler.fir_resampler[1] );
if ( !dst->resampler.fir_resampler[1] ) {
- lanczos_resampler_delete( dst->resampler.fir_resampler[0] );
+ sinc_resampler_delete( dst->resampler.fir_resampler[0] );
blip_delete( dst->resampler.blip_buffer[1] );
blip_delete( dst->resampler.blip_buffer[0] );
free( dst );
--- 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\lanczos_resampler.c" />
+ <ClCompile Include="..\..\src\helpers\sinc_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\lanczos_resampler.h" />
+ <ClInclude Include="..\..\include\internal\sinc_resampler.h" />
<ClInclude Include="..\..\include\internal\lpc.h" />
<ClInclude Include="..\..\include\internal\riff.h" />
<ClInclude Include="..\..\include\internal\stack_alloc.h" />
@@ -218,4 +218,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
\ No newline at end of file
+</Project>
--- 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\lanczos_resampler.c">
+ <ClCompile Include="..\..\src\helpers\sinc_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\lanczos_resampler.h">
+ <ClInclude Include="..\..\include\internal\sinc_resampler.h">
<Filter>include\internal</Filter>
</ClInclude>
<ClInclude Include="..\..\include\internal\tarray.h">
@@ -338,4 +338,4 @@
<Filter>src\helpers</Filter>
</CustomBuild>
</ItemGroup>
-</Project>
\ No newline at end of file
+</Project>