Renamed Lanczos resampler to sinc resampler, changed window type to Blackman

CQTexperiment
Chris Moeller 2014-03-22 19:16:42 -07:00
parent f90ef2bf0c
commit 93b427ae4e
16 changed files with 425 additions and 413 deletions

View File

@ -56,7 +56,7 @@
8370B62C17F60FE2001A4D7A /* stack_alloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B62417F60FE2001A4D7A /* stack_alloc.h */; }; 8370B62C17F60FE2001A4D7A /* stack_alloc.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B62417F60FE2001A4D7A /* stack_alloc.h */; };
8370B62D17F60FE2001A4D7A /* tarray.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B62517F60FE2001A4D7A /* tarray.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8370B62D17F60FE2001A4D7A /* tarray.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B62517F60FE2001A4D7A /* tarray.h */; settings = {ATTRIBUTES = (Public, ); }; };
8370B63417F61001001A4D7A /* barray.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B62E17F61001001A4D7A /* barray.c */; }; 8370B63417F61001001A4D7A /* barray.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B62E17F61001001A4D7A /* barray.c */; };
8370B63617F61001001A4D7A /* lanczos_resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63017F61001001A4D7A /* lanczos_resampler.c */; }; 8370B63617F61001001A4D7A /* sinc_resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63017F61001001A4D7A /* sinc_resampler.c */; };
8370B63717F61001001A4D7A /* lpc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63117F61001001A4D7A /* lpc.c */; }; 8370B63717F61001001A4D7A /* lpc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63117F61001001A4D7A /* lpc.c */; };
8370B63817F61001001A4D7A /* riff.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63217F61001001A4D7A /* riff.c */; }; 8370B63817F61001001A4D7A /* riff.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63217F61001001A4D7A /* riff.c */; };
8370B63917F61001001A4D7A /* tarray.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63317F61001001A4D7A /* tarray.c */; }; 8370B63917F61001001A4D7A /* tarray.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B63317F61001001A4D7A /* tarray.c */; };
@ -101,7 +101,7 @@
8370B68917F61038001A4D7A /* readriff.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B66017F61038001A4D7A /* readriff.c */; }; 8370B68917F61038001A4D7A /* readriff.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B66017F61038001A4D7A /* readriff.c */; };
8370B68A17F61038001A4D7A /* readstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B66117F61038001A4D7A /* readstm.c */; }; 8370B68A17F61038001A4D7A /* readstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B66117F61038001A4D7A /* readstm.c */; };
8370B68B17F61038001A4D7A /* readstm2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B66217F61038001A4D7A /* readstm2.c */; }; 8370B68B17F61038001A4D7A /* readstm2.c in Sources */ = {isa = PBXBuildFile; fileRef = 8370B66217F61038001A4D7A /* readstm2.c */; };
8370B7EA17F62A40001A4D7A /* lanczos_resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B7E817F62A40001A4D7A /* lanczos_resampler.h */; }; 8370B7EA17F62A40001A4D7A /* sinc_resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B7E817F62A40001A4D7A /* sinc_resampler.h */; };
83C8DF1D18C6B31400750AF7 /* blip_buf.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8DF1C18C6B31400750AF7 /* blip_buf.c */; }; 83C8DF1D18C6B31400750AF7 /* blip_buf.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C8DF1C18C6B31400750AF7 /* blip_buf.c */; };
83C8DF1F18C6B32100750AF7 /* blip_buf.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8DF1E18C6B32100750AF7 /* blip_buf.h */; }; 83C8DF1F18C6B32100750AF7 /* blip_buf.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C8DF1E18C6B32100750AF7 /* blip_buf.h */; };
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; }; 8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
@ -165,7 +165,7 @@
8370B62417F60FE2001A4D7A /* stack_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_alloc.h; sourceTree = "<group>"; }; 8370B62417F60FE2001A4D7A /* stack_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stack_alloc.h; sourceTree = "<group>"; };
8370B62517F60FE2001A4D7A /* tarray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tarray.h; sourceTree = "<group>"; }; 8370B62517F60FE2001A4D7A /* tarray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tarray.h; sourceTree = "<group>"; };
8370B62E17F61001001A4D7A /* barray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = barray.c; sourceTree = "<group>"; }; 8370B62E17F61001001A4D7A /* barray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = barray.c; sourceTree = "<group>"; };
8370B63017F61001001A4D7A /* lanczos_resampler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lanczos_resampler.c; sourceTree = "<group>"; }; 8370B63017F61001001A4D7A /* sinc_resampler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sinc_resampler.c; sourceTree = "<group>"; };
8370B63117F61001001A4D7A /* lpc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpc.c; sourceTree = "<group>"; }; 8370B63117F61001001A4D7A /* lpc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpc.c; sourceTree = "<group>"; };
8370B63217F61001001A4D7A /* riff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = riff.c; sourceTree = "<group>"; }; 8370B63217F61001001A4D7A /* riff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = riff.c; sourceTree = "<group>"; };
8370B63317F61001001A4D7A /* tarray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tarray.c; sourceTree = "<group>"; }; 8370B63317F61001001A4D7A /* tarray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tarray.c; sourceTree = "<group>"; };
@ -210,7 +210,7 @@
8370B66017F61038001A4D7A /* readriff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readriff.c; sourceTree = "<group>"; }; 8370B66017F61038001A4D7A /* readriff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readriff.c; sourceTree = "<group>"; };
8370B66117F61038001A4D7A /* readstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readstm.c; sourceTree = "<group>"; }; 8370B66117F61038001A4D7A /* readstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readstm.c; sourceTree = "<group>"; };
8370B66217F61038001A4D7A /* readstm2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readstm2.c; sourceTree = "<group>"; }; 8370B66217F61038001A4D7A /* readstm2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = readstm2.c; sourceTree = "<group>"; };
8370B7E817F62A40001A4D7A /* lanczos_resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lanczos_resampler.h; sourceTree = "<group>"; }; 8370B7E817F62A40001A4D7A /* sinc_resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sinc_resampler.h; sourceTree = "<group>"; };
83C8DF1C18C6B31400750AF7 /* blip_buf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blip_buf.c; sourceTree = "<group>"; }; 83C8DF1C18C6B31400750AF7 /* blip_buf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blip_buf.c; sourceTree = "<group>"; };
83C8DF1E18C6B32100750AF7 /* blip_buf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blip_buf.h; sourceTree = "<group>"; }; 83C8DF1E18C6B32100750AF7 /* blip_buf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blip_buf.h; sourceTree = "<group>"; };
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; }; 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
@ -308,7 +308,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
83C8DF1E18C6B32100750AF7 /* blip_buf.h */, 83C8DF1E18C6B32100750AF7 /* blip_buf.h */,
8370B7E817F62A40001A4D7A /* lanczos_resampler.h */, 8370B7E817F62A40001A4D7A /* sinc_resampler.h */,
8370B61E17F60FE2001A4D7A /* barray.h */, 8370B61E17F60FE2001A4D7A /* barray.h */,
8370B62017F60FE2001A4D7A /* dumbfile.h */, 8370B62017F60FE2001A4D7A /* dumbfile.h */,
8370B62217F60FE2001A4D7A /* lpc.h */, 8370B62217F60FE2001A4D7A /* lpc.h */,
@ -356,7 +356,7 @@
children = ( children = (
83C8DF1C18C6B31400750AF7 /* blip_buf.c */, 83C8DF1C18C6B31400750AF7 /* blip_buf.c */,
8370B62E17F61001001A4D7A /* barray.c */, 8370B62E17F61001001A4D7A /* barray.c */,
8370B63017F61001001A4D7A /* lanczos_resampler.c */, 8370B63017F61001001A4D7A /* sinc_resampler.c */,
8370B63117F61001001A4D7A /* lpc.c */, 8370B63117F61001001A4D7A /* lpc.c */,
8370B63217F61001001A4D7A /* riff.c */, 8370B63217F61001001A4D7A /* riff.c */,
8370B63317F61001001A4D7A /* tarray.c */, 8370B63317F61001001A4D7A /* tarray.c */,
@ -454,7 +454,7 @@
8370B62617F60FE2001A4D7A /* barray.h in Headers */, 8370B62617F60FE2001A4D7A /* barray.h in Headers */,
17C8F63E0CBEE797008D969D /* dumb.h in Headers */, 17C8F63E0CBEE797008D969D /* dumb.h in Headers */,
17C8F6400CBEE797008D969D /* it.h in Headers */, 17C8F6400CBEE797008D969D /* it.h in Headers */,
8370B7EA17F62A40001A4D7A /* lanczos_resampler.h in Headers */, 8370B7EA17F62A40001A4D7A /* sinc_resampler.h in Headers */,
17C8F63F0CBEE797008D969D /* dumb.h in Headers */, 17C8F63F0CBEE797008D969D /* dumb.h in Headers */,
8370B62B17F60FE2001A4D7A /* riff.h in Headers */, 8370B62B17F60FE2001A4D7A /* riff.h in Headers */,
8370B62A17F60FE2001A4D7A /* lpc.h in Headers */, 8370B62A17F60FE2001A4D7A /* lpc.h in Headers */,
@ -567,7 +567,7 @@
8370B66417F61038001A4D7A /* load6692.c in Sources */, 8370B66417F61038001A4D7A /* load6692.c in Sources */,
17C8F6560CBEE797008D969D /* itload.c in Sources */, 17C8F6560CBEE797008D969D /* itload.c in Sources */,
17C8F6570CBEE797008D969D /* itload2.c in Sources */, 17C8F6570CBEE797008D969D /* itload2.c in Sources */,
8370B63617F61001001A4D7A /* lanczos_resampler.c in Sources */, 8370B63617F61001001A4D7A /* sinc_resampler.c in Sources */,
17C8F6580CBEE797008D969D /* itmisc.c in Sources */, 17C8F6580CBEE797008D969D /* itmisc.c in Sources */,
8370B67517F61038001A4D7A /* loadriff.c in Sources */, 8370B67517F61038001A4D7A /* loadriff.c in Sources */,
8370B66917F61038001A4D7A /* loadasy.c in Sources */, 8370B66917F61038001A4D7A /* loadasy.c in Sources */,

View File

@ -1,39 +0,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

View File

@ -0,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

View File

@ -198,20 +198,20 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
/* FIR resampling, backwards */ /* FIR resampling, backwards */
SRCTYPE *x; SRCTYPE *x;
if ( resampler->fir_resampler_ratio != delta ) { if ( resampler->fir_resampler_ratio != delta ) {
lanczos_resampler_set_rate( resampler->fir_resampler[0], delta ); sinc_resampler_set_rate( resampler->fir_resampler[0], delta );
lanczos_resampler_set_rate( resampler->fir_resampler[1], delta ); sinc_resampler_set_rate( resampler->fir_resampler[1], delta );
resampler->fir_resampler_ratio = delta; resampler->fir_resampler_ratio = delta;
} }
x = &src[pos*SRC_CHANNELS]; x = &src[pos*SRC_CHANNELS];
while ( todo ) { 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 ) pos >= resampler->start )
{ {
POKE_FIR(0); POKE_FIR(0);
pos--; pos--;
x -= SRC_CHANNELS; 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; MIX_FIR;
ADVANCE_FIR; ADVANCE_FIR;
--todo; --todo;
@ -330,20 +330,20 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
/* FIR resampling, forwards */ /* FIR resampling, forwards */
SRCTYPE *x; SRCTYPE *x;
if ( resampler->fir_resampler_ratio != delta ) { if ( resampler->fir_resampler_ratio != delta ) {
lanczos_resampler_set_rate( resampler->fir_resampler[0], delta ); sinc_resampler_set_rate( resampler->fir_resampler[0], delta );
lanczos_resampler_set_rate( resampler->fir_resampler[1], delta ); sinc_resampler_set_rate( resampler->fir_resampler[1], delta );
resampler->fir_resampler_ratio = delta; resampler->fir_resampler_ratio = delta;
} }
x = &src[pos*SRC_CHANNELS]; x = &src[pos*SRC_CHANNELS];
while ( todo ) { 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 ) pos < resampler->end )
{ {
POKE_FIR(0); POKE_FIR(0);
pos++; pos++;
x += SRC_CHANNELS; 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; MIX_FIR;
ADVANCE_FIR; ADVANCE_FIR;
--todo; --todo;

View File

@ -46,7 +46,7 @@
#include "dumb.h" #include "dumb.h"
#include "internal/blip_buf.h" #include "internal/blip_buf.h"
#include "internal/lanczos_resampler.h" #include "internal/sinc_resampler.h"
@ -171,7 +171,7 @@ void _dumb_init_cubic(void)
cubicA1[t] = (int)(3*t*t*t >> 17) - (int)(5*t*t >> 7) + (int)(1 << 14); cubicA1[t] = (int)(3*t*t*t >> 17) - (int)(5*t*t >> 7) + (int)(1 << 14);
} }
lanczos_init(); sinc_init();
done = 1; done = 1;
} }

View File

@ -75,8 +75,8 @@ void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src, int src_chann
blip_clear(resampler->blip_buffer[0]); blip_clear(resampler->blip_buffer[0]);
blip_clear(resampler->blip_buffer[1]); blip_clear(resampler->blip_buffer[1]);
resampler->fir_resampler_ratio = 0; resampler->fir_resampler_ratio = 0;
lanczos_resampler_clear(resampler->fir_resampler[0]); sinc_resampler_clear(resampler->fir_resampler[0]);
lanczos_resampler_clear(resampler->fir_resampler[1]); sinc_resampler_clear(resampler->fir_resampler[1]);
} }
@ -158,15 +158,15 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
resampler->last_clock += inv_dt; \ resampler->last_clock += inv_dt; \
} }
#define POKE_FIR(offset) { \ #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_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 { \ #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 ); \ 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) { \ #define MONO_DEST_MIX_ALIAS(count) { \
int n = 0; \ int n = 0; \
resampler->last_clock -= count * 65536; \ resampler->last_clock -= count * 65536; \
@ -184,12 +184,12 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
*dst++ = MULSC( sample, rvol ); \ *dst++ = MULSC( sample, rvol ); \
} }
#define STEREO_DEST_PEEK_FIR { \ #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, lvol ); \
*dst++ = MULSC( sample, rvol ); \ *dst++ = MULSC( sample, rvol ); \
} }
#define STEREO_DEST_MIX_FIR { \ #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, lvol ); \
*dst++ += MULSC( sample, rvol ); \ *dst++ += MULSC( sample, rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \ UPDATE_VOLUME( volume_left, lvol ); \
@ -296,26 +296,26 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
resampler->last_clock += inv_dt; \ resampler->last_clock += inv_dt; \
} }
#define POKE_FIR(offset) { \ #define POKE_FIR(offset) { \
lanczos_resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \ sinc_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[1], FIR(x[(offset)*2+1]) ); \
} }
#define MONO_DEST_PEEK_ALIAS { \ #define MONO_DEST_PEEK_ALIAS { \
*dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ) + \ *dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ) + \
MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \ MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
} }
#define MONO_DEST_PEEK_FIR { \ #define MONO_DEST_PEEK_FIR { \
*dst = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \ *dst = MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \ MULSC( sinc_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
} }
#define MONO_DEST_MIX_FIR { \ #define MONO_DEST_MIX_FIR { \
*dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \ *dst++ += MULSC( sinc_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \ MULSC( sinc_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \ UPDATE_VOLUME( volume_left, lvol ); \
UPDATE_VOLUME( volume_right, rvol ); \ UPDATE_VOLUME( volume_right, rvol ); \
} }
#define ADVANCE_FIR { \ #define ADVANCE_FIR { \
lanczos_resampler_remove_sample( resampler->fir_resampler[0] ); \ sinc_resampler_remove_sample( resampler->fir_resampler[0] ); \
lanczos_resampler_remove_sample( resampler->fir_resampler[1] ); \ sinc_resampler_remove_sample( resampler->fir_resampler[1] ); \
} }
#define MONO_DEST_MIX_ALIAS(count) { \ #define MONO_DEST_MIX_ALIAS(count) { \
int n = 0; \ int n = 0; \
@ -336,12 +336,12 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \ *dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
} }
#define STEREO_DEST_PEEK_FIR { \ #define STEREO_DEST_PEEK_FIR { \
*dst++ = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \ *dst++ = MULSC( sinc_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[1] ), rvol ); \
} }
#define STEREO_DEST_MIX_FIR { \ #define STEREO_DEST_MIX_FIR { \
*dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \ *dst++ += MULSC( sinc_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[1] ), rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \ UPDATE_VOLUME( volume_left, lvol ); \
UPDATE_VOLUME( volume_right, rvol ); \ UPDATE_VOLUME( volume_right, rvol ); \
} }

View File

@ -4,22 +4,22 @@
#include <math.h> #include <math.h>
#if (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__)) #if (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__))
#include <xmmintrin.h> #include <xmmintrin.h>
#define LANCZOS_SSE #define SINC_SSE
#endif #endif
#ifndef M_PI #ifndef M_PI
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
#endif #endif
#include "internal/lanczos_resampler.h" #include "internal/sinc_resampler.h"
enum { LANCZOS_RESOLUTION = 8192 }; enum { SINC_RESOLUTION = 8192 };
enum { LANCZOS_WIDTH = 16 }; enum { SINC_WIDTH = 16 };
enum { LANCZOS_SAMPLES = LANCZOS_RESOLUTION * LANCZOS_WIDTH }; enum { SINC_SAMPLES = SINC_RESOLUTION * SINC_WIDTH };
static float lanczos_lut[LANCZOS_SAMPLES + 1]; static float sinc_lut[SINC_SAMPLES + 1];
enum { lanczos_buffer_size = LANCZOS_WIDTH * 4 }; enum { sinc_buffer_size = SINC_WIDTH * 4 };
static int fEqual(const float b, const float a) static int fEqual(const float b, const float a)
{ {
@ -31,7 +31,7 @@ static float sinc(float x)
return fEqual(x, 0.0) ? 1.0 : sin(x * M_PI) / (x * M_PI); return fEqual(x, 0.0) ? 1.0 : sin(x * M_PI) / (x * M_PI);
} }
#ifdef LANCZOS_SSE #ifdef SINC_SSE
#ifdef _MSC_VER #ifdef _MSC_VER
#include <intrin.h> #include <intrin.h>
#elif defined(__clang__) || defined(__GNUC__) #elif defined(__clang__) || defined(__GNUC__)
@ -56,33 +56,37 @@ static int query_cpu_feature_sse() {
return 1; return 1;
} }
static int lanczos_has_sse = 0; static int sinc_has_sse = 0;
#endif #endif
void lanczos_init(void) void sinc_init(void)
{ {
unsigned i; unsigned i;
float dx = (float)(LANCZOS_WIDTH) / LANCZOS_SAMPLES, x = 0.0; float dx = (float)(SINC_WIDTH) / SINC_SAMPLES, x = 0.0;
for (i = 0; i < LANCZOS_SAMPLES + 1; ++i, x += dx) for (i = 0; i < SINC_SAMPLES + 1; ++i, x += dx)
lanczos_lut[i] = fabs(x) < LANCZOS_WIDTH ? sinc(x) * sinc(x / LANCZOS_WIDTH) : 0.0; {
#ifdef LANCZOS_SSE float y = x / SINC_WIDTH;
lanczos_has_sse = query_cpu_feature_sse(); 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 #endif
} }
typedef struct lanczos_resampler typedef struct sinc_resampler
{ {
int write_pos, write_filled; int write_pos, write_filled;
int read_pos, read_filled; int read_pos, read_filled;
unsigned short phase; unsigned short phase;
unsigned int phase_inc; unsigned int phase_inc;
float buffer_in[lanczos_buffer_size * 2]; float buffer_in[sinc_buffer_size * 2];
int buffer_out[lanczos_buffer_size]; int buffer_out[sinc_buffer_size];
} lanczos_resampler; } sinc_resampler;
void * lanczos_resampler_create(void) void * sinc_resampler_create(void)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) malloc( sizeof(lanczos_resampler) ); sinc_resampler * r = ( sinc_resampler * ) malloc( sizeof(sinc_resampler) );
if ( !r ) return 0; if ( !r ) return 0;
r->write_pos = 0; r->write_pos = 0;
@ -97,15 +101,15 @@ void * lanczos_resampler_create(void)
return r; return r;
} }
void lanczos_resampler_delete(void * _r) void sinc_resampler_delete(void * _r)
{ {
free( _r ); free( _r );
} }
void * lanczos_resampler_dup(const void * _r) void * sinc_resampler_dup(const void * _r)
{ {
const lanczos_resampler * r_in = ( const lanczos_resampler * ) _r; const sinc_resampler * r_in = ( const sinc_resampler * ) _r;
lanczos_resampler * r_out = ( lanczos_resampler * ) malloc( sizeof(lanczos_resampler) ); sinc_resampler * r_out = ( sinc_resampler * ) malloc( sizeof(sinc_resampler) );
if ( !r_out ) return 0; if ( !r_out ) return 0;
r_out->write_pos = r_in->write_pos; r_out->write_pos = r_in->write_pos;
@ -120,10 +124,10 @@ void * lanczos_resampler_dup(const void * _r)
return r_out; return r_out;
} }
void lanczos_resampler_dup_inplace(void *_d, const void *_s) void sinc_resampler_dup_inplace(void *_d, const void *_s)
{ {
const lanczos_resampler * r_in = ( const lanczos_resampler * ) _s; const sinc_resampler * r_in = ( const sinc_resampler * ) _s;
lanczos_resampler * r_out = ( lanczos_resampler * ) _d; sinc_resampler * r_out = ( sinc_resampler * ) _d;
r_out->write_pos = r_in->write_pos; r_out->write_pos = r_in->write_pos;
r_out->write_filled = r_in->write_filled; r_out->write_filled = r_in->write_filled;
@ -135,21 +139,21 @@ void lanczos_resampler_dup_inplace(void *_d, const void *_s)
memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) ); memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) );
} }
int lanczos_resampler_get_free_count(void *_r) int sinc_resampler_get_free_count(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
return lanczos_buffer_size - r->write_filled; return sinc_buffer_size - r->write_filled;
} }
int lanczos_resampler_ready(void *_r) int sinc_resampler_ready(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
return r->write_filled > (LANCZOS_WIDTH * 2); return r->write_filled > (SINC_WIDTH * 2);
} }
void lanczos_resampler_clear(void *_r) void sinc_resampler_clear(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
r->write_pos = 0; r->write_pos = 0;
r->write_filled = 0; r->write_filled = 0;
r->read_pos = 0; r->read_pos = 0;
@ -157,35 +161,35 @@ void lanczos_resampler_clear(void *_r)
r->phase = 0; r->phase = 0;
} }
void lanczos_resampler_set_rate(void *_r, double new_factor) void sinc_resampler_set_rate(void *_r, double new_factor)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
r->phase_inc = (int)( new_factor * LANCZOS_RESOLUTION ); r->phase_inc = (int)( new_factor * SINC_RESOLUTION );
} }
void lanczos_resampler_write_sample(void *_r, short s) void sinc_resampler_write_sample(void *_r, short s)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
if ( r->write_filled < lanczos_buffer_size ) if ( r->write_filled < sinc_buffer_size )
{ {
float s32 = s; float s32 = s;
r->buffer_in[ r->write_pos ] = s32; r->buffer_in[ r->write_pos ] = s32;
r->buffer_in[ r->write_pos + lanczos_buffer_size ] = s32; r->buffer_in[ r->write_pos + sinc_buffer_size ] = s32;
++r->write_filled; ++r->write_filled;
r->write_pos = ( r->write_pos + 1 ) % lanczos_buffer_size; r->write_pos = ( r->write_pos + 1 ) % sinc_buffer_size;
} }
} }
static int lanczos_resampler_run(lanczos_resampler * r, int ** out_, int * out_end) static int sinc_resampler_run(sinc_resampler * r, int ** out_, int * out_end)
{ {
int in_size = r->write_filled; int in_size = r->write_filled;
float const* in_ = r->buffer_in + lanczos_buffer_size + r->write_pos - r->write_filled; float const* in_ = r->buffer_in + sinc_buffer_size + r->write_pos - r->write_filled;
int used = 0; int used = 0;
in_size -= LANCZOS_WIDTH * 2; in_size -= SINC_WIDTH * 2;
if ( in_size > 0 ) if ( in_size > 0 )
{ {
int* out = *out_; int* out = *out_;
@ -194,24 +198,25 @@ static int lanczos_resampler_run(lanczos_resampler * r, int ** out_, int * out_e
int phase = r->phase; int phase = r->phase;
int phase_inc = r->phase_inc; int phase_inc = r->phase_inc;
int step = phase_inc > LANCZOS_RESOLUTION ? LANCZOS_RESOLUTION * LANCZOS_RESOLUTION / phase_inc : LANCZOS_RESOLUTION; int step = phase_inc > SINC_RESOLUTION ? SINC_RESOLUTION * SINC_RESOLUTION / phase_inc : SINC_RESOLUTION;
do do
{ {
float kernel[LANCZOS_WIDTH * 2], kernel_sum = 0.0; // accumulate in extended precision
int i = LANCZOS_WIDTH; float kernel[SINC_WIDTH * 2], kernel_sum = 0.0;
int phase_adj = phase * step / LANCZOS_RESOLUTION; int i = SINC_WIDTH;
int phase_adj = phase * step / SINC_RESOLUTION;
float sample; float sample;
if ( out >= out_end ) if ( out >= out_end )
break; break;
for (; i >= -LANCZOS_WIDTH + 1; --i) for (; i >= -SINC_WIDTH + 1; --i)
{ {
int pos = i * step; int pos = i * step;
kernel_sum += kernel[i + LANCZOS_WIDTH - 1] = lanczos_lut[abs(phase_adj - pos)]; kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)];
} }
for (sample = 0, i = 0; i < LANCZOS_WIDTH * 2; ++i) for (sample = 0, i = 0; i < SINC_WIDTH * 2; ++i)
sample += in[i] * kernel[i]; sample += in[i] * kernel[i];
*out++ = (int)(sample / kernel_sum * 256.0); *out++ = (int)(sample / kernel_sum * 256.0);
@ -234,13 +239,13 @@ static int lanczos_resampler_run(lanczos_resampler * r, int ** out_, int * out_e
return used; return used;
} }
#ifdef LANCZOS_SSE #ifdef SINC_SSE
static int lanczos_resampler_run_sse(lanczos_resampler * r, int ** out_, int * out_end) static int sinc_resampler_run_sse(sinc_resampler * r, int ** out_, int * out_end)
{ {
int in_size = r->write_filled; int in_size = r->write_filled;
float const* in_ = r->buffer_in + lanczos_buffer_size + r->write_pos - r->write_filled; float const* in_ = r->buffer_in + sinc_buffer_size + r->write_pos - r->write_filled;
int used = 0; int used = 0;
in_size -= LANCZOS_WIDTH * 2; in_size -= SINC_WIDTH * 2;
if ( in_size > 0 ) if ( in_size > 0 )
{ {
int* out = *out_; int* out = *out_;
@ -249,27 +254,28 @@ static int lanczos_resampler_run_sse(lanczos_resampler * r, int ** out_, int * o
int phase = r->phase; int phase = r->phase;
int phase_inc = r->phase_inc; int phase_inc = r->phase_inc;
int step = phase_inc > LANCZOS_RESOLUTION ? LANCZOS_RESOLUTION * LANCZOS_RESOLUTION / phase_inc : LANCZOS_RESOLUTION; int step = phase_inc > SINC_RESOLUTION ? SINC_RESOLUTION * SINC_RESOLUTION / phase_inc : SINC_RESOLUTION;
do do
{ {
// accumulate in extended precision
float kernel_sum = 0.0; float kernel_sum = 0.0;
__m128 kernel[LANCZOS_WIDTH / 2]; __m128 kernel[SINC_WIDTH / 2];
__m128 temp1, temp2; __m128 temp1, temp2;
__m128 samplex = _mm_setzero_ps(); __m128 samplex = _mm_setzero_ps();
float *kernelf = (float*)(&kernel); float *kernelf = (float*)(&kernel);
int i = LANCZOS_WIDTH; int i = SINC_WIDTH;
int phase_adj = phase * step / LANCZOS_RESOLUTION; int phase_adj = phase * step / SINC_RESOLUTION;
if ( out >= out_end ) if ( out >= out_end )
break; break;
for (; i >= -LANCZOS_WIDTH + 1; --i) for (; i >= -SINC_WIDTH + 1; --i)
{ {
int pos = i * step; int pos = i * step;
kernel_sum += kernelf[i + LANCZOS_WIDTH - 1] = lanczos_lut[abs(phase_adj - pos)]; kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)];
} }
for (i = 0; i < LANCZOS_WIDTH / 2; ++i) for (i = 0; i < SINC_WIDTH / 2; ++i)
{ {
temp1 = _mm_loadu_ps( (const float *)( in + i * 4 ) ); temp1 = _mm_loadu_ps( (const float *)( in + i * 4 ) );
temp2 = _mm_load_ps( (const float *)( kernel + i ) ); temp2 = _mm_load_ps( (const float *)( kernel + i ) );
@ -306,50 +312,50 @@ static int lanczos_resampler_run_sse(lanczos_resampler * r, int ** out_, int * o
} }
#endif #endif
static void lanczos_resampler_fill(lanczos_resampler * r) static void sinc_resampler_fill(sinc_resampler * r)
{ {
while ( r->write_filled > (LANCZOS_WIDTH * 2) && while ( r->write_filled > (SINC_WIDTH * 2) &&
r->read_filled < lanczos_buffer_size ) r->read_filled < sinc_buffer_size )
{ {
int write_pos = ( r->read_pos + r->read_filled ) % lanczos_buffer_size; int write_pos = ( r->read_pos + r->read_filled ) % sinc_buffer_size;
int write_size = lanczos_buffer_size - write_pos; int write_size = sinc_buffer_size - write_pos;
int * out = r->buffer_out + write_pos; int * out = r->buffer_out + write_pos;
if ( write_size > ( lanczos_buffer_size - r->read_filled ) ) if ( write_size > ( sinc_buffer_size - r->read_filled ) )
write_size = lanczos_buffer_size - r->read_filled; write_size = sinc_buffer_size - r->read_filled;
#ifdef LANCZOS_SSE #ifdef SINC_SSE
if ( lanczos_has_sse ) if ( sinc_has_sse )
lanczos_resampler_run_sse( r, &out, out + write_size ); sinc_resampler_run_sse( r, &out, out + write_size );
else else
#endif #endif
lanczos_resampler_run( r, &out, out + write_size ); sinc_resampler_run( r, &out, out + write_size );
r->read_filled += out - r->buffer_out - write_pos; r->read_filled += out - r->buffer_out - write_pos;
} }
} }
int lanczos_resampler_get_sample_count(void *_r) int sinc_resampler_get_sample_count(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
if ( r->read_filled < 1 ) if ( r->read_filled < 1 )
lanczos_resampler_fill( r ); sinc_resampler_fill( r );
return r->read_filled; return r->read_filled;
} }
int lanczos_resampler_get_sample(void *_r) int sinc_resampler_get_sample(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
if ( r->read_filled < 1 ) if ( r->read_filled < 1 )
lanczos_resampler_fill( r ); sinc_resampler_fill( r );
if ( r->read_filled < 1 ) if ( r->read_filled < 1 )
return 0; return 0;
return r->buffer_out[ r->read_pos ]; return r->buffer_out[ r->read_pos ];
} }
void lanczos_resampler_remove_sample(void *_r) void sinc_resampler_remove_sample(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
if ( r->read_filled > 0 ) if ( r->read_filled > 0 )
{ {
--r->read_filled; --r->read_filled;
r->read_pos = ( r->read_pos + 1 ) % lanczos_buffer_size; r->read_pos = ( r->read_pos + 1 ) % sinc_buffer_size;
} }
} }

View File

@ -27,7 +27,7 @@
#include "internal/lpc.h" #include "internal/lpc.h"
#include "internal/blip_buf.h" #include "internal/blip_buf.h"
#include "internal/lanczos_resampler.h" #include "internal/sinc_resampler.h"
// #define BIT_ARRAY_BULLSHIT // #define BIT_ARRAY_BULLSHIT
@ -52,16 +52,16 @@ static IT_PLAYING *new_playing()
blip_set_rates(r->resampler.blip_buffer[0], 65536, 1); blip_set_rates(r->resampler.blip_buffer[0], 65536, 1);
blip_set_rates(r->resampler.blip_buffer[1], 65536, 1); blip_set_rates(r->resampler.blip_buffer[1], 65536, 1);
r->resampler.fir_resampler_ratio = 0.0; 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] ) { if ( !r->resampler.fir_resampler[0] ) {
free( r->resampler.blip_buffer[1] ); free( r->resampler.blip_buffer[1] );
free( r->resampler.blip_buffer[0] ); free( r->resampler.blip_buffer[0] );
free( r ); free( r );
return NULL; return NULL;
} }
r->resampler.fir_resampler[1] = lanczos_resampler_create(); r->resampler.fir_resampler[1] = sinc_resampler_create();
if ( !r->resampler.fir_resampler[1] ) { 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[1] );
free( r->resampler.blip_buffer[0] ); free( r->resampler.blip_buffer[0] );
free( r ); free( r );
@ -73,8 +73,8 @@ static IT_PLAYING *new_playing()
static void free_playing(IT_PLAYING * r) static void free_playing(IT_PLAYING * r)
{ {
lanczos_resampler_delete( r->resampler.fir_resampler[1] ); sinc_resampler_delete( r->resampler.fir_resampler[1] );
lanczos_resampler_delete( r->resampler.fir_resampler[0] ); sinc_resampler_delete( r->resampler.fir_resampler[0] );
blip_delete( r->resampler.blip_buffer[1] ); blip_delete( r->resampler.blip_buffer[1] );
blip_delete( r->resampler.blip_buffer[0] ); blip_delete( r->resampler.blip_buffer[0] );
free( r ); free( r );
@ -180,16 +180,16 @@ static IT_PLAYING *dup_playing(IT_PLAYING *src, IT_CHANNEL *dstchannel, IT_CHANN
return NULL; return NULL;
} }
dst->resampler.fir_resampler_ratio = src->resampler.fir_resampler_ratio; 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] ) { if ( !dst->resampler.fir_resampler[0] ) {
blip_delete( dst->resampler.blip_buffer[1] ); blip_delete( dst->resampler.blip_buffer[1] );
blip_delete( dst->resampler.blip_buffer[0] ); blip_delete( dst->resampler.blip_buffer[0] );
free( dst ); free( dst );
return NULL; 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] ) { 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[1] );
blip_delete( dst->resampler.blip_buffer[0] ); blip_delete( dst->resampler.blip_buffer[0] );
free( dst ); free( dst );

View File

@ -112,7 +112,7 @@
<ClCompile Include="..\..\src\helpers\blip_buf.c" /> <ClCompile Include="..\..\src\helpers\blip_buf.c" />
<ClCompile Include="..\..\src\helpers\clickrem.c" /> <ClCompile Include="..\..\src\helpers\clickrem.c" />
<ClCompile Include="..\..\src\helpers\fir_resampler.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\lpc.c" />
<ClCompile Include="..\..\src\helpers\memfile.c" /> <ClCompile Include="..\..\src\helpers\memfile.c" />
<ClCompile Include="..\..\src\helpers\resample.c" /> <ClCompile Include="..\..\src\helpers\resample.c" />
@ -209,7 +209,7 @@
<ClInclude Include="..\..\include\internal\dumbfile.h" /> <ClInclude Include="..\..\include\internal\dumbfile.h" />
<ClInclude Include="..\..\include\internal\fir_resampler.h" /> <ClInclude Include="..\..\include\internal\fir_resampler.h" />
<ClInclude Include="..\..\include\internal\it.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\lpc.h" />
<ClInclude Include="..\..\include\internal\riff.h" /> <ClInclude Include="..\..\include\internal\riff.h" />
<ClInclude Include="..\..\include\internal\stack_alloc.h" /> <ClInclude Include="..\..\include\internal\stack_alloc.h" />

View File

@ -282,7 +282,7 @@
<ClCompile Include="..\..\src\it\readany2.c"> <ClCompile Include="..\..\src\it\readany2.c">
<Filter>src\it\readers</Filter> <Filter>src\it\readers</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\helpers\lanczos_resampler.c"> <ClCompile Include="..\..\src\helpers\sinc_resampler.c">
<Filter>src\helpers</Filter> <Filter>src\helpers</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\helpers\tarray.c"> <ClCompile Include="..\..\src\helpers\tarray.c">
@ -320,7 +320,7 @@
<ClInclude Include="..\..\include\internal\blip_buf.h"> <ClInclude Include="..\..\include\internal\blip_buf.h">
<Filter>include\internal</Filter> <Filter>include\internal</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\include\internal\lanczos_resampler.h"> <ClInclude Include="..\..\include\internal\sinc_resampler.h">
<Filter>include\internal</Filter> <Filter>include\internal</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\include\internal\tarray.h"> <ClInclude Include="..\..\include\internal\tarray.h">

View File

@ -10,10 +10,10 @@
835CBC8218DA95AC0087A03E /* ft2play.h in Headers */ = {isa = PBXBuildFile; fileRef = 839CAC3E18DA744700D67EA9 /* ft2play.h */; settings = {ATTRIBUTES = (Public, ); }; }; 835CBC8218DA95AC0087A03E /* ft2play.h in Headers */ = {isa = PBXBuildFile; fileRef = 839CAC3E18DA744700D67EA9 /* ft2play.h */; settings = {ATTRIBUTES = (Public, ); }; };
839CAC4018DA746000D67EA9 /* ft2play.c in Sources */ = {isa = PBXBuildFile; fileRef = 839CAC3F18DA746000D67EA9 /* ft2play.c */; }; 839CAC4018DA746000D67EA9 /* ft2play.c in Sources */ = {isa = PBXBuildFile; fileRef = 839CAC3F18DA746000D67EA9 /* ft2play.c */; };
83F4D54818D82105009B2DE6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 83F4D54618D82105009B2DE6 /* InfoPlist.strings */; }; 83F4D54818D82105009B2DE6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 83F4D54618D82105009B2DE6 /* InfoPlist.strings */; };
83F4D57518D821D2009B2DE6 /* lanczos_resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F4D57118D821D2009B2DE6 /* lanczos_resampler.c */; };
83F4D57618D821D2009B2DE6 /* lanczos_resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F4D57218D821D2009B2DE6 /* lanczos_resampler.h */; };
83F4D57718D821D2009B2DE6 /* st3play.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F4D57318D821D2009B2DE6 /* st3play.c */; }; 83F4D57718D821D2009B2DE6 /* st3play.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F4D57318D821D2009B2DE6 /* st3play.c */; };
83F4D57818D821D2009B2DE6 /* st3play.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F4D57418D821D2009B2DE6 /* st3play.h */; settings = {ATTRIBUTES = (Public, ); }; }; 83F4D57818D821D2009B2DE6 /* st3play.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F4D57418D821D2009B2DE6 /* st3play.h */; settings = {ATTRIBUTES = (Public, ); }; };
83F81CBB18DE4CEC0058B7C3 /* sinc_resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F81CB918DE4CEC0058B7C3 /* sinc_resampler.c */; };
83F81CBC18DE4CEC0058B7C3 /* sinc_resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F81CBA18DE4CEC0058B7C3 /* sinc_resampler.h */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
@ -22,10 +22,10 @@
83F4D53A18D82105009B2DE6 /* modplay.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = modplay.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 83F4D53A18D82105009B2DE6 /* modplay.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = modplay.framework; sourceTree = BUILT_PRODUCTS_DIR; };
83F4D54518D82105009B2DE6 /* modplay-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "modplay-Info.plist"; sourceTree = "<group>"; }; 83F4D54518D82105009B2DE6 /* modplay-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "modplay-Info.plist"; sourceTree = "<group>"; };
83F4D54718D82105009B2DE6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 83F4D54718D82105009B2DE6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
83F4D57118D821D2009B2DE6 /* lanczos_resampler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lanczos_resampler.c; sourceTree = "<group>"; };
83F4D57218D821D2009B2DE6 /* lanczos_resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lanczos_resampler.h; sourceTree = "<group>"; };
83F4D57318D821D2009B2DE6 /* st3play.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = st3play.c; sourceTree = "<group>"; }; 83F4D57318D821D2009B2DE6 /* st3play.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = st3play.c; sourceTree = "<group>"; };
83F4D57418D821D2009B2DE6 /* st3play.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = st3play.h; sourceTree = "<group>"; }; 83F4D57418D821D2009B2DE6 /* st3play.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = st3play.h; sourceTree = "<group>"; };
83F81CB918DE4CEC0058B7C3 /* sinc_resampler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sinc_resampler.c; sourceTree = "<group>"; };
83F81CBA18DE4CEC0058B7C3 /* sinc_resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sinc_resampler.h; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -74,8 +74,8 @@
83F4D54318D82105009B2DE6 /* modplay */ = { 83F4D54318D82105009B2DE6 /* modplay */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
83F4D57118D821D2009B2DE6 /* lanczos_resampler.c */, 83F81CB918DE4CEC0058B7C3 /* sinc_resampler.c */,
83F4D57218D821D2009B2DE6 /* lanczos_resampler.h */, 83F81CBA18DE4CEC0058B7C3 /* sinc_resampler.h */,
83F4D57318D821D2009B2DE6 /* st3play.c */, 83F4D57318D821D2009B2DE6 /* st3play.c */,
83F4D57418D821D2009B2DE6 /* st3play.h */, 83F4D57418D821D2009B2DE6 /* st3play.h */,
839CAC3F18DA746000D67EA9 /* ft2play.c */, 839CAC3F18DA746000D67EA9 /* ft2play.c */,
@ -101,9 +101,9 @@
isa = PBXHeadersBuildPhase; isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
83F81CBC18DE4CEC0058B7C3 /* sinc_resampler.h in Headers */,
835CBC8218DA95AC0087A03E /* ft2play.h in Headers */, 835CBC8218DA95AC0087A03E /* ft2play.h in Headers */,
83F4D57818D821D2009B2DE6 /* st3play.h in Headers */, 83F4D57818D821D2009B2DE6 /* st3play.h in Headers */,
83F4D57618D821D2009B2DE6 /* lanczos_resampler.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -171,8 +171,8 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
83F4D57718D821D2009B2DE6 /* st3play.c in Sources */, 83F4D57718D821D2009B2DE6 /* st3play.c in Sources */,
83F4D57518D821D2009B2DE6 /* lanczos_resampler.c in Sources */,
839CAC4018DA746000D67EA9 /* ft2play.c in Sources */, 839CAC4018DA746000D67EA9 /* ft2play.c in Sources */,
83F81CBB18DE4CEC0058B7C3 /* sinc_resampler.c in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

View File

@ -29,7 +29,7 @@
#include <math.h> #include <math.h>
#include <assert.h> #include <assert.h>
#include "lanczos_resampler.h" #include "sinc_resampler.h"
#include "ft2play.h" #include "ft2play.h"
@ -2000,8 +2000,8 @@ static void MainPlayer(PLAYER *p) // periodically called from mixer
p->voice[ch->Nr + 127] = p->voice[ch->Nr]; p->voice[ch->Nr + 127] = p->voice[ch->Nr];
voiceSetVolume(p, ch->Nr, ch->FinalVol, ch->FinalPan, 1); voiceSetVolume(p, ch->Nr, ch->FinalVol, ch->FinalPan, 1);
voiceSetVolume(p, ch->Nr + 127, 0, ch->FinalPan, 1); voiceSetVolume(p, ch->Nr + 127, 0, ch->FinalPan, 1);
lanczos_resampler_dup_inplace(p->resampler[ch->Nr + 127], p->resampler[ch->Nr]); sinc_resampler_dup_inplace(p->resampler[ch->Nr + 127], p->resampler[ch->Nr]);
lanczos_resampler_dup_inplace(p->resampler[ch->Nr + 127 + 254], p->resampler[ch->Nr + 254]); sinc_resampler_dup_inplace(p->resampler[ch->Nr + 127 + 254], p->resampler[ch->Nr + 254]);
#endif #endif
s = ch->InstrOfs; s = ch->InstrOfs;
@ -2687,11 +2687,11 @@ void voiceSetSource(PLAYER *p, uint8_t i, const int8_t *sampleData,
p->voice[i].rampTerminates = 0; p->voice[i].rampTerminates = 0;
#endif #endif
lanczos_resampler_clear(p->resampler[i]); sinc_resampler_clear(p->resampler[i]);
#ifdef USE_VOL_RAMP #ifdef USE_VOL_RAMP
lanczos_resampler_clear(p->resampler[i+254]); sinc_resampler_clear(p->resampler[i+254]);
#else #else
lanczos_resampler_clear(p->resampler[i+127]); sinc_resampler_clear(p->resampler[i+127]);
#endif #endif
} }
@ -2707,11 +2707,11 @@ void voiceSetSamplePosition(PLAYER *p, uint8_t i, uint16_t value)
p->voice[i].interpolating = 1; p->voice[i].interpolating = 1;
p->voice[i].oversampleCount = 0; p->voice[i].oversampleCount = 0;
lanczos_resampler_clear(p->resampler[i]); sinc_resampler_clear(p->resampler[i]);
#ifdef USE_VOL_RAMP #ifdef USE_VOL_RAMP
lanczos_resampler_clear(p->resampler[i+254]); sinc_resampler_clear(p->resampler[i+254]);
#else #else
lanczos_resampler_clear(p->resampler[i+127]); sinc_resampler_clear(p->resampler[i+127]);
#endif #endif
} }
@ -2786,17 +2786,17 @@ static inline void mix8b(PLAYER *p, uint32_t ch, uint32_t samples)
resampler = p->resampler[ch]; resampler = p->resampler[ch];
lanczos_resampler_set_rate(resampler, p->voice[ch].incRate * (float)samplingInterpolation); sinc_resampler_set_rate(resampler, p->voice[ch].incRate * (float)samplingInterpolation);
for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j) for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j)
{ {
p->voice[ch].busy = 1; p->voice[ch].busy = 1;
samplePosition = p->voice[ch].samplePosition; samplePosition = p->voice[ch].samplePosition;
while (interpolating && lanczos_resampler_get_free_count(resampler)) while (interpolating && sinc_resampler_get_free_count(resampler))
{ {
for (;oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler); ++oversampleCount) for (;oversampleCount < samplingInterpolation && sinc_resampler_get_free_count(resampler); ++oversampleCount)
lanczos_resampler_write_sample(resampler, sampleData[samplePosition] * 256); sinc_resampler_write_sample(resampler, sampleData[samplePosition] * 256);
if (oversampleCount < samplingInterpolation) if (oversampleCount < samplingInterpolation)
break; break;
@ -2852,7 +2852,7 @@ static inline void mix8b(PLAYER *p, uint32_t ch, uint32_t samples)
p->voice[ch].interpolating = (int8_t)interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = (int8_t)oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler) ) if ( !sinc_resampler_ready(resampler) )
{ {
p->voice[ch].sampleData = NULL; p->voice[ch].sampleData = NULL;
p->voice[ch].samplePosition = 0; p->voice[ch].samplePosition = 0;
@ -2860,8 +2860,8 @@ static inline void mix8b(PLAYER *p, uint32_t ch, uint32_t samples)
break; break;
} }
sample = lanczos_resampler_get_sample(resampler); sample = sinc_resampler_get_sample(resampler);
lanczos_resampler_remove_sample(resampler); sinc_resampler_remove_sample(resampler);
sampleL = (sample * p->voice[ch].volumeL); sampleL = (sample * p->voice[ch].volumeL);
sampleR = (sample * p->voice[ch].volumeR); sampleR = (sample * p->voice[ch].volumeR);
@ -2952,20 +2952,20 @@ static inline void mix8bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
resampler[1] = p->resampler[ch+127]; resampler[1] = p->resampler[ch+127];
#endif #endif
lanczos_resampler_set_rate(resampler[0], p->voice[ch].incRate * (float)samplingInterpolation); sinc_resampler_set_rate(resampler[0], p->voice[ch].incRate * (float)samplingInterpolation);
lanczos_resampler_set_rate(resampler[1], p->voice[ch].incRate * (float)samplingInterpolation); sinc_resampler_set_rate(resampler[1], p->voice[ch].incRate * (float)samplingInterpolation);
for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j) for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j)
{ {
p->voice[ch].busy = 1; p->voice[ch].busy = 1;
samplePosition = p->voice[ch].samplePosition; samplePosition = p->voice[ch].samplePosition;
while (interpolating && lanczos_resampler_get_free_count(resampler[0])) while (interpolating && sinc_resampler_get_free_count(resampler[0]))
{ {
for (;oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler[0]); ++oversampleCount) for (;oversampleCount < samplingInterpolation && sinc_resampler_get_free_count(resampler[0]); ++oversampleCount)
{ {
lanczos_resampler_write_sample(resampler[0], sampleData[samplePosition] * 256); sinc_resampler_write_sample(resampler[0], sampleData[samplePosition] * 256);
lanczos_resampler_write_sample(resampler[1], sampleData[sampleLength + samplePosition] * 256); sinc_resampler_write_sample(resampler[1], sampleData[sampleLength + samplePosition] * 256);
} }
if (oversampleCount < samplingInterpolation) if (oversampleCount < samplingInterpolation)
@ -3022,7 +3022,7 @@ static inline void mix8bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
p->voice[ch].interpolating = (int8_t)interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = (int8_t)oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler[0]) ) if ( !sinc_resampler_ready(resampler[0]) )
{ {
p->voice[ch].sampleData = NULL; p->voice[ch].sampleData = NULL;
p->voice[ch].samplePosition = 0; p->voice[ch].samplePosition = 0;
@ -3030,10 +3030,10 @@ static inline void mix8bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
break; break;
} }
sampleL = lanczos_resampler_get_sample(resampler[0]); sampleL = sinc_resampler_get_sample(resampler[0]);
sampleR = lanczos_resampler_get_sample(resampler[1]); sampleR = sinc_resampler_get_sample(resampler[1]);
lanczos_resampler_remove_sample(resampler[0]); sinc_resampler_remove_sample(resampler[0]);
lanczos_resampler_remove_sample(resampler[1]); sinc_resampler_remove_sample(resampler[1]);
sampleL = (sampleL * p->voice[ch].volumeL); sampleL = (sampleL * p->voice[ch].volumeL);
sampleR = (sampleR * p->voice[ch].volumeR); sampleR = (sampleR * p->voice[ch].volumeR);
@ -3120,17 +3120,17 @@ static inline void mix16b(PLAYER *p, uint32_t ch, uint32_t samples)
resampler = p->resampler[ch]; resampler = p->resampler[ch];
lanczos_resampler_set_rate(resampler, p->voice[ch].incRate * (float)samplingInterpolation); sinc_resampler_set_rate(resampler, p->voice[ch].incRate * (float)samplingInterpolation);
for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j) for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j)
{ {
p->voice[ch].busy = 1; p->voice[ch].busy = 1;
samplePosition = p->voice[ch].samplePosition; samplePosition = p->voice[ch].samplePosition;
while (interpolating && lanczos_resampler_get_free_count(resampler)) while (interpolating && sinc_resampler_get_free_count(resampler))
{ {
for (;oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler); ++oversampleCount) for (;oversampleCount < samplingInterpolation && sinc_resampler_get_free_count(resampler); ++oversampleCount)
lanczos_resampler_write_sample(resampler, sampleData[samplePosition]); sinc_resampler_write_sample(resampler, sampleData[samplePosition]);
if (oversampleCount < samplingInterpolation) if (oversampleCount < samplingInterpolation)
break; break;
@ -3186,7 +3186,7 @@ static inline void mix16b(PLAYER *p, uint32_t ch, uint32_t samples)
p->voice[ch].interpolating = (int8_t)interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = (int8_t)oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler) ) if ( !sinc_resampler_ready(resampler) )
{ {
p->voice[ch].sampleData = NULL; p->voice[ch].sampleData = NULL;
p->voice[ch].samplePosition = 0; p->voice[ch].samplePosition = 0;
@ -3194,8 +3194,8 @@ static inline void mix16b(PLAYER *p, uint32_t ch, uint32_t samples)
break; break;
} }
sample = lanczos_resampler_get_sample(resampler); sample = sinc_resampler_get_sample(resampler);
lanczos_resampler_remove_sample(resampler); sinc_resampler_remove_sample(resampler);
sampleL = (sample * p->voice[ch].volumeL); sampleL = (sample * p->voice[ch].volumeL);
sampleR = (sample * p->voice[ch].volumeR); sampleR = (sample * p->voice[ch].volumeR);
@ -3286,20 +3286,20 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
resampler[1] = p->resampler[ch+127]; resampler[1] = p->resampler[ch+127];
#endif #endif
lanczos_resampler_set_rate(resampler[0], p->voice[ch].incRate * (float)samplingInterpolation); sinc_resampler_set_rate(resampler[0], p->voice[ch].incRate * (float)samplingInterpolation);
lanczos_resampler_set_rate(resampler[1], p->voice[ch].incRate * (float)samplingInterpolation); sinc_resampler_set_rate(resampler[1], p->voice[ch].incRate * (float)samplingInterpolation);
for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j) for (j = 0; (j < samples) && (p->voice[ch].sampleData != NULL); ++j)
{ {
p->voice[ch].busy = 1; p->voice[ch].busy = 1;
samplePosition = p->voice[ch].samplePosition; samplePosition = p->voice[ch].samplePosition;
while (interpolating && lanczos_resampler_get_free_count(resampler[0])) while (interpolating && sinc_resampler_get_free_count(resampler[0]))
{ {
for (;oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler[0]); ++oversampleCount) for (;oversampleCount < samplingInterpolation && sinc_resampler_get_free_count(resampler[0]); ++oversampleCount)
{ {
lanczos_resampler_write_sample(resampler[0], sampleData[samplePosition]); sinc_resampler_write_sample(resampler[0], sampleData[samplePosition]);
lanczos_resampler_write_sample(resampler[1], sampleData[sampleLength + samplePosition]); sinc_resampler_write_sample(resampler[1], sampleData[sampleLength + samplePosition]);
} }
if (oversampleCount < samplingInterpolation) if (oversampleCount < samplingInterpolation)
@ -3356,7 +3356,7 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
p->voice[ch].interpolating = (int8_t)interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = (int8_t)oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler[0]) ) if ( !sinc_resampler_ready(resampler[0]) )
{ {
p->voice[ch].sampleData = NULL; p->voice[ch].sampleData = NULL;
p->voice[ch].samplePosition = 0; p->voice[ch].samplePosition = 0;
@ -3364,10 +3364,10 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
break; break;
} }
sampleL = lanczos_resampler_get_sample(resampler[0]); sampleL = sinc_resampler_get_sample(resampler[0]);
sampleR = lanczos_resampler_get_sample(resampler[1]); sampleR = sinc_resampler_get_sample(resampler[1]);
lanczos_resampler_remove_sample(resampler[0]); sinc_resampler_remove_sample(resampler[0]);
lanczos_resampler_remove_sample(resampler[1]); sinc_resampler_remove_sample(resampler[1]);
sampleL = (sampleL * p->voice[ch].volumeL); sampleL = (sampleL * p->voice[ch].volumeL);
sampleR = (sampleR * p->voice[ch].volumeR); sampleR = (sampleR * p->voice[ch].volumeR);
@ -3566,7 +3566,7 @@ void * ft2play_Alloc(uint32_t _samplingFrequency, int8_t interpolation)
p->samplingInterpolation = interpolation; p->samplingInterpolation = interpolation;
lanczos_init(); sinc_init();
#ifdef USE_VOL_RAMP #ifdef USE_VOL_RAMP
for ( i = 0; i < 127 * 2 * 2; ++i ) for ( i = 0; i < 127 * 2 * 2; ++i )
@ -3574,7 +3574,7 @@ void * ft2play_Alloc(uint32_t _samplingFrequency, int8_t interpolation)
for ( i = 0; i < 127 * 2; ++i ) for ( i = 0; i < 127 * 2; ++i )
#endif #endif
{ {
p->resampler[i] = lanczos_resampler_create(); p->resampler[i] = sinc_resampler_create();
if ( !p->resampler[i] ) if ( !p->resampler[i] )
goto error; goto error;
} }
@ -3675,7 +3675,7 @@ void ft2play_Free(void *_p)
#endif #endif
{ {
if ( p->resampler[i] ) if ( p->resampler[i] )
lanczos_resampler_delete( p->resampler[i] ); sinc_resampler_delete( p->resampler[i] );
p->resampler[i] = NULL; p->resampler[i] = NULL;
} }

View File

@ -1,39 +0,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 *);
float lanczos_resampler_get_sample(void *);
void lanczos_resampler_remove_sample(void *);
#endif

View File

@ -4,22 +4,22 @@
#include <math.h> #include <math.h>
#if (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__)) #if (defined(_M_IX86) || defined(__i386__) || defined(_M_X64) || defined(__amd64__))
#include <xmmintrin.h> #include <xmmintrin.h>
#define LANCZOS_SSE #define SINC_SSE
#endif #endif
#ifndef M_PI #ifndef M_PI
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
#endif #endif
#include "lanczos_resampler.h" #include "sinc_resampler.h"
enum { LANCZOS_RESOLUTION = 8192 }; enum { SINC_RESOLUTION = 8192 };
enum { LANCZOS_WIDTH = 16 }; enum { SINC_WIDTH = 16 };
enum { LANCZOS_SAMPLES = LANCZOS_RESOLUTION * LANCZOS_WIDTH }; enum { SINC_SAMPLES = SINC_RESOLUTION * SINC_WIDTH };
static float lanczos_lut[LANCZOS_SAMPLES + 1]; static float sinc_lut[SINC_SAMPLES + 1];
enum { lanczos_buffer_size = LANCZOS_WIDTH * 4 }; enum { sinc_buffer_size = SINC_WIDTH * 4 };
static int fEqual(const float b, const float a) static int fEqual(const float b, const float a)
{ {
@ -31,7 +31,7 @@ static float sinc(float x)
return fEqual(x, 0.0) ? 1.0 : sin(x * M_PI) / (x * M_PI); return fEqual(x, 0.0) ? 1.0 : sin(x * M_PI) / (x * M_PI);
} }
#ifdef LANCZOS_SSE #ifdef SINC_SSE
#ifdef _MSC_VER #ifdef _MSC_VER
#include <intrin.h> #include <intrin.h>
#elif defined(__clang__) || defined(__GNUC__) #elif defined(__clang__) || defined(__GNUC__)
@ -56,33 +56,37 @@ static int query_cpu_feature_sse() {
return 1; return 1;
} }
static int lanczos_has_sse = 0; static int sinc_has_sse = 0;
#endif #endif
void lanczos_init(void) void sinc_init(void)
{ {
unsigned i; unsigned i;
float dx = (float)(LANCZOS_WIDTH) / LANCZOS_SAMPLES, x = 0.0; float dx = (float)(SINC_WIDTH) / SINC_SAMPLES, x = 0.0;
for (i = 0; i < LANCZOS_SAMPLES + 1; ++i, x += dx) for (i = 0; i < SINC_SAMPLES + 1; ++i, x += dx)
lanczos_lut[i] = fabs(x) < LANCZOS_WIDTH ? sinc(x) * sinc(x / LANCZOS_WIDTH) : 0.0; {
#ifdef LANCZOS_SSE float y = x / SINC_WIDTH;
lanczos_has_sse = query_cpu_feature_sse(); 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 #endif
} }
typedef struct lanczos_resampler typedef struct sinc_resampler
{ {
int write_pos, write_filled; int write_pos, write_filled;
int read_pos, read_filled; int read_pos, read_filled;
unsigned short phase; unsigned short phase;
unsigned int phase_inc; unsigned int phase_inc;
float buffer_in[lanczos_buffer_size * 2]; float buffer_in[sinc_buffer_size * 2];
float buffer_out[lanczos_buffer_size]; float buffer_out[sinc_buffer_size];
} lanczos_resampler; } sinc_resampler;
void * lanczos_resampler_create(void) void * sinc_resampler_create(void)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) malloc( sizeof(lanczos_resampler) ); sinc_resampler * r = ( sinc_resampler * ) malloc( sizeof(sinc_resampler) );
if ( !r ) return 0; if ( !r ) return 0;
r->write_pos = 0; r->write_pos = 0;
@ -97,15 +101,15 @@ void * lanczos_resampler_create(void)
return r; return r;
} }
void lanczos_resampler_delete(void * _r) void sinc_resampler_delete(void * _r)
{ {
free( _r ); free( _r );
} }
void * lanczos_resampler_dup(const void * _r) void * sinc_resampler_dup(const void * _r)
{ {
const lanczos_resampler * r_in = ( const lanczos_resampler * ) _r; const sinc_resampler * r_in = ( const sinc_resampler * ) _r;
lanczos_resampler * r_out = ( lanczos_resampler * ) malloc( sizeof(lanczos_resampler) ); sinc_resampler * r_out = ( sinc_resampler * ) malloc( sizeof(sinc_resampler) );
if ( !r_out ) return 0; if ( !r_out ) return 0;
r_out->write_pos = r_in->write_pos; r_out->write_pos = r_in->write_pos;
@ -120,10 +124,10 @@ void * lanczos_resampler_dup(const void * _r)
return r_out; return r_out;
} }
void lanczos_resampler_dup_inplace(void *_d, const void *_s) void sinc_resampler_dup_inplace(void *_d, const void *_s)
{ {
const lanczos_resampler * r_in = ( const lanczos_resampler * ) _s; const sinc_resampler * r_in = ( const sinc_resampler * ) _s;
lanczos_resampler * r_out = ( lanczos_resampler * ) _d; sinc_resampler * r_out = ( sinc_resampler * ) _d;
r_out->write_pos = r_in->write_pos; r_out->write_pos = r_in->write_pos;
r_out->write_filled = r_in->write_filled; r_out->write_filled = r_in->write_filled;
@ -135,21 +139,21 @@ void lanczos_resampler_dup_inplace(void *_d, const void *_s)
memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) ); memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) );
} }
int lanczos_resampler_get_free_count(void *_r) int sinc_resampler_get_free_count(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
return lanczos_buffer_size - r->write_filled; return sinc_buffer_size - r->write_filled;
} }
int lanczos_resampler_ready(void *_r) int sinc_resampler_ready(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
return r->write_filled > (LANCZOS_WIDTH * 2); return r->write_filled > (SINC_WIDTH * 2);
} }
void lanczos_resampler_clear(void *_r) void sinc_resampler_clear(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
r->write_pos = 0; r->write_pos = 0;
r->write_filled = 0; r->write_filled = 0;
r->read_pos = 0; r->read_pos = 0;
@ -157,35 +161,35 @@ void lanczos_resampler_clear(void *_r)
r->phase = 0; r->phase = 0;
} }
void lanczos_resampler_set_rate(void *_r, double new_factor) void sinc_resampler_set_rate(void *_r, double new_factor)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
r->phase_inc = (int)( new_factor * LANCZOS_RESOLUTION ); r->phase_inc = (int)( new_factor * SINC_RESOLUTION );
} }
void lanczos_resampler_write_sample(void *_r, short s) void sinc_resampler_write_sample(void *_r, short s)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
if ( r->write_filled < lanczos_buffer_size ) if ( r->write_filled < sinc_buffer_size )
{ {
float s32 = s; float s32 = s;
r->buffer_in[ r->write_pos ] = s32; r->buffer_in[ r->write_pos ] = s32;
r->buffer_in[ r->write_pos + lanczos_buffer_size ] = s32; r->buffer_in[ r->write_pos + sinc_buffer_size ] = s32;
++r->write_filled; ++r->write_filled;
r->write_pos = ( r->write_pos + 1 ) % lanczos_buffer_size; r->write_pos = ( r->write_pos + 1 ) % sinc_buffer_size;
} }
} }
static int lanczos_resampler_run(lanczos_resampler * r, float ** out_, float * out_end) static int sinc_resampler_run(sinc_resampler * r, float ** out_, float * out_end)
{ {
int in_size = r->write_filled; int in_size = r->write_filled;
float const* in_ = r->buffer_in + lanczos_buffer_size + r->write_pos - r->write_filled; float const* in_ = r->buffer_in + sinc_buffer_size + r->write_pos - r->write_filled;
int used = 0; int used = 0;
in_size -= LANCZOS_WIDTH * 2; in_size -= SINC_WIDTH * 2;
if ( in_size > 0 ) if ( in_size > 0 )
{ {
float* out = *out_; float* out = *out_;
@ -194,24 +198,25 @@ static int lanczos_resampler_run(lanczos_resampler * r, float ** out_, float * o
int phase = r->phase; int phase = r->phase;
int phase_inc = r->phase_inc; int phase_inc = r->phase_inc;
int step = phase_inc > LANCZOS_RESOLUTION ? LANCZOS_RESOLUTION * LANCZOS_RESOLUTION / phase_inc : LANCZOS_RESOLUTION; int step = phase_inc > SINC_RESOLUTION ? SINC_RESOLUTION * SINC_RESOLUTION / phase_inc : SINC_RESOLUTION;
do do
{ {
float kernel[LANCZOS_WIDTH * 2], kernel_sum = 0.0; // accumulate in extended precision
int i = LANCZOS_WIDTH; float kernel[SINC_WIDTH * 2], kernel_sum = 0.0;
int phase_adj = phase * step / LANCZOS_RESOLUTION; int i = SINC_WIDTH;
int phase_adj = phase * step / SINC_RESOLUTION;
float sample; float sample;
if ( out >= out_end ) if ( out >= out_end )
break; break;
for (; i >= -LANCZOS_WIDTH + 1; --i) for (; i >= -SINC_WIDTH + 1; --i)
{ {
int pos = i * step; int pos = i * step;
kernel_sum += kernel[i + LANCZOS_WIDTH - 1] = lanczos_lut[abs(phase_adj - pos)]; kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)];
} }
for (sample = 0, i = 0; i < LANCZOS_WIDTH * 2; ++i) for (sample = 0, i = 0; i < SINC_WIDTH * 2; ++i)
sample += in[i] * kernel[i]; sample += in[i] * kernel[i];
*out++ = (float)(sample / kernel_sum * (1.0 / 32768.0)); *out++ = (float)(sample / kernel_sum * (1.0 / 32768.0));
@ -234,13 +239,13 @@ static int lanczos_resampler_run(lanczos_resampler * r, float ** out_, float * o
return used; return used;
} }
#ifdef LANCZOS_SSE #ifdef SINC_SSE
static int lanczos_resampler_run_sse(lanczos_resampler * r, float ** out_, float * out_end) static int sinc_resampler_run_sse(sinc_resampler * r, float ** out_, float * out_end)
{ {
int in_size = r->write_filled; int in_size = r->write_filled;
float const* in_ = r->buffer_in + lanczos_buffer_size + r->write_pos - r->write_filled; float const* in_ = r->buffer_in + sinc_buffer_size + r->write_pos - r->write_filled;
int used = 0; int used = 0;
in_size -= LANCZOS_WIDTH * 2; in_size -= SINC_WIDTH * 2;
if ( in_size > 0 ) if ( in_size > 0 )
{ {
float* out = *out_; float* out = *out_;
@ -249,27 +254,28 @@ static int lanczos_resampler_run_sse(lanczos_resampler * r, float ** out_, float
int phase = r->phase; int phase = r->phase;
int phase_inc = r->phase_inc; int phase_inc = r->phase_inc;
int step = phase_inc > LANCZOS_RESOLUTION ? LANCZOS_RESOLUTION * LANCZOS_RESOLUTION / phase_inc : LANCZOS_RESOLUTION; int step = phase_inc > SINC_RESOLUTION ? SINC_RESOLUTION * SINC_RESOLUTION / phase_inc : SINC_RESOLUTION;
do do
{ {
// accumulate in extended precision
float kernel_sum = 0.0; float kernel_sum = 0.0;
__m128 kernel[LANCZOS_WIDTH / 2]; __m128 kernel[SINC_WIDTH / 2];
__m128 temp1, temp2; __m128 temp1, temp2;
__m128 samplex = _mm_setzero_ps(); __m128 samplex = _mm_setzero_ps();
float *kernelf = (float*)(&kernel); float *kernelf = (float*)(&kernel);
int i = LANCZOS_WIDTH; int i = SINC_WIDTH;
int phase_adj = phase * step / LANCZOS_RESOLUTION; int phase_adj = phase * step / SINC_RESOLUTION;
if ( out >= out_end ) if ( out >= out_end )
break; break;
for (; i >= -LANCZOS_WIDTH + 1; --i) for (; i >= -SINC_WIDTH + 1; --i)
{ {
int pos = i * step; int pos = i * step;
kernel_sum += kernelf[i + LANCZOS_WIDTH - 1] = lanczos_lut[abs(phase_adj - pos)]; kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)];
} }
for (i = 0; i < LANCZOS_WIDTH / 2; ++i) for (i = 0; i < SINC_WIDTH / 2; ++i)
{ {
temp1 = _mm_loadu_ps( (const float *)( in + i * 4 ) ); temp1 = _mm_loadu_ps( (const float *)( in + i * 4 ) );
temp2 = _mm_load_ps( (const float *)( kernel + i ) ); temp2 = _mm_load_ps( (const float *)( kernel + i ) );
@ -307,50 +313,50 @@ static int lanczos_resampler_run_sse(lanczos_resampler * r, float ** out_, float
} }
#endif #endif
static void lanczos_resampler_fill(lanczos_resampler * r) static void sinc_resampler_fill(sinc_resampler * r)
{ {
while ( r->write_filled > (LANCZOS_WIDTH * 2) && while ( r->write_filled > (SINC_WIDTH * 2) &&
r->read_filled < lanczos_buffer_size ) r->read_filled < sinc_buffer_size )
{ {
int write_pos = ( r->read_pos + r->read_filled ) % lanczos_buffer_size; int write_pos = ( r->read_pos + r->read_filled ) % sinc_buffer_size;
int write_size = lanczos_buffer_size - write_pos; int write_size = sinc_buffer_size - write_pos;
float * out = r->buffer_out + write_pos; float * out = r->buffer_out + write_pos;
if ( write_size > ( lanczos_buffer_size - r->read_filled ) ) if ( write_size > ( sinc_buffer_size - r->read_filled ) )
write_size = lanczos_buffer_size - r->read_filled; write_size = sinc_buffer_size - r->read_filled;
#ifdef LANCZOS_SSE #ifdef SINC_SSE
if ( lanczos_has_sse ) if ( sinc_has_sse )
lanczos_resampler_run_sse( r, &out, out + write_size ); sinc_resampler_run_sse( r, &out, out + write_size );
else else
#endif #endif
lanczos_resampler_run( r, &out, out + write_size ); sinc_resampler_run( r, &out, out + write_size );
r->read_filled += out - r->buffer_out - write_pos; r->read_filled += out - r->buffer_out - write_pos;
} }
} }
int lanczos_resampler_get_sample_count(void *_r) int sinc_resampler_get_sample_count(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
if ( r->read_filled < 1 ) if ( r->read_filled < 1 )
lanczos_resampler_fill( r ); sinc_resampler_fill( r );
return r->read_filled; return r->read_filled;
} }
float lanczos_resampler_get_sample(void *_r) float sinc_resampler_get_sample(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
if ( r->read_filled < 1 ) if ( r->read_filled < 1 )
lanczos_resampler_fill( r ); sinc_resampler_fill( r );
if ( r->read_filled < 1 ) if ( r->read_filled < 1 )
return 0; return 0;
return r->buffer_out[ r->read_pos ]; return r->buffer_out[ r->read_pos ];
} }
void lanczos_resampler_remove_sample(void *_r) void sinc_resampler_remove_sample(void *_r)
{ {
lanczos_resampler * r = ( lanczos_resampler * ) _r; sinc_resampler * r = ( sinc_resampler * ) _r;
if ( r->read_filled > 0 ) if ( r->read_filled > 0 )
{ {
--r->read_filled; --r->read_filled;
r->read_pos = ( r->read_pos + 1 ) % lanczos_buffer_size; r->read_pos = ( r->read_pos + 1 ) % sinc_buffer_size;
} }
} }

View File

@ -0,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 *);
float sinc_resampler_get_sample(void *);
void sinc_resampler_remove_sample(void *);
#endif

View File

@ -63,7 +63,7 @@
#define inline __forceinline #define inline __forceinline
#endif #endif
#include "lanczos_resampler.h" #include "sinc_resampler.h"
#include "st3play.h" #include "st3play.h"
@ -485,7 +485,7 @@ void * st3play_Alloc(uint32_t outputFreq, int8_t interpolation)
if ( !p ) if ( !p )
return 0; return 0;
lanczos_init(); sinc_init();
#ifdef USE_VOL_RAMP #ifdef USE_VOL_RAMP
for (i = 0; i < 64 * 2; ++i) for (i = 0; i < 64 * 2; ++i)
@ -493,7 +493,7 @@ void * st3play_Alloc(uint32_t outputFreq, int8_t interpolation)
for (i = 0; i < 64; ++i) for (i = 0; i < 64; ++i)
#endif #endif
{ {
p->resampler[i] = lanczos_resampler_create(); p->resampler[i] = sinc_resampler_create();
if ( !p->resampler[i] ) if ( !p->resampler[i] )
{ {
st3play_Free( p ); st3play_Free( p );
@ -540,7 +540,7 @@ void st3play_Free(void *_p)
#endif #endif
{ {
if ( p->resampler[i] ) if ( p->resampler[i] )
lanczos_resampler_delete( p->resampler[i] ); sinc_resampler_delete( p->resampler[i] );
} }
if ( p->masterBufferL ) if ( p->masterBufferL )
@ -928,8 +928,8 @@ static inline void doamiga(PLAYER *p, uint8_t ch)
#ifdef USE_VOL_RAMP #ifdef USE_VOL_RAMP
p->voice[ch + 32] = p->voice[ch]; p->voice[ch + 32] = p->voice[ch];
setvol(p, ch, 2); setvol(p, ch, 2);
lanczos_resampler_dup_inplace(p->resampler[ch + 32], p->resampler[ch]); sinc_resampler_dup_inplace(p->resampler[ch + 32], p->resampler[ch]);
lanczos_resampler_dup_inplace(p->resampler[ch + 32 + 64], p->resampler[ch + 64]); sinc_resampler_dup_inplace(p->resampler[ch + 32 + 64], p->resampler[ch + 64]);
if (p->chn[ch].vol != 255) if (p->chn[ch].vol != 255)
{ {
if (p->chn[ch].vol <= 64) if (p->chn[ch].vol <= 64)
@ -2628,11 +2628,11 @@ void voiceSetSource(PLAYER *p, uint8_t voiceNumber, const int8_t *sampleData,
if (p->voice[voiceNumber].samplePosition >= p->voice[voiceNumber].sampleLength) if (p->voice[voiceNumber].samplePosition >= p->voice[voiceNumber].sampleLength)
p->voice[voiceNumber].samplePosition = 0; p->voice[voiceNumber].samplePosition = 0;
lanczos_resampler_clear( p->resampler[voiceNumber] ); sinc_resampler_clear( p->resampler[voiceNumber] );
#ifdef USE_VOL_RAMP #ifdef USE_VOL_RAMP
lanczos_resampler_clear( p->resampler[voiceNumber+64] ); sinc_resampler_clear( p->resampler[voiceNumber+64] );
#else #else
lanczos_resampler_clear( p->resampler[voiceNumber+32] ); sinc_resampler_clear( p->resampler[voiceNumber+32] );
#endif #endif
} }
@ -2655,11 +2655,11 @@ void voiceSetSamplePosition(PLAYER *p, uint8_t voiceNumber, uint16_t value)
p->voice[voiceNumber].samplePosition = 0; p->voice[voiceNumber].samplePosition = 0;
} }
lanczos_resampler_clear( p->resampler[voiceNumber] ); sinc_resampler_clear( p->resampler[voiceNumber] );
#ifdef USE_VOL_RAMP #ifdef USE_VOL_RAMP
lanczos_resampler_clear( p->resampler[voiceNumber+64] ); sinc_resampler_clear( p->resampler[voiceNumber+64] );
#else #else
lanczos_resampler_clear( p->resampler[voiceNumber+32] ); sinc_resampler_clear( p->resampler[voiceNumber+32] );
#endif #endif
} }
@ -2758,16 +2758,16 @@ static inline void mix8b(PLAYER *p, uint8_t ch, uint32_t samples)
resampler = p->resampler[ch]; resampler = p->resampler[ch];
lanczos_resampler_set_rate( resampler, p->voice[ch].incRate * (float)samplingInterpolation ); sinc_resampler_set_rate( resampler, p->voice[ch].incRate * (float)samplingInterpolation );
for (j = 0; (j < samples) && sampleData; ++j) for (j = 0; (j < samples) && sampleData; ++j)
{ {
samplePosition = p->voice[ch].samplePosition; samplePosition = p->voice[ch].samplePosition;
while (interpolating && lanczos_resampler_get_free_count(resampler)) while (interpolating && sinc_resampler_get_free_count(resampler))
{ {
for (; oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler); ++oversampleCount) for (; oversampleCount < samplingInterpolation && sinc_resampler_get_free_count(resampler); ++oversampleCount)
lanczos_resampler_write_sample(resampler, sampleData[samplePosition] * 256); sinc_resampler_write_sample(resampler, sampleData[samplePosition] * 256);
if (oversampleCount < samplingInterpolation) if (oversampleCount < samplingInterpolation)
break; break;
@ -2794,14 +2794,14 @@ static inline void mix8b(PLAYER *p, uint8_t ch, uint32_t samples)
p->voice[ch].interpolating = (int8_t)interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = (int8_t)oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler) ) if ( !sinc_resampler_ready(resampler) )
{ {
p->voice[ch].mixing = 0; p->voice[ch].mixing = 0;
break; break;
} }
sample = lanczos_resampler_get_sample(resampler); sample = sinc_resampler_get_sample(resampler);
lanczos_resampler_remove_sample(resampler); sinc_resampler_remove_sample(resampler);
sample *= volume; sample *= volume;
@ -2899,19 +2899,19 @@ static inline void mix8bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
resampler[1] = p->resampler[ch+32]; resampler[1] = p->resampler[ch+32];
#endif #endif
lanczos_resampler_set_rate(resampler[0], p->voice[ch].incRate * (float)samplingInterpolation); sinc_resampler_set_rate(resampler[0], p->voice[ch].incRate * (float)samplingInterpolation);
lanczos_resampler_set_rate(resampler[1], p->voice[ch].incRate * (float)samplingInterpolation); sinc_resampler_set_rate(resampler[1], p->voice[ch].incRate * (float)samplingInterpolation);
for (j = 0; (j < samples) && sampleData; ++j) for (j = 0; (j < samples) && sampleData; ++j)
{ {
samplePosition = p->voice[ch].samplePosition; samplePosition = p->voice[ch].samplePosition;
while (interpolating && lanczos_resampler_get_free_count(resampler[0])) while (interpolating && sinc_resampler_get_free_count(resampler[0]))
{ {
for (; oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler[0]); ++oversampleCount) for (; oversampleCount < samplingInterpolation && sinc_resampler_get_free_count(resampler[0]); ++oversampleCount)
{ {
lanczos_resampler_write_sample(resampler[0], sampleData[samplePosition] * 256); sinc_resampler_write_sample(resampler[0], sampleData[samplePosition] * 256);
lanczos_resampler_write_sample(resampler[1], sampleData[sampleLength + samplePosition] * 256); sinc_resampler_write_sample(resampler[1], sampleData[sampleLength + samplePosition] * 256);
} }
if (oversampleCount < samplingInterpolation) if (oversampleCount < samplingInterpolation)
@ -2939,16 +2939,16 @@ static inline void mix8bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
p->voice[ch].interpolating = (int8_t)interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = (int8_t)oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler[0]) ) if ( !sinc_resampler_ready(resampler[0]) )
{ {
p->voice[ch].mixing = 0; p->voice[ch].mixing = 0;
break; break;
} }
sampleL = lanczos_resampler_get_sample(resampler[0]); sampleL = sinc_resampler_get_sample(resampler[0]);
sampleR = lanczos_resampler_get_sample(resampler[1]); sampleR = sinc_resampler_get_sample(resampler[1]);
lanczos_resampler_remove_sample(resampler[0]); sinc_resampler_remove_sample(resampler[0]);
lanczos_resampler_remove_sample(resampler[1]); sinc_resampler_remove_sample(resampler[1]);
sampleL *= volume; sampleL *= volume;
sampleR *= volume; sampleR *= volume;
@ -3041,16 +3041,16 @@ static inline void mix16b(PLAYER *p, uint8_t ch, uint32_t samples)
resampler = p->resampler[ch]; resampler = p->resampler[ch];
lanczos_resampler_set_rate( resampler, p->voice[ch].incRate * (float)samplingInterpolation ); sinc_resampler_set_rate( resampler, p->voice[ch].incRate * (float)samplingInterpolation );
for (j = 0; (j < samples) && sampleData; ++j) for (j = 0; (j < samples) && sampleData; ++j)
{ {
samplePosition = p->voice[ch].samplePosition; samplePosition = p->voice[ch].samplePosition;
while (interpolating && lanczos_resampler_get_free_count(resampler)) while (interpolating && sinc_resampler_get_free_count(resampler))
{ {
for (; oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler); ++oversampleCount) for (; oversampleCount < samplingInterpolation && sinc_resampler_get_free_count(resampler); ++oversampleCount)
lanczos_resampler_write_sample(resampler, get_le16(&sampleData[samplePosition])); sinc_resampler_write_sample(resampler, get_le16(&sampleData[samplePosition]));
if (oversampleCount < samplingInterpolation) if (oversampleCount < samplingInterpolation)
break; break;
@ -3077,14 +3077,14 @@ static inline void mix16b(PLAYER *p, uint8_t ch, uint32_t samples)
p->voice[ch].interpolating = (int8_t)interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = (int8_t)oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler) ) if ( !sinc_resampler_ready(resampler) )
{ {
p->voice[ch].mixing = 0; p->voice[ch].mixing = 0;
break; break;
} }
sample = lanczos_resampler_get_sample(resampler); sample = sinc_resampler_get_sample(resampler);
lanczos_resampler_remove_sample(resampler); sinc_resampler_remove_sample(resampler);
sample *= volume; sample *= volume;
@ -3182,19 +3182,19 @@ static inline void mix16bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
resampler[1] = p->resampler[ch+32]; resampler[1] = p->resampler[ch+32];
#endif #endif
lanczos_resampler_set_rate(resampler[0], p->voice[ch].incRate * (float)samplingInterpolation); sinc_resampler_set_rate(resampler[0], p->voice[ch].incRate * (float)samplingInterpolation);
lanczos_resampler_set_rate(resampler[1], p->voice[ch].incRate * (float)samplingInterpolation); sinc_resampler_set_rate(resampler[1], p->voice[ch].incRate * (float)samplingInterpolation);
for (j = 0; (j < samples) && sampleData; ++j) for (j = 0; (j < samples) && sampleData; ++j)
{ {
samplePosition = p->voice[ch].samplePosition; samplePosition = p->voice[ch].samplePosition;
while (interpolating && lanczos_resampler_get_free_count(resampler[0])) while (interpolating && sinc_resampler_get_free_count(resampler[0]))
{ {
for (; oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler[0]); ++oversampleCount) for (; oversampleCount < samplingInterpolation && sinc_resampler_get_free_count(resampler[0]); ++oversampleCount)
{ {
lanczos_resampler_write_sample(resampler[0], get_le16(&sampleData[samplePosition])); sinc_resampler_write_sample(resampler[0], get_le16(&sampleData[samplePosition]));
lanczos_resampler_write_sample(resampler[1], get_le16(&sampleData[sampleLength + samplePosition])); sinc_resampler_write_sample(resampler[1], get_le16(&sampleData[sampleLength + samplePosition]));
} }
if (oversampleCount < samplingInterpolation) if (oversampleCount < samplingInterpolation)
@ -3222,16 +3222,16 @@ static inline void mix16bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
p->voice[ch].interpolating = (int8_t)interpolating; p->voice[ch].interpolating = (int8_t)interpolating;
p->voice[ch].oversampleCount = (int8_t)oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
if ( !lanczos_resampler_ready(resampler[0]) ) if ( !sinc_resampler_ready(resampler[0]) )
{ {
p->voice[ch].mixing = 0; p->voice[ch].mixing = 0;
break; break;
} }
sampleL = lanczos_resampler_get_sample(resampler[0]); sampleL = sinc_resampler_get_sample(resampler[0]);
sampleR = lanczos_resampler_get_sample(resampler[1]); sampleR = sinc_resampler_get_sample(resampler[1]);
lanczos_resampler_remove_sample(resampler[0]); sinc_resampler_remove_sample(resampler[0]);
lanczos_resampler_remove_sample(resampler[1]); sinc_resampler_remove_sample(resampler[1]);
sampleL *= volume; sampleL *= volume;
sampleR *= volume; sampleR *= volume;
@ -3343,19 +3343,19 @@ static inline void mixadpcm(PLAYER *p, uint8_t ch, uint32_t samples)
resampler = p->resampler[ch]; resampler = p->resampler[ch];
lanczos_resampler_set_rate( resampler, p->voice[ch].incRate * (float)samplingInterpolation ); sinc_resampler_set_rate( resampler, p->voice[ch].incRate * (float)samplingInterpolation );
for (j = 0; (j < samples) && sampleData; ++j) for (j = 0; (j < samples) && sampleData; ++j)
{ {
samplePosition = p->voice[ch].samplePosition; samplePosition = p->voice[ch].samplePosition;
while (interpolating && lanczos_resampler_get_free_count(resampler)) while (interpolating && sinc_resampler_get_free_count(resampler))
{ {
int8_t nextDelta = lastDelta; int8_t nextDelta = lastDelta;
int16_t sample = get_adpcm_sample(sampleDictionary, sampleData, samplePosition, &nextDelta) * 256; int16_t sample = get_adpcm_sample(sampleDictionary, sampleData, samplePosition, &nextDelta) * 256;
for (; oversampleCount < samplingInterpolation && lanczos_resampler_get_free_count(resampler); ++oversampleCount) for (; oversampleCount < samplingInterpolation && sinc_resampler_get_free_count(resampler); ++oversampleCount)
lanczos_resampler_write_sample(resampler, sample); sinc_resampler_write_sample(resampler, sample);
if (oversampleCount < samplingInterpolation) if (oversampleCount < samplingInterpolation)
break; break;
@ -3392,14 +3392,14 @@ static inline void mixadpcm(PLAYER *p, uint8_t ch, uint32_t samples)
p->voice[ch].oversampleCount = (int8_t)oversampleCount; p->voice[ch].oversampleCount = (int8_t)oversampleCount;
p->voice[ch].lastDelta = lastDelta; p->voice[ch].lastDelta = lastDelta;
if ( !lanczos_resampler_ready(resampler) ) if ( !sinc_resampler_ready(resampler) )
{ {
p->voice[ch].mixing = 0; p->voice[ch].mixing = 0;
break; break;
} }
sample = lanczos_resampler_get_sample(resampler); sample = sinc_resampler_get_sample(resampler);
lanczos_resampler_remove_sample(resampler); sinc_resampler_remove_sample(resampler);
sample *= volume; sample *= volume;