Major overhaul of module playback routines, including a new band-limited linear interpolation mode, softer default pan separation, and better band-limited synthesis for MOD files
parent
9c54354c44
commit
1950124506
|
@ -676,9 +676,10 @@ void dumb_destroy_click_remover_array(int n, DUMB_CLICK_REMOVER **cr);
|
|||
#define DUMB_RQ_ALIASING 0
|
||||
#define DUMB_RQ_BLEP 1
|
||||
#define DUMB_RQ_LINEAR 2
|
||||
#define DUMB_RQ_CUBIC 3
|
||||
#define DUMB_RQ_FIR 4
|
||||
#define DUMB_RQ_N_LEVELS 5
|
||||
#define DUMB_RQ_BLAM 3
|
||||
#define DUMB_RQ_CUBIC 4
|
||||
#define DUMB_RQ_FIR 5
|
||||
#define DUMB_RQ_N_LEVELS 6
|
||||
|
||||
extern int dumb_resampling_quality; /* This specifies the default */
|
||||
void dumb_it_set_resampling_quality(DUMB_IT_SIGRENDERER * sigrenderer, int quality); /* This overrides it */
|
||||
|
@ -767,6 +768,11 @@ void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler, DU
|
|||
void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst);
|
||||
void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler);
|
||||
|
||||
/* This sets the default panning separation for hard panned formats,
|
||||
or for formats with default panning information. This must be set
|
||||
before using any readers or loaders, and is not really thread safe. */
|
||||
|
||||
extern int dumb_it_default_panning_separation; /* in percent, default 25 */
|
||||
|
||||
/* DUH Construction */
|
||||
|
||||
|
|
|
@ -36,9 +36,10 @@ enum
|
|||
RESAMPLER_QUALITY_ZOH = 0,
|
||||
RESAMPLER_QUALITY_BLEP = 1,
|
||||
RESAMPLER_QUALITY_LINEAR = 2,
|
||||
RESAMPLER_QUALITY_CUBIC = 3,
|
||||
RESAMPLER_QUALITY_SINC = 4,
|
||||
RESAMPLER_QUALITY_MAX = 4
|
||||
RESAMPLER_QUALITY_BLAM = 3,
|
||||
RESAMPLER_QUALITY_CUBIC = 4,
|
||||
RESAMPLER_QUALITY_SINC = 5,
|
||||
RESAMPLER_QUALITY_MAX = 5
|
||||
};
|
||||
|
||||
void resampler_set_quality(void *, int quality);
|
||||
|
@ -52,6 +53,6 @@ void resampler_clear(void *);
|
|||
int resampler_get_sample_count(void *);
|
||||
int resampler_get_sample(void *);
|
||||
float resampler_get_sample_float(void *);
|
||||
void resampler_remove_sample(void *);
|
||||
void resampler_remove_sample(void *, int decay);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -114,8 +114,12 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
|
|||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
while ( todo ) {
|
||||
while ( resampler_get_free_count( resampler->fir_resampler[0] ) &&
|
||||
pos >= resampler->start )
|
||||
while ( ( resampler_get_free_count( resampler->fir_resampler[0] ) ||
|
||||
(!resampler_get_sample_count( resampler->fir_resampler[0] )
|
||||
#if SRC_CHANNELS == 2
|
||||
&& !resampler_get_sample_count( resampler->fir_resampler[1] )
|
||||
#endif
|
||||
) ) && pos >= resampler->start )
|
||||
{
|
||||
POKE_FIR(0);
|
||||
pos--;
|
||||
|
@ -159,8 +163,12 @@ long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, VOLU
|
|||
}
|
||||
x = &src[pos*SRC_CHANNELS];
|
||||
while ( todo ) {
|
||||
while ( resampler_get_free_count( resampler->fir_resampler[0] ) &&
|
||||
pos < resampler->end )
|
||||
while ( ( resampler_get_free_count( resampler->fir_resampler[0] ) ||
|
||||
(!resampler_get_sample_count( resampler->fir_resampler[0] )
|
||||
#if SRC_CHANNELS == 2
|
||||
&& !resampler_get_sample_count( resampler->fir_resampler[1] )
|
||||
#endif
|
||||
) ) && pos < resampler->end )
|
||||
{
|
||||
POKE_FIR(0);
|
||||
pos++;
|
||||
|
|
|
@ -74,13 +74,14 @@
|
|||
* 0 - DUMB_RQ_ALIASING - fastest
|
||||
* 1 - DUMB_RQ_BLEP - nicer than aliasing, but slower
|
||||
* 2 - DUMB_RQ_LINEAR
|
||||
* 3 - DUMB_RQ_CUBIC
|
||||
* 4 - DUMB_RQ_FIR - nicest
|
||||
* 3 - DUMB_RQ_BLAM - band-limited linear interpolation, nice but slower
|
||||
* 4 - DUMB_RQ_CUBIC
|
||||
* 5 - DUMB_RQ_FIR - nicest
|
||||
*
|
||||
* Values outside the range 0-4 will behave the same as the nearest
|
||||
* value within the range.
|
||||
*/
|
||||
int dumb_resampling_quality = DUMB_RQ_CUBIC;
|
||||
int dumb_resampling_quality = DUMB_RQ_BLAM;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
|
|||
*dst++ += MULSC( resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
|
||||
UPDATE_VOLUME( volume, vol ); \
|
||||
}
|
||||
#define ADVANCE_FIR resampler_remove_sample( resampler->fir_resampler[0] )
|
||||
#define ADVANCE_FIR resampler_remove_sample( resampler->fir_resampler[0], 1 )
|
||||
#define STEREO_DEST_PEEK_FIR { \
|
||||
int sample = resampler_get_sample( resampler->fir_resampler[0] ); \
|
||||
*dst++ = MULSC( sample, lvol ); \
|
||||
|
@ -225,8 +225,8 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l
|
|||
UPDATE_VOLUME( volume_right, rvol ); \
|
||||
}
|
||||
#define ADVANCE_FIR { \
|
||||
resampler_remove_sample( resampler->fir_resampler[0] ); \
|
||||
resampler_remove_sample( resampler->fir_resampler[1] ); \
|
||||
resampler_remove_sample( resampler->fir_resampler[0], 1 ); \
|
||||
resampler_remove_sample( resampler->fir_resampler[1], 1 ); \
|
||||
}
|
||||
#define STEREO_DEST_PEEK_FIR { \
|
||||
*dst++ = MULSC( resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,6 +21,8 @@
|
|||
#include "internal/it.h"
|
||||
|
||||
|
||||
int dumb_it_default_panning_separation = 25;
|
||||
|
||||
|
||||
DUMB_IT_SIGDATA *duh_get_it_sigdata(DUH *duh)
|
||||
{
|
||||
|
|
|
@ -3976,7 +3976,7 @@ static void process_playing(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playin
|
|||
playing->sample_vibrato_time += playing->sample->vibrato_speed;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||
static float log2(float x) {return (float)log(x)/(float)log(2.0f);}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -413,8 +413,9 @@ static DUMB_IT_SIGDATA *it_669_load_sigdata(DUMBFILE *f, int * ext)
|
|||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (i = 0; i < DUMB_IT_N_CHANNELS; i += 2) {
|
||||
sigdata->channel_pan[i+0] = 48;
|
||||
sigdata->channel_pan[i+1] = 16;
|
||||
int sep = 32 * dumb_it_default_panning_separation / 100;
|
||||
sigdata->channel_pan[i+0] = 32 + sep;
|
||||
sigdata->channel_pan[i+1] = 32 - sep;
|
||||
}
|
||||
|
||||
_dumb_it_fix_invalid_orders(sigdata);
|
||||
|
|
|
@ -347,10 +347,11 @@ static DUMB_IT_SIGDATA *it_riff_amff_load_sigdata( DUMBFILE * f, struct riff * s
|
|||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
|
||||
sigdata->channel_pan[n ] = 16;
|
||||
sigdata->channel_pan[n+1] = 48;
|
||||
sigdata->channel_pan[n+2] = 48;
|
||||
sigdata->channel_pan[n+3] = 16;
|
||||
int sep = 32 * dumb_it_default_panning_separation / 100;
|
||||
sigdata->channel_pan[n ] = 32 - sep;
|
||||
sigdata->channel_pan[n+1] = 32 + sep;
|
||||
sigdata->channel_pan[n+2] = 32 + sep;
|
||||
sigdata->channel_pan[n+3] = 32 - sep;
|
||||
}
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
|
@ -578,10 +579,11 @@ static DUMB_IT_SIGDATA *it_riff_am_load_sigdata( DUMBFILE * f, struct riff * str
|
|||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
|
||||
sigdata->channel_pan[n ] = 16;
|
||||
sigdata->channel_pan[n+1] = 48;
|
||||
sigdata->channel_pan[n+2] = 48;
|
||||
sigdata->channel_pan[n+3] = 16;
|
||||
int sep = 32 * dumb_it_default_panning_separation / 100;
|
||||
sigdata->channel_pan[n ] = 32 - sep;
|
||||
sigdata->channel_pan[n+1] = 32 + sep;
|
||||
sigdata->channel_pan[n+2] = 32 + sep;
|
||||
sigdata->channel_pan[n+3] = 32 - sep;
|
||||
}
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
|
|
|
@ -334,8 +334,9 @@ static DUMB_IT_SIGDATA *it_amf_load_sigdata(DUMBFILE *f, int * version)
|
|||
}
|
||||
}
|
||||
else {
|
||||
int sep = 32 * dumb_it_default_panning_separation / 100;
|
||||
for ( i = 0; i < 16; i++ ) {
|
||||
sigdata->channel_pan[ i ] = ( dumbfile_getc( f ) & 1 ) ? 16 : 48;
|
||||
sigdata->channel_pan[ i ] = ( dumbfile_getc( f ) & 1 ) ? 32 - sep : 32 + sep;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -303,10 +303,11 @@ static DUMB_IT_SIGDATA *it_asy_load_sigdata(DUMBFILE *f)
|
|||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) {
|
||||
sigdata->channel_pan[i+0] = 16;
|
||||
sigdata->channel_pan[i+1] = 48;
|
||||
sigdata->channel_pan[i+2] = 48;
|
||||
sigdata->channel_pan[i+3] = 16;
|
||||
int sep = 32 * dumb_it_default_panning_separation / 100;
|
||||
sigdata->channel_pan[i+0] = 32 - sep;
|
||||
sigdata->channel_pan[i+1] = 32 + sep;
|
||||
sigdata->channel_pan[i+2] = 32 + sep;
|
||||
sigdata->channel_pan[i+3] = 32 - sep;
|
||||
}
|
||||
|
||||
_dumb_it_fix_invalid_orders(sigdata);
|
||||
|
|
|
@ -272,10 +272,11 @@ static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( DUMBFILE * f, struct riff * s
|
|||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
|
||||
sigdata->channel_pan[n ] = 16;
|
||||
sigdata->channel_pan[n+1] = 48;
|
||||
sigdata->channel_pan[n+2] = 48;
|
||||
sigdata->channel_pan[n+3] = 16;
|
||||
int sep = 32 * dumb_it_default_panning_separation / 100;
|
||||
sigdata->channel_pan[n ] = 32 - sep;
|
||||
sigdata->channel_pan[n+1] = 32 + sep;
|
||||
sigdata->channel_pan[n+2] = 32 + sep;
|
||||
sigdata->channel_pan[n+3] = 32 - sep;
|
||||
}
|
||||
|
||||
for ( n = 0; (unsigned)n < stream->chunk_count; ++n )
|
||||
|
|
|
@ -596,10 +596,11 @@ static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict_)
|
|||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (i = 0; i < DUMB_IT_N_CHANNELS; i += 4) {
|
||||
sigdata->channel_pan[i+0] = 16;
|
||||
sigdata->channel_pan[i+1] = 48;
|
||||
sigdata->channel_pan[i+2] = 48;
|
||||
sigdata->channel_pan[i+3] = 16;
|
||||
int sep = 32 * dumb_it_default_panning_separation / 100;
|
||||
sigdata->channel_pan[i+0] = 32 - sep;
|
||||
sigdata->channel_pan[i+1] = 32 + sep;
|
||||
sigdata->channel_pan[i+2] = 32 + sep;
|
||||
sigdata->channel_pan[i+3] = 32 - sep;
|
||||
}
|
||||
|
||||
_dumb_it_fix_invalid_orders(sigdata);
|
||||
|
|
|
@ -229,10 +229,11 @@ static DUMB_IT_SIGDATA *it_mtm_load_sigdata(DUMBFILE *f, int * version)
|
|||
}
|
||||
|
||||
for (n = 32; n < DUMB_IT_N_CHANNELS; n += 4) {
|
||||
sigdata->channel_pan[n ] = 16;
|
||||
sigdata->channel_pan[n+1] = 48;
|
||||
sigdata->channel_pan[n+2] = 48;
|
||||
sigdata->channel_pan[n+3] = 16;
|
||||
int sep = 32 * dumb_it_default_panning_separation / 100;
|
||||
sigdata->channel_pan[n ] = 32 - sep;
|
||||
sigdata->channel_pan[n+1] = 32 + sep;
|
||||
sigdata->channel_pan[n+2] = 32 + sep;
|
||||
sigdata->channel_pan[n+3] = 32 - sep;
|
||||
}
|
||||
|
||||
sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
|
||||
|
|
|
@ -598,10 +598,11 @@ static DUMB_IT_SIGDATA *it_old_psm_load_sigdata(DUMBFILE *f)
|
|||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
|
||||
sigdata->channel_pan[n ] = 16;
|
||||
sigdata->channel_pan[n+1] = 48;
|
||||
sigdata->channel_pan[n+2] = 48;
|
||||
sigdata->channel_pan[n+3] = 16;
|
||||
int sep = 32 * dumb_it_default_panning_separation / 100;
|
||||
sigdata->channel_pan[n ] = 32 - sep;
|
||||
sigdata->channel_pan[n+1] = 32 + sep;
|
||||
sigdata->channel_pan[n+2] = 32 + sep;
|
||||
sigdata->channel_pan[n+3] = 32 - sep;
|
||||
}
|
||||
|
||||
for (n = 0; n < n_components; n++)
|
||||
|
|
|
@ -659,10 +659,11 @@ static DUMB_IT_SIGDATA *it_psm_load_sigdata(DUMBFILE *f, int * ver, int subsong)
|
|||
memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
|
||||
|
||||
for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
|
||||
sigdata->channel_pan[n ] = 16;
|
||||
sigdata->channel_pan[n+1] = 48;
|
||||
sigdata->channel_pan[n+2] = 48;
|
||||
sigdata->channel_pan[n+3] = 16;
|
||||
int sep = 32 * dumb_it_default_panning_separation / 100;
|
||||
sigdata->channel_pan[n ] = 32 - sep;
|
||||
sigdata->channel_pan[n+1] = 32 + sep;
|
||||
sigdata->channel_pan[n+2] = 32 + sep;
|
||||
sigdata->channel_pan[n+3] = 32 - sep;
|
||||
}
|
||||
|
||||
for (n = 0; n < n_song_chunks; n++) {
|
||||
|
|
|
@ -557,12 +557,13 @@ static DUMB_IT_SIGDATA *it_s3m_load_sigdata(DUMBFILE *f, int * cwtv)
|
|||
/* Channel settings for 32 channels, 255=unused, +128=disabled */
|
||||
{
|
||||
int i;
|
||||
int sep = (7 * dumb_it_default_panning_separation + 50) / 100;
|
||||
for (i = 0; i < 32; i++) {
|
||||
int c = dumbfile_getc(f);
|
||||
if (!(c & (128 | 16))) { /* +128=disabled, +16=Adlib */
|
||||
if (sigdata->n_pchannels < i + 1) sigdata->n_pchannels = i + 1;
|
||||
sigdata->channel_volume[i] = 64;
|
||||
sigdata->channel_pan[i] = c & 8 ? 12 : 3;
|
||||
sigdata->channel_pan[i] = c & 8 ? 7 + sep : 7 - sep;
|
||||
/** WARNING: ah, but it should be 7 for mono... */
|
||||
} else {
|
||||
/** WARNING: this could be improved if we support channel muting... */
|
||||
|
|
|
@ -61,6 +61,7 @@ static int it_stm_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f, unsigned s
|
|||
/* Looks like no-existy. */
|
||||
sample->flags &= ~IT_SAMPLE_EXISTS;
|
||||
sample->length = 0;
|
||||
*offset = 0;
|
||||
return dumbfile_error( f );
|
||||
}
|
||||
|
||||
|
@ -278,10 +279,11 @@ static DUMB_IT_SIGDATA *it_stm_load_sigdata(DUMBFILE *f, int * version)
|
|||
}
|
||||
|
||||
memset( sigdata->channel_volume, 64, 4 );
|
||||
sigdata->channel_pan[ 0 ] = 48;
|
||||
sigdata->channel_pan[ 1 ] = 16;
|
||||
sigdata->channel_pan[ 2 ] = 48;
|
||||
sigdata->channel_pan[ 3 ] = 16;
|
||||
n = 32 * dumb_it_default_panning_separation / 100;
|
||||
sigdata->channel_pan[ 0 ] = 32 + n;
|
||||
sigdata->channel_pan[ 1 ] = 32 - n;
|
||||
sigdata->channel_pan[ 2 ] = 32 + n;
|
||||
sigdata->channel_pan[ 3 ] = 32 - n;
|
||||
|
||||
for ( n = 0; n < sigdata->n_samples; ++n ) {
|
||||
if ( it_stm_read_sample_header( &sigdata->sample[ n ], f, &sample_offset[ n ] ) ) {
|
||||
|
|
|
@ -3030,7 +3030,8 @@ static inline void mix8b(PLAYER *p, uint32_t ch, uint32_t samples)
|
|||
{
|
||||
samplePosition = v->samplePosition;
|
||||
|
||||
while (interpolating && resampler_get_free_count(resampler))
|
||||
while (interpolating && (resampler_get_free_count(resampler) ||
|
||||
!resampler_get_sample_count(resampler)))
|
||||
{
|
||||
resampler_write_sample_fixed(resampler, sampleData[samplePosition], 8);
|
||||
|
||||
|
@ -3085,7 +3086,7 @@ static inline void mix8b(PLAYER *p, uint32_t ch, uint32_t samples)
|
|||
}
|
||||
|
||||
sample = resampler_get_sample_float(resampler);
|
||||
resampler_remove_sample(resampler);
|
||||
resampler_remove_sample(resampler, 1);
|
||||
|
||||
#ifdef USE_VOL_RAMP
|
||||
if (rampStyle > 0)
|
||||
|
@ -3193,7 +3194,9 @@ static inline void mix8bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
|
|||
{
|
||||
samplePosition = v->samplePosition;
|
||||
|
||||
while (interpolating && resampler_get_free_count(resampler[0]))
|
||||
while (interpolating && (resampler_get_free_count(resampler[0]) ||
|
||||
(!resampler_get_sample_count(resampler[0]) &&
|
||||
!resampler_get_sample_count(resampler[1]))))
|
||||
{
|
||||
resampler_write_sample_fixed(resampler[0], sampleData[samplePosition], 8);
|
||||
resampler_write_sample_fixed(resampler[1], sampleData[sampleLength + samplePosition], 8);
|
||||
|
@ -3250,8 +3253,8 @@ static inline void mix8bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
|
|||
|
||||
sampleL = resampler_get_sample_float(resampler[0]);
|
||||
sampleR = resampler_get_sample_float(resampler[1]);
|
||||
resampler_remove_sample(resampler[0]);
|
||||
resampler_remove_sample(resampler[1]);
|
||||
resampler_remove_sample(resampler[0], 1);
|
||||
resampler_remove_sample(resampler[1], 1);
|
||||
|
||||
#ifdef USE_VOL_RAMP
|
||||
if (rampStyle > 0)
|
||||
|
@ -3359,7 +3362,8 @@ static inline void mix16b(PLAYER *p, uint32_t ch, uint32_t samples)
|
|||
{
|
||||
samplePosition = v->samplePosition;
|
||||
|
||||
while (interpolating && resampler_get_free_count(resampler))
|
||||
while (interpolating && (resampler_get_free_count(resampler) ||
|
||||
!resampler_get_sample_count(resampler)))
|
||||
{
|
||||
resampler_write_sample_fixed(resampler, sampleData[samplePosition], 16);
|
||||
|
||||
|
@ -3414,7 +3418,7 @@ static inline void mix16b(PLAYER *p, uint32_t ch, uint32_t samples)
|
|||
}
|
||||
|
||||
sample = resampler_get_sample_float(resampler);
|
||||
resampler_remove_sample(resampler);
|
||||
resampler_remove_sample(resampler, 1);
|
||||
|
||||
#ifdef USE_VOL_RAMP
|
||||
if (rampStyle > 0)
|
||||
|
@ -3522,7 +3526,9 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
|
|||
{
|
||||
samplePosition = v->samplePosition;
|
||||
|
||||
while (interpolating && resampler_get_free_count(resampler[0]))
|
||||
while (interpolating && (resampler_get_free_count(resampler[0]) ||
|
||||
(!resampler_get_sample_count(resampler[0]) &&
|
||||
!resampler_get_sample_count(resampler[1]))))
|
||||
{
|
||||
resampler_write_sample_fixed(resampler[0], sampleData[samplePosition], 16);
|
||||
resampler_write_sample_fixed(resampler[1], sampleData[sampleLength + samplePosition], 16);
|
||||
|
@ -3579,8 +3585,8 @@ static inline void mix16bstereo(PLAYER *p, uint32_t ch, uint32_t samples)
|
|||
|
||||
sampleL = resampler_get_sample_float(resampler[0]);
|
||||
sampleR = resampler_get_sample_float(resampler[1]);
|
||||
resampler_remove_sample(resampler[0]);
|
||||
resampler_remove_sample(resampler[1]);
|
||||
resampler_remove_sample(resampler[0], 1);
|
||||
resampler_remove_sample(resampler[1], 1);
|
||||
|
||||
#ifdef USE_VOL_RAMP
|
||||
if (rampStyle > 0)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -36,9 +36,10 @@ enum
|
|||
RESAMPLER_QUALITY_ZOH = 0,
|
||||
RESAMPLER_QUALITY_BLEP = 1,
|
||||
RESAMPLER_QUALITY_LINEAR = 2,
|
||||
RESAMPLER_QUALITY_CUBIC = 3,
|
||||
RESAMPLER_QUALITY_SINC = 4,
|
||||
RESAMPLER_QUALITY_MAX = 4
|
||||
RESAMPLER_QUALITY_BLAM = 3,
|
||||
RESAMPLER_QUALITY_CUBIC = 4,
|
||||
RESAMPLER_QUALITY_SINC = 5,
|
||||
RESAMPLER_QUALITY_MAX = 5
|
||||
};
|
||||
|
||||
void resampler_set_quality(void *, int quality);
|
||||
|
@ -52,6 +53,6 @@ void resampler_clear(void *);
|
|||
int resampler_get_sample_count(void *);
|
||||
int resampler_get_sample(void *);
|
||||
float resampler_get_sample_float(void *);
|
||||
void resampler_remove_sample(void *);
|
||||
void resampler_remove_sample(void *, int decay);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2947,7 +2947,8 @@ static inline void mix8b(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
{
|
||||
samplePosition = v->samplePosition;
|
||||
|
||||
while (interpolating && resampler_get_free_count(resampler))
|
||||
while (interpolating && (resampler_get_free_count(resampler) ||
|
||||
!resampler_get_sample_count(resampler)))
|
||||
{
|
||||
resampler_write_sample_fixed(resampler, sampleData[samplePosition], 8);
|
||||
|
||||
|
@ -2976,7 +2977,7 @@ static inline void mix8b(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
}
|
||||
|
||||
sample = resampler_get_sample_float(resampler);
|
||||
resampler_remove_sample(resampler);
|
||||
resampler_remove_sample(resampler, 1);
|
||||
|
||||
#ifdef USE_VOL_RAMP
|
||||
if (rampStyle > 0)
|
||||
|
@ -2991,7 +2992,8 @@ static inline void mix8b(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
{
|
||||
v->fader = v->faderDest;
|
||||
resampler_clear(resampler);
|
||||
p->voice[ch].mixing = 0;
|
||||
v->mixing = 0;
|
||||
sampleData = 0;
|
||||
}
|
||||
|
||||
sample *= v->fader;
|
||||
|
@ -3099,7 +3101,9 @@ static inline void mix8bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
{
|
||||
samplePosition = v->samplePosition;
|
||||
|
||||
while (interpolating && resampler_get_free_count(resampler[0]))
|
||||
while (interpolating && (resampler_get_free_count(resampler[0]) ||
|
||||
(!resampler_get_sample_count(resampler[0]) &&
|
||||
!resampler_get_sample_count(resampler[1]))))
|
||||
{
|
||||
resampler_write_sample_fixed(resampler[0], sampleData[samplePosition], 8);
|
||||
resampler_write_sample_fixed(resampler[1], sampleData[sampleLength + samplePosition], 8);
|
||||
|
@ -3131,8 +3135,8 @@ static inline void mix8bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
|
||||
sampleL = resampler_get_sample_float(resampler[0]);
|
||||
sampleR = resampler_get_sample_float(resampler[1]);
|
||||
resampler_remove_sample(resampler[0]);
|
||||
resampler_remove_sample(resampler[1]);
|
||||
resampler_remove_sample(resampler[0], 1);
|
||||
resampler_remove_sample(resampler[1], 1);
|
||||
|
||||
#ifdef USE_VOL_RAMP
|
||||
if (rampStyle > 0)
|
||||
|
@ -3148,6 +3152,7 @@ static inline void mix8bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
v->fader = v->faderDest;
|
||||
resampler_clear(resampler);
|
||||
v->mixing = 0;
|
||||
sampleData = 0;
|
||||
}
|
||||
|
||||
sampleL *= v->fader;
|
||||
|
@ -3250,7 +3255,8 @@ static inline void mix16b(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
{
|
||||
samplePosition = v->samplePosition;
|
||||
|
||||
while (interpolating && resampler_get_free_count(resampler))
|
||||
while (interpolating && (resampler_get_free_count(resampler) ||
|
||||
!resampler_get_sample_count(resampler)))
|
||||
{
|
||||
resampler_write_sample_fixed(resampler, (int16_t)get_le16(&sampleData[samplePosition]), 16);
|
||||
|
||||
|
@ -3279,7 +3285,7 @@ static inline void mix16b(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
}
|
||||
|
||||
sample = resampler_get_sample_float(resampler);
|
||||
resampler_remove_sample(resampler);
|
||||
resampler_remove_sample(resampler, 1);
|
||||
|
||||
#ifdef USE_VOL_RAMP
|
||||
if (rampStyle > 0)
|
||||
|
@ -3295,6 +3301,7 @@ static inline void mix16b(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
v->fader = v->faderDest;
|
||||
resampler_clear(resampler);
|
||||
v->mixing = 0;
|
||||
sampleData = 0;
|
||||
}
|
||||
|
||||
sample *= v->fader;
|
||||
|
@ -3402,7 +3409,9 @@ static inline void mix16bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
{
|
||||
samplePosition = v->samplePosition;
|
||||
|
||||
while (interpolating && resampler_get_free_count(resampler[0]))
|
||||
while (interpolating && (resampler_get_free_count(resampler[0]) ||
|
||||
(!resampler_get_sample_count(resampler[0]) &&
|
||||
!resampler_get_sample_count(resampler[1]))))
|
||||
{
|
||||
resampler_write_sample_fixed(resampler[0], (int16_t)get_le16(&sampleData[samplePosition]), 16);
|
||||
resampler_write_sample_fixed(resampler[1], (int16_t)get_le16(&sampleData[sampleLength + samplePosition]), 16);
|
||||
|
@ -3434,8 +3443,8 @@ static inline void mix16bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
|
||||
sampleL = resampler_get_sample_float(resampler[0]);
|
||||
sampleR = resampler_get_sample_float(resampler[1]);
|
||||
resampler_remove_sample(resampler[0]);
|
||||
resampler_remove_sample(resampler[1]);
|
||||
resampler_remove_sample(resampler[0], 1);
|
||||
resampler_remove_sample(resampler[1], 1);
|
||||
|
||||
#ifdef USE_VOL_RAMP
|
||||
if (rampStyle > 0)
|
||||
|
@ -3451,6 +3460,7 @@ static inline void mix16bstereo(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
v->fader = v->faderDest;
|
||||
resampler_clear(resampler);
|
||||
v->mixing = 0;
|
||||
sampleData = 0;
|
||||
}
|
||||
|
||||
sampleL *= v->fader;
|
||||
|
@ -3572,7 +3582,8 @@ static inline void mixadpcm(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
{
|
||||
samplePosition = v->samplePosition;
|
||||
|
||||
while (interpolating && resampler_get_free_count(resampler))
|
||||
while (interpolating && (resampler_get_free_count(resampler) ||
|
||||
!resampler_get_sample_count(resampler)))
|
||||
{
|
||||
int8_t nextDelta = lastDelta;
|
||||
int16_t sample = get_adpcm_sample(sampleDictionary, sampleData, samplePosition, &nextDelta);
|
||||
|
@ -3614,7 +3625,7 @@ static inline void mixadpcm(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
}
|
||||
|
||||
sample = resampler_get_sample_float(resampler);
|
||||
resampler_remove_sample(resampler);
|
||||
resampler_remove_sample(resampler, 1);
|
||||
|
||||
#ifdef USE_VOL_RAMP
|
||||
if (rampStyle > 0)
|
||||
|
@ -3630,6 +3641,7 @@ static inline void mixadpcm(PLAYER *p, uint8_t ch, uint32_t samples)
|
|||
v->fader = v->faderDest;
|
||||
resampler_clear(resampler);
|
||||
v->mixing = 0;
|
||||
sampleData = 0;
|
||||
}
|
||||
|
||||
sample *= v->fader;
|
||||
|
@ -3773,7 +3785,7 @@ static void st3play_AdlibMix(PLAYER *p, float *buffer, int32_t count)
|
|||
for (i = 0; i < outbuffer_avail; ++i)
|
||||
{
|
||||
float sample = resampler_get_sample_float( p->fmResampler );
|
||||
resampler_remove_sample( p->fmResampler );
|
||||
resampler_remove_sample( p->fmResampler, 1 );
|
||||
|
||||
buffer[i * 2 + 0] += sample;
|
||||
buffer[i * 2 + 1] += sample;
|
||||
|
|
|
@ -7,16 +7,16 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
83304C9B1A5F9A1C0066CDDA /* pt_blep.c in Sources */ = {isa = PBXBuildFile; fileRef = 83304C991A5F9A1C0066CDDA /* pt_blep.c */; };
|
||||
83304C9C1A5F9A1C0066CDDA /* pt_blep.h in Headers */ = {isa = PBXBuildFile; fileRef = 83304C9A1A5F9A1C0066CDDA /* pt_blep.h */; };
|
||||
832127D71A622EEC00979C39 /* resampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 832127D51A622EEC00979C39 /* resampler.h */; };
|
||||
832127D81A622EEC00979C39 /* resampler.c in Sources */ = {isa = PBXBuildFile; fileRef = 832127D61A622EEC00979C39 /* resampler.c */; };
|
||||
83A0F4A61816CEAD00119DB4 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 83A0F4A41816CEAD00119DB4 /* InfoPlist.strings */; };
|
||||
83A0F4D51816CF9500119DB4 /* playptmod.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A0F4D11816CF9500119DB4 /* playptmod.c */; };
|
||||
83A0F4D61816CF9500119DB4 /* playptmod.h in Headers */ = {isa = PBXBuildFile; fileRef = 83A0F4D21816CF9500119DB4 /* playptmod.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
83304C991A5F9A1C0066CDDA /* pt_blep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pt_blep.c; sourceTree = "<group>"; };
|
||||
83304C9A1A5F9A1C0066CDDA /* pt_blep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pt_blep.h; sourceTree = "<group>"; };
|
||||
832127D51A622EEC00979C39 /* resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resampler.h; sourceTree = "<group>"; };
|
||||
832127D61A622EEC00979C39 /* resampler.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resampler.c; sourceTree = "<group>"; };
|
||||
83A0F4981816CEAD00119DB4 /* playptmod.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = playptmod.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
83A0F4A31816CEAD00119DB4 /* playptmod-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "playptmod-Info.plist"; sourceTree = "<group>"; };
|
||||
83A0F4A51816CEAD00119DB4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
|
@ -70,8 +70,8 @@
|
|||
83A0F4A11816CEAD00119DB4 /* playptmod */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
83304C991A5F9A1C0066CDDA /* pt_blep.c */,
|
||||
83304C9A1A5F9A1C0066CDDA /* pt_blep.h */,
|
||||
832127D51A622EEC00979C39 /* resampler.h */,
|
||||
832127D61A622EEC00979C39 /* resampler.c */,
|
||||
83A0F4D11816CF9500119DB4 /* playptmod.c */,
|
||||
83A0F4D21816CF9500119DB4 /* playptmod.h */,
|
||||
83A0F4A21816CEAD00119DB4 /* Supporting Files */,
|
||||
|
@ -95,8 +95,8 @@
|
|||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
832127D71A622EEC00979C39 /* resampler.h in Headers */,
|
||||
83A0F4D61816CF9500119DB4 /* playptmod.h in Headers */,
|
||||
83304C9C1A5F9A1C0066CDDA /* pt_blep.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -163,8 +163,8 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
83304C9B1A5F9A1C0066CDDA /* pt_blep.c in Sources */,
|
||||
83A0F4D51816CF9500119DB4 /* playptmod.c in Sources */,
|
||||
832127D81A622EEC00979C39 /* resampler.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#define _USE_MATH_DEFINES // visual studio
|
||||
|
||||
#include "playptmod.h"
|
||||
#include "pt_blep.h"
|
||||
#include "resampler.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h> // memcpy()
|
||||
|
@ -185,8 +185,8 @@ typedef struct voice_data
|
|||
int panR;
|
||||
int step;
|
||||
int newStep;
|
||||
float frac;
|
||||
float rate;
|
||||
int interpolating;
|
||||
int mute;
|
||||
} Voice;
|
||||
|
||||
|
@ -241,8 +241,8 @@ typedef struct
|
|||
FilterC filterC;
|
||||
float *mixBufferL;
|
||||
float *mixBufferR;
|
||||
BLEP blep[MAX_CHANNELS];
|
||||
BLEP blepVol[MAX_CHANNELS];
|
||||
void * blep[MAX_CHANNELS];
|
||||
void * blepVol[MAX_CHANNELS];
|
||||
unsigned int orderPlayed[256];
|
||||
MODULE *source;
|
||||
} player;
|
||||
|
@ -437,6 +437,7 @@ static void mixerSwapChSource(player *p, int ch, const signed char *src, int len
|
|||
v->newLoopBegin = loopStart;
|
||||
v->newLoopEnd = loopStart + loopLength;
|
||||
v->newStep = step;
|
||||
v->interpolating = 1;
|
||||
|
||||
// if the mixer was already shut down because of a short non-loop sample, force swap
|
||||
if (v->data == NULL)
|
||||
|
@ -446,7 +447,6 @@ static void mixerSwapChSource(player *p, int ch, const signed char *src, int len
|
|||
v->loopFlag = v->newLoopFlag;
|
||||
v->data = v->newData;
|
||||
v->length = v->newLength;
|
||||
v->frac = 0.0f;
|
||||
v->step = v->newStep;
|
||||
|
||||
// for safety, shut down voice if the sample position is overriding the length
|
||||
|
@ -464,12 +464,12 @@ static void mixerSetChSource(player *p, int ch, const signed char *src, int leng
|
|||
v->swapSampleFlag = false;
|
||||
v->data = src;
|
||||
v->index = offset;
|
||||
v->frac = 0.0f;
|
||||
v->length = length;
|
||||
v->loopFlag = loopLength > (2 * step);
|
||||
v->loopBegin = loopStart;
|
||||
v->loopEnd = loopStart + loopLength;
|
||||
v->step = step;
|
||||
v->interpolating = 1;
|
||||
|
||||
// Check external 9xx usage (Set Sample Offset)
|
||||
if (v->loopFlag)
|
||||
|
@ -525,8 +525,8 @@ static void mixerCutChannels(player *p)
|
|||
memset(p->v, 0, sizeof (p->v));
|
||||
for (i = 0; i < MAX_CHANNELS; ++i)
|
||||
{
|
||||
memset(&p->blep[i], 0, sizeof(BLEP));
|
||||
memset(&p->blepVol[i], 0, sizeof(BLEP));
|
||||
resampler_clear(p->blep[i]);
|
||||
resampler_clear(p->blepVol[i]);
|
||||
}
|
||||
|
||||
memset(&p->filter, 0, sizeof (p->filter));
|
||||
|
@ -545,7 +545,7 @@ static void mixerCutChannels(player *p)
|
|||
|
||||
static void mixerSetChRate(player *p, int ch, float rate)
|
||||
{
|
||||
p->v[ch].rate = rate;
|
||||
p->v[ch].rate = 1.0f / rate;
|
||||
}
|
||||
|
||||
static void outputAudio(player *p, int *target, int numSamples)
|
||||
|
@ -556,6 +556,7 @@ static void outputAudio(player *p, int *target, int numSamples)
|
|||
int step;
|
||||
int tempVolume;
|
||||
int delta;
|
||||
int interpolating;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
float L;
|
||||
|
@ -565,8 +566,8 @@ static void outputAudio(player *p, int *target, int numSamples)
|
|||
float downscale;
|
||||
|
||||
Voice *v;
|
||||
BLEP *bSmp;
|
||||
BLEP *bVol;
|
||||
void *bSmp;
|
||||
void *bVol;
|
||||
|
||||
memset(p->mixBufferL, 0, numSamples * sizeof (float));
|
||||
memset(p->mixBufferR, 0, numSamples * sizeof (float));
|
||||
|
@ -576,27 +577,99 @@ static void outputAudio(player *p, int *target, int numSamples)
|
|||
j = 0;
|
||||
|
||||
v = &p->v[i];
|
||||
bSmp = &p->blep[i];
|
||||
bVol = &p->blepVol[i];
|
||||
bSmp = p->blep[i];
|
||||
bVol = p->blepVol[i];
|
||||
|
||||
if (v->data && v->rate)
|
||||
{
|
||||
step = v->step;
|
||||
interpolating = v->interpolating;
|
||||
resampler_set_rate(bSmp, v->rate);
|
||||
resampler_set_rate(bVol, v->rate);
|
||||
|
||||
for (j = 0; j < numSamples;)
|
||||
{
|
||||
tempSample = (v->data ? (step == 2 ? (v->data[v->index] + v->data[v->index + 1] * 0x100) : v->data[v->index] * 0x100) : 0);
|
||||
tempVolume = (v->data && !v->mute ? v->vol : 0);
|
||||
|
||||
while (j < numSamples && (!v->data || v->frac >= 1.0f))
|
||||
while (interpolating && (resampler_get_free_count(bSmp) ||
|
||||
!resampler_get_sample_count(bSmp)))
|
||||
{
|
||||
t_vol = 0.0f;
|
||||
t_smp = 0.0f;
|
||||
tempSample = (v->data ? (step == 2 ? (v->data[v->index] + v->data[v->index + 1] * 0x100) : v->data[v->index] * 0x100) : 0);
|
||||
|
||||
resampler_write_sample_fixed(bSmp, tempSample, 1);
|
||||
resampler_write_sample_fixed(bVol, tempVolume, 1);
|
||||
|
||||
if (v->data)
|
||||
v->frac -= 1.0f;
|
||||
|
||||
t_vol += blepRun(bVol);
|
||||
t_smp += blepRun(bSmp);
|
||||
{
|
||||
v->index += step;
|
||||
|
||||
if (v->loopFlag)
|
||||
{
|
||||
if (v->index >= v->loopEnd)
|
||||
{
|
||||
if (v->swapSampleFlag)
|
||||
{
|
||||
v->swapSampleFlag = false;
|
||||
|
||||
if (!v->newLoopFlag)
|
||||
{
|
||||
interpolating = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
v->loopBegin = v->newLoopBegin;
|
||||
v->loopEnd = v->newLoopEnd;
|
||||
v->loopFlag = v->newLoopFlag;
|
||||
v->data = v->newData;
|
||||
v->length = v->newLength;
|
||||
v->step = v->newStep;
|
||||
|
||||
v->index = v->loopBegin;
|
||||
}
|
||||
else
|
||||
{
|
||||
v->index = v->loopBegin;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (v->index >= v->length)
|
||||
{
|
||||
if (v->swapSampleFlag)
|
||||
{
|
||||
v->swapSampleFlag = false;
|
||||
|
||||
if (!v->newLoopFlag)
|
||||
{
|
||||
interpolating = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
v->loopBegin = v->newLoopBegin;
|
||||
v->loopEnd = v->newLoopEnd;
|
||||
v->loopFlag = v->newLoopFlag;
|
||||
v->data = v->newData;
|
||||
v->length = v->newLength;
|
||||
v->step = v->newStep;
|
||||
|
||||
v->index = v->loopBegin;
|
||||
}
|
||||
else
|
||||
{
|
||||
interpolating = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v->interpolating = interpolating;
|
||||
|
||||
while (j < numSamples && resampler_get_sample_count(bSmp))
|
||||
{
|
||||
t_vol = resampler_get_sample_float(bVol);
|
||||
t_smp = resampler_get_sample_float(bSmp);
|
||||
resampler_remove_sample(bVol, 0);
|
||||
resampler_remove_sample(bSmp, 1);
|
||||
|
||||
t_smp *= t_vol;
|
||||
i_smp = (signed int)t_smp;
|
||||
|
@ -606,108 +679,12 @@ static void outputAudio(player *p, int *target, int numSamples)
|
|||
|
||||
j++;
|
||||
}
|
||||
|
||||
if (j >= numSamples)
|
||||
|
||||
if (!interpolating && j < numSamples)
|
||||
{
|
||||
v->data = NULL;
|
||||
break;
|
||||
|
||||
if (tempSample != bSmp->lastInput && v->frac >= 0.0f && v->frac < 1.0f)
|
||||
{
|
||||
delta = tempSample - bSmp->lastInput;
|
||||
bSmp->lastInput = tempSample;
|
||||
blepAdd(bSmp, v->frac, delta);
|
||||
}
|
||||
|
||||
if (tempVolume != bVol->lastInput)
|
||||
{
|
||||
delta = tempVolume - bVol->lastInput;
|
||||
bVol->lastInput = tempVolume;
|
||||
blepAdd(bVol, 0, delta);
|
||||
}
|
||||
|
||||
if (v->data)
|
||||
{
|
||||
v->index += step;
|
||||
v->frac += v->rate;
|
||||
|
||||
if (v->loopFlag)
|
||||
{
|
||||
if (v->index >= v->loopEnd)
|
||||
{
|
||||
if (v->swapSampleFlag)
|
||||
{
|
||||
v->swapSampleFlag = false;
|
||||
|
||||
if (!v->newLoopFlag)
|
||||
{
|
||||
v->data = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
v->loopBegin = v->newLoopBegin;
|
||||
v->loopEnd = v->newLoopEnd;
|
||||
v->loopFlag = v->newLoopFlag;
|
||||
v->data = v->newData;
|
||||
v->length = v->newLength;
|
||||
v->frac = 0.0f;
|
||||
v->step = v->newStep;
|
||||
|
||||
while (v->index >= v->loopEnd)
|
||||
v->index = v->loopBegin + (v->index - v->loopEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (v->index >= v->loopEnd)
|
||||
v->index = v->loopBegin + (v->index - v->loopEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (v->index >= v->length)
|
||||
{
|
||||
if (v->swapSampleFlag)
|
||||
{
|
||||
v->swapSampleFlag = false;
|
||||
|
||||
if (!v->newLoopFlag)
|
||||
{
|
||||
v->data = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
v->loopBegin = v->newLoopBegin;
|
||||
v->loopEnd = v->newLoopEnd;
|
||||
v->loopFlag = v->newLoopFlag;
|
||||
v->data = v->newData;
|
||||
v->length = v->newLength;
|
||||
v->frac = 0.0f;
|
||||
v->step = v->newStep;
|
||||
|
||||
while (v->index >= v->loopEnd)
|
||||
v->index = v->loopBegin + (v->index - v->loopEnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
v->data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((j < numSamples) && (v->data == NULL))
|
||||
{
|
||||
for (; j < numSamples; ++j)
|
||||
{
|
||||
tempVolume = 0.0f;
|
||||
tempSample = 0.0f;
|
||||
|
||||
tempVolume += blepRun(bVol);
|
||||
tempSample += blepRun(bSmp);
|
||||
|
||||
tempSample *= tempVolume;
|
||||
i_smp = (signed int)tempSample;
|
||||
|
||||
p->mixBufferL[j] += i_smp * v->panL;
|
||||
p->mixBufferR[j] += i_smp * v->panR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2787,6 +2764,8 @@ void *playptmod_Create(int samplingFrequency)
|
|||
player *p = (player *) calloc(1, sizeof (player));
|
||||
|
||||
int i, j;
|
||||
|
||||
resampler_init();
|
||||
|
||||
p->tempoTimerVal = (samplingFrequency * 125) / 50;
|
||||
|
||||
|
@ -2820,8 +2799,20 @@ void *playptmod_Create(int samplingFrequency)
|
|||
|
||||
p->useLEDFilter = false;
|
||||
|
||||
for (i = 0; i < MAX_CHANNELS; ++i)
|
||||
{
|
||||
p->blep[i] = resampler_create();
|
||||
resampler_set_quality(p->blep[i], RESAMPLER_QUALITY_BLEP);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CHANNELS; ++i)
|
||||
{
|
||||
p->blepVol[i] = resampler_create();
|
||||
resampler_set_quality(p->blepVol[i], RESAMPLER_QUALITY_BLEP);
|
||||
}
|
||||
|
||||
mixerCutChannels(p);
|
||||
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -2953,6 +2944,12 @@ void playptmod_Free(void *_p)
|
|||
p->extendedFrequencyTable = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CHANNELS; ++i)
|
||||
{
|
||||
resampler_delete(p->blep[i]);
|
||||
resampler_delete(p->blepVol[i]);
|
||||
}
|
||||
|
||||
free(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
** This file is part of the ProTracker 2.3D port/clone
|
||||
** project by Olav "8bitbubsy" Sorensen.
|
||||
**
|
||||
** It contains unstructured and unclean code, but I care
|
||||
** more about how the program works than how the source
|
||||
** code looks. Although, I do respect coders that can
|
||||
** master the art of writing clean and structured code.
|
||||
** I know I can't.
|
||||
**
|
||||
** All of the files are considered 'public domain',
|
||||
** do whatever you want with it.
|
||||
**
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "pt_blep.h"
|
||||
|
||||
#define _LERP(I, F) ((I[0]) + ((I[1]) - (I[0])) * (F))
|
||||
|
||||
static const uint32_t blepData[48] =
|
||||
{
|
||||
0x3F7FE1F1, 0x3F7FD548, 0x3F7FD6A3, 0x3F7FD4E3,
|
||||
0x3F7FAD85, 0x3F7F2152, 0x3F7DBFAE, 0x3F7ACCDF,
|
||||
0x3F752F1E, 0x3F6B7384, 0x3F5BFBCB, 0x3F455CF2,
|
||||
0x3F26E524, 0x3F0128C4, 0x3EACC7DC, 0x3E29E86B,
|
||||
0x3C1C1D29, 0xBDE4BBE6, 0xBE3AAE04, 0xBE48DEDD,
|
||||
0xBE22AD7E, 0xBDB2309A, 0xBB82B620, 0x3D881411,
|
||||
0x3DDADBF3, 0x3DE2C81D, 0x3DAAA01F, 0x3D1E769A,
|
||||
0xBBC116D7, 0xBD1402E8, 0xBD38A069, 0xBD0C53BB,
|
||||
0xBC3FFB8C, 0x3C465FD2, 0x3CEA5764, 0x3D0A51D6,
|
||||
0x3CEAE2D5, 0x3C92AC5A, 0x3BE4CBF7, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
};
|
||||
|
||||
void blepAdd(BLEP *b, float offset, float amplitude)
|
||||
{
|
||||
int8_t n;
|
||||
|
||||
uint32_t i;
|
||||
|
||||
const float *src;
|
||||
float f;
|
||||
float a;
|
||||
|
||||
float k[NS];
|
||||
|
||||
n = NS;
|
||||
i = (uint32_t)(offset * SP);
|
||||
src = (const float *)(blepData) + i + OS;
|
||||
f = (offset * SP) - i;
|
||||
i = b->index;
|
||||
a = 0.0f;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
a += k[n] = _LERP(src, f);
|
||||
src += SP;
|
||||
}
|
||||
|
||||
n = NS;
|
||||
a = 1.0f / a;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
b->buffer[i] += (amplitude * k[n]) * a;
|
||||
|
||||
i++;
|
||||
i &= RNS;
|
||||
}
|
||||
|
||||
b->samplesLeft = NS;
|
||||
}
|
||||
|
||||
float blepRun(BLEP *b)
|
||||
{
|
||||
float output;
|
||||
|
||||
output = b->buffer[b->index];
|
||||
b->buffer[b->index] = 0.0f;
|
||||
|
||||
b->index++;
|
||||
b->index &= RNS;
|
||||
|
||||
b->samplesLeft--;
|
||||
|
||||
output += b->lastOutput;
|
||||
b->lastOutput = output;
|
||||
|
||||
return (output);
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
** This file is part of the ProTracker 2.3D port/clone
|
||||
** project by Olav "8bitbubsy" Sorensen.
|
||||
**
|
||||
** It contains unstructured and unclean code, but I care
|
||||
** more about how the program works than how the source
|
||||
** code looks. Although, I do respect coders that can
|
||||
** master the art of writing clean and structured code.
|
||||
** I know I can't.
|
||||
**
|
||||
** All of the files are considered 'public domain',
|
||||
** do whatever you want with it.
|
||||
**
|
||||
*/
|
||||
|
||||
#ifndef __PT_BLEP_H
|
||||
#define __PT_BLEP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// thanks to aciddose/ad/adejr for the blep/cutoff/filter stuff!
|
||||
|
||||
// information on blep variables
|
||||
//
|
||||
// ZC = zero crossings, the number of ripples in the impulse
|
||||
// OS = oversampling, how many samples per zero crossing are taken
|
||||
// SP = step size per output sample, used to lower the cutoff (play the impulse slower)
|
||||
// NS = number of samples of impulse to insert
|
||||
// RNS = the lowest power of two greater than NS, minus one (used to wrap output buffer)
|
||||
//
|
||||
// ZC and OS are here only for reference, they depend upon the data in the table and can't be changed.
|
||||
// SP, the step size can be any number lower or equal to OS, as long as the result NS remains an integer.
|
||||
// for example, if ZC=8,OS=5, you can set SP=1, the result is NS=40, and RNS must then be 63.
|
||||
// the result of that is the filter cutoff is set at nyquist * (SP/OS), in this case nyquist/5.
|
||||
|
||||
#define ZC 8
|
||||
#define OS 5
|
||||
#define SP 5
|
||||
#define NS (ZC * OS / SP)
|
||||
#define RNS 7 // RNS = (2^ > NS) - 1
|
||||
|
||||
typedef struct blep_data
|
||||
{
|
||||
int32_t index;
|
||||
int32_t samplesLeft;
|
||||
float buffer[RNS + 1];
|
||||
float lastInput;
|
||||
float lastOutput;
|
||||
} BLEP;
|
||||
|
||||
void blepAdd(BLEP *b, float offset, float amplitude);
|
||||
float blepRun(BLEP *b);
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,58 @@
|
|||
#ifndef _RESAMPLER_H_
|
||||
#define _RESAMPLER_H_
|
||||
|
||||
// Ugglay
|
||||
#ifdef RESAMPLER_DECORATE
|
||||
#define PASTE(a,b) a ## b
|
||||
#define EVALUATE(a,b) PASTE(a,b)
|
||||
#define resampler_init EVALUATE(RESAMPLER_DECORATE,_resampler_init)
|
||||
#define resampler_create EVALUATE(RESAMPLER_DECORATE,_resampler_create)
|
||||
#define resampler_delete EVALUATE(RESAMPLER_DECORATE,_resampler_delete)
|
||||
#define resampler_dup EVALUATE(RESAMPLER_DECORATE,_resampler_dup)
|
||||
#define resampler_dup_inplace EVALUATE(RESAMPLER_DECORATE,_resampler_dup_inplace)
|
||||
#define resampler_set_quality EVALUATE(RESAMPLER_DECORATE,_resampler_set_quality)
|
||||
#define resampler_get_free_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_free_count)
|
||||
#define resampler_write_sample EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample)
|
||||
#define resampler_write_sample_fixed EVALUATE(RESAMPLER_DECORATE,_resampler_write_sample_fixed)
|
||||
#define resampler_set_rate EVALUATE(RESAMPLER_DECORATE,_resampler_set_rate)
|
||||
#define resampler_ready EVALUATE(RESAMPLER_DECORATE,_resampler_ready)
|
||||
#define resampler_clear EVALUATE(RESAMPLER_DECORATE,_resampler_clear)
|
||||
#define resampler_get_sample_count EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_count)
|
||||
#define resampler_get_sample EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample)
|
||||
#define resampler_get_sample_float EVALUATE(RESAMPLER_DECORATE,_resampler_get_sample_float)
|
||||
#define resampler_remove_sample EVALUATE(RESAMPLER_DECORATE,_resampler_remove_sample)
|
||||
#endif
|
||||
|
||||
void resampler_init(void);
|
||||
|
||||
void * resampler_create(void);
|
||||
void resampler_delete(void *);
|
||||
void * resampler_dup(const void *);
|
||||
void resampler_dup_inplace(void *, const void *);
|
||||
|
||||
enum
|
||||
{
|
||||
RESAMPLER_QUALITY_MIN = 0,
|
||||
RESAMPLER_QUALITY_ZOH = 0,
|
||||
RESAMPLER_QUALITY_BLEP = 1,
|
||||
RESAMPLER_QUALITY_LINEAR = 2,
|
||||
RESAMPLER_QUALITY_BLAM = 3,
|
||||
RESAMPLER_QUALITY_CUBIC = 4,
|
||||
RESAMPLER_QUALITY_SINC = 5,
|
||||
RESAMPLER_QUALITY_MAX = 5
|
||||
};
|
||||
|
||||
void resampler_set_quality(void *, int quality);
|
||||
|
||||
int resampler_get_free_count(void *);
|
||||
void resampler_write_sample(void *, short sample);
|
||||
void resampler_write_sample_fixed(void *, int sample, unsigned char depth);
|
||||
void resampler_set_rate( void *, double new_factor );
|
||||
int resampler_ready(void *);
|
||||
void resampler_clear(void *);
|
||||
int resampler_get_sample_count(void *);
|
||||
int resampler_get_sample(void *);
|
||||
float resampler_get_sample_float(void *);
|
||||
void resampler_remove_sample(void *, int decay);
|
||||
|
||||
#endif
|
|
@ -106,6 +106,8 @@ static void SyncProc( HSYNC handle, DWORD channel, DWORD data, void *user )
|
|||
resampling_int = 0;
|
||||
else if ([resampling isEqualToString:@"linear"])
|
||||
resampling_int = 1;
|
||||
else if ([resampling isEqualToString:@"blam"])
|
||||
resampling_int = 1;
|
||||
else if ([resampling isEqualToString:@"cubic"])
|
||||
resampling_int = 1;
|
||||
else if ([resampling isEqualToString:@"sinc"])
|
||||
|
|
|
@ -205,10 +205,12 @@ int callbackLoop(void *data)
|
|||
resampling_int = 1;
|
||||
else if ([resampling isEqualToString:@"linear"])
|
||||
resampling_int = 2;
|
||||
else if ([resampling isEqualToString:@"cubic"])
|
||||
else if ([resampling isEqualToString:@"blam"])
|
||||
resampling_int = 3;
|
||||
else if ([resampling isEqualToString:@"sinc"])
|
||||
else if ([resampling isEqualToString:@"cubic"])
|
||||
resampling_int = 4;
|
||||
else if ([resampling isEqualToString:@"sinc"])
|
||||
resampling_int = 5;
|
||||
|
||||
dumb_it_set_resampling_quality( itsr, resampling_int );
|
||||
dumb_it_set_ramp_style(itsr, 2);
|
||||
|
|
|
@ -190,10 +190,12 @@ BOOL xm_probe_length( unsigned long * intro_length, unsigned long * loop_length,
|
|||
resampling_int = 1;
|
||||
else if ([resampling isEqualToString:@"linear"])
|
||||
resampling_int = 2;
|
||||
else if ([resampling isEqualToString:@"cubic"])
|
||||
else if ([resampling isEqualToString:@"blam"])
|
||||
resampling_int = 3;
|
||||
else if ([resampling isEqualToString:@"sinc"])
|
||||
else if ([resampling isEqualToString:@"cubic"])
|
||||
resampling_int = 4;
|
||||
else if ([resampling isEqualToString:@"sinc"])
|
||||
resampling_int = 5;
|
||||
|
||||
if ( type == TYPE_S3M )
|
||||
{
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
NSLocalizedStringFromTableInBundle(@"Linear Interpolation", nil, [NSBundle bundleForClass:[self class]], @"") , @"name",
|
||||
@"linear", @"preference",nil]];
|
||||
|
||||
[self addObject:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
NSLocalizedStringFromTableInBundle(@"Blam Synthesis", nil, [NSBundle bundleForClass:[self class]], @"") , @"name",
|
||||
@"blam", @"preference",nil]];
|
||||
|
||||
[self addObject:
|
||||
[NSDictionary dictionaryWithObjectsAndKeys:
|
||||
NSLocalizedStringFromTableInBundle(@"Cubic Interpolation", nil, [NSBundle bundleForClass:[self class]], @"") , @"name",
|
||||
|
|
Loading…
Reference in New Issue