Updated DUMB
parent
579f385a14
commit
c75cfa27bd
|
@ -102,6 +102,8 @@
|
||||||
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 /* lanczos_resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 8370B7E817F62A40001A4D7A /* lanczos_resampler.h */; };
|
||||||
|
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 */; };
|
||||||
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
|
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
|
||||||
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
|
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
@ -209,6 +211,8 @@
|
||||||
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 /* lanczos_resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lanczos_resampler.h; 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>"; };
|
||||||
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>"; };
|
||||||
8DC2EF5B0486A6940098B216 /* Dumb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Dumb.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
8DC2EF5B0486A6940098B216 /* Dumb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Dumb.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
|
D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
|
||||||
|
@ -303,6 +307,7 @@
|
||||||
17C8F60D0CBEE797008D969D /* internal */ = {
|
17C8F60D0CBEE797008D969D /* internal */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
83C8DF1E18C6B32100750AF7 /* blip_buf.h */,
|
||||||
8370B7E817F62A40001A4D7A /* lanczos_resampler.h */,
|
8370B7E817F62A40001A4D7A /* lanczos_resampler.h */,
|
||||||
8370B61E17F60FE2001A4D7A /* barray.h */,
|
8370B61E17F60FE2001A4D7A /* barray.h */,
|
||||||
8370B62017F60FE2001A4D7A /* dumbfile.h */,
|
8370B62017F60FE2001A4D7A /* dumbfile.h */,
|
||||||
|
@ -349,6 +354,7 @@
|
||||||
17C8F61E0CBEE797008D969D /* helpers */ = {
|
17C8F61E0CBEE797008D969D /* helpers */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
83C8DF1C18C6B31400750AF7 /* blip_buf.c */,
|
||||||
8370B62E17F61001001A4D7A /* barray.c */,
|
8370B62E17F61001001A4D7A /* barray.c */,
|
||||||
8370B63017F61001001A4D7A /* lanczos_resampler.c */,
|
8370B63017F61001001A4D7A /* lanczos_resampler.c */,
|
||||||
8370B63117F61001001A4D7A /* lpc.c */,
|
8370B63117F61001001A4D7A /* lpc.c */,
|
||||||
|
@ -444,6 +450,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
8370B62D17F60FE2001A4D7A /* tarray.h in Headers */,
|
8370B62D17F60FE2001A4D7A /* tarray.h in Headers */,
|
||||||
|
83C8DF1F18C6B32100750AF7 /* blip_buf.h in Headers */,
|
||||||
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 */,
|
||||||
|
@ -581,6 +588,7 @@
|
||||||
17C8F6620CBEE797008D969D /* loadxm.c in Sources */,
|
17C8F6620CBEE797008D969D /* loadxm.c in Sources */,
|
||||||
17C8F6630CBEE797008D969D /* loadxm2.c in Sources */,
|
17C8F6630CBEE797008D969D /* loadxm2.c in Sources */,
|
||||||
8370B67117F61038001A4D7A /* loadpsm.c in Sources */,
|
8370B67117F61038001A4D7A /* loadpsm.c in Sources */,
|
||||||
|
83C8DF1D18C6B31400750AF7 /* blip_buf.c in Sources */,
|
||||||
8370B67617F61038001A4D7A /* loadriff2.c in Sources */,
|
8370B67617F61038001A4D7A /* loadriff2.c in Sources */,
|
||||||
8370B66C17F61038001A4D7A /* loadmtm2.c in Sources */,
|
8370B66C17F61038001A4D7A /* loadmtm2.c in Sources */,
|
||||||
8370B67A17F61038001A4D7A /* read669.c in Sources */,
|
8370B67A17F61038001A4D7A /* read669.c in Sources */,
|
||||||
|
|
|
@ -679,6 +679,11 @@ typedef struct DUMB_VOLUME_RAMP_INFO DUMB_VOLUME_RAMP_INFO;
|
||||||
|
|
||||||
typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data);
|
typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data);
|
||||||
|
|
||||||
|
#ifndef BLIP_T_DEFINED
|
||||||
|
#define BLIP_T_DEFINED
|
||||||
|
typedef struct blip_t blip_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct DUMB_RESAMPLER
|
struct DUMB_RESAMPLER
|
||||||
{
|
{
|
||||||
void *src;
|
void *src;
|
||||||
|
@ -696,6 +701,9 @@ struct DUMB_RESAMPLER
|
||||||
signed char x8[3*2];
|
signed char x8[3*2];
|
||||||
} x;
|
} x;
|
||||||
int overshot;
|
int overshot;
|
||||||
|
int last_clock;
|
||||||
|
int last_amp[2];
|
||||||
|
blip_t* blip_buffer[2];
|
||||||
double fir_resampler_ratio;
|
double fir_resampler_ratio;
|
||||||
void* fir_resampler[2];
|
void* fir_resampler[2];
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
/** \file
|
||||||
|
Sample buffer that resamples from input clock rate to output sample rate */
|
||||||
|
|
||||||
|
/* blip_buf 1.1.0 */
|
||||||
|
#ifndef BLIP_BUF_H
|
||||||
|
#define BLIP_BUF_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** First parameter of most functions is blip_t*, or const blip_t* if nothing
|
||||||
|
is changed. */
|
||||||
|
#ifndef BLIP_T_DEFINED
|
||||||
|
#define BLIP_T_DEFINED
|
||||||
|
typedef struct blip_t blip_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Creates new buffer that can hold at most sample_count samples. Sets rates
|
||||||
|
so that there are blip_max_ratio clocks per sample. Returns pointer to new
|
||||||
|
buffer, or NULL if insufficient memory. */
|
||||||
|
blip_t* blip_new( int sample_count );
|
||||||
|
|
||||||
|
blip_t* blip_dup( blip_t* );
|
||||||
|
|
||||||
|
/** Sets approximate input clock rate and output sample rate. For every
|
||||||
|
clock_rate input clocks, approximately sample_rate samples are generated. */
|
||||||
|
void blip_set_rates( blip_t*, double clock_rate, double sample_rate );
|
||||||
|
|
||||||
|
enum { /** Maximum clock_rate/sample_rate ratio. For a given sample_rate,
|
||||||
|
clock_rate must not be greater than sample_rate*blip_max_ratio. */
|
||||||
|
blip_max_ratio = 1 << 20 };
|
||||||
|
|
||||||
|
/** Clears entire buffer. Afterwards, blip_samples_avail() == 0. */
|
||||||
|
void blip_clear( blip_t* );
|
||||||
|
|
||||||
|
/** Adds positive/negative delta into buffer at specified clock time. */
|
||||||
|
void blip_add_delta( blip_t*, unsigned int clock_time, int delta );
|
||||||
|
|
||||||
|
/** Same as blip_add_delta(), but uses faster, lower-quality synthesis. */
|
||||||
|
void blip_add_delta_fast( blip_t*, unsigned int clock_time, int delta );
|
||||||
|
|
||||||
|
/** Length of time frame, in clocks, needed to make sample_count additional
|
||||||
|
samples available. */
|
||||||
|
int blip_clocks_needed( const blip_t*, int sample_count );
|
||||||
|
|
||||||
|
enum { /** Maximum number of samples that can be generated from one time frame. */
|
||||||
|
blip_max_frame = 4000 };
|
||||||
|
|
||||||
|
/** Makes input clocks before clock_duration available for reading as output
|
||||||
|
samples. Also begins new time frame at clock_duration, so that clock time 0 in
|
||||||
|
the new time frame specifies the same clock as clock_duration in the old time
|
||||||
|
frame specified. Deltas can have been added slightly past clock_duration (up to
|
||||||
|
however many clocks there are in two output samples). */
|
||||||
|
void blip_end_frame( blip_t*, unsigned int clock_duration );
|
||||||
|
|
||||||
|
/** Number of buffered samples available for reading. */
|
||||||
|
int blip_samples_avail( const blip_t* );
|
||||||
|
|
||||||
|
/** Reads and removes at most 'count' samples and writes them to 'out'. If
|
||||||
|
'stereo' is true, writes output to every other element of 'out', allowing easy
|
||||||
|
interleaving of two buffers into a stereo sample stream. Outputs 16-bit signed
|
||||||
|
samples. Returns number of samples actually read. */
|
||||||
|
int blip_read_samples( blip_t*, int out [], int count );
|
||||||
|
|
||||||
|
/** Reads the current integrator and returns it */
|
||||||
|
int blip_peek_sample( blip_t* );
|
||||||
|
|
||||||
|
/** Frees buffer. No effect if NULL is passed. */
|
||||||
|
void blip_delete( blip_t* );
|
||||||
|
|
||||||
|
|
||||||
|
/* Deprecated */
|
||||||
|
typedef blip_t blip_buffer_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,354 @@
|
||||||
|
/* blip_buf 1.1.0. http://www.slack.net/~ant/ */
|
||||||
|
|
||||||
|
#include "internal/blip_buf.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Library Copyright (C) 2003-2009 Shay Green. This library is free software;
|
||||||
|
you can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||||
|
General Public License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
|
library is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
|
#if defined (BLARGG_TEST) && BLARGG_TEST
|
||||||
|
#include "blargg_test.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Equivalent to ULONG_MAX >= 0xFFFFFFFF00000000.
|
||||||
|
Avoids constants that don't fit in 32 bits. */
|
||||||
|
#if ULONG_MAX/0xFFFFFFFF > 0xFFFFFFFF
|
||||||
|
typedef unsigned long fixed_t;
|
||||||
|
enum { pre_shift = 32 };
|
||||||
|
|
||||||
|
#elif defined(ULLONG_MAX)
|
||||||
|
typedef unsigned long long fixed_t;
|
||||||
|
enum { pre_shift = 32 };
|
||||||
|
|
||||||
|
#else
|
||||||
|
typedef unsigned fixed_t;
|
||||||
|
enum { pre_shift = 0 };
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum { time_bits = pre_shift + 20 };
|
||||||
|
|
||||||
|
static fixed_t const time_unit = (fixed_t) 1 << time_bits;
|
||||||
|
|
||||||
|
enum { bass_shift = 9 }; /* affects high-pass filter breakpoint frequency */
|
||||||
|
enum { end_frame_extra = 2 }; /* allows deltas slightly after frame length */
|
||||||
|
|
||||||
|
enum { half_width = 8 };
|
||||||
|
enum { buf_extra = half_width*2 + end_frame_extra };
|
||||||
|
enum { phase_bits = 5 };
|
||||||
|
enum { phase_count = 1 << phase_bits };
|
||||||
|
enum { delta_bits = 15 };
|
||||||
|
enum { delta_unit = 1 << delta_bits };
|
||||||
|
enum { frac_bits = time_bits - pre_shift };
|
||||||
|
|
||||||
|
/* We could eliminate avail and encode whole samples in offset, but that would
|
||||||
|
limit the total buffered samples to blip_max_frame. That could only be
|
||||||
|
increased by decreasing time_bits, which would reduce resample ratio accuracy.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Sample buffer that resamples to output rate and accumulates samples
|
||||||
|
until they're read out */
|
||||||
|
struct blip_t
|
||||||
|
{
|
||||||
|
fixed_t factor;
|
||||||
|
fixed_t offset;
|
||||||
|
int avail;
|
||||||
|
int size;
|
||||||
|
int integrator;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int buf_t;
|
||||||
|
|
||||||
|
/* probably not totally portable */
|
||||||
|
#define SAMPLES( buf ) ((buf_t*) ((buf) + 1))
|
||||||
|
|
||||||
|
/* Arithmetic (sign-preserving) right shift */
|
||||||
|
#define ARITH_SHIFT( n, shift ) \
|
||||||
|
((n) >> (shift))
|
||||||
|
|
||||||
|
enum { max_sample = +32767 };
|
||||||
|
enum { min_sample = -32768 };
|
||||||
|
|
||||||
|
#define CLAMP( n ) \
|
||||||
|
{\
|
||||||
|
if ( (short) n != n )\
|
||||||
|
n = ARITH_SHIFT( n, 16 ) ^ max_sample;\
|
||||||
|
}
|
||||||
|
|
||||||
|
static void check_assumptions( void )
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
#if INT_MAX < 0x7FFFFFFF || UINT_MAX < 0xFFFFFFFF
|
||||||
|
#error "int must be at least 32 bits"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
assert( (-3 >> 1) == -2 ); /* right shift must preserve sign */
|
||||||
|
|
||||||
|
n = max_sample * 2;
|
||||||
|
CLAMP( n );
|
||||||
|
assert( n == max_sample );
|
||||||
|
|
||||||
|
n = min_sample * 2;
|
||||||
|
CLAMP( n );
|
||||||
|
assert( n == min_sample );
|
||||||
|
|
||||||
|
assert( blip_max_ratio <= time_unit );
|
||||||
|
assert( blip_max_frame <= (fixed_t) -1 >> time_bits );
|
||||||
|
}
|
||||||
|
|
||||||
|
blip_t* blip_new( int size )
|
||||||
|
{
|
||||||
|
blip_t* m;
|
||||||
|
assert( size >= 0 );
|
||||||
|
|
||||||
|
m = (blip_t*) malloc( sizeof *m + (size + buf_extra) * sizeof (buf_t) );
|
||||||
|
if ( m )
|
||||||
|
{
|
||||||
|
m->factor = time_unit / blip_max_ratio;
|
||||||
|
m->size = size;
|
||||||
|
blip_clear( m );
|
||||||
|
check_assumptions();
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
blip_t* blip_dup( blip_t* m )
|
||||||
|
{
|
||||||
|
size_t size = sizeof *m + (m->size + buf_extra) * sizeof(buf_t);
|
||||||
|
blip_t* r = (blip_t*) malloc( size );
|
||||||
|
if ( r ) memcpy( r, m, size );
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void blip_delete( blip_t* m )
|
||||||
|
{
|
||||||
|
if ( m != NULL )
|
||||||
|
{
|
||||||
|
/* Clear fields in case user tries to use after freeing */
|
||||||
|
memset( m, 0, sizeof *m );
|
||||||
|
free( m );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void blip_set_rates( blip_t* m, double clock_rate, double sample_rate )
|
||||||
|
{
|
||||||
|
double factor = time_unit * sample_rate / clock_rate;
|
||||||
|
m->factor = (fixed_t) factor;
|
||||||
|
|
||||||
|
/* Fails if clock_rate exceeds maximum, relative to sample_rate */
|
||||||
|
assert( 0 <= factor - m->factor && factor - m->factor < 1 );
|
||||||
|
|
||||||
|
/* Avoid requiring math.h. Equivalent to
|
||||||
|
m->factor = (int) ceil( factor ) */
|
||||||
|
if ( m->factor < factor )
|
||||||
|
m->factor++;
|
||||||
|
|
||||||
|
/* At this point, factor is most likely rounded up, but could still
|
||||||
|
have been rounded down in the floating-point calculation. */
|
||||||
|
}
|
||||||
|
|
||||||
|
void blip_clear( blip_t* m )
|
||||||
|
{
|
||||||
|
/* We could set offset to 0, factor/2, or factor-1. 0 is suitable if
|
||||||
|
factor is rounded up. factor-1 is suitable if factor is rounded down.
|
||||||
|
Since we don't know rounding direction, factor/2 accommodates either,
|
||||||
|
with the slight loss of showing an error in half the time. Since for
|
||||||
|
a 64-bit factor this is years, the halving isn't a problem. */
|
||||||
|
|
||||||
|
m->offset = m->factor / 2;
|
||||||
|
m->avail = 0;
|
||||||
|
m->integrator = 0;
|
||||||
|
memset( SAMPLES( m ), 0, (m->size + buf_extra) * sizeof (buf_t) );
|
||||||
|
}
|
||||||
|
|
||||||
|
int blip_clocks_needed( const blip_t* m, int samples )
|
||||||
|
{
|
||||||
|
fixed_t needed;
|
||||||
|
|
||||||
|
/* Fails if buffer can't hold that many more samples */
|
||||||
|
assert( samples >= 0 && m->avail + samples <= m->size );
|
||||||
|
|
||||||
|
needed = (fixed_t) samples * time_unit;
|
||||||
|
if ( needed < m->offset )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (needed - m->offset + m->factor - 1) / m->factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void blip_end_frame( blip_t* m, unsigned t )
|
||||||
|
{
|
||||||
|
fixed_t off = t * m->factor + m->offset;
|
||||||
|
m->avail += off >> time_bits;
|
||||||
|
m->offset = off & (time_unit - 1);
|
||||||
|
|
||||||
|
/* Fails if buffer size was exceeded */
|
||||||
|
assert( m->avail <= m->size );
|
||||||
|
}
|
||||||
|
|
||||||
|
int blip_samples_avail( const blip_t* m )
|
||||||
|
{
|
||||||
|
return m->avail;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_samples( blip_t* m, int count )
|
||||||
|
{
|
||||||
|
buf_t* buf = SAMPLES( m );
|
||||||
|
int remain = m->avail + buf_extra - count;
|
||||||
|
m->avail -= count;
|
||||||
|
|
||||||
|
memmove( &buf [0], &buf [count], remain * sizeof buf [0] );
|
||||||
|
memset( &buf [remain], 0, count * sizeof buf [0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
int blip_read_samples( blip_t* m, int out [], int count )
|
||||||
|
{
|
||||||
|
assert( count >= 0 );
|
||||||
|
|
||||||
|
if ( count > m->avail )
|
||||||
|
count = m->avail;
|
||||||
|
|
||||||
|
if ( count )
|
||||||
|
{
|
||||||
|
buf_t const* in = SAMPLES( m );
|
||||||
|
buf_t const* end = in + count;
|
||||||
|
int sum = m->integrator;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Eliminate fraction */
|
||||||
|
int s = ARITH_SHIFT( sum, delta_bits - 8 );
|
||||||
|
|
||||||
|
sum += *in++;
|
||||||
|
|
||||||
|
*out = s;
|
||||||
|
out++;
|
||||||
|
|
||||||
|
/* High-pass filter */
|
||||||
|
sum -= s >> (8 - (delta_bits - bass_shift)); //<< (delta_bits - bass_shift - 8);
|
||||||
|
}
|
||||||
|
while ( in != end );
|
||||||
|
m->integrator = sum;
|
||||||
|
|
||||||
|
remove_samples( m, count );
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int blip_peek_sample( blip_t* m )
|
||||||
|
{
|
||||||
|
return ARITH_SHIFT( m->integrator, delta_bits - 8 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Things that didn't help performance on x86:
|
||||||
|
__attribute__((aligned(128)))
|
||||||
|
#define short int
|
||||||
|
restrict
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Sinc_Generator( 0.9, 0.55, 4.5 ) */
|
||||||
|
static short const bl_step [phase_count + 1] [half_width] =
|
||||||
|
{
|
||||||
|
{ 43, -115, 350, -488, 1136, -914, 5861,21022},
|
||||||
|
{ 44, -118, 348, -473, 1076, -799, 5274,21001},
|
||||||
|
{ 45, -121, 344, -454, 1011, -677, 4706,20936},
|
||||||
|
{ 46, -122, 336, -431, 942, -549, 4156,20829},
|
||||||
|
{ 47, -123, 327, -404, 868, -418, 3629,20679},
|
||||||
|
{ 47, -122, 316, -375, 792, -285, 3124,20488},
|
||||||
|
{ 47, -120, 303, -344, 714, -151, 2644,20256},
|
||||||
|
{ 46, -117, 289, -310, 634, -17, 2188,19985},
|
||||||
|
{ 46, -114, 273, -275, 553, 117, 1758,19675},
|
||||||
|
{ 44, -108, 255, -237, 471, 247, 1356,19327},
|
||||||
|
{ 43, -103, 237, -199, 390, 373, 981,18944},
|
||||||
|
{ 42, -98, 218, -160, 310, 495, 633,18527},
|
||||||
|
{ 40, -91, 198, -121, 231, 611, 314,18078},
|
||||||
|
{ 38, -84, 178, -81, 153, 722, 22,17599},
|
||||||
|
{ 36, -76, 157, -43, 80, 824, -241,17092},
|
||||||
|
{ 34, -68, 135, -3, 8, 919, -476,16558},
|
||||||
|
{ 32, -61, 115, 34, -60, 1006, -683,16001},
|
||||||
|
{ 29, -52, 94, 70, -123, 1083, -862,15422},
|
||||||
|
{ 27, -44, 73, 106, -184, 1152,-1015,14824},
|
||||||
|
{ 25, -36, 53, 139, -239, 1211,-1142,14210},
|
||||||
|
{ 22, -27, 34, 170, -290, 1261,-1244,13582},
|
||||||
|
{ 20, -20, 16, 199, -335, 1301,-1322,12942},
|
||||||
|
{ 18, -12, -3, 226, -375, 1331,-1376,12293},
|
||||||
|
{ 15, -4, -19, 250, -410, 1351,-1408,11638},
|
||||||
|
{ 13, 3, -35, 272, -439, 1361,-1419,10979},
|
||||||
|
{ 11, 9, -49, 292, -464, 1362,-1410,10319},
|
||||||
|
{ 9, 16, -63, 309, -483, 1354,-1383, 9660},
|
||||||
|
{ 7, 22, -75, 322, -496, 1337,-1339, 9005},
|
||||||
|
{ 6, 26, -85, 333, -504, 1312,-1280, 8355},
|
||||||
|
{ 4, 31, -94, 341, -507, 1278,-1205, 7713},
|
||||||
|
{ 3, 35, -102, 347, -506, 1238,-1119, 7082},
|
||||||
|
{ 1, 40, -110, 350, -499, 1190,-1021, 6464},
|
||||||
|
{ 0, 43, -115, 350, -488, 1136, -914, 5861}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Shifting by pre_shift allows calculation using unsigned int rather than
|
||||||
|
possibly-wider fixed_t. On 32-bit platforms, this is likely more efficient.
|
||||||
|
And by having pre_shift 32, a 32-bit platform can easily do the shift by
|
||||||
|
simply ignoring the low half. */
|
||||||
|
|
||||||
|
void blip_add_delta( blip_t* m, unsigned time, int delta )
|
||||||
|
{
|
||||||
|
unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift);
|
||||||
|
buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits);
|
||||||
|
|
||||||
|
int const phase_shift = frac_bits - phase_bits;
|
||||||
|
int phase = fixed >> phase_shift & (phase_count - 1);
|
||||||
|
short const* in = bl_step [phase];
|
||||||
|
short const* rev = bl_step [phase_count - phase];
|
||||||
|
|
||||||
|
int interp = fixed >> (phase_shift - delta_bits) & (delta_unit - 1);
|
||||||
|
int delta2 = (delta * interp) >> delta_bits;
|
||||||
|
delta -= delta2;
|
||||||
|
|
||||||
|
/* Fails if buffer size was exceeded */
|
||||||
|
assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] );
|
||||||
|
|
||||||
|
out [0] += in[0]*delta + in[half_width+0]*delta2;
|
||||||
|
out [1] += in[1]*delta + in[half_width+1]*delta2;
|
||||||
|
out [2] += in[2]*delta + in[half_width+2]*delta2;
|
||||||
|
out [3] += in[3]*delta + in[half_width+3]*delta2;
|
||||||
|
out [4] += in[4]*delta + in[half_width+4]*delta2;
|
||||||
|
out [5] += in[5]*delta + in[half_width+5]*delta2;
|
||||||
|
out [6] += in[6]*delta + in[half_width+6]*delta2;
|
||||||
|
out [7] += in[7]*delta + in[half_width+7]*delta2;
|
||||||
|
|
||||||
|
in = rev;
|
||||||
|
out [ 8] += in[7]*delta + in[7-half_width]*delta2;
|
||||||
|
out [ 9] += in[6]*delta + in[6-half_width]*delta2;
|
||||||
|
out [10] += in[5]*delta + in[5-half_width]*delta2;
|
||||||
|
out [11] += in[4]*delta + in[4-half_width]*delta2;
|
||||||
|
out [12] += in[3]*delta + in[3-half_width]*delta2;
|
||||||
|
out [13] += in[2]*delta + in[2-half_width]*delta2;
|
||||||
|
out [14] += in[1]*delta + in[1-half_width]*delta2;
|
||||||
|
out [15] += in[0]*delta + in[0-half_width]*delta2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void blip_add_delta_fast( blip_t* m, unsigned time, int delta )
|
||||||
|
{
|
||||||
|
unsigned fixed = (unsigned) ((time * m->factor + m->offset) >> pre_shift);
|
||||||
|
buf_t* out = SAMPLES( m ) + m->avail + (fixed >> frac_bits);
|
||||||
|
|
||||||
|
int interp = fixed >> (frac_bits - delta_bits) & (delta_unit - 1);
|
||||||
|
int delta2 = delta * interp;
|
||||||
|
|
||||||
|
/* Fails if buffer size was exceeded */
|
||||||
|
assert( out <= &SAMPLES( m ) [m->size + end_frame_extra] );
|
||||||
|
|
||||||
|
out [7] += delta * delta_unit - delta2;
|
||||||
|
out [8] += delta2;
|
||||||
|
}
|
|
@ -94,6 +94,8 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
|
||||||
#define SET_VOLUME_VARIABLES SET_MONO_DEST_VOLUME_VARIABLES
|
#define SET_VOLUME_VARIABLES SET_MONO_DEST_VOLUME_VARIABLES
|
||||||
#define RETURN_VOLUME_VARIABLES RETURN_MONO_DEST_VOLUME_VARIABLES
|
#define RETURN_VOLUME_VARIABLES RETURN_MONO_DEST_VOLUME_VARIABLES
|
||||||
#define VOLUMES_ARE_ZERO MONO_DEST_VOLUMES_ARE_ZERO
|
#define VOLUMES_ARE_ZERO MONO_DEST_VOLUMES_ARE_ZERO
|
||||||
|
#define MIX_ALIAS(count) MONO_DEST_MIX_ALIAS(count)
|
||||||
|
#define PEEK_ALIAS MONO_DEST_PEEK_ALIAS
|
||||||
#define PEEK_FIR MONO_DEST_PEEK_FIR
|
#define PEEK_FIR MONO_DEST_PEEK_FIR
|
||||||
#define MIX_FIR MONO_DEST_MIX_FIR
|
#define MIX_FIR MONO_DEST_MIX_FIR
|
||||||
#define MIX_LINEAR(op, upd, o0, o1) MONO_DEST_MIX_LINEAR(op, upd, o0, o1)
|
#define MIX_LINEAR(op, upd, o0, o1) MONO_DEST_MIX_LINEAR(op, upd, o0, o1)
|
||||||
|
@ -138,6 +140,8 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
|
||||||
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
||||||
}
|
}
|
||||||
#define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
#define VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
||||||
|
#define MIX_ALIAS(count) STEREO_DEST_MIX_ALIAS(count)
|
||||||
|
#define PEEK_ALIAS STEREO_DEST_PEEK_ALIAS
|
||||||
#define PEEK_FIR STEREO_DEST_PEEK_FIR
|
#define PEEK_FIR STEREO_DEST_PEEK_FIR
|
||||||
#define MIX_FIR STEREO_DEST_MIX_FIR
|
#define MIX_FIR STEREO_DEST_MIX_FIR
|
||||||
#define MIX_LINEAR(op, upd, o0, o1) STEREO_DEST_MIX_LINEAR(op, upd, o0, o1)
|
#define MIX_LINEAR(op, upd, o0, o1) STEREO_DEST_MIX_LINEAR(op, upd, o0, o1)
|
||||||
|
@ -151,12 +155,17 @@ static int process_pickup(DUMB_RESAMPLER *resampler)
|
||||||
#undef MONO_DEST_MIX_CUBIC
|
#undef MONO_DEST_MIX_CUBIC
|
||||||
#undef STEREO_DEST_MIX_LINEAR
|
#undef STEREO_DEST_MIX_LINEAR
|
||||||
#undef MONO_DEST_MIX_LINEAR
|
#undef MONO_DEST_MIX_LINEAR
|
||||||
|
#undef STEREO_DEST_MIX_ALIAS
|
||||||
|
#undef MONO_DEST_MIX_ALIAS
|
||||||
#undef MONO_DEST_VOLUMES_ARE_ZERO
|
#undef MONO_DEST_VOLUMES_ARE_ZERO
|
||||||
#undef SET_MONO_DEST_VOLUME_VARIABLES
|
#undef SET_MONO_DEST_VOLUME_VARIABLES
|
||||||
#undef RETURN_MONO_DEST_VOLUME_VARIABLES
|
#undef RETURN_MONO_DEST_VOLUME_VARIABLES
|
||||||
#undef MONO_DEST_VOLUME_ZEROS
|
#undef MONO_DEST_VOLUME_ZEROS
|
||||||
#undef MONO_DEST_VOLUME_VARIABLES
|
#undef MONO_DEST_VOLUME_VARIABLES
|
||||||
#undef MONO_DEST_VOLUME_PARAMETERS
|
#undef MONO_DEST_VOLUME_PARAMETERS
|
||||||
|
#undef STEREO_DEST_PEEK_ALIAS
|
||||||
|
#undef MONO_DEST_PEEK_ALIAS
|
||||||
|
#undef POKE_ALIAS
|
||||||
#undef MONO_DEST_PEEK_FIR
|
#undef MONO_DEST_PEEK_FIR
|
||||||
#undef STEREO_DEST_PEEK_FIR
|
#undef STEREO_DEST_PEEK_FIR
|
||||||
#undef MONO_DEST_MIX_FIR
|
#undef MONO_DEST_MIX_FIR
|
||||||
|
|
|
@ -52,6 +52,8 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
|
||||||
long todo;
|
long todo;
|
||||||
LONG_LONG todo64;
|
LONG_LONG todo64;
|
||||||
int quality;
|
int quality;
|
||||||
|
int blip_samples[256*SRC_CHANNELS];
|
||||||
|
int check;
|
||||||
|
|
||||||
if (!resampler || resampler->dir == 0) return 0;
|
if (!resampler || resampler->dir == 0) return 0;
|
||||||
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
ASSERT(resampler->dir == -1 || resampler->dir == 1);
|
||||||
|
@ -105,29 +107,39 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
|
||||||
subpos = (long)new_subpos & 65535;
|
subpos = (long)new_subpos & 65535;
|
||||||
} else if (quality <= DUMB_RQ_ALIASING) {
|
} else if (quality <= DUMB_RQ_ALIASING) {
|
||||||
/* Aliasing, backwards */
|
/* Aliasing, backwards */
|
||||||
SRCTYPE *x;
|
int todo_clocks = todo << 16, todo_clocks_set = todo_clocks;
|
||||||
if ( resampler->fir_resampler_ratio != delta ) {
|
SRCTYPE xbuf[2*SRC_CHANNELS];
|
||||||
lanczos_resampler_set_rate( resampler->fir_resampler[0], delta * 32.0 );
|
SRCTYPE *x = &xbuf[0];
|
||||||
lanczos_resampler_set_rate( resampler->fir_resampler[1], delta * 32.0 );
|
check = resampler->start;
|
||||||
resampler->fir_resampler_ratio = delta;
|
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||||
|
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||||
|
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||||
|
while (resampler->last_clock < todo_clocks_set && x < &xbuf[2*SRC_CHANNELS]) {
|
||||||
|
// TODO: check what happens when multiple tempo slides occur per row
|
||||||
|
HEAVYASSERT(pos >= resampler->start);
|
||||||
|
POKE_ALIAS(0);
|
||||||
|
pos--;
|
||||||
|
x += SRC_CHANNELS;
|
||||||
}
|
}
|
||||||
x = &src[pos*SRC_CHANNELS];
|
x = &src[pos*SRC_CHANNELS];
|
||||||
while ( todo ) {
|
while ( todo_clocks ) {
|
||||||
while ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
|
todo_clocks_set = todo_clocks;
|
||||||
pos >= resampler->start ) {
|
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||||
POKE_FIR(0);
|
todo_clocks -= todo_clocks_set;
|
||||||
if ( ( subpos -= 2048 ) < 0 ) {
|
while ( resampler->last_clock < todo_clocks_set && pos >= check ) {
|
||||||
pos--;
|
POKE_ALIAS(2);
|
||||||
x -= SRC_CHANNELS;
|
pos--;
|
||||||
subpos += 65536;
|
x -= SRC_CHANNELS;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
|
todo = todo_clocks_set >> 16;
|
||||||
MIX_FIR;
|
check = 0;
|
||||||
ADVANCE_FIR;
|
if ( resampler->last_clock < todo_clocks_set ) {
|
||||||
--todo;
|
check = ( todo_clocks_set - resampler->last_clock + 65535 ) >> 16;
|
||||||
|
}
|
||||||
|
todo -= check;
|
||||||
|
MIX_ALIAS( todo );
|
||||||
|
done -= check;
|
||||||
}
|
}
|
||||||
done -= todo;
|
|
||||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||||
/* Linear interpolation, backwards */
|
/* Linear interpolation, backwards */
|
||||||
SRCTYPE xbuf[3*SRC_CHANNELS];
|
SRCTYPE xbuf[3*SRC_CHANNELS];
|
||||||
|
@ -182,29 +194,30 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
|
||||||
x += (subpos >> 16) * SRC_CHANNELS;
|
x += (subpos >> 16) * SRC_CHANNELS;
|
||||||
subpos &= 65535;
|
subpos &= 65535;
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
/* 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 );
|
lanczos_resampler_set_rate( resampler->fir_resampler[0], delta );
|
||||||
lanczos_resampler_set_rate( resampler->fir_resampler[1], delta );
|
lanczos_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 ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
|
||||||
pos >= resampler->start ) {
|
pos >= resampler->start )
|
||||||
POKE_FIR(0);
|
{
|
||||||
pos--;
|
POKE_FIR(0);
|
||||||
x -= SRC_CHANNELS;
|
pos--;
|
||||||
}
|
x -= SRC_CHANNELS;
|
||||||
if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
|
}
|
||||||
MIX_FIR;
|
if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
|
||||||
ADVANCE_FIR;
|
MIX_FIR;
|
||||||
--todo;
|
ADVANCE_FIR;
|
||||||
}
|
--todo;
|
||||||
done -= todo;
|
}
|
||||||
}
|
done -= todo;
|
||||||
|
}
|
||||||
diff = diff - pos;
|
diff = diff - pos;
|
||||||
overshot = resampler->start - pos - 1;
|
overshot = resampler->start - pos - 1;
|
||||||
if (diff >= 3) {
|
if (diff >= 3) {
|
||||||
|
@ -228,29 +241,38 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
|
||||||
subpos = (long)new_subpos & 65535;
|
subpos = (long)new_subpos & 65535;
|
||||||
} else if (quality <= DUMB_RQ_ALIASING) {
|
} else if (quality <= DUMB_RQ_ALIASING) {
|
||||||
/* Aliasing, forwards */
|
/* Aliasing, forwards */
|
||||||
SRCTYPE *x;
|
int todo_clocks = todo << 16, todo_clocks_set = todo_clocks;
|
||||||
if ( resampler->fir_resampler_ratio != delta ) {
|
SRCTYPE xbuf[2*SRC_CHANNELS];
|
||||||
lanczos_resampler_set_rate( resampler->fir_resampler[0], delta * 32.0 );
|
SRCTYPE *x = &xbuf[0];
|
||||||
lanczos_resampler_set_rate( resampler->fir_resampler[1], delta * 32.0 );
|
check = resampler->end;
|
||||||
resampler->fir_resampler_ratio = delta;
|
COPYSRC(xbuf, 0, resampler->X, 1);
|
||||||
|
COPYSRC(xbuf, 1, resampler->X, 2);
|
||||||
|
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||||
|
while (resampler->last_clock < todo_clocks_set && x < &xbuf[2*SRC_CHANNELS]) {
|
||||||
|
HEAVYASSERT(pos < resampler->end);
|
||||||
|
POKE_ALIAS(0);
|
||||||
|
pos++;
|
||||||
|
x += SRC_CHANNELS;
|
||||||
}
|
}
|
||||||
x = &src[pos*SRC_CHANNELS];
|
x = &src[pos*SRC_CHANNELS];
|
||||||
while ( todo ) {
|
while ( todo_clocks ) {
|
||||||
while ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
|
todo_clocks_set = todo_clocks;
|
||||||
pos < resampler->end ) {
|
if ( todo_clocks_set > 256 * 65536 ) todo_clocks_set = 256 * 65536;
|
||||||
POKE_FIR(0);
|
todo_clocks -= todo_clocks_set;
|
||||||
if ( ( subpos += 2048 ) >= 65536 ) {
|
while ( resampler->last_clock < todo_clocks_set && pos < check ) {
|
||||||
pos++;
|
POKE_ALIAS(-2);
|
||||||
x += SRC_CHANNELS;
|
pos++;
|
||||||
subpos -= 65536;
|
x += SRC_CHANNELS;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
|
todo = todo_clocks_set >> 16;
|
||||||
MIX_FIR;
|
check = 0;
|
||||||
ADVANCE_FIR;
|
if ( resampler->last_clock < todo_clocks_set ) {
|
||||||
--todo;
|
check = ( todo_clocks_set - resampler->last_clock + 65535 ) >> 16;
|
||||||
|
}
|
||||||
|
todo -= check;
|
||||||
|
MIX_ALIAS( todo );
|
||||||
|
done -= check;
|
||||||
}
|
}
|
||||||
done -= todo;
|
|
||||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||||
/* Linear interpolation, forwards */
|
/* Linear interpolation, forwards */
|
||||||
SRCTYPE xbuf[3*SRC_CHANNELS];
|
SRCTYPE xbuf[3*SRC_CHANNELS];
|
||||||
|
@ -304,29 +326,30 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
|
||||||
x += (subpos >> 16) * SRC_CHANNELS;
|
x += (subpos >> 16) * SRC_CHANNELS;
|
||||||
subpos &= 65535;
|
subpos &= 65535;
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
/* 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 );
|
lanczos_resampler_set_rate( resampler->fir_resampler[0], delta );
|
||||||
lanczos_resampler_set_rate( resampler->fir_resampler[1], delta );
|
lanczos_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 ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
|
||||||
pos < resampler->end ) {
|
pos < resampler->end )
|
||||||
POKE_FIR(0);
|
{
|
||||||
pos++;
|
POKE_FIR(0);
|
||||||
x += SRC_CHANNELS;
|
pos++;
|
||||||
}
|
x += SRC_CHANNELS;
|
||||||
if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
|
}
|
||||||
MIX_FIR;
|
if ( !lanczos_resampler_get_sample_count( resampler->fir_resampler[0] ) ) break;
|
||||||
ADVANCE_FIR;
|
MIX_FIR;
|
||||||
--todo;
|
ADVANCE_FIR;
|
||||||
}
|
--todo;
|
||||||
done -= todo;
|
}
|
||||||
}
|
done -= todo;
|
||||||
|
}
|
||||||
diff = pos - diff;
|
diff = pos - diff;
|
||||||
overshot = pos - resampler->end;
|
overshot = pos - resampler->end;
|
||||||
if (diff >= 3) {
|
if (diff >= 3) {
|
||||||
|
@ -385,32 +408,32 @@ void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETE
|
||||||
HEAVYASSERT(pos >= resampler->start);
|
HEAVYASSERT(pos >= resampler->start);
|
||||||
if (quality <= DUMB_RQ_ALIASING) {
|
if (quality <= DUMB_RQ_ALIASING) {
|
||||||
/* Aliasing, backwards */
|
/* Aliasing, backwards */
|
||||||
PEEK_FIR;
|
PEEK_ALIAS;
|
||||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||||
/* Linear interpolation, backwards */
|
/* Linear interpolation, backwards */
|
||||||
MIX_LINEAR(=, 0, 2, 1);
|
MIX_LINEAR(=, 0, 2, 1);
|
||||||
} else if (quality <= DUMB_RQ_CUBIC) {
|
} else if (quality <= DUMB_RQ_CUBIC) {
|
||||||
/* Cubic interpolation, backwards */
|
/* Cubic interpolation, backwards */
|
||||||
MIX_CUBIC(=, 0, src, x, pos, 2, 1, 0);
|
MIX_CUBIC(=, 0, src, x, pos, 2, 1, 0);
|
||||||
} else {
|
} else {
|
||||||
/* FIR resampling, backwards */
|
/* FIR resampling, backwards */
|
||||||
PEEK_FIR;
|
PEEK_FIR;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
HEAVYASSERT(pos < resampler->end);
|
HEAVYASSERT(pos < resampler->end);
|
||||||
if (quality <= DUMB_RQ_ALIASING) {
|
if (quality <= DUMB_RQ_ALIASING) {
|
||||||
/* Aliasing */
|
/* Aliasing */
|
||||||
PEEK_FIR;
|
PEEK_ALIAS;
|
||||||
} else if (quality <= DUMB_RQ_LINEAR) {
|
} else if (quality <= DUMB_RQ_LINEAR) {
|
||||||
/* Linear interpolation, forwards */
|
/* Linear interpolation, forwards */
|
||||||
MIX_LINEAR(=, 0, 1, 2);
|
MIX_LINEAR(=, 0, 1, 2);
|
||||||
} else if (quality <= DUMB_RQ_CUBIC) {
|
} else if (quality <= DUMB_RQ_CUBIC) {
|
||||||
/* Cubic interpolation, forwards */
|
/* Cubic interpolation, forwards */
|
||||||
MIX_CUBIC(=, 0, x, src, 0, 1, 2, pos);
|
MIX_CUBIC(=, 0, x, src, 0, 1, 2, pos);
|
||||||
} else {
|
} else {
|
||||||
/* FIR resampling, forwards */
|
/* FIR resampling, forwards */
|
||||||
PEEK_FIR;
|
PEEK_FIR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +442,9 @@ void dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, VOLUME_PARAMETE
|
||||||
#undef MIX_ZEROS
|
#undef MIX_ZEROS
|
||||||
#undef MIX_CUBIC
|
#undef MIX_CUBIC
|
||||||
#undef MIX_LINEAR
|
#undef MIX_LINEAR
|
||||||
|
#undef MIX_ALIAS
|
||||||
#undef MIX_FIR
|
#undef MIX_FIR
|
||||||
|
#undef PEEK_ALIAS
|
||||||
#undef PEEK_FIR
|
#undef PEEK_FIR
|
||||||
#undef VOLUMES_ARE_ZERO
|
#undef VOLUMES_ARE_ZERO
|
||||||
#undef SET_VOLUME_VARIABLES
|
#undef SET_VOLUME_VARIABLES
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "dumb.h"
|
#include "dumb.h"
|
||||||
|
|
||||||
|
#include "internal/blip_buf.h"
|
||||||
#include "internal/lanczos_resampler.h"
|
#include "internal/lanczos_resampler.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,6 +191,7 @@ void _dumb_init_cubic(void)
|
||||||
|
|
||||||
#define SRCTYPE sample_t
|
#define SRCTYPE sample_t
|
||||||
#define SRCBITS 24
|
#define SRCBITS 24
|
||||||
|
#define ALIAS(x) (x >> 8)
|
||||||
#define FIR(x) (x >> 8)
|
#define FIR(x) (x >> 8)
|
||||||
#define LINEAR(x0, x1) (x0 + MULSC(x1 - x0, subpos))
|
#define LINEAR(x0, x1) (x0 + MULSC(x1 - x0, subpos))
|
||||||
/*
|
/*
|
||||||
|
@ -226,6 +228,7 @@ void _dumb_init_cubic(void)
|
||||||
#define SUFFIX _16
|
#define SUFFIX _16
|
||||||
#define SRCTYPE short
|
#define SRCTYPE short
|
||||||
#define SRCBITS 16
|
#define SRCBITS 16
|
||||||
|
#define ALIAS(x) (x)
|
||||||
#define FIR(x) (x)
|
#define FIR(x) (x)
|
||||||
#define LINEAR(x0, x1) ((x0 << 8) + MULSC16(x1 - x0, subpos))
|
#define LINEAR(x0, x1) ((x0 << 8) + MULSC16(x1 - x0, subpos))
|
||||||
/*
|
/*
|
||||||
|
@ -248,6 +251,7 @@ void _dumb_init_cubic(void)
|
||||||
#define SUFFIX _8
|
#define SUFFIX _8
|
||||||
#define SRCTYPE signed char
|
#define SRCTYPE signed char
|
||||||
#define SRCBITS 8
|
#define SRCBITS 8
|
||||||
|
#define ALIAS(x) (x << 8)
|
||||||
#define FIR(x) (x << 8)
|
#define FIR(x) (x << 8)
|
||||||
#define LINEAR(x0, x1) ((x0 << 16) + (x1 - x0) * subpos)
|
#define LINEAR(x0, x1) ((x0 << 16) + (x1 - x0) * subpos)
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -69,9 +69,14 @@ void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src, int src_chann
|
||||||
}
|
}
|
||||||
for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0;
|
for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0;
|
||||||
resampler->overshot = -1;
|
resampler->overshot = -1;
|
||||||
resampler->fir_resampler_ratio = 0;
|
resampler->last_clock = 0;
|
||||||
lanczos_resampler_clear(resampler->fir_resampler[0]);
|
resampler->last_amp[0] = 0;
|
||||||
lanczos_resampler_clear(resampler->fir_resampler[1]);
|
resampler->last_amp[1] = 0;
|
||||||
|
blip_clear(resampler->blip_buffer[0]);
|
||||||
|
blip_clear(resampler->blip_buffer[1]);
|
||||||
|
resampler->fir_resampler_ratio = 0;
|
||||||
|
lanczos_resampler_clear(resampler->fir_resampler[0]);
|
||||||
|
lanczos_resampler_clear(resampler->fir_resampler[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,6 +85,21 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
|
||||||
{
|
{
|
||||||
DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
|
DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
|
||||||
if (!resampler) return NULL;
|
if (!resampler) return NULL;
|
||||||
|
resampler->blip_buffer[0] = blip_new( 256 );
|
||||||
|
if (!resampler->blip_buffer[0])
|
||||||
|
{
|
||||||
|
free(resampler);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
resampler->blip_buffer[1] = blip_new( 256 );
|
||||||
|
if (!resampler->blip_buffer[1])
|
||||||
|
{
|
||||||
|
free(resampler->blip_buffer[0]);
|
||||||
|
free(resampler);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
blip_set_rates(resampler->blip_buffer[0], 65536, 1);
|
||||||
|
blip_set_rates(resampler->blip_buffer[1], 65536, 1);
|
||||||
dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
|
dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
|
||||||
return resampler;
|
return resampler;
|
||||||
}
|
}
|
||||||
|
@ -128,15 +148,38 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
|
||||||
}
|
}
|
||||||
#define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = (float)volr / 16777216.0f
|
#define RETURN_MONO_DEST_VOLUME_VARIABLES if ( volume ) volume->volume = (float)volr / 16777216.0f
|
||||||
#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0)
|
#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0 && volt == 0)
|
||||||
|
#define POKE_ALIAS(offset) { \
|
||||||
|
int delta = ALIAS(x[offset]) - resampler->last_amp[0]; \
|
||||||
|
resampler->last_amp[0] += delta; \
|
||||||
|
if ( delta ) blip_add_delta( resampler->blip_buffer[0], resampler->last_clock, delta ); \
|
||||||
|
resampler->last_clock += inv_dt; \
|
||||||
|
}
|
||||||
#define POKE_FIR(offset) { \
|
#define POKE_FIR(offset) { \
|
||||||
lanczos_resampler_write_sample( resampler->fir_resampler[0], FIR(x[offset]) ); \
|
lanczos_resampler_write_sample( resampler->fir_resampler[0], FIR(x[offset]) ); \
|
||||||
}
|
}
|
||||||
|
#define MONO_DEST_PEEK_ALIAS *dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), vol )
|
||||||
#define MONO_DEST_PEEK_FIR *dst = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), vol )
|
#define MONO_DEST_PEEK_FIR *dst = MULSC( lanczos_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( lanczos_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 lanczos_resampler_remove_sample( resampler->fir_resampler[0] )
|
||||||
|
#define MONO_DEST_MIX_ALIAS(count) { \
|
||||||
|
int n = 0; \
|
||||||
|
resampler->last_clock -= count * 65536; \
|
||||||
|
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||||
|
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||||
|
LOOP4( count, \
|
||||||
|
*dst++ += MULSC( blip_samples[n], vol ); \
|
||||||
|
n++; \
|
||||||
|
UPDATE_VOLUME( volume, vol ); \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
#define STEREO_DEST_PEEK_ALIAS { \
|
||||||
|
int sample = blip_peek_sample( resampler->blip_buffer[0] ); \
|
||||||
|
*dst++ = MULSC( sample, lvol ); \
|
||||||
|
*dst++ = MULSC( sample, rvol ); \
|
||||||
|
}
|
||||||
#define STEREO_DEST_PEEK_FIR { \
|
#define STEREO_DEST_PEEK_FIR { \
|
||||||
int sample = lanczos_resampler_get_sample( resampler->fir_resampler[0] ); \
|
int sample = lanczos_resampler_get_sample( resampler->fir_resampler[0] ); \
|
||||||
*dst++ = MULSC( sample, lvol ); \
|
*dst++ = MULSC( sample, lvol ); \
|
||||||
|
@ -149,6 +192,19 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
|
||||||
UPDATE_VOLUME( volume_left, lvol ); \
|
UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
UPDATE_VOLUME( volume_right, rvol ); \
|
UPDATE_VOLUME( volume_right, rvol ); \
|
||||||
}
|
}
|
||||||
|
#define STEREO_DEST_MIX_ALIAS(count) { \
|
||||||
|
int sample, n = 0; \
|
||||||
|
resampler->last_clock -= count * 65536; \
|
||||||
|
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||||
|
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||||
|
LOOP4( count, \
|
||||||
|
sample = blip_samples[n++]; \
|
||||||
|
*dst++ += MULSC( sample, lvol ); \
|
||||||
|
*dst++ += MULSC( sample, rvol ); \
|
||||||
|
UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
|
UPDATE_VOLUME( volume_right, rvol ); \
|
||||||
|
); \
|
||||||
|
}
|
||||||
#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
||||||
*dst++ op MULSC(LINEAR(x[o0], x[o1]), vol); \
|
*dst++ op MULSC(LINEAR(x[o0], x[o1]), vol); \
|
||||||
if ( upd ) UPDATE_VOLUME( volume, vol ); \
|
if ( upd ) UPDATE_VOLUME( volume, vol ); \
|
||||||
|
@ -227,10 +283,23 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
|
||||||
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
if ( volume_right ) volume_right->volume = (float)rvolr / 16777216.0f; \
|
||||||
}
|
}
|
||||||
#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && lvolt == 0 && rvol == 0 && rvolt == 0)
|
||||||
|
#define POKE_ALIAS(offset) { \
|
||||||
|
int deltal = ALIAS(x[(offset)*2+0]) - resampler->last_amp[0]; \
|
||||||
|
int deltar = ALIAS(x[(offset)*2+1]) - resampler->last_amp[1]; \
|
||||||
|
resampler->last_amp[0] += deltal; \
|
||||||
|
resampler->last_amp[1] += deltar; \
|
||||||
|
if ( deltal ) blip_add_delta( resampler->blip_buffer[0], resampler->last_clock, deltal ); \
|
||||||
|
if ( deltar ) blip_add_delta( resampler->blip_buffer[1], resampler->last_clock, deltar ); \
|
||||||
|
resampler->last_clock += inv_dt; \
|
||||||
|
}
|
||||||
#define POKE_FIR(offset) { \
|
#define POKE_FIR(offset) { \
|
||||||
lanczos_resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \
|
lanczos_resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \
|
||||||
lanczos_resampler_write_sample( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \
|
lanczos_resampler_write_sample( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \
|
||||||
}
|
}
|
||||||
|
#define MONO_DEST_PEEK_ALIAS { \
|
||||||
|
*dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ) + \
|
||||||
|
MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
|
||||||
|
}
|
||||||
#define MONO_DEST_PEEK_FIR { \
|
#define MONO_DEST_PEEK_FIR { \
|
||||||
*dst = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
|
*dst = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
|
||||||
MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
||||||
|
@ -245,6 +314,24 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
|
||||||
lanczos_resampler_remove_sample( resampler->fir_resampler[0] ); \
|
lanczos_resampler_remove_sample( resampler->fir_resampler[0] ); \
|
||||||
lanczos_resampler_remove_sample( resampler->fir_resampler[1] ); \
|
lanczos_resampler_remove_sample( resampler->fir_resampler[1] ); \
|
||||||
}
|
}
|
||||||
|
#define MONO_DEST_MIX_ALIAS(count) { \
|
||||||
|
int n = 0; \
|
||||||
|
resampler->last_clock -= count * 65536; \
|
||||||
|
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||||
|
blip_end_frame( resampler->blip_buffer[1], count * 65536 ); \
|
||||||
|
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||||
|
blip_read_samples( resampler->blip_buffer[1], blip_samples + 256, count ); \
|
||||||
|
LOOP4( count, \
|
||||||
|
*dst++ += MULSC( blip_samples[n], lvol ) + MULSC( blip_samples[256+n], rvol ); \
|
||||||
|
n++; \
|
||||||
|
UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
|
UPDATE_VOLUME( volume_right, rvol ); \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
#define STEREO_DEST_PEEK_ALIAS { \
|
||||||
|
*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ); \
|
||||||
|
*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
|
||||||
|
}
|
||||||
#define STEREO_DEST_PEEK_FIR { \
|
#define STEREO_DEST_PEEK_FIR { \
|
||||||
*dst++ = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
|
*dst++ = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
|
||||||
*dst++ = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
*dst++ = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
|
||||||
|
@ -255,6 +342,21 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
|
||||||
UPDATE_VOLUME( volume_left, lvol ); \
|
UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
UPDATE_VOLUME( volume_right, rvol ); \
|
UPDATE_VOLUME( volume_right, rvol ); \
|
||||||
}
|
}
|
||||||
|
#define STEREO_DEST_MIX_ALIAS(count) { \
|
||||||
|
int n = 0; \
|
||||||
|
resampler->last_clock -= count * 65536; \
|
||||||
|
blip_end_frame( resampler->blip_buffer[0], count * 65536 ); \
|
||||||
|
blip_end_frame( resampler->blip_buffer[1], count * 65536 ); \
|
||||||
|
blip_read_samples( resampler->blip_buffer[0], blip_samples, count ); \
|
||||||
|
blip_read_samples( resampler->blip_buffer[1], blip_samples + 256, count ); \
|
||||||
|
LOOP4( count, \
|
||||||
|
*dst++ += MULSC( blip_samples[n], lvol); \
|
||||||
|
*dst++ += MULSC( blip_samples[256+n], rvol); \
|
||||||
|
n++; \
|
||||||
|
UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
|
UPDATE_VOLUME( volume_right, rvol ); \
|
||||||
|
); \
|
||||||
|
}
|
||||||
#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
#define MONO_DEST_MIX_LINEAR(op, upd, o0, o1) { \
|
||||||
*dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol) + MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol); \
|
*dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol) + MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol); \
|
||||||
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
|
if ( upd ) UPDATE_VOLUME( volume_left, lvol ); \
|
||||||
|
@ -294,6 +396,7 @@ void dumb_end_resampler(DUMB_RESAMPLER *resampler)
|
||||||
#undef CUBICVOL
|
#undef CUBICVOL
|
||||||
#undef CUBIC
|
#undef CUBIC
|
||||||
#undef LINEAR
|
#undef LINEAR
|
||||||
|
#undef ALIAS
|
||||||
#undef FIR
|
#undef FIR
|
||||||
#undef SRCBITS
|
#undef SRCBITS
|
||||||
#undef SRCTYPE
|
#undef SRCTYPE
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "internal/it.h"
|
#include "internal/it.h"
|
||||||
#include "internal/lpc.h"
|
#include "internal/lpc.h"
|
||||||
|
|
||||||
|
#include "internal/blip_buf.h"
|
||||||
#include "internal/lanczos_resampler.h"
|
#include "internal/lanczos_resampler.h"
|
||||||
|
|
||||||
// #define BIT_ARRAY_BULLSHIT
|
// #define BIT_ARRAY_BULLSHIT
|
||||||
|
@ -38,15 +39,34 @@ static IT_PLAYING *new_playing()
|
||||||
IT_PLAYING * r = (IT_PLAYING*) malloc(sizeof(*r));
|
IT_PLAYING * r = (IT_PLAYING*) malloc(sizeof(*r));
|
||||||
if (r)
|
if (r)
|
||||||
{
|
{
|
||||||
|
r->resampler.blip_buffer[0] = blip_new( 256 );
|
||||||
|
if ( !r->resampler.blip_buffer[0] )
|
||||||
|
{
|
||||||
|
free( r );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
r->resampler.blip_buffer[1] = blip_new( 256 );
|
||||||
|
if ( !r->resampler.blip_buffer[1] )
|
||||||
|
{
|
||||||
|
free( r->resampler.blip_buffer[0] );
|
||||||
|
free( r );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
blip_set_rates(r->resampler.blip_buffer[0], 65536, 1);
|
||||||
|
blip_set_rates(r->resampler.blip_buffer[1], 65536, 1);
|
||||||
r->resampler.fir_resampler_ratio = 0.0;
|
r->resampler.fir_resampler_ratio = 0.0;
|
||||||
r->resampler.fir_resampler[0] = lanczos_resampler_create();
|
r->resampler.fir_resampler[0] = lanczos_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[0] );
|
||||||
free( r );
|
free( r );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
r->resampler.fir_resampler[1] = lanczos_resampler_create();
|
r->resampler.fir_resampler[1] = lanczos_resampler_create();
|
||||||
if ( !r->resampler.fir_resampler[1] ) {
|
if ( !r->resampler.fir_resampler[1] ) {
|
||||||
lanczos_resampler_delete( r->resampler.fir_resampler[0] );
|
lanczos_resampler_delete( r->resampler.fir_resampler[0] );
|
||||||
|
free( r->resampler.blip_buffer[1] );
|
||||||
|
free( r->resampler.blip_buffer[0] );
|
||||||
free( r );
|
free( r );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -58,6 +78,8 @@ static void free_playing(IT_PLAYING * r)
|
||||||
{
|
{
|
||||||
lanczos_resampler_delete( r->resampler.fir_resampler[1] );
|
lanczos_resampler_delete( r->resampler.fir_resampler[1] );
|
||||||
lanczos_resampler_delete( r->resampler.fir_resampler[0] );
|
lanczos_resampler_delete( r->resampler.fir_resampler[0] );
|
||||||
|
blip_delete( r->resampler.blip_buffer[1] );
|
||||||
|
blip_delete( r->resampler.blip_buffer[0] );
|
||||||
free( r );
|
free( r );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,15 +172,32 @@ static IT_PLAYING *dup_playing(IT_PLAYING *src, IT_CHANNEL *dstchannel, IT_CHANN
|
||||||
|
|
||||||
dst->resampler = src->resampler;
|
dst->resampler = src->resampler;
|
||||||
dst->resampler.pickup_data = dst;
|
dst->resampler.pickup_data = dst;
|
||||||
|
dst->resampler.blip_buffer[0] = blip_dup( src->resampler.blip_buffer[0] );
|
||||||
|
if ( !dst->resampler.blip_buffer[0] )
|
||||||
|
{
|
||||||
|
free( dst );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dst->resampler.blip_buffer[1] = blip_dup( src->resampler.blip_buffer[1] );
|
||||||
|
if ( !dst->resampler.blip_buffer[1] )
|
||||||
|
{
|
||||||
|
blip_delete( dst->resampler.blip_buffer[0] );
|
||||||
|
free( dst );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
dst->resampler.fir_resampler_ratio = src->resampler.fir_resampler_ratio;
|
dst->resampler.fir_resampler_ratio = src->resampler.fir_resampler_ratio;
|
||||||
dst->resampler.fir_resampler[0] = lanczos_resampler_dup( src->resampler.fir_resampler[0] );
|
dst->resampler.fir_resampler[0] = lanczos_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[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] = lanczos_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] );
|
lanczos_resampler_delete( dst->resampler.fir_resampler[0] );
|
||||||
|
blip_delete( dst->resampler.blip_buffer[1] );
|
||||||
|
blip_delete( dst->resampler.blip_buffer[0] );
|
||||||
free( dst );
|
free( dst );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -2569,8 +2608,11 @@ Yxy This uses a table 4 times larger (hence 4 times slower) than
|
||||||
end = sample->sus_loop_end;
|
end = sample->sus_loop_end;
|
||||||
else if (sample->flags & IT_SAMPLE_LOOP)
|
else if (sample->flags & IT_SAMPLE_LOOP)
|
||||||
end = sample->loop_end;
|
end = sample->loop_end;
|
||||||
else
|
else {
|
||||||
end = sample->length;
|
end = sample->length;
|
||||||
|
if ( sigdata->flags & IT_WAS_PROCESSED && end > 64 ) // XXX bah damn LPC and edge case modules
|
||||||
|
end -= 64;
|
||||||
|
}
|
||||||
if ((sigdata->flags & IT_WAS_A_PTM) && (sample->flags & IT_SAMPLE_16BIT))
|
if ((sigdata->flags & IT_WAS_A_PTM) && (sample->flags & IT_SAMPLE_16BIT))
|
||||||
offset >>= 1;
|
offset >>= 1;
|
||||||
if (offset < end) {
|
if (offset < end) {
|
||||||
|
@ -3847,14 +3889,14 @@ static int update_it_envelope(IT_PLAYING *playing, IT_ENVELOPE *envelope, IT_PLA
|
||||||
if ((envelope->flags & IT_ENVELOPE_SUSTAIN_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF)) {
|
if ((envelope->flags & IT_ENVELOPE_SUSTAIN_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF)) {
|
||||||
if (pe->tick > envelope->node_t[envelope->sus_loop_end]) {
|
if (pe->tick > envelope->node_t[envelope->sus_loop_end]) {
|
||||||
pe->next_node = envelope->sus_loop_start + 1;
|
pe->next_node = envelope->sus_loop_start + 1;
|
||||||
ASSERT(pe->next_node < envelope->n_nodes);
|
ASSERT(pe->next_node <= envelope->n_nodes);
|
||||||
pe->tick = envelope->node_t[envelope->sus_loop_start];
|
pe->tick = envelope->node_t[envelope->sus_loop_start];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if (envelope->flags & IT_ENVELOPE_LOOP_ON) {
|
} else if (envelope->flags & IT_ENVELOPE_LOOP_ON) {
|
||||||
if (pe->tick > envelope->node_t[envelope->loop_end]) {
|
if (pe->tick > envelope->node_t[envelope->loop_end]) {
|
||||||
pe->next_node = envelope->loop_start + 1;
|
pe->next_node = envelope->loop_start + 1;
|
||||||
ASSERT(pe->next_node < envelope->n_nodes);
|
ASSERT(pe->next_node <= envelope->n_nodes);
|
||||||
pe->tick = envelope->node_t[envelope->loop_start];
|
pe->tick = envelope->node_t[envelope->loop_start];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue