ref: 1eef4c9f892c119f2f92f0d928efe1b7a98af934
parent: 8605fb3a520aafb2d43febb6c0a9acde871090e7
author: Chris Moeller <kode54@gmail.com>
date: Thu Apr 25 20:25:04 EDT 2013
- Implemented Lanczos resampler - Fixed overhead of performing effects updates on background voices
--- a/dumb/include/dumb.h
+++ b/dumb/include/dumb.h
@@ -675,7 +675,7 @@
typedef void (*DUMB_RESAMPLE_PICKUP)(DUMB_RESAMPLER *resampler, void *data);
#include "internal/blip_buf.h"
-#include "internal/fir_resampler.h"
+#include "internal/lanczos_resampler.h"
struct DUMB_RESAMPLER
{
--- /dev/null
+++ b/dumb/include/internal/lanczos_resampler.h
@@ -1,0 +1,18 @@
+#ifndef _LANCZOS_RESAMPLER_H_
+#define _LANCZOS_RESAMPLER_H_
+
+void lanczos_init();
+
+void * lanczos_resampler_create();
+void lanczos_resampler_delete(void *);
+void * lanczos_resampler_dup(void *);
+
+int lanczos_resampler_get_free_count(void *);
+void lanczos_resampler_write_sample(void *, short sample);
+void lanczos_resampler_set_rate( void *, double new_factor );
+int lanczos_resampler_ready(void *);
+void lanczos_resampler_clear(void *);
+int lanczos_resampler_get_sample(void *);
+void lanczos_resampler_remove_sample(void *);
+
+#endif
--- /dev/null
+++ b/dumb/src/helpers/lanczos_resampler.c
@@ -1,0 +1,216 @@
+#include <stdlib.h>
+#include <string.h>
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+#include "internal/lanczos_resampler.h"
+
+enum { COSINE_RESOLUTION = 8192 };
+enum { LANCZOS_RESOLUTION = 8192 };
+enum { LANCZOS_WIDTH = 8 };
+enum { LANCZOS_SAMPLES = LANCZOS_RESOLUTION * LANCZOS_WIDTH };
+
+static double cosine_lut[COSINE_RESOLUTION];
+static double lanczos_lut[LANCZOS_SAMPLES];
+
+enum { lanczos_buffer_size = LANCZOS_WIDTH * 4 };
+
+int fEqual(const double b, const double a)
+{
+ return fabs(a - b) < 1.0e-6;
+}
+
+static double sinc(double x)
+{
+ return fEqual(x, 0.0) ? 1.0 : sin(x * M_PI) / (x * M_PI);
+}
+
+void lanczos_init()
+{
+ unsigned i;
+ double dx, x;
+ for (i = 0; i < COSINE_RESOLUTION; ++i)
+ cosine_lut[i] = (1.0 - cos(((double)(i) / COSINE_RESOLUTION) * M_PI)) * 0.5;
+ dx = (double)(LANCZOS_WIDTH) / LANCZOS_SAMPLES; x = 0.0;
+ for (i = 0; i < LANCZOS_SAMPLES; ++i, x += dx)
+ lanczos_lut[i] = abs(x) < LANCZOS_WIDTH ? sinc(x) * (0.35875 + 0.48829 * cos((M_PI * x) / 3) + 0.14128 * cos((2 * M_PI * x) / 3) + 0.01168 * cos(M_PI * x)) : 0.0;
+}
+
+typedef struct lanczos_resampler
+{
+ int write_pos, write_filled;
+ int read_pos, read_filled;
+ unsigned short phase;
+ unsigned int phase_inc;
+ int buffer_in[lanczos_buffer_size * 2];
+ int buffer_out[lanczos_buffer_size];
+} lanczos_resampler;
+
+void * lanczos_resampler_create()
+{
+ lanczos_resampler * r = ( lanczos_resampler * ) malloc( sizeof(lanczos_resampler) );
+ if ( !r ) return 0;
+
+ r->write_pos = 0;
+ r->write_filled = 0;
+ r->read_pos = 0;
+ r->read_filled = 0;
+ r->phase = 0;
+ r->phase_inc = 0;
+ memset( r->buffer_in, 0, sizeof(r->buffer_in) );
+ memset( r->buffer_out, 0, sizeof(r->buffer_out) );
+
+ return r;
+}
+
+void lanczos_resampler_delete(void * _r)
+{
+ free( _r );
+}
+
+void * lanczos_resampler_dup(void * _r)
+{
+ lanczos_resampler * r_in = ( lanczos_resampler * ) _r;
+ lanczos_resampler * r_out = ( lanczos_resampler * ) malloc( sizeof(lanczos_resampler) );
+ if ( !r_out ) return 0;
+
+ r_out->write_pos = r_in->write_pos;
+ r_out->write_filled = r_in->write_filled;
+ r_out->read_pos = r_in->read_pos;
+ r_out->read_filled = r_in->read_filled;
+ r_out->phase = r_in->phase;
+ r_out->phase_inc = r_in->phase_inc;
+ memcpy( r_out->buffer_in, r_in->buffer_in, sizeof(r_in->buffer_in) );
+ memcpy( r_out->buffer_out, r_in->buffer_out, sizeof(r_in->buffer_out) );
+
+ return r_out;
+}
+
+int lanczos_resampler_get_free_count(void *_r)
+{
+ lanczos_resampler * r = ( lanczos_resampler * ) _r;
+ return lanczos_buffer_size - r->write_filled;
+}
+
+int lanczos_resampler_ready(void *_r)
+{
+ lanczos_resampler * r = ( lanczos_resampler * ) _r;
+ return r->write_filled > (LANCZOS_WIDTH * 2);
+}
+
+void lanczos_resampler_clear(void *_r)
+{
+ lanczos_resampler * r = ( lanczos_resampler * ) _r;
+ r->write_pos = 0;
+ r->write_filled = 0;
+ r->read_pos = 0;
+ r->read_filled = 0;
+ r->phase = 0;
+ memset( r->buffer_in, 0, sizeof(r->buffer_in) );
+}
+
+void lanczos_resampler_set_rate(void *_r, double new_factor)
+{
+ lanczos_resampler * r = ( lanczos_resampler * ) _r;
+ r->phase_inc = (int)( new_factor * LANCZOS_RESOLUTION );
+}
+
+void lanczos_resampler_write_sample(void *_r, short s)
+{
+ lanczos_resampler * r = ( lanczos_resampler * ) _r;
+
+ if ( r->write_filled < lanczos_buffer_size )
+ {
+ int s32 = s;
+
+ r->buffer_in[ r->write_pos ] = s32;
+ r->buffer_in[ r->write_pos + lanczos_buffer_size ] = s32;
+
+ ++r->write_filled;
+
+ r->write_pos = ( r->write_pos + 1 ) % lanczos_buffer_size;
+ }
+}
+
+int lanczos_resampler_run(void *_r, int ** out_, int * out_end)
+{
+ lanczos_resampler * r = ( lanczos_resampler * ) _r;
+ int in_size = r->write_filled;
+ int const* in_ = r->buffer_in + lanczos_buffer_size + r->write_pos - r->write_filled;
+ int used = 0;
+ in_size -= LANCZOS_WIDTH * 2;
+ if ( in_size > 0 )
+ {
+ int* out = *out_;
+ int const* in = in_;
+ int const* const in_end = in + in_size;
+ int phase = r->phase;
+ int phase_inc = r->phase_inc;
+
+ int step = phase_inc > LANCZOS_RESOLUTION ? LANCZOS_RESOLUTION * LANCZOS_RESOLUTION / phase_inc : LANCZOS_RESOLUTION;
+
+ do
+ {
+ // accumulate in extended precision
+ double kernel[LANCZOS_WIDTH * 2], kernel_sum = 0.0;
+ int i = LANCZOS_WIDTH;
+ double sample;
+
+ if ( out >= out_end )
+ break;
+
+ for (; i >= -LANCZOS_WIDTH + 1; --i)
+ {
+ int pos = i * step;
+ kernel_sum += kernel[i + LANCZOS_WIDTH - 1] = lanczos_lut[abs(phase - pos)];
+ }
+ for (sample = 0, i = 0; i < LANCZOS_WIDTH * 2; ++i)
+ sample += in[i] * kernel[i];
+ *out++ = (int) (sample / kernel_sum * 256.0);
+
+ phase += phase_inc;
+
+ in += phase >> 13;
+
+ phase &= 8191;
+ }
+ while ( in < in_end );
+
+ r->phase = phase;
+ *out_ = out;
+
+ used = in - in_;
+
+ r->write_filled -= used;
+ }
+
+ return used;
+}
+
+int lanczos_resampler_get_sample(void *_r)
+{
+ lanczos_resampler * r = ( lanczos_resampler * ) _r;
+ if ( r->read_filled < 1 )
+ {
+ int write_pos = ( r->read_pos + r->read_filled ) % lanczos_buffer_size;
+ int write_size = lanczos_buffer_size - write_pos;
+ int * out = r->buffer_out + write_pos;
+ if ( write_size > ( lanczos_buffer_size - r->read_filled ) )
+ write_size = lanczos_buffer_size - r->read_filled;
+ lanczos_resampler_run( r, &out, out + write_size );
+ r->read_filled += out - r->buffer_out - write_pos;
+ }
+ if ( r->read_filled < 1 )
+ return 0;
+ return r->buffer_out[ r->read_pos ];
+}
+
+void lanczos_resampler_remove_sample(void *_r)
+{
+ lanczos_resampler * r = ( lanczos_resampler * ) _r;
+ if ( r->read_filled > 0 )
+ {
+ --r->read_filled;
+ r->read_pos = ( r->read_pos + 1 ) % lanczos_buffer_size;
+ }
+}
--- a/dumb/src/helpers/resamp3.inc
+++ b/dumb/src/helpers/resamp3.inc
@@ -191,13 +191,13 @@
/* FIR resampling, backwards */
SRCTYPE *x;
if ( resampler->fir_resampler_ratio != delta ) {
- fir_resampler_set_rate( resampler->fir_resampler[0], delta );
- fir_resampler_set_rate( resampler->fir_resampler[1], delta );
+ lanczos_resampler_set_rate( resampler->fir_resampler[0], delta );
+ lanczos_resampler_set_rate( resampler->fir_resampler[1], delta );
resampler->fir_resampler_ratio = delta;
}
x = &src[pos*SRC_CHANNELS];
while ( todo ) {
- while ( fir_resampler_get_free_count( resampler->fir_resampler[0] ) &&
+ while ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
pos >= resampler->start )
{
POKE_FIR(0);
@@ -204,7 +204,7 @@
pos--;
x -= SRC_CHANNELS;
}
- if ( !fir_resampler_ready( resampler->fir_resampler[0] ) ) break;
+ if ( !lanczos_resampler_ready( resampler->fir_resampler[0] ) ) break;
MIX_FIR;
ADVANCE_FIR;
--todo;
@@ -317,13 +317,13 @@
/* FIR resampling, forwards */
SRCTYPE *x;
if ( resampler->fir_resampler_ratio != delta ) {
- fir_resampler_set_rate( resampler->fir_resampler[0], delta );
- fir_resampler_set_rate( resampler->fir_resampler[1], delta );
+ lanczos_resampler_set_rate( resampler->fir_resampler[0], delta );
+ lanczos_resampler_set_rate( resampler->fir_resampler[1], delta );
resampler->fir_resampler_ratio = delta;
}
x = &src[pos*SRC_CHANNELS];
while ( todo ) {
- while ( fir_resampler_get_free_count( resampler->fir_resampler[0] ) &&
+ while ( lanczos_resampler_get_free_count( resampler->fir_resampler[0] ) &&
pos < resampler->end )
{
POKE_FIR(0);
@@ -330,7 +330,7 @@
pos++;
x += SRC_CHANNELS;
}
- if ( !fir_resampler_ready( resampler->fir_resampler[0] ) ) break;
+ if ( !lanczos_resampler_ready( resampler->fir_resampler[0] ) ) break;
MIX_FIR;
ADVANCE_FIR;
--todo;
--- a/dumb/src/helpers/resample.c
+++ b/dumb/src/helpers/resample.c
@@ -169,7 +169,7 @@
cubicA1[t] = (int)(3*t*t*t >> 17) - (int)(5*t*t >> 7) + (int)(1 << 14);
}
- fir_init();
+ lanczos_init();
}
--- a/dumb/src/helpers/resample.inc
+++ b/dumb/src/helpers/resample.inc
@@ -75,8 +75,8 @@
blip_clear(resampler->blip_buffer[0]);
blip_clear(resampler->blip_buffer[1]);
resampler->fir_resampler_ratio = 0;
- fir_resampler_clear(resampler->fir_resampler[0]);
- fir_resampler_clear(resampler->fir_resampler[1]);
+ lanczos_resampler_clear(resampler->fir_resampler[0]);
+ lanczos_resampler_clear(resampler->fir_resampler[1]);
}
@@ -153,15 +153,15 @@
resampler->last_clock += inv_dt; \
}
#define POKE_FIR(offset) { \
- fir_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( fir_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 { \
- *dst++ += MULSC( fir_resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
+ *dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), vol ); \
UPDATE_VOLUME( volume, vol ); \
}
-#define ADVANCE_FIR fir_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; \
@@ -179,12 +179,12 @@
*dst++ = MULSC( sample, rvol ); \
}
#define STEREO_DEST_PEEK_FIR { \
- int sample = fir_resampler_get_sample( resampler->fir_resampler[0] ); \
+ int sample = lanczos_resampler_get_sample( resampler->fir_resampler[0] ); \
*dst++ = MULSC( sample, lvol ); \
*dst++ = MULSC( sample, rvol ); \
}
#define STEREO_DEST_MIX_FIR { \
- int sample = fir_resampler_get_sample( resampler->fir_resampler[0] ); \
+ int sample = lanczos_resampler_get_sample( resampler->fir_resampler[0] ); \
*dst++ += MULSC( sample, lvol ); \
*dst++ += MULSC( sample, rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \
@@ -287,8 +287,8 @@
resampler->last_clock += inv_dt; \
}
#define POKE_FIR(offset) { \
- fir_resampler_write_sample( resampler->fir_resampler[0], FIR(x[(offset)*2+0]) ); \
- fir_resampler_write_sample( resampler->fir_resampler[1], FIR(x[(offset)*2+1]) ); \
+ 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]) ); \
}
#define MONO_DEST_PEEK_ALIAS { \
*dst = MULSC( blip_peek_sample( resampler->blip_buffer[0] ), lvol ) + \
@@ -295,18 +295,18 @@
MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
}
#define MONO_DEST_PEEK_FIR { \
- *dst = MULSC( fir_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
- MULSC( fir_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
+ MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
}
#define MONO_DEST_MIX_FIR { \
- *dst++ += MULSC( fir_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
- MULSC( fir_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ) + \
+ MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \
UPDATE_VOLUME( volume_right, rvol ); \
}
#define ADVANCE_FIR { \
- fir_resampler_remove_sample( resampler->fir_resampler[0] ); \
- fir_resampler_remove_sample( resampler->fir_resampler[1] ); \
+ lanczos_resampler_remove_sample( resampler->fir_resampler[0] ); \
+ lanczos_resampler_remove_sample( resampler->fir_resampler[1] ); \
}
#define MONO_DEST_MIX_ALIAS(count) { \
int n = 0; \
@@ -327,12 +327,12 @@
*dst++ = MULSC( blip_peek_sample( resampler->blip_buffer[1] ), rvol ); \
}
#define STEREO_DEST_PEEK_FIR { \
- *dst++ = MULSC( fir_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
- *dst++ = MULSC( fir_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst++ = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
+ *dst++ = MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
}
#define STEREO_DEST_MIX_FIR { \
- *dst++ += MULSC( fir_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
- *dst++ += MULSC( fir_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
+ *dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[0] ), lvol ); \
+ *dst++ += MULSC( lanczos_resampler_get_sample( resampler->fir_resampler[1] ), rvol ); \
UPDATE_VOLUME( volume_left, lvol ); \
UPDATE_VOLUME( volume_right, rvol ); \
}
--- a/dumb/src/it/itrender.c
+++ b/dumb/src/it/itrender.c
@@ -51,7 +51,7 @@
blip_set_rates(r->resampler.blip_buffer[0], 65536, 1);
blip_set_rates(r->resampler.blip_buffer[1], 65536, 1);
r->resampler.fir_resampler_ratio = 0.0;
- r->resampler.fir_resampler[0] = fir_resampler_create();
+ r->resampler.fir_resampler[0] = lanczos_resampler_create();
if ( !r->resampler.fir_resampler[0] )
{
free( r->resampler.blip_buffer[1] );
@@ -59,10 +59,10 @@
free( r );
return NULL;
}
- r->resampler.fir_resampler[1] = fir_resampler_create();
+ r->resampler.fir_resampler[1] = lanczos_resampler_create();
if ( !r->resampler.fir_resampler[1] )
{
- fir_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 );
@@ -74,8 +74,8 @@
static void free_playing(IT_PLAYING * r)
{
- fir_resampler_delete( r->resampler.fir_resampler[1] );
- fir_resampler_delete( r->resampler.fir_resampler[0] );
+ lanczos_resampler_delete( r->resampler.fir_resampler[1] );
+ lanczos_resampler_delete( r->resampler.fir_resampler[0] );
blip_delete( r->resampler.blip_buffer[1] );
blip_delete( r->resampler.blip_buffer[0] );
free( r );
@@ -184,7 +184,7 @@
return NULL;
}
dst->resampler.fir_resampler_ratio = src->resampler.fir_resampler_ratio;
- dst->resampler.fir_resampler[0] = fir_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] )
{
blip_delete( dst->resampler.blip_buffer[1] );
@@ -192,10 +192,10 @@
free( dst );
return NULL;
}
- dst->resampler.fir_resampler[1] = fir_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] )
{
- fir_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 );
@@ -305,7 +305,6 @@
dst->playing = dup_playing(src->playing, dst, src);
-
#ifdef BIT_ARRAY_BULLSHIT
dst->played_patjump = bit_array_dup(src->played_patjump);
dst->played_patjump_order = src->played_patjump_order;
@@ -1223,7 +1222,47 @@
}
+static void update_playing_effects(IT_PLAYING *playing)
+{
+ IT_CHANNEL *channel = playing->channel;
+ if (channel->channelvolslide) {
+ playing->channel_volume = channel->channelvolume;
+ }
+
+ if (channel->okt_toneslide) {
+ if (channel->okt_toneslide--) {
+ playing->note += channel->toneslide;
+ if (playing->note >= 120) {
+ if (channel->toneslide < 0) playing->note = 0;
+ else playing->note = 119;
+ }
+ }
+ } else if (channel->ptm_toneslide) {
+ if (--channel->toneslide_tick == 0) {
+ channel->toneslide_tick = channel->ptm_toneslide;
+ if (playing) {
+ playing->note += channel->toneslide;
+ if (playing->note >= 120) {
+ if (channel->toneslide < 0) playing->note = 0;
+ else playing->note = 119;
+ }
+ if (channel->playing == playing) {
+ channel->note = channel->truenote = playing->note;
+ }
+ if (channel->toneslide_retrig) {
+ it_playing_reset_resamplers(playing, 0);
+#ifdef END_RAMPING
+ playing->declick_stage = 0;
+ playing->declick_volume = 1.f / 256.f;
+#endif
+ }
+ }
+ }
+ }
+}
+
+
static void update_effects(DUMB_IT_SIGRENDERER *sigrenderer)
{
int i, j;
@@ -1308,12 +1347,6 @@
else
channel->channelvolume = 0;
}
- if (channel->playing)
- channel->playing->channel_volume = channel->channelvolume;
- for (j = 0; j < DUMB_IT_N_NNA_CHANNELS; j++) {
- if (sigrenderer->playing[j] && sigrenderer->playing[j]->channel == channel)
- sigrenderer->playing[j]->channel_volume = channel->channelvolume;
- }
}
update_tremor(channel);
@@ -1324,128 +1357,67 @@
if (channel->inv_loop_speed) update_invert_loop(channel, playing ? playing->sample : NULL);
- for (j = 0; j < DUMB_IT_N_NNA_CHANNELS; j++) {
- if (sigrenderer->playing[j] && sigrenderer->playing[j]->channel == channel) break;
- }
+ if (playing) {
+ playing->slide += channel->portamento;
- if (playing || j < DUMB_IT_N_NNA_CHANNELS) {
- if (playing) playing->slide += channel->portamento;
- for (j = 0; j < DUMB_IT_N_NNA_CHANNELS; j++) {
- if (sigrenderer->playing[j] && sigrenderer->playing[j]->channel == channel)
- sigrenderer->playing[j]->slide += channel->portamento;
- }
-
- if (channel->okt_toneslide) {
- if (channel->okt_toneslide--) {
- if (playing) {
- playing->note += channel->toneslide;
- if (playing->note >= 120) {
- if (channel->toneslide < 0) playing->note = 0;
- else playing->note = 119;
+ if (sigrenderer->sigdata->flags & IT_LINEAR_SLIDES) {
+ if (channel->toneporta && channel->destnote < 120) {
+ int currpitch = ((playing->note - 60) << 8) + playing->slide;
+ int destpitch = (channel->destnote - 60) << 8;
+ if (currpitch > destpitch) {
+ currpitch -= channel->toneporta;
+ if (currpitch < destpitch) {
+ currpitch = destpitch;
+ channel->destnote = IT_NOTE_OFF;
}
- }
- for (j = 0; j < DUMB_IT_N_NNA_CHANNELS; j++) {
- if (sigrenderer->playing[j] && sigrenderer->playing[j]->channel == channel) {
- IT_PLAYING *playing = sigrenderer->playing[j];
- playing->note += channel->toneslide;
- if (playing->note >= 120) {
- if (channel->toneslide < 0) playing->note = 0;
- else playing->note = 119;
- }
+ } else if (currpitch < destpitch) {
+ currpitch += channel->toneporta;
+ if (currpitch > destpitch) {
+ currpitch = destpitch;
+ channel->destnote = IT_NOTE_OFF;
}
}
+ playing->slide = currpitch - ((playing->note - 60) << 8);
}
- } else if (channel->ptm_toneslide) {
- if (--channel->toneslide_tick == 0) {
- channel->toneslide_tick = channel->ptm_toneslide;
- if (playing) {
- playing->note += channel->toneslide;
- if (playing->note >= 120) {
- if (channel->toneslide < 0) playing->note = 0;
- else playing->note = 119;
- }
- channel->note = channel->truenote = playing->note;
- if (channel->toneslide_retrig) {
- it_playing_reset_resamplers(playing, 0);
-#ifdef END_RAMPING
- playing->declick_stage = 0;
- playing->declick_volume = 1.f / 256.f;
-#endif
- }
- }
- for (j = 0; j < DUMB_IT_N_NNA_CHANNELS; j++) {
- if (sigrenderer->playing[j] && sigrenderer->playing[j]->channel == channel) {
- IT_PLAYING *playing = sigrenderer->playing[j];
- playing->note += channel->toneslide;
- if (playing->note >= 120) {
- if (channel->toneslide < 0) playing->note = 0;
- else playing->note = 119;
- }
- if (channel->toneslide_retrig) {
- it_playing_reset_resamplers(playing, 0);
-#ifdef END_RAMPING
- playing->declick_stage = 0;
- playing->declick_volume = 1.f / 256.f;
-#endif
- }
- }
- }
- }
- }
+ } else {
+ if (channel->toneporta && channel->destnote < 120) {
+ float amiga_multiplier = playing->sample->C5_speed * (1.0f / AMIGA_DIVISOR);
- if (playing) {
- if (sigrenderer->sigdata->flags & IT_LINEAR_SLIDES) {
- if (channel->toneporta && channel->destnote < 120) {
- int currpitch = ((playing->note - 60) << 8) + playing->slide;
- int destpitch = (channel->destnote - 60) << 8;
- if (currpitch > destpitch) {
- currpitch -= channel->toneporta;
- if (currpitch < destpitch) {
- currpitch = destpitch;
- channel->destnote = IT_NOTE_OFF;
- }
- } else if (currpitch < destpitch) {
- currpitch += channel->toneporta;
- if (currpitch > destpitch) {
- currpitch = destpitch;
- channel->destnote = IT_NOTE_OFF;
- }
- }
- playing->slide = currpitch - ((playing->note - 60) << 8);
- }
- } else {
- if (channel->toneporta && channel->destnote < 120) {
- float amiga_multiplier = playing->sample->C5_speed * (1.0f / AMIGA_DIVISOR);
+ float deltanote = (float)pow(DUMB_SEMITONE_BASE, 60 - playing->note);
+ /* deltanote is 1.0 for C-5, 0.5 for C-6, etc. */
- float deltanote = (float)pow(DUMB_SEMITONE_BASE, 60 - playing->note);
- /* deltanote is 1.0 for C-5, 0.5 for C-6, etc. */
+ float deltaslid = deltanote - playing->slide * amiga_multiplier;
- float deltaslid = deltanote - playing->slide * amiga_multiplier;
-
- float destdelta = (float)pow(DUMB_SEMITONE_BASE, 60 - channel->destnote);
+ float destdelta = (float)pow(DUMB_SEMITONE_BASE, 60 - channel->destnote);
+ if (deltaslid < destdelta) {
+ playing->slide -= channel->toneporta;
+ deltaslid = deltanote - playing->slide * amiga_multiplier;
+ if (deltaslid > destdelta) {
+ playing->note = channel->destnote;
+ playing->slide = 0;
+ channel->destnote = IT_NOTE_OFF;
+ }
+ } else {
+ playing->slide += channel->toneporta;
+ deltaslid = deltanote - playing->slide * amiga_multiplier;
if (deltaslid < destdelta) {
- playing->slide -= channel->toneporta;
- deltaslid = deltanote - playing->slide * amiga_multiplier;
- if (deltaslid > destdelta) {
- playing->note = channel->destnote;
- playing->slide = 0;
- channel->destnote = IT_NOTE_OFF;
- }
- } else {
- playing->slide += channel->toneporta;
- deltaslid = deltanote - playing->slide * amiga_multiplier;
- if (deltaslid < destdelta) {
- playing->note = channel->destnote;
- playing->slide = 0;
- channel->destnote = IT_NOTE_OFF;
- }
+ playing->note = channel->destnote;
+ playing->slide = 0;
+ channel->destnote = IT_NOTE_OFF;
}
}
}
}
+
+ update_playing_effects(playing);
}
}
+ for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
+ IT_PLAYING *playing = sigrenderer->playing[i];
+ if (playing) update_playing_effects(playing);
+ }
+
update_smooth_effects(sigrenderer);
}
@@ -1714,7 +1686,6 @@
}
-
static void it_retrigger_note(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *channel)
{
IT_PLAYING_ENVELOPE volume_envelope;
@@ -1865,7 +1836,7 @@
if (channel->playing)
free_playing(channel->playing);
- channel->playing = new_playing();
+ channel->playing = new_playing(channel);
if (!channel->playing)
return;
@@ -3505,7 +3476,7 @@
channel->destnote = IT_NOTE_OFF;
if (!channel->playing) {
- channel->playing = new_playing();
+ channel->playing = new_playing(channel);
if (!channel->playing) {
if (playing) free_playing(playing);
return;
--- a/dumb/vc6/dumb/dumb.vcxproj
+++ b/dumb/vc6/dumb/dumb.vcxproj
@@ -108,6 +108,7 @@
<ClCompile Include="..\..\src\helpers\blip_buf.c" />
<ClCompile Include="..\..\src\helpers\clickrem.c" />
<ClCompile Include="..\..\src\helpers\fir_resampler.c" />
+ <ClCompile Include="..\..\src\helpers\lanczos_resampler.c" />
<ClCompile Include="..\..\src\helpers\lpc.c" />
<ClCompile Include="..\..\src\helpers\memfile.c" />
<ClCompile Include="..\..\src\helpers\resample.c" />
@@ -202,6 +203,7 @@
<ClInclude Include="..\..\include\internal\dumb.h" />
<ClInclude Include="..\..\include\internal\fir_resampler.h" />
<ClInclude Include="..\..\include\internal\it.h" />
+ <ClInclude Include="..\..\include\internal\lanczos_resampler.h" />
<ClInclude Include="..\..\include\internal\lpc.h" />
<ClInclude Include="..\..\include\internal\riff.h" />
<ClInclude Include="..\..\include\internal\stack_alloc.h" />
--- a/dumb/vc6/dumb/dumb.vcxproj.filters
+++ b/dumb/vc6/dumb/dumb.vcxproj.filters
@@ -282,6 +282,9 @@
<ClCompile Include="..\..\src\it\readany2.c">
<Filter>src\it\readers</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\helpers\lanczos_resampler.c">
+ <Filter>src\helpers</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\dumb.h">
@@ -309,6 +312,9 @@
<Filter>include\internal</Filter>
</ClInclude>
<ClInclude Include="..\..\include\internal\blip_buf.h">
+ <Filter>include\internal</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\include\internal\lanczos_resampler.h">
<Filter>include\internal</Filter>
</ClInclude>
</ItemGroup>