ref: f230355b7f90105f13ca56343c4d2e2c1763d68f
parent: 684f4672fe54d3e82a6912a8896cf812ca0acbdb
author: Chris Moeller <kode54@gmail.com>
date: Mon Jan 11 04:00:56 EST 2010
{7/24/2007 3:48:08 PM}2007-01-26 22:50 UTC - kode54 - Moved IT S70-2 effects alongside the rest of S7x so they all trigger after paired notes. - Integrated note on/cut ramping with volume transition ramping to reduce setup/cleanup overhead of calling render_playing and the resampler functions for single samples. - Note on/cut ramping scaled from 7 sample logarithmic and 256 sample linear to .75ms and 5ms respectively, both linear. - Integrated the pattern looping changes from DUMB 0.9.3, since a few files seemed to be broken. The XM-only features still needed to be flagged for XM so they won't break MOD. git-tfs-id: [http://localhost:8080/tfs/DefaultCollection/]$/foobar2000/files/plugins.root;C181
--- a/dumb/include/internal/it.h
+++ b/dumb/include/internal/it.h
@@ -626,7 +626,7 @@
unsigned char lastS;
unsigned char pat_loop_row;
unsigned char pat_loop_count;
- //unsigned char pat_loop_end_row; /* Used to catch infinite pattern loops */
+ unsigned char pat_loop_end_row; /* Used to catch infinite pattern loops */
unsigned char lastW;
unsigned char xm_lastE1;
--- a/dumb/src/helpers/resamp2.inc
+++ b/dumb/src/helpers/resamp2.inc
@@ -109,8 +109,8 @@
lvolr = (int)(volume_left->volume * 16777216.0); \
lvold = (int)(volume_left->delta * 16777216.0); \
lvolt = (int)(volume_left->target * 16777216.0); \
- lvolm = (int)(volume_left->mix * 65536.0); \
- lvol = MULSC( lvolr >> 8, lvolm ); \
+ lvolm = (int)(volume_left->mix * 16777216.0); \
+ lvol = MULSCV( lvolr, lvolm ); \
if ( lvolr == lvolt ) volume_left = NULL; \
} else { \
lvol = 0; \
@@ -120,8 +120,8 @@
rvolr = (int)(volume_right->volume * 16777216.0); \
rvold = (int)(volume_right->delta * 16777216.0); \
rvolt = (int)(volume_right->target * 16777216.0); \
- rvolm = (int)(volume_right->mix * 65536.0); \
- rvol = MULSC( rvolr >> 8, rvolm ); \
+ rvolm = (int)(volume_right->mix * 16777216.0); \
+ rvol = MULSCV( rvolr, rvolm ); \
if ( rvolr == rvolt ) volume_right = NULL; \
} else { \
rvol = 0; \
--- a/dumb/src/helpers/resample.c
+++ b/dumb/src/helpers/resample.c
@@ -82,6 +82,7 @@
//#define MULSC(a, b) ((int)((LONG_LONG)(a) * (b) >> 16))
//#define MULSC(a, b) ((a) * ((b) >> 2) >> 14)
+#define MULSCV(a, b) ((int)((LONG_LONG)(a) * (b) >> 32))
#define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32))
#define MULSC16(a, b) ((int)((LONG_LONG)((a) << 12) * ((b) << 12) >> 32))
--- a/dumb/src/helpers/resample.inc
+++ b/dumb/src/helpers/resample.inc
@@ -90,9 +90,9 @@
(vol##d > 0 && vol##r >= vol##t)) { \
pvol->volume = pvol->target; \
pvol = NULL; \
- vol = MULSC( vol##t >> 8, vol##m ); \
+ vol = MULSCV( vol##t, vol##m ); \
} else { \
- vol = MULSC( vol##r >> 8, vol##m ); \
+ vol = MULSCV( vol##r, vol##m ); \
} \
} \
}
@@ -113,8 +113,8 @@
volr = (int)(volume->volume * 16777216.0); \
vold = (int)(volume->delta * 16777216.0); \
volt = (int)(volume->target * 16777216.0); \
- volm = (int)(volume->mix * 65536.0); \
- vol = MULSC( volr >> 8, volm ); \
+ volm = (int)(volume->mix * 16777216.0); \
+ vol = MULSCV( volr, volm ); \
if ( volr == volt ) volume = NULL; \
} else { \
vol = 0; \
@@ -184,8 +184,8 @@
lvolr = (int)(volume_left->volume * 16777216.0); \
lvold = (int)(volume_left->delta * 16777216.0); \
lvolt = (int)(volume_left->target * 16777216.0); \
- lvolm = (int)(volume_left->mix * 65536.0); \
- lvol = MULSC( lvolr >> 8, lvolm ); \
+ lvolm = (int)(volume_left->mix * 16777216.0); \
+ lvol = MULSCV( lvolr, lvolm ); \
if ( lvolr == lvolt ) volume_left = NULL; \
} else { \
lvol = 0; \
@@ -195,8 +195,8 @@
rvolr = (int)(volume_right->volume * 16777216.0); \
rvold = (int)(volume_right->delta * 16777216.0); \
rvolt = (int)(volume_right->target * 16777216.0); \
- rvolm = (int)(volume_right->mix * 65536.0); \
- rvol = MULSC( rvolr >> 8, rvolm ); \
+ rvolm = (int)(volume_right->mix * 16777216.0); \
+ rvol = MULSCV( rvolr, rvolm ); \
if ( rvolr == rvolt ) volume_right = NULL; \
} else { \
rvol = 0; \
--- a/dumb/src/it/itread.c
+++ b/dumb/src/it/itread.c
@@ -1188,6 +1188,9 @@
switch (component[n].type) {
case IT_COMPONENT_SONG_MESSAGE:
+ if ( n < n_components ) {
+ message_length = min( message_length, component[n+1].offset - component[n].offset );
+ }
sigdata->song_message = malloc(message_length + 1);
if (sigdata->song_message) {
if (dumbfile_getnc(sigdata->song_message, message_length, f) < message_length) {
--- a/dumb/src/it/itrender.c
+++ b/dumb/src/it/itrender.c
@@ -202,7 +202,7 @@
dst->lastS = src->lastS;
dst->pat_loop_row = src->pat_loop_row;
dst->pat_loop_count = src->pat_loop_count;
- //dst->pat_loop_end_row = src->pat_loop_end_row;
+ dst->pat_loop_end_row = src->pat_loop_end_row;
dst->lastW = src->lastW;
dst->xm_lastE1 = src->xm_lastE1;
@@ -486,6 +486,7 @@
+#if 0
#define LOG10 2.30258509299
/* IMPORTANT: This function expects one extra sample in 'src' so it can apply
@@ -493,6 +494,7 @@
* output starting at dst[pos]. The pos parameter is required for getting
* click removal right.
*/
+
static void it_filter(DUMB_CLICK_REMOVER *cr, IT_FILTER_STATE *state, sample_t *dst, long pos, sample_t *src, long size, int step, int sampfreq, int cutoff, int resonance)
{
sample_t currsample = state->currsample;
@@ -595,8 +597,8 @@
state->currsample = currsample;
state->prevsample = prevsample;
}
-
#undef LOG10
+#endif
@@ -1171,56 +1173,6 @@
effectvalue = channel->lastS;
channel->lastS = effectvalue;
switch (effectvalue >> 4) {
-#if 1
- case IT_S7:
- {
- if (sigrenderer->sigdata->flags & IT_USE_INSTRUMENTS)
- {
- int i;
- switch (effectvalue & 15)
- {
- case 0: /* cut background notes */
- for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
- {
- IT_PLAYING * playing = sigrenderer->playing[i];
- if (playing && channel == playing->channel)
- {
-#ifdef RAMP_DOWN
- playing->declick_stage = 2;
-#else
- free(playing);
- sigrenderer->playing[i] = NULL;
-#endif
- if (channel->playing == playing) channel->playing = NULL;
- }
- }
- break;
- case 1: /* release background notes */
- for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
- {
- IT_PLAYING * playing = sigrenderer->playing[i];
- if (playing && channel == playing->channel && !(playing->flags & IT_PLAYING_SUSTAINOFF))
- {
- it_note_off(playing);
- }
- }
- break;
- case 2: /* fade background notes */
- for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
- {
- IT_PLAYING * playing = sigrenderer->playing[i];
- if (playing && channel == playing->channel)
- {
- //playing->flags &= IT_PLAYING_SUSTAINOFF;
- playing->flags |= IT_PLAYING_FADING;
- }
- }
- break;
- }
- }
- }
- break;
-#endif
case IT_S_PATTERN_LOOP:
{
unsigned char v = effectvalue & 15;
@@ -1254,7 +1206,19 @@
#endif
channel->pat_loop_count = v;
sigrenderer->breakrow = channel->pat_loop_row;
- if (!(sigrenderer->sigdata->flags & IT_WAS_AN_XM) || ( ( sigrenderer->processrow | 0xC00 ) == 0xFFFE ) ) {
+ if ((sigrenderer->sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD)) == IT_WAS_AN_XM) {
+ /* For XM files, if a loop occurs by itself, keep breakrow set for when the pattern ends - fun bug in FT2! */
+ if ((sigrenderer->processrow|0xC00) < 0xFFFE) {
+ /* Infinite pattern loops are possible, so we check whether the pattern loop we're hitting now is earlier than the last one we hit. */
+ if (sigrenderer->processrow < channel->pat_loop_end_row)
+ sigrenderer->processorder = 0xFFFE; /* suspect infinite loop, so trigger loop callback */
+ else
+ sigrenderer->processorder = 0xFFFF; /* don't trigger loop callback */
+ channel->pat_loop_end_row = sigrenderer->processrow;
+ sigrenderer->processrow = 0xFFFF; /* special case: don't reset breakrow or pat_loop_end_row */
+ }
+ } else {
+ /* IT files do this regardless of other flow control effects seen here. */
sigrenderer->processorder = 0xFFFF; /* special case: don't trigger loop callback */
sigrenderer->processrow = 0xFFFE;
}
@@ -1268,16 +1232,38 @@
}
#endif
sigrenderer->breakrow = channel->pat_loop_row;
- if (!(sigrenderer->sigdata->flags & IT_WAS_AN_XM) || ( ( sigrenderer->processrow | 0xC00 ) == 0xFFFE ) ) {
+ if ((sigrenderer->sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD)) == IT_WAS_AN_XM) {
+ /* For XM files, if a loop occurs by itself, keep breakrow set for when the pattern ends - fun bug in FT2! */
+ if ((sigrenderer->processrow|0xC00) < 0xFFFE) {
+ /* Infinite pattern loops are possible, so we check whether the pattern loop we're hitting now is earlier than the last one we hit. */
+ if (sigrenderer->processrow < channel->pat_loop_end_row)
+ sigrenderer->processorder = 0xFFFE; /* suspect infinite loop, so trigger loop callback */
+ else
+ sigrenderer->processorder = 0xFFFF; /* don't trigger loop callback */
+ channel->pat_loop_end_row = sigrenderer->processrow;
+ sigrenderer->processrow = 0xFFFF; /* special case: don't reset breakrow or pat_loop_end_row */
+ }
+ } else {
+ /* IT files do this regardless of other flow control effects seen here. */
sigrenderer->processorder = 0xFFFF; /* special case: don't trigger loop callback */
sigrenderer->processrow = 0xFFFE;
}
return 1;
} else if ((sigrenderer->sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD)) == IT_WAS_AN_XM) {
- sigrenderer->breakrow = channel->pat_loop_row; /* emulate bug in FT2 */
- } else {
+ channel->pat_loop_end_row = 0;
+ // TODO
+ /* Findings:
+ - If a pattern loop completes successfully, and then the pattern terminates, then the next pattern will start on the row corresponding to the E60.
+ - If a pattern loop doesn't do any loops, and then the pattern terminates, then the next pattern will start on the first row.
+ - If a break appears to the left of the pattern loop, it jumps into the relevant position in the next pattern, and that's it.
+ - If a break appears to the right of the pattern loop, it jumps to the start of the next pattern, and that's it.
+ - If we jump, then effect a loop using an old E60, and then the pattern ends, the next pattern starts on the row corresponding to the E60.
+ - Theory: breakrow is not cleared when it's a pattern loop effect!
+ */
+ //if (sigrenderer->processrow < 0xFFFE) // I have no idea if this is correct or not - FT2 is so weird :(
+ // sigrenderer->breakrow = channel->pat_loop_row; /* emulate bug in FT2 */
+ } else
channel->pat_loop_row = sigrenderer->processrow + 1;
- }
#ifdef BIT_ARRAY_BULLSHIT
/*channel->played_patjump_order |= 0x8000;*/
if (channel->played_patjump_order == sigrenderer->order) {
@@ -2359,8 +2345,46 @@
{
if (sigrenderer->sigdata->flags & IT_USE_INSTRUMENTS)
{
+ int i;
switch (effectvalue & 15)
{
+ case 0: /* cut background notes */
+ for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
+ {
+ IT_PLAYING * playing = sigrenderer->playing[i];
+ if (playing && channel == playing->channel)
+ {
+#ifdef RAMP_DOWN
+ playing->declick_stage = 2;
+#else
+ free(playing);
+ sigrenderer->playing[i] = NULL;
+#endif
+ if (channel->playing == playing) channel->playing = NULL;
+ }
+ }
+ break;
+ case 1: /* release background notes */
+ for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
+ {
+ IT_PLAYING * playing = sigrenderer->playing[i];
+ if (playing && channel == playing->channel && !(playing->flags & IT_PLAYING_SUSTAINOFF))
+ {
+ it_note_off(playing);
+ }
+ }
+ break;
+ case 2: /* fade background notes */
+ for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++)
+ {
+ IT_PLAYING * playing = sigrenderer->playing[i];
+ if (playing && channel == playing->channel)
+ {
+ //playing->flags &= IT_PLAYING_SUSTAINOFF;
+ playing->flags |= IT_PLAYING_FADING;
+ }
+ }
+ break;
case 3:
channel->new_note_action = NNA_NOTE_CUT;
break;
@@ -3765,8 +3789,12 @@
int n;
int processorder = sigrenderer->processorder;
- sigrenderer->processrow = sigrenderer->breakrow;
- sigrenderer->breakrow = 0;
+ if ((sigrenderer->processrow|0xC00) == 0xFFFE + 1) { /* It was incremented above! */
+ sigrenderer->processrow = sigrenderer->breakrow;
+ sigrenderer->breakrow = 0;
+ for (n = 0; n < DUMB_IT_N_CHANNELS; n++) sigrenderer->channel[n].pat_loop_end_row = 0;
+ } else
+ sigrenderer->processrow = sigrenderer->breakrow;
if (sigrenderer->processorder == 0xFFFF)
sigrenderer->processorder = sigrenderer->order - 1;
@@ -4197,8 +4225,193 @@
}
#ifdef END_RAMPING
+#if 1
+static long render_playing_part(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, DUMB_VOLUME_RAMP_INFO * lvol, DUMB_VOLUME_RAMP_INFO * rvol, int bits, float delta, long pos, long size, sample_t **samples, int store_end_sample, int cr_record_which)
+{
+ long size_rendered = 0;
+
+ if (sigrenderer->n_channels == 2) {
+ if (playing->sample->flags & IT_SAMPLE_STEREO) {
+ if ((cr_record_which & 1) && sigrenderer->click_remover) {
+ sample_t click[2];
+ dumb_resample_get_current_sample_n_2_2(bits, &playing->resampler, lvol, rvol, click);
+ dumb_record_click(sigrenderer->click_remover[0], pos, click[0]);
+ dumb_record_click(sigrenderer->click_remover[1], pos, click[1]);
+ }
+ size_rendered = dumb_resample_n_2_2(bits, &playing->resampler, samples[0] + pos*2, size, lvol, rvol, delta);
+ if (store_end_sample) {
+ sample_t click[2];
+ dumb_resample_get_current_sample_n_2_2(bits, &playing->resampler, lvol, rvol, click);
+ samples[0][(pos + size_rendered) * 2] = click[0];
+ samples[0][(pos + size_rendered) * 2 + 1] = click[1];
+ }
+ if ((cr_record_which & 2) && sigrenderer->click_remover) {
+ sample_t click[2];
+ dumb_resample_get_current_sample_n_2_2(bits, &playing->resampler, lvol, rvol, click);
+ dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -click[0]);
+ dumb_record_click(sigrenderer->click_remover[1], pos + size_rendered, -click[1]);
+ }
+ } else {
+ if ((cr_record_which & 1) && sigrenderer->click_remover) {
+ sample_t click[2];
+ dumb_resample_get_current_sample_n_1_2(bits, &playing->resampler, lvol, rvol, click);
+ dumb_record_click(sigrenderer->click_remover[0], pos, click[0]);
+ dumb_record_click(sigrenderer->click_remover[1], pos, click[1]);
+ }
+ size_rendered = dumb_resample_n_1_2(bits, &playing->resampler, samples[0] + pos*2, size, lvol, rvol, delta);
+ if (store_end_sample) {
+ sample_t click[2];
+ dumb_resample_get_current_sample_n_1_2(bits, &playing->resampler, lvol, rvol, click);
+ samples[0][(pos + size_rendered) * 2] = click[0];
+ samples[0][(pos + size_rendered) * 2 + 1] = click[1];
+ }
+ if ((cr_record_which & 2) && sigrenderer->click_remover) {
+ sample_t click[2];
+ dumb_resample_get_current_sample_n_1_2(bits, &playing->resampler, lvol, rvol, click);
+ dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -click[0]);
+ dumb_record_click(sigrenderer->click_remover[1], pos + size_rendered, -click[1]);
+ }
+ }
+ } else {
+ if (playing->sample->flags & IT_SAMPLE_STEREO) {
+ if ((cr_record_which & 1) && sigrenderer->click_remover) {
+ sample_t click;
+ dumb_resample_get_current_sample_n_2_1(bits, &playing->resampler, lvol, rvol, &click);
+ dumb_record_click(sigrenderer->click_remover[0], pos, click);
+ }
+ size_rendered = dumb_resample_n_2_1(bits, &playing->resampler, samples[0] + pos, size, lvol, rvol, delta);
+ if (store_end_sample)
+ dumb_resample_get_current_sample_n_2_1(bits, &playing->resampler, lvol, rvol, &samples[0][pos + size_rendered]);
+ if ((cr_record_which & 2) && sigrenderer->click_remover) {
+ sample_t click;
+ dumb_resample_get_current_sample_n_2_1(bits, &playing->resampler, lvol, rvol, &click);
+ dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -click);
+ }
+ } else {
+ if ((cr_record_which & 1) && sigrenderer->click_remover) {
+ sample_t click;
+ dumb_resample_get_current_sample_n_1_1(bits, &playing->resampler, lvol, &click);
+ dumb_record_click(sigrenderer->click_remover[0], pos, click);
+ }
+ size_rendered = dumb_resample_n_1_1(bits, &playing->resampler, samples[0] + pos, size, lvol, delta);
+ if (store_end_sample)
+ dumb_resample_get_current_sample_n_1_1(bits, &playing->resampler, lvol, &samples[0][pos + size_rendered]);
+ if ((cr_record_which & 2) && sigrenderer->click_remover) {
+ sample_t click;
+ dumb_resample_get_current_sample_n_1_1(bits, &playing->resampler, lvol, &click);
+ dumb_record_click(sigrenderer->click_remover[0], pos + size_rendered, -click);
+ }
+ }
+ }
+ return size_rendered;
+}
+
static long render_playing_ramp(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, float volume, float main_delta, float delta, long pos, long size, sample_t **samples, int store_end_sample, int *left_to_mix, int ramp_style)
{
+ int bits;
+
+ long size_rendered;
+
+ DUMB_VOLUME_RAMP_INFO lvol, rvol;
+
+ if (!size) return 0;
+
+ if (playing->flags & IT_PLAYING_DEAD)
+ return 0;
+
+ if (*left_to_mix <= 0)
+ volume = 0;
+
+ {
+ int quality = sigrenderer->resampling_quality;
+ if (playing->sample->max_resampling_quality >= 0 && quality > playing->sample->max_resampling_quality)
+ quality = playing->sample->max_resampling_quality;
+ playing->resampler.quality = quality;
+ }
+
+ bits = playing->sample->flags & IT_SAMPLE_16BIT ? 16 : 8;
+ size_rendered = size;
+
+ if (volume == 0) {
+ if (playing->declick_stage < 2) {
+ if (playing->sample->flags & IT_SAMPLE_STEREO)
+ size_rendered = dumb_resample_n_2_1(bits, &playing->resampler, NULL, size, 0, 0, delta);
+ else
+ size_rendered = dumb_resample_n_1_1(bits, &playing->resampler, NULL, size, 0, delta);
+ } else {
+ playing->declick_stage = 3;
+ }
+ } else {
+ lvol.volume = playing->ramp_volume [0];
+ rvol.volume = playing->ramp_volume [1];
+ lvol.delta = playing->ramp_delta [0] * main_delta;
+ rvol.delta = playing->ramp_delta [1] * main_delta;
+ lvol.target = playing->float_volume [0];
+ rvol.target = playing->float_volume [1];
+ rvol.mix = lvol.mix = volume;
+ if (ramp_style) {
+ if (playing->declick_stage == 1) {
+ size_rendered = render_playing_part(sigrenderer, playing, &lvol, &rvol, bits, delta, pos, size, samples, store_end_sample, 3);
+ } else if (playing->declick_stage == 0 || playing->declick_stage == 2) {
+ float declick_count = ((ramp_style == 2) ? 327.68 : 49.152) / main_delta; /* 5ms / 0.75ms */
+ float declick_remain = playing->declick_volume * declick_count;
+ float declick_dir = -1;
+ float declick_target;
+ int remain;
+ DUMB_VOLUME_RAMP_INFO declick_lvol, declick_rvol;
+ if (playing->declick_stage == 0) {
+ declick_remain = declick_count - declick_remain;
+ declick_dir = 1;
+ }
+ if (size < declick_remain) declick_remain = size;
+ remain = declick_remain;
+ declick_target = playing->declick_volume + declick_dir / declick_count * declick_remain;
+ declick_lvol.volume = lvol.volume * playing->declick_volume;
+ declick_rvol.volume = rvol.volume * playing->declick_volume;
+ lvol.volume += lvol.delta * declick_remain;
+ rvol.volume += rvol.delta * declick_remain;
+ declick_lvol.target = lvol.volume * declick_target;
+ declick_rvol.target = rvol.volume * declick_target;
+ declick_lvol.delta = (declick_lvol.target - declick_lvol.volume) / declick_remain;
+ declick_rvol.delta = (declick_rvol.target - declick_rvol.volume) / declick_remain;
+ declick_lvol.mix = declick_rvol.mix = volume;
+ if (remain < size) {
+ size_rendered = render_playing_part(sigrenderer, playing, &declick_lvol, &declick_rvol, bits, delta, pos, remain, samples, 0, 1);
+ if (size_rendered == remain) {
+ if (playing->declick_stage == 0) {
+ size_rendered += render_playing_part(sigrenderer, playing, &lvol, &rvol, bits, delta, pos + remain, size - remain, samples, store_end_sample, 2);
+ } else {
+ size_rendered = size;
+ }
+ }
+ playing->declick_stage++;
+ playing->declick_volume = 1;
+ } else {
+ size_rendered = render_playing_part(sigrenderer, playing, &declick_lvol, &declick_rvol, bits, delta, pos, remain, samples, store_end_sample, 3);
+ playing->declick_volume = declick_target;
+ }
+ } else /*if (playing->declick_stage == 3)*/ {
+ (*left_to_mix)++;
+ }
+ } else if (playing->declick_stage < 2) {
+ size_rendered = render_playing_part(sigrenderer, playing, &lvol, &rvol, bits, delta, pos, size, samples, store_end_sample, 3);
+ } else {
+ playing->declick_stage = 3;
+ (*left_to_mix)++;
+ }
+ playing->ramp_volume [0] = lvol.volume;
+ playing->ramp_volume [1] = rvol.volume;
+ (*left_to_mix)--;
+ }
+
+ if (playing->resampler.dir == 0)
+ playing->flags |= IT_PLAYING_DEAD;
+
+ return size_rendered;
+}
+#else
+static long render_playing_ramp(DUMB_IT_SIGRENDERER *sigrenderer, IT_PLAYING *playing, float volume, float main_delta, float delta, long pos, long size, sample_t **samples, int store_end_sample, int *left_to_mix, int ramp_style)
+{
long rv, trv;
int l_t_m_temp, cr_which;
if (!size) return 0;
@@ -4286,6 +4499,7 @@
return rv + render_playing(sigrenderer, playing, volume, main_delta, delta, pos, size, samples, store_end_sample, left_to_mix, cr_which);
}
+#endif
#else
#define render_playing_ramp(sigrenderer, playing, volume, main_delta, delta, pos, size, samples, store_end_sample, left_to_mix, ramp_style) render_playing(sigrenderer, playing, volume, main_delta, delta, pos, size, samples, store_end_sample, left_to_mix, 3)
#endif
@@ -4577,6 +4791,7 @@
channel->lastS = 0;
channel->pat_loop_row = 0;
channel->pat_loop_count = 0;
+ channel->pat_loop_end_row = 0;
channel->lastW = 0;
channel->xm_lastE1 = 0;
channel->xm_lastE2 = 0;
--- a/dumb/src/it/reads3m.c
+++ b/dumb/src/it/reads3m.c
@@ -51,12 +51,18 @@
type = dumbfile_getc(f);
+ dumbfile_getnc(sample->filename, 12, f);
+ sample->filename[12] = 0;
+
if (type > 1) {
/** WARNING: no adlib support */
+ dumbfile_skip(f, 3 + 12 + 1 + 1 + 2 + 2 + 2 + 12);
+ dumbfile_getnc(sample->name, 28, f);
+ sample->name[28] = 0;
+ dumbfile_skip(f, 4);
+ sample->flags &= ~IT_SAMPLE_EXISTS;
+ return dumbfile_error(f);
}
-
- dumbfile_getnc(sample->filename, 12, f);
- sample->filename[12] = 0;
*offset = dumbfile_getc(f) << 20;
*offset += dumbfile_igetw(f) << 4;
--- a/dumb/src/it/readxm.c
+++ b/dumb/src/it/readxm.c
@@ -660,6 +660,7 @@
DUMB_IT_SIGDATA *sigdata;
char id_text[18];
+ int header_size;
int flags;
int n_channels;
int total_samples;
@@ -712,7 +713,8 @@
*/
/* header size */
- if (dumbfile_igetl(f) != 0x0114) {
+ header_size = dumbfile_igetl(f);
+ if (header_size < (4 + 2*8 + 1) || header_size > 0x114) {
TRACE("XM error: unexpected header size\n");
free(sigdata);
return NULL;
@@ -740,7 +742,8 @@
/* sanity checks */
// XXX
- if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_orders > 256 || sigdata->n_patterns > 256 || sigdata->n_instruments > 256 || n_channels > DUMB_IT_N_CHANNELS) {
+ i = header_size - 4 - 2 * 8; /* Maximum number of orders expected */
+ if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_orders > i || sigdata->n_patterns > 256 || sigdata->n_instruments > 256 || n_channels > DUMB_IT_N_CHANNELS) {
_dumb_it_unload_sigdata(sigdata);
return NULL;
}
@@ -755,7 +758,7 @@
return NULL;
}
dumbfile_getnc(sigdata->order, sigdata->n_orders, f);
- dumbfile_skip(f, 256 - sigdata->n_orders);
+ dumbfile_skip(f, i - sigdata->n_orders);
if (dumbfile_error(f)) {
_dumb_it_unload_sigdata(sigdata);
--- a/dumb/vc6/dumb/dumb.vcproj
+++ b/dumb/vc6/dumb/dumb.vcproj
@@ -174,6 +174,7 @@
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="2"
+ WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"