Reworked DUMB volume ramping ever so slightly
This commit is contained in:
parent
9aae7b9c41
commit
94fcb71671
4 changed files with 22 additions and 69 deletions
|
@ -712,7 +712,7 @@ struct DUMB_VOLUME_RAMP_INFO
|
||||||
float delta;
|
float delta;
|
||||||
float target;
|
float target;
|
||||||
float mix;
|
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);
|
void dumb_reset_resampler(DUMB_RESAMPLER *resampler, sample_t *src, int src_channels, long pos, long start, long end, int quality);
|
||||||
|
|
|
@ -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)
|
void _dumb_init_cubic(void)
|
||||||
{
|
{
|
||||||
unsigned int t; /* 3*1024*1024*1024 is within range if it's unsigned */
|
|
||||||
static int done = 0;
|
static int done = 0;
|
||||||
if (done) return;
|
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();
|
resampler_init();
|
||||||
|
|
||||||
|
|
|
@ -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) || \
|
if ((vol##d < 0 && vol##r <= vol##t) || \
|
||||||
(vol##d > 0 && vol##r >= vol##t)) { \
|
(vol##d > 0 && vol##r >= vol##t)) { \
|
||||||
pvol->volume = pvol->target; \
|
pvol->volume = pvol->target; \
|
||||||
if ( *pvol->declick_stage == 0 || \
|
if ( pvol->declick_stage == 0 || \
|
||||||
*pvol->declick_stage >= 3) \
|
pvol->declick_stage >= 3) \
|
||||||
(*pvol->declick_stage)++; \
|
pvol->declick_stage++; \
|
||||||
pvol = NULL; \
|
pvol = NULL; \
|
||||||
vol = MULSCV( vol##t, vol##m ); \
|
vol = MULSCV( vol##t, vol##m ); \
|
||||||
} else { \
|
} else { \
|
||||||
|
|
|
@ -1799,7 +1799,7 @@ static void it_retrigger_note(DUMB_IT_SIGRENDERER *sigrenderer, IT_CHANNEL *chan
|
||||||
|
|
||||||
switch (nna) {
|
switch (nna) {
|
||||||
case NNA_NOTE_CUT:
|
case NNA_NOTE_CUT:
|
||||||
channel->playing->declick_stage = 2;
|
channel->playing->declick_stage = 3;
|
||||||
break;
|
break;
|
||||||
case NNA_NOTE_OFF:
|
case NNA_NOTE_OFF:
|
||||||
it_note_off(channel->playing);
|
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)
|
switch (playing->instrument->dup_check_action)
|
||||||
{
|
{
|
||||||
case DCA_NOTE_CUT:
|
case DCA_NOTE_CUT:
|
||||||
playing->declick_stage = 2;
|
playing->declick_stage = 3;
|
||||||
if (channel->playing == playing) channel->playing = NULL;
|
if (channel->playing == playing) channel->playing = NULL;
|
||||||
break;
|
break;
|
||||||
case DCA_NOTE_OFF:
|
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];
|
IT_PLAYING * playing = sigrenderer->playing[i];
|
||||||
if (playing && channel == playing->channel)
|
if (playing && channel == playing->channel)
|
||||||
{
|
{
|
||||||
playing->declick_stage = 2;
|
playing->declick_stage = 3;
|
||||||
if (channel->playing == playing) channel->playing = NULL;
|
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;
|
int i;
|
||||||
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
|
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
|
||||||
if (!sigrenderer->playing[i]) {
|
if (!sigrenderer->playing[i]) {
|
||||||
channel->playing->declick_stage = 2;
|
channel->playing->declick_stage = 3;
|
||||||
sigrenderer->playing[i] = channel->playing;
|
sigrenderer->playing[i] = channel->playing;
|
||||||
channel->playing = NULL;
|
channel->playing = NULL;
|
||||||
break;
|
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++) {
|
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
|
||||||
if (!sigrenderer->playing[i]) {
|
if (!sigrenderer->playing[i]) {
|
||||||
channel->playing->declick_stage = 2;
|
channel->playing->declick_stage = 3;
|
||||||
sigrenderer->playing[i] = channel->playing;
|
sigrenderer->playing[i] = channel->playing;
|
||||||
channel->playing = NULL;
|
channel->playing = NULL;
|
||||||
break;
|
break;
|
||||||
|
@ -3475,7 +3475,7 @@ static void process_xm_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *ent
|
||||||
playing = NULL;
|
playing = NULL;
|
||||||
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
|
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
|
||||||
if (!sigrenderer->playing[i]) {
|
if (!sigrenderer->playing[i]) {
|
||||||
ptemp->declick_stage = 2;
|
ptemp->declick_stage = 3;
|
||||||
ptemp->flags |= IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING;
|
ptemp->flags |= IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING;
|
||||||
sigrenderer->playing[i] = ptemp;
|
sigrenderer->playing[i] = ptemp;
|
||||||
ptemp = NULL;
|
ptemp = NULL;
|
||||||
|
@ -3699,7 +3699,7 @@ static void update_tick_counts(DUMB_IT_SIGRENDERER *sigrenderer)
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
|
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
|
||||||
if (!sigrenderer->playing[i]) {
|
if (!sigrenderer->playing[i]) {
|
||||||
channel->playing->declick_stage = 2;
|
channel->playing->declick_stage = 3;
|
||||||
sigrenderer->playing[i] = channel->playing;
|
sigrenderer->playing[i] = channel->playing;
|
||||||
channel->playing = NULL;
|
channel->playing = NULL;
|
||||||
break;
|
break;
|
||||||
|
@ -3949,16 +3949,14 @@ static void playing_volume_setup(DUMB_IT_SIGRENDERER * sigrenderer, IT_PLAYING *
|
||||||
playing->ramp_volume[0] = 0;
|
playing->ramp_volume[0] = 0;
|
||||||
playing->ramp_volume[1] = 0;
|
playing->ramp_volume[1] = 0;
|
||||||
rampScale = 48;
|
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++;
|
playing->declick_stage++;
|
||||||
|
} else if (playing->declick_stage == 1) {
|
||||||
rampScale = 48;
|
rampScale = 48;
|
||||||
} else if (playing->declick_stage >= 3) {
|
} else if (playing->declick_stage >= 3) {
|
||||||
playing->float_volume[0] = 0;
|
playing->float_volume[0] = 0;
|
||||||
playing->float_volume[1] = 0;
|
playing->float_volume[1] = 0;
|
||||||
|
if (playing->declick_stage == 3)
|
||||||
|
playing->declick_stage++;
|
||||||
rampScale = 48;
|
rampScale = 48;
|
||||||
}
|
}
|
||||||
playing->ramp_delta[0] = rampScale * invt2g * (playing->float_volume[0] - playing->ramp_volume[0]);
|
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)) {
|
//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.
|
// 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) ||
|
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);
|
free_playing(sigrenderer->channel[i].playing);
|
||||||
sigrenderer->channel[i].playing = NULL;
|
sigrenderer->channel[i].playing = NULL;
|
||||||
}
|
}
|
||||||
|
@ -4187,7 +4185,7 @@ static void process_all_playing(DUMB_IT_SIGRENDERER *sigrenderer)
|
||||||
if (sigrenderer->playing[i]) {
|
if (sigrenderer->playing[i]) {
|
||||||
process_playing(sigrenderer, sigrenderer->playing[i], invt2g);
|
process_playing(sigrenderer, sigrenderer->playing[i], invt2g);
|
||||||
if ((sigrenderer->playing[i]->flags & IT_PLAYING_DEAD) ||
|
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]);
|
free_playing(sigrenderer->playing[i]);
|
||||||
sigrenderer->playing[i] = NULL;
|
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];
|
lvol.target = playing->float_volume [0];
|
||||||
rvol.target = playing->float_volume [1];
|
rvol.target = playing->float_volume [1];
|
||||||
rvol.mix = lvol.mix = volume;
|
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 (sigrenderer->n_channels >= 2) {
|
||||||
if (playing->sample->flags & IT_SAMPLE_STEREO) {
|
if (playing->sample->flags & IT_SAMPLE_STEREO) {
|
||||||
if (sigrenderer->click_remover) {
|
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 [0] = lvol.volume;
|
||||||
playing->ramp_volume [1] = rvol.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)--;
|
(*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) {
|
||||||
//if ((sigrenderer->channel[i].playing->flags & (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) == (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) {
|
//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.
|
// 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 (
|
if ((sigrenderer->channel[i].playing->declick_stage > 4) ||
|
||||||
#ifdef RAMP_DOWN
|
|
||||||
(sigrenderer->channel[i].playing->declick_stage == 3) ||
|
|
||||||
#endif
|
|
||||||
(sigrenderer->channel[i].playing->flags & IT_PLAYING_DEAD)) {
|
(sigrenderer->channel[i].playing->flags & IT_PLAYING_DEAD)) {
|
||||||
free_playing(sigrenderer->channel[i].playing);
|
free_playing(sigrenderer->channel[i].playing);
|
||||||
sigrenderer->channel[i].playing = NULL;
|
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++) {
|
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
|
||||||
if (sigrenderer->playing[i]) {
|
if (sigrenderer->playing[i]) {
|
||||||
if (
|
if ((sigrenderer->playing[i]->declick_stage > 4) ||
|
||||||
#ifdef RAMP_DOWN
|
|
||||||
(sigrenderer->playing[i]->declick_stage == 3) ||
|
|
||||||
#endif
|
|
||||||
(sigrenderer->playing[i]->flags & IT_PLAYING_DEAD)) {
|
(sigrenderer->playing[i]->flags & IT_PLAYING_DEAD)) {
|
||||||
free_playing(sigrenderer->playing[i]);
|
free_playing(sigrenderer->playing[i]);
|
||||||
sigrenderer->playing[i] = NULL;
|
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) {
|
||||||
//if ((sigrenderer->channel[i].playing->flags & (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) == (IT_PLAYING_BACKGROUND | IT_PLAYING_DEAD)) {
|
//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.
|
// 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 (
|
if ((sigrenderer->channel[i].playing->declick_stage > 4) ||
|
||||||
#ifdef RAMP_DOWN
|
|
||||||
(sigrenderer->channel[i].playing->declick_stage == 3) ||
|
|
||||||
#endif
|
|
||||||
(sigrenderer->channel[i].playing->flags & IT_PLAYING_DEAD)) {
|
(sigrenderer->channel[i].playing->flags & IT_PLAYING_DEAD)) {
|
||||||
free_playing(sigrenderer->channel[i].playing);
|
free_playing(sigrenderer->channel[i].playing);
|
||||||
sigrenderer->channel[i].playing = NULL;
|
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++) {
|
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
|
||||||
if (sigrenderer->playing[i]) {
|
if (sigrenderer->playing[i]) {
|
||||||
if (
|
if ((sigrenderer->playing[i]->declick_stage > 4) ||
|
||||||
#ifdef RAMP_DOWN
|
|
||||||
(sigrenderer->playing[i]->declick_stage == 3) ||
|
|
||||||
#endif
|
|
||||||
(sigrenderer->playing[i]->flags & IT_PLAYING_DEAD)) {
|
(sigrenderer->playing[i]->flags & IT_PLAYING_DEAD)) {
|
||||||
free_playing(sigrenderer->playing[i]);
|
free_playing(sigrenderer->playing[i]);
|
||||||
sigrenderer->playing[i] = NULL;
|
sigrenderer->playing[i] = NULL;
|
||||||
|
|
Loading…
Reference in a new issue