diff --git a/Frameworks/Dumb/dumb/include/dumb.h b/Frameworks/Dumb/dumb/include/dumb.h index bed17a1e5..4507eece1 100644 --- a/Frameworks/Dumb/dumb/include/dumb.h +++ b/Frameworks/Dumb/dumb/include/dumb.h @@ -712,7 +712,7 @@ struct DUMB_VOLUME_RAMP_INFO float delta; float target; float mix; - unsigned char * declick_stage; + unsigned char declick_stage; }; void dumb_reset_resampler(DUMB_RESAMPLER *resampler, sample_t *src, int src_channels, long pos, long start, long end, int quality); diff --git a/Frameworks/Dumb/dumb/src/helpers/resample.c b/Frameworks/Dumb/dumb/src/helpers/resample.c index 15936ae94..4a3a08b7a 100644 --- a/Frameworks/Dumb/dumb/src/helpers/resample.c +++ b/Frameworks/Dumb/dumb/src/helpers/resample.c @@ -132,44 +132,10 @@ int dumb_resampling_quality = DUMB_RQ_CUBIC; -/* Cubic resampler: look-up tables - * - * a = 1.5*x1 - 1.5*x2 + 0.5*x3 - 0.5*x0 - * b = 2*x2 + x0 - 2.5*x1 - 0.5*x3 - * c = 0.5*x2 - 0.5*x0 - * d = x1 - * - * x = a*t*t*t + b*t*t + c*t + d - * = (-0.5*x0 + 1.5*x1 - 1.5*x2 + 0.5*x3) * t*t*t + - * ( 1*x0 - 2.5*x1 + 2 *x2 - 0.5*x3) * t*t + - * (-0.5*x0 + 0.5*x2 ) * t + - * ( 1*x1 ) - * = (-0.5*t*t*t + 1 *t*t - 0.5*t ) * x0 + - * ( 1.5*t*t*t - 2.5*t*t + 1) * x1 + - * (-1.5*t*t*t + 2 *t*t + 0.5*t ) * x2 + - * ( 0.5*t*t*t - 0.5*t*t ) * x3 - * = A0(t) * x0 + A1(t) * x1 + A2(t) * x2 + A3(t) * x3 - * - * A0, A1, A2 and A3 stay within the range [-1,1]. - * In the tables, they are scaled with 14 fractional bits. - * - * Turns out we don't need to store A2 and A3; they are symmetrical to A1 and A0. - * - * TODO: A0 and A3 stay very small indeed. Consider different scale/resolution? - */ - -static short cubicA0[1025], cubicA1[1025]; - void _dumb_init_cubic(void) { - unsigned int t; /* 3*1024*1024*1024 is within range if it's unsigned */ static int done = 0; if (done) return; - for (t = 0; t < 1025; t++) { - /* int casts to pacify warnings about negating unsigned values */ - cubicA0[t] = -(int)( t*t*t >> 17) + (int)( t*t >> 6) - (int)(t << 3); - cubicA1[t] = (int)(3*t*t*t >> 17) - (int)(5*t*t >> 7) + (int)(1 << 14); - } resampler_init(); diff --git a/Frameworks/Dumb/dumb/src/helpers/resample.inc b/Frameworks/Dumb/dumb/src/helpers/resample.inc index 01b2fcf8e..84eead97f 100644 --- a/Frameworks/Dumb/dumb/src/helpers/resample.inc +++ b/Frameworks/Dumb/dumb/src/helpers/resample.inc @@ -114,9 +114,9 @@ DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, l if ((vol##d < 0 && vol##r <= vol##t) || \ (vol##d > 0 && vol##r >= vol##t)) { \ pvol->volume = pvol->target; \ - if ( *pvol->declick_stage == 0 || \ - *pvol->declick_stage >= 3) \ - (*pvol->declick_stage)++; \ + if ( pvol->declick_stage == 0 || \ + pvol->declick_stage >= 3) \ + pvol->declick_stage++; \ pvol = NULL; \ vol = MULSCV( vol##t, vol##m ); \ } else { \ diff --git a/Frameworks/Dumb/dumb/src/it/itrender.c b/Frameworks/Dumb/dumb/src/it/itrender.c index 151c1430b..15191b8cd 100644 --- a/Frameworks/Dumb/dumb/src/it/itrender.c +++ b/Frameworks/Dumb/dumb/src/it/itrender.c @@ -1799,7 +1799,7 @@ static void it_retrigger_note(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *chan switch (nna) { case NNA_NOTE_CUT: - channel->playing->declick_stage = 2; + channel->playing->declick_stage = 3; break; case NNA_NOTE_OFF: it_note_off(channel->playing); @@ -1848,7 +1848,7 @@ static void it_retrigger_note(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *chan switch (playing->instrument->dup_check_action) { case DCA_NOTE_CUT: - playing->declick_stage = 2; + playing->declick_stage = 3; if (channel->playing == playing) channel->playing = NULL; break; case DCA_NOTE_OFF: @@ -2786,7 +2786,7 @@ Yxy This uses a table 4 times larger (hence 4 times slower) than IT_PLAYING * playing = sigrenderer->playing[i]; if (playing && channel == playing->channel) { - playing->declick_stage = 2; + playing->declick_stage = 3; if (channel->playing == playing) channel->playing = NULL; } } @@ -3373,7 +3373,7 @@ static void process_xm_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *ent int i; for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) { if (!sigrenderer->playing[i]) { - channel->playing->declick_stage = 2; + channel->playing->declick_stage = 3; sigrenderer->playing[i] = channel->playing; channel->playing = NULL; break; @@ -3430,7 +3430,7 @@ static void process_xm_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *ent } for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) { if (!sigrenderer->playing[i]) { - channel->playing->declick_stage = 2; + channel->playing->declick_stage = 3; sigrenderer->playing[i] = channel->playing; channel->playing = NULL; break; @@ -3475,7 +3475,7 @@ static void process_xm_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *ent playing = NULL; for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) { if (!sigrenderer->playing[i]) { - ptemp->declick_stage = 2; + ptemp->declick_stage = 3; ptemp->flags |= IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING; sigrenderer->playing[i] = ptemp; ptemp = NULL; @@ -3699,7 +3699,7 @@ static void update_tick_counts(DUMB_IT_SIGRENDERER *sigrenderer) int i; for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) { if (!sigrenderer->playing[i]) { - channel->playing->declick_stage = 2; + channel->playing->declick_stage = 3; sigrenderer->playing[i] = channel->playing; channel->playing = NULL; break; @@ -3949,16 +3949,14 @@ static void playing_volume_setup(DUMB_IT_SIGRENDERER * sigrenderer, IT_PLAYING * playing->ramp_volume[0] = 0; playing->ramp_volume[1] = 0; rampScale = 48; - } else if (playing->declick_stage == 2) { - playing->ramp_volume[0] = playing->float_volume[0]; - playing->ramp_volume[1] = playing->float_volume[1]; - playing->float_volume[0] = 0; - playing->float_volume[1] = 0; playing->declick_stage++; + } else if (playing->declick_stage == 1) { rampScale = 48; } else if (playing->declick_stage >= 3) { playing->float_volume[0] = 0; playing->float_volume[1] = 0; + if (playing->declick_stage == 3) + playing->declick_stage++; rampScale = 48; } playing->ramp_delta[0] = rampScale * invt2g * (playing->float_volume[0] - playing->ramp_volume[0]); @@ -4175,7 +4173,7 @@ static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer) //if ((sigrenderer->channel[i].playing->flags & (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) == (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) { // This change was made so Gxx would work correctly when a note faded out or whatever. Let's hope nothing else was broken by it. if ((sigrenderer->channel[i].playing->flags & IT_PLAYING_DEAD) || - (sigrenderer->channel[i].playing->declick_stage > 3)) { + (sigrenderer->channel[i].playing->declick_stage > 4)) { free_playing(sigrenderer->channel[i].playing); sigrenderer->channel[i].playing = NULL; } @@ -4187,7 +4185,7 @@ static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer) if (sigrenderer->playing[i]) { process_playing(sigrenderer, sigrenderer->playing[i], invt2g); if ((sigrenderer->playing[i]->flags & IT_PLAYING_DEAD) || - (sigrenderer->playing[i]->declick_stage > 3)) { + (sigrenderer->playing[i]->declick_stage > 4)) { free_playing(sigrenderer->playing[i]); sigrenderer->playing[i] = NULL; } @@ -4679,7 +4677,7 @@ static long render_playing(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing lvol.target = playing->float_volume [0]; rvol.target = playing->float_volume [1]; rvol.mix = lvol.mix = volume; - lvol.declick_stage = rvol.declick_stage = &(playing->declick_stage); + lvol.declick_stage = rvol.declick_stage = playing->declick_stage; if (sigrenderer->n_channels >= 2) { if (playing->sample->flags & IT_SAMPLE_STEREO) { if (sigrenderer->click_remover) { @@ -4755,6 +4753,7 @@ static long render_playing(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing } playing->ramp_volume [0] = lvol.volume; playing->ramp_volume [1] = rvol.volume; + playing->declick_stage = (lvol.declick_stage > rvol.declick_stage) ? lvol.declick_stage : rvol.declick_stage; (*left_to_mix)--; } @@ -4944,10 +4943,7 @@ static void render_normal(DUMB_IT_SIGRENDERER *sigrenderer, float volume, float if (sigrenderer->channel[i].playing) { //if ((sigrenderer->channel[i].playing->flags & (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) == (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) { // This change was made so Gxx would work correctly when a note faded out or whatever. Let's hope nothing else was broken by it. - if ( -#ifdef RAMP_DOWN - (sigrenderer->channel[i].playing->declick_stage == 3) || -#endif + if ((sigrenderer->channel[i].playing->declick_stage > 4) || (sigrenderer->channel[i].playing->flags & IT_PLAYING_DEAD)) { free_playing(sigrenderer->channel[i].playing); sigrenderer->channel[i].playing = NULL; @@ -4957,10 +4953,7 @@ static void render_normal(DUMB_IT_SIGRENDERER *sigrenderer, float volume, float for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) { if (sigrenderer->playing[i]) { - if ( -#ifdef RAMP_DOWN - (sigrenderer->playing[i]->declick_stage == 3) || -#endif + if ((sigrenderer->playing[i]->declick_stage > 4) || (sigrenderer->playing[i]->flags & IT_PLAYING_DEAD)) { free_playing(sigrenderer->playing[i]); sigrenderer->playing[i] = NULL; @@ -5105,10 +5098,7 @@ static void render_surround(DUMB_IT_SIGRENDERER *sigrenderer, float volume, floa if (sigrenderer->channel[i].playing) { //if ((sigrenderer->channel[i].playing->flags & (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) == (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) { // This change was made so Gxx would work correctly when a note faded out or whatever. Let's hope nothing else was broken by it. - if ( -#ifdef RAMP_DOWN - (sigrenderer->channel[i].playing->declick_stage == 3) || -#endif + if ((sigrenderer->channel[i].playing->declick_stage > 4) || (sigrenderer->channel[i].playing->flags & IT_PLAYING_DEAD)) { free_playing(sigrenderer->channel[i].playing); sigrenderer->channel[i].playing = NULL; @@ -5118,10 +5108,7 @@ static void render_surround(DUMB_IT_SIGRENDERER *sigrenderer, float volume, floa for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) { if (sigrenderer->playing[i]) { - if ( -#ifdef RAMP_DOWN - (sigrenderer->playing[i]->declick_stage == 3) || -#endif + if ((sigrenderer->playing[i]->declick_stage > 4) || (sigrenderer->playing[i]->flags & IT_PLAYING_DEAD)) { free_playing(sigrenderer->playing[i]); sigrenderer->playing[i] = NULL;