in doom_py/src/vizdoom/dumb/src/it/itrender.c [2171:3162]
static int process_effects(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry, int ignore_cxx)
{
DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
IT_PLAYING *playing;
int i;
IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
if (entry->mask & IT_ENTRY_EFFECT) {
switch (entry->effect) {
/*
Notes about effects (as compared to other module formats)
C This is now in *HEX*. (Used to be in decimal in ST3)
E/F/G/H/U You need to check whether the song uses Amiga/Linear slides.
H/U Vibrato in Impulse Tracker is two times finer than in
any other tracker and is updated EVERY tick.
If "Old Effects" is *ON*, then the vibrato is played in the
normal manner (every non-row tick and normal depth)
E/F/G These commands ALL share the same memory.
Oxx Offsets to samples are to the 'xx00th' SAMPLE. (ie. for
16 bit samples, the offset is xx00h*2)
Oxx past the sample end will be ignored, unless "Old Effects"
is ON, in which case the Oxx will play from the end of the
sample.
Yxy This uses a table 4 times larger (hence 4 times slower) than
vibrato or tremelo. If the waveform is set to random, then
the 'speed' part of the command is interpreted as a delay.
*/
case IT_SET_SPEED:
if (entry->effectvalue)
{
/*if (entry->effectvalue == 255)
if (sigrenderer->callbacks->xm_speed_zero && (*sigrenderer->callbacks->xm_speed_zero)(sigrenderer->callbacks->xm_speed_zero_data))
return 1;*/
if (sigdata->flags & IT_WAS_AN_STM) {
int n = entry->effectvalue;
if (n >= 32) {
sigrenderer->tick = sigrenderer->speed = n;
}
} else {
sigrenderer->tick = sigrenderer->speed = entry->effectvalue;
}
}
else if ((sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD)) == IT_WAS_AN_XM) {
#ifdef BIT_ARRAY_BULLSHIT
bit_array_set(sigrenderer->played, sigrenderer->order * 256 + sigrenderer->row);
#endif
sigrenderer->speed = 0;
if (sigrenderer->callbacks->xm_speed_zero && (*sigrenderer->callbacks->xm_speed_zero)(sigrenderer->callbacks->xm_speed_zero_data))
return 1;
}
break;
case IT_BREAK_TO_ROW:
if (ignore_cxx) break;
sigrenderer->breakrow = entry->effectvalue;
/* XXX jump and break on the same row */
if ( ( ( sigrenderer->processrow | 0xC00 ) == 0xFFFE ) &&
! ( sigrenderer->processrow & 0x400 ) ) {
sigrenderer->processrow = 0xFFFE & ~0xC00;
} else {
sigrenderer->processorder = sigrenderer->order;
sigrenderer->processrow = 0xFFFE & ~0x800;
}
break;
case IT_VOLSLIDE_VIBRATO:
for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
if (i < 0) playing = channel->playing;
else {
playing = sigrenderer->playing[i];
if (!playing || playing->channel != channel) continue;
}
if (playing) {
playing->vibrato_speed = channel->lastHspeed;
playing->vibrato_depth = channel->lastHdepth;
playing->vibrato_n++;
}
}
/* Fall through and process volume slide. */
case IT_VOLUME_SLIDE:
case IT_VOLSLIDE_TONEPORTA:
/* The tone portamento component is handled elsewhere. */
{
unsigned char v = entry->effectvalue;
if (!(sigdata->flags & IT_WAS_A_MOD)) {
if (v == 0)
v = channel->lastDKL;
channel->lastDKL = v;
}
if (!(sigdata->flags & IT_WAS_AN_XM)) {
int clip = (sigdata->flags & IT_WAS_AN_S3M) ? 63 : 64;
if ((v & 0x0F) == 0x0F) {
if (!(v & 0xF0)) {
channel->volslide = -15;
channel->volume -= 15;
if (channel->volume > clip) channel->volume = 0;
} else {
channel->volume += v >> 4;
if (channel->volume > clip) channel->volume = clip;
}
} else if ((v & 0xF0) == 0xF0) {
if (!(v & 0x0F)) {
channel->volslide = 15;
channel->volume += 15;
if (channel->volume > clip) channel->volume = clip;
} else {
channel->volume -= v & 15;
if (channel->volume > clip) channel->volume = 0;
}
} else if (!(v & 0x0F)) {
channel->volslide = v >> 4;
} else {
channel->volslide = -(v & 15);
}
} else {
if ((v & 0x0F) == 0) { /* Dx0 */
channel->volslide = v >> 4;
} else if ((v & 0xF0) == 0) { /* D0x */
channel->volslide = -v;
} else if ((v & 0x0F) == 0x0F) { /* DxF */
channel->volume += v >> 4;
if (channel->volume > 64) channel->volume = 64;
} else if ((v & 0xF0) == 0xF0) { /* DFx */
channel->volume -= v & 15;
if (channel->volume > 64) channel->volume = 0;
}
}
}
break;
case IT_XM_FINE_VOLSLIDE_DOWN:
{
unsigned char v = entry->effectvalue;
if (v == 0)
v = channel->xm_lastEB;
channel->xm_lastEB = v;
channel->volume -= v;
if (channel->volume > 64) channel->volume = 0;
}
break;
case IT_XM_FINE_VOLSLIDE_UP:
{
unsigned char v = entry->effectvalue;
if (v == 0)
v = channel->xm_lastEA;
channel->xm_lastEA = v;
channel->volume += v;
if (channel->volume > 64) channel->volume = 64;
}
break;
case IT_PORTAMENTO_DOWN:
{
unsigned char v = entry->effectvalue;
if (sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_669)) {
if (!(sigdata->flags & IT_WAS_A_MOD)) {
if (v == 0xF0)
v |= channel->xm_lastE2;
else if (v >= 0xF0)
channel->xm_lastE2 = v & 15;
else if (v == 0xE0)
v |= channel->xm_lastX2;
else
channel->xm_lastX2 = v & 15;
}
} else if (sigdata->flags & IT_WAS_AN_S3M) {
if (v == 0)
v = channel->lastDKL;
channel->lastDKL = v;
} else {
if (v == 0)
v = channel->lastEF;
channel->lastEF = v;
}
for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
if (i < 0) playing = channel->playing;
else {
playing = sigrenderer->playing[i];
if (!playing || playing->channel != channel) continue;
}
if (playing) {
if ((v & 0xF0) == 0xF0)
playing->slide -= (v & 15) << 4;
else if ((v & 0xF0) == 0xE0)
playing->slide -= (v & 15) << 2;
else if (i < 0 && sigdata->flags & IT_WAS_A_669)
channel->portamento -= v << 3;
else if (i < 0)
channel->portamento -= v << 4;
}
}
}
break;
case IT_PORTAMENTO_UP:
{
unsigned char v = entry->effectvalue;
if (sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_669)) {
if (!(sigdata->flags & IT_WAS_A_MOD)) {
if (v == 0xF0)
v |= channel->xm_lastE1;
else if (v >= 0xF0)
channel->xm_lastE1 = v & 15;
else if (v == 0xE0)
v |= channel->xm_lastX1;
else
channel->xm_lastX1 = v & 15;
}
} else if (sigdata->flags & IT_WAS_AN_S3M) {
if (v == 0)
v = channel->lastDKL;
channel->lastDKL = v;
} else {
if (v == 0)
v = channel->lastEF;
channel->lastEF = v;
}
for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
if (i < 0) playing = channel->playing;
else {
playing = sigrenderer->playing[i];
if (!playing || playing->channel != channel) continue;
}
if (playing) {
if ((v & 0xF0) == 0xF0)
playing->slide += (v & 15) << 4;
else if ((v & 0xF0) == 0xE0)
playing->slide += (v & 15) << 2;
else if (i < 0 && sigdata->flags & IT_WAS_A_669)
channel->portamento += v << 3;
else if (i < 0)
channel->portamento += v << 4;
}
}
}
break;
case IT_XM_PORTAMENTO_DOWN:
{
unsigned char v = entry->effectvalue;
if (!(sigdata->flags & IT_WAS_A_MOD)) {
if (v == 0)
v = channel->lastJ;
channel->lastJ = v;
}
if (channel->playing)
channel->portamento -= v << 4;
}
break;
case IT_XM_PORTAMENTO_UP:
{
unsigned char v = entry->effectvalue;
if (!(sigdata->flags & IT_WAS_A_MOD)) {
if (v == 0)
v = channel->lastEF;
channel->lastEF = v;
}
if (channel->playing)
channel->portamento += v << 4;
}
break;
case IT_XM_KEY_OFF:
channel->key_off_count = entry->effectvalue;
if (!channel->key_off_count) xm_note_off(sigdata, channel);
break;
case IT_VIBRATO:
{
if (entry->effectvalue || !(sigdata->flags & IT_WAS_A_669)) {
unsigned char speed = entry->effectvalue >> 4;
unsigned char depth = entry->effectvalue & 15;
if (speed == 0)
speed = channel->lastHspeed;
channel->lastHspeed = speed;
if (depth == 0)
depth = channel->lastHdepth;
else {
if (sigdata->flags & IT_OLD_EFFECTS && !(sigdata->flags & IT_WAS_A_MOD))
depth <<= 3;
else
depth <<= 2;
channel->lastHdepth = depth;
}
for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
if (i < 0) playing = channel->playing;
else {
playing = sigrenderer->playing[i];
if (!playing || playing->channel != channel) continue;
}
if (playing) {
playing->vibrato_speed = speed;
playing->vibrato_depth = depth;
playing->vibrato_n++;
}
}
}
}
break;
case IT_TREMOR:
{
unsigned char v = entry->effectvalue;
if (v == 0) {
if (sigdata->flags & IT_WAS_AN_S3M)
v = channel->lastDKL;
else
v = channel->lastI;
}
else if (!(sigdata->flags & IT_OLD_EFFECTS)) {
if (v & 0xF0) v -= 0x10;
if (v & 0x0F) v -= 0x01;
}
if (sigdata->flags & IT_WAS_AN_S3M)
channel->lastDKL = v;
else
channel->lastI = v;
channel->tremor_time |= 128;
}
update_tremor(channel);
break;
case IT_ARPEGGIO:
{
unsigned char v = entry->effectvalue;
/* XM files have no memory for arpeggio (000 = no effect)
* and we use lastJ for portamento down instead.
*/
if (!(sigdata->flags & IT_WAS_AN_XM)) {
if (sigdata->flags & IT_WAS_AN_S3M) {
if (v == 0)
v = channel->lastDKL;
channel->lastDKL = v;
} else {
if (v == 0)
v = channel->lastJ;
channel->lastJ = v;
}
}
channel->arpeggio_offsets[0] = 0;
channel->arpeggio_offsets[1] = (v & 0xF0) >> 4;
channel->arpeggio_offsets[2] = (v & 0x0F);
channel->arpeggio_table = (const unsigned char *)(((sigdata->flags & (IT_WAS_AN_XM|IT_WAS_A_MOD))==IT_WAS_AN_XM) ? &arpeggio_xm : &arpeggio_mod);
}
break;
case IT_SET_CHANNEL_VOLUME:
if (sigdata->flags & IT_WAS_AN_XM)
channel->volume = MIN(entry->effectvalue, 64);
else if (entry->effectvalue <= 64)
channel->channelvolume = entry->effectvalue;
#ifdef VOLUME_OUT_OF_RANGE_SETS_MAXIMUM
else
channel->channelvolume = 64;
#endif
if (channel->playing)
channel->playing->channel_volume = channel->channelvolume;
break;
case IT_CHANNEL_VOLUME_SLIDE:
{
unsigned char v = entry->effectvalue;
if (v == 0)
v = channel->lastN;
channel->lastN = v;
if ((v & 0x0F) == 0) { /* Nx0 */
channel->channelvolslide = v >> 4;
} else if ((v & 0xF0) == 0) { /* N0x */
channel->channelvolslide = -v;
} else {
if ((v & 0x0F) == 0x0F) { /* NxF */
channel->channelvolume += v >> 4;
if (channel->channelvolume > 64) channel->channelvolume = 64;
} else if ((v & 0xF0) == 0xF0) { /* NFx */
channel->channelvolume -= v & 15;
if (channel->channelvolume > 64) channel->channelvolume = 0;
} else
break;
if (channel->playing)
channel->playing->channel_volume = channel->channelvolume;
}
}
break;
case IT_SET_SAMPLE_OFFSET:
{
unsigned char v = entry->effectvalue;
/*if (sigdata->flags & IT_WAS_A_MOD) {
if (v == 0) break;
} else*/ {
if (v == 0)
v = channel->lastO;
channel->lastO = v;
}
/* Note: we set the offset even if tone portamento is
* specified. Impulse Tracker does the same.
*/
if (entry->mask & IT_ENTRY_NOTE) {
if (channel->playing) {
int offset = ((int)channel->high_offset << 16) | ((int)v << 8);
IT_PLAYING *playing = channel->playing;
IT_SAMPLE *sample = playing->sample;
int end;
if ((sample->flags & IT_SAMPLE_SUS_LOOP) && !(playing->flags & IT_PLAYING_SUSTAINOFF))
end = sample->sus_loop_end;
else if (sample->flags & IT_SAMPLE_LOOP)
end = sample->loop_end;
else {
end = sample->length;
if ( sigdata->flags & IT_WAS_PROCESSED && end > 64 ) // XXX bah damn LPC and edge case modules
end -= 64;
}
if ((sigdata->flags & IT_WAS_A_PTM) && (sample->flags & IT_SAMPLE_16BIT))
offset >>= 1;
if (offset < end) {
it_playing_reset_resamplers(playing, offset);
playing->declick_stage = 0;
} else if (sigdata->flags & IT_OLD_EFFECTS) {
it_playing_reset_resamplers(playing, end);
playing->declick_stage = 0;
}
}
}
}
break;
case IT_PANNING_SLIDE:
/** JULIEN: guess what? the docs are wrong! (how unusual ;)
* Pxy seems to memorize its previous value... and there
* might be other mistakes like that... (sigh!)
*/
/** ENTHEH: umm... but... the docs say that Pxy memorises its
* value... don't they? :o
*/
{
unsigned char v = entry->effectvalue;
int p = channel->truepan;
if (sigdata->flags & IT_WAS_AN_XM)
{
if (IT_IS_SURROUND(channel->pan))
{
channel->pan = 32;
p = 32 + 128 * 64;
}
p >>= 6;
}
else {
if (IT_IS_SURROUND(channel->pan)) p = 32 << 8;
p = (p + 128) >> 8;
channel->pan = p;
}
if (v == 0)
v = channel->lastP;
channel->lastP = v;
if ((v & 0x0F) == 0) { /* Px0 */
channel->panslide = -(v >> 4);
} else if ((v & 0xF0) == 0) { /* P0x */
channel->panslide = v;
} else if ((v & 0x0F) == 0x0F) { /* PxF */
p -= v >> 4;
} else if ((v & 0xF0) == 0xF0) { /* PFx */
p += v & 15;
}
if (sigdata->flags & IT_WAS_AN_XM)
channel->truepan = 32 + MID(0, p, 255) * 64;
else {
if (p < 0) p = 0;
else if (p > 64) p = 64;
channel->pan = p;
channel->truepan = p << 8;
}
}
break;
case IT_RETRIGGER_NOTE:
{
unsigned char v = entry->effectvalue;
if (sigdata->flags & IT_WAS_AN_XM) {
if ((v & 0x0F) == 0) v |= channel->lastQ & 0x0F;
if ((v & 0xF0) == 0) v |= channel->lastQ & 0xF0;
channel->lastQ = v;
} else if (sigdata->flags & IT_WAS_AN_S3M) {
if (v == 0)
v = channel->lastDKL;
channel->lastDKL = v;
} else {
if (v == 0)
v = channel->lastQ;
channel->lastQ = v;
}
if ((v & 0x0F) == 0) v |= 0x01;
channel->retrig = v;
if (entry->mask & IT_ENTRY_NOTE) {
channel->retrig_tick = v & 0x0F;
/* Emulate a bug */
if (sigdata->flags & IT_WAS_AN_XM)
update_retrig(sigrenderer, channel);
} else
update_retrig(sigrenderer, channel);
}
break;
case IT_XM_RETRIGGER_NOTE:
channel->retrig_tick = channel->xm_retrig = entry->effectvalue;
if (entry->effectvalue == 0)
if (channel->playing) {
it_playing_reset_resamplers(channel->playing, 0);
channel->playing->declick_stage = 0;
}
break;
case IT_TREMOLO:
{
unsigned char speed, depth;
if (sigdata->flags & IT_WAS_AN_S3M) {
unsigned char v = entry->effectvalue;
if (v == 0)
v = channel->lastDKL;
channel->lastDKL = v;
speed = v >> 4;
depth = v & 15;
} else {
speed = entry->effectvalue >> 4;
depth = entry->effectvalue & 15;
if (speed == 0)
speed = channel->lastRspeed;
channel->lastRspeed = speed;
if (depth == 0)
depth = channel->lastRdepth;
channel->lastRdepth = depth;
}
for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
if (i < 0) playing = channel->playing;
else {
playing = sigrenderer->playing[i];
if (!playing || playing->channel != channel) continue;
}
if (playing) {
playing->tremolo_speed = speed;
playing->tremolo_depth = depth;
}
}
}
break;
case IT_S:
{
/* channel->lastS was set in update_pattern_variables(). */
unsigned char effectvalue = channel->lastS;
switch (effectvalue >> 4) {
//case IT_S_SET_FILTER:
/* Waveforms for commands S3x, S4x and S5x:
* 0: Sine wave
* 1: Ramp down
* 2: Square wave
* 3: Random wave
*/
case IT_S_SET_GLISSANDO_CONTROL:
channel->glissando = effectvalue & 15;
break;
case IT_S_FINETUNE:
if (channel->playing) {
channel->playing->finetune = ((int)(effectvalue & 15) - 8) << 5;
}
break;
case IT_S_SET_VIBRATO_WAVEFORM:
{
int waveform = effectvalue & 3;
if (sigdata->flags & IT_WAS_A_MOD) waveform = mod_convert_vibrato[waveform];
else if (sigdata->flags & IT_WAS_AN_XM) waveform = xm_convert_vibrato[waveform];
channel->vibrato_waveform = waveform;
if (channel->playing) {
channel->playing->vibrato_waveform = waveform;
if (!(effectvalue & 4))
channel->playing->vibrato_time = 0;
}
}
break;
case IT_S_SET_TREMOLO_WAVEFORM:
{
int waveform = effectvalue & 3;
if (sigdata->flags & IT_WAS_A_MOD) waveform = mod_convert_vibrato[waveform];
else if (sigdata->flags & IT_WAS_AN_XM) waveform = xm_convert_vibrato[waveform];
channel->tremolo_waveform = waveform;
if (channel->playing) {
channel->playing->tremolo_waveform = waveform;
if (!(effectvalue & 4))
channel->playing->tremolo_time = 0;
}
}
break;
case IT_S_SET_PANBRELLO_WAVEFORM:
channel->panbrello_waveform = effectvalue & 3;
if (channel->playing) {
channel->playing->panbrello_waveform = effectvalue & 3;
if (!(effectvalue & 4))
channel->playing->panbrello_time = 0;
}
break;
case IT_S_FINE_PATTERN_DELAY:
sigrenderer->tick += effectvalue & 15;
break;
#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)
{
playing->declick_stage = 3;
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;
case 4:
channel->new_note_action = NNA_NOTE_CONTINUE;
break;
case 5:
channel->new_note_action = NNA_NOTE_OFF;
break;
case 6:
channel->new_note_action = NNA_NOTE_FADE;
break;
case 7:
if (channel->playing)
channel->playing->enabled_envelopes &= ~IT_ENV_VOLUME;
break;
case 8:
if (channel->playing)
channel->playing->enabled_envelopes |= IT_ENV_VOLUME;
break;
case 9:
if (channel->playing)
channel->playing->enabled_envelopes &= ~IT_ENV_PANNING;
break;
case 10:
if (channel->playing)
channel->playing->enabled_envelopes |= IT_ENV_PANNING;
break;
case 11:
if (channel->playing)
channel->playing->enabled_envelopes &= ~IT_ENV_PITCH;
break;
case 12:
if (channel->playing)
channel->playing->enabled_envelopes |= IT_ENV_PITCH;
break;
}
}
}
break;
#endif
case IT_S_SET_PAN:
//ASSERT(!(sigdata->flags & IT_WAS_AN_XM));
channel->pan =
((effectvalue & 15) << 2) |
((effectvalue & 15) >> 2);
channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
if (channel->playing)
channel->playing->panbrello_depth = 0;
break;
case IT_S_SET_SURROUND_SOUND:
if ((effectvalue & 15) == 15) {
if (channel->playing && channel->playing->sample &&
!(channel->playing->sample->flags & (IT_SAMPLE_LOOP | IT_SAMPLE_SUS_LOOP))) {
channel->playing->flags |= IT_PLAYING_REVERSE;
it_playing_reset_resamplers( channel->playing, channel->playing->sample->length - 1 );
}
} else if ((effectvalue & 15) == 1) {
channel->pan = IT_SURROUND;
channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
}
if (channel->playing)
channel->playing->panbrello_depth = 0;
break;
case IT_S_SET_HIGH_OFFSET:
channel->high_offset = effectvalue & 15;
break;
//case IT_S_PATTERN_LOOP:
case IT_S_DELAYED_NOTE_CUT:
channel->note_cut_count = effectvalue & 15;
if (!channel->note_cut_count) {
if (sigdata->flags & (IT_WAS_AN_XM | IT_WAS_A_PTM))
channel->volume = 0;
else
channel->note_cut_count = 1;
}
break;
case IT_S_SET_MIDI_MACRO:
if ((sigdata->flags & (IT_WAS_AN_XM | IT_WAS_A_MOD)) == (IT_WAS_AN_XM | IT_WAS_A_MOD)) {
channel->inv_loop_speed = effectvalue & 15;
update_invert_loop(channel, channel->playing ? channel->playing->sample : NULL);
} else channel->SFmacro = effectvalue & 15;
break;
}
}
break;
case IT_SET_SONG_TEMPO:
{
unsigned char v = entry->effectvalue;
if (v == 0)
v = channel->lastW;
channel->lastW = v;
if (v < 0x10)
sigrenderer->temposlide = -v;
else if (v < 0x20)
sigrenderer->temposlide = v & 15;
else
sigrenderer->tempo = v;
}
break;
case IT_FINE_VIBRATO:
{
unsigned char speed = entry->effectvalue >> 4;
unsigned char depth = entry->effectvalue & 15;
if (speed == 0)
speed = channel->lastHspeed;
channel->lastHspeed = speed;
if (depth == 0)
depth = channel->lastHdepth;
else {
if (sigdata->flags & IT_OLD_EFFECTS)
depth <<= 1;
channel->lastHdepth = depth;
}
for (i = -1; i < DUMB_IT_N_NNA_CHANNELS; i++) {
if (i < 0) playing = channel->playing;
else {
playing = sigrenderer->playing[i];
if (!playing || playing->channel != channel) continue;
}
if (playing) {
playing->vibrato_speed = speed;
playing->vibrato_depth = depth;
playing->vibrato_n++;
}
}
}
break;
case IT_SET_GLOBAL_VOLUME:
if ((sigdata->flags & IT_WAS_AN_S3M) && (entry->effectvalue > 64))
break;
if (entry->effectvalue <= 128)
sigrenderer->globalvolume = entry->effectvalue;
#ifdef VOLUME_OUT_OF_RANGE_SETS_MAXIMUM
else
sigrenderer->globalvolume = 128;
#endif
break;
case IT_GLOBAL_VOLUME_SLIDE:
{
unsigned char v = entry->effectvalue;
if (v == 0)
v = channel->lastW;
channel->lastW = v;
if ((v & 0x0F) == 0) { /* Wx0 */
sigrenderer->globalvolslide =
(sigdata->flags & IT_WAS_AN_XM) ? (v >> 4)*2 : (v >> 4);
} else if ((v & 0xF0) == 0) { /* W0x */
sigrenderer->globalvolslide =
(sigdata->flags & IT_WAS_AN_XM) ? (-v)*2 : (-v);
} else if ((v & 0x0F) == 0x0F) { /* WxF */
sigrenderer->globalvolume += v >> 4;
if (sigrenderer->globalvolume > 128) sigrenderer->globalvolume = 128;
} else if ((v & 0xF0) == 0xF0) { /* WFx */
sigrenderer->globalvolume -= v & 15;
if (sigrenderer->globalvolume > 128) sigrenderer->globalvolume = 0;
}
}
break;
case IT_SET_PANNING:
if (sigdata->flags & IT_WAS_AN_XM) {
channel->truepan = 32 + entry->effectvalue*64;
} else {
if (sigdata->flags & IT_WAS_AN_S3M)
channel->pan = (entry->effectvalue + 1) >> 1;
else
channel->pan = (entry->effectvalue + 2) >> 2;
channel->truepan = channel->pan << IT_ENVELOPE_SHIFT;
}
if (channel->playing)
channel->playing->panbrello_depth = 0;
break;
case IT_PANBRELLO:
{
unsigned char speed = entry->effectvalue >> 4;
unsigned char depth = entry->effectvalue & 15;
if (speed == 0)
speed = channel->lastYspeed;
channel->lastYspeed = speed;
if (depth == 0)
depth = channel->lastYdepth;
channel->lastYdepth = depth;
if (channel->playing) {
channel->playing->panbrello_speed = speed;
channel->playing->panbrello_depth = depth;
}
}
break;
case IT_MIDI_MACRO:
{
const IT_MIDI *midi = sigdata->midi ? sigdata->midi : &default_midi;
if (entry->effectvalue >= 0x80) {
int n = midi->Zmacrolen[entry->effectvalue-0x80];
int i;
for (i = 0; i < n; i++)
it_send_midi(sigrenderer, channel, midi->Zmacro[entry->effectvalue-0x80][i]);
} else {
int n = midi->SFmacrolen[channel->SFmacro];
int i, j;
for (i = 0, j = 1; i < n; i++, j <<= 1)
it_send_midi(sigrenderer, channel,
(unsigned char)(midi->SFmacroz[channel->SFmacro] & j ?
entry->effectvalue : midi->SFmacro[channel->SFmacro][i]));
}
}
break;
case IT_XM_SET_ENVELOPE_POSITION:
if (channel->playing && channel->playing->env_instrument) {
IT_ENVELOPE *envelope = &channel->playing->env_instrument->volume_envelope;
if (envelope->flags & IT_ENVELOPE_ON) {
IT_PLAYING_ENVELOPE *pe = &channel->playing->volume_envelope;
pe->tick = entry->effectvalue;
if (pe->tick >= envelope->node_t[envelope->n_nodes-1])
pe->tick = envelope->node_t[envelope->n_nodes-1];
pe->next_node = 0;
while (pe->tick > envelope->node_t[pe->next_node]) pe->next_node++;
xm_envelope_calculate_value(envelope, pe);
}
}
break;
/* uggly plain portamento for now */
case IT_PTM_NOTE_SLIDE_DOWN:
case IT_PTM_NOTE_SLIDE_DOWN_RETRIG:
{
channel->toneslide_retrig = (entry->effect == IT_PTM_NOTE_SLIDE_DOWN_RETRIG);
if (channel->ptm_last_toneslide) {
channel->toneslide_tick = channel->last_toneslide_tick;
if (--channel->toneslide_tick == 0) {
channel->truenote += channel->toneslide;
if (channel->truenote >= 120) {
if (channel->toneslide < 0) channel->truenote = 0;
else channel->truenote = 119;
}
channel->note += channel->toneslide;
if (channel->note >= 120) {
if (channel->toneslide < 0) channel->note = 0;
else channel->note = 119;
}
if (channel->playing) {
if (channel->sample) channel->playing->note = channel->truenote;
else channel->playing->note = channel->note;
it_playing_reset_resamplers(channel->playing, 0);
channel->playing->declick_stage = 0;
}
}
}
channel->ptm_last_toneslide = 0;
channel->toneslide = -(entry->effectvalue & 15);
channel->ptm_toneslide = (entry->effectvalue & 0xF0) >> 4;
channel->toneslide_tick += channel->ptm_toneslide;
}
break;
case IT_PTM_NOTE_SLIDE_UP:
case IT_PTM_NOTE_SLIDE_UP_RETRIG:
{
channel->toneslide_retrig = (entry->effect == IT_PTM_NOTE_SLIDE_UP_RETRIG);
if (channel->ptm_last_toneslide) {
channel->toneslide_tick = channel->last_toneslide_tick;
if (--channel->toneslide_tick == 0) {
channel->truenote += channel->toneslide;
if (channel->truenote >= 120) {
if (channel->toneslide < 0) channel->truenote = 0;
else channel->truenote = 119;
}
channel->note += channel->toneslide;
if (channel->note >= 120) {
if (channel->toneslide < 0) channel->note = 0;
else channel->note = 119;
}
if (channel->playing) {
if (channel->sample) channel->playing->note = channel->truenote;
else channel->playing->note = channel->note;
it_playing_reset_resamplers(channel->playing, 0);
channel->playing->declick_stage = 0;
}
}
}
channel->ptm_last_toneslide = 0;
channel->toneslide = -(entry->effectvalue & 15);
channel->ptm_toneslide = (entry->effectvalue & 0xF0) >> 4;
channel->toneslide_tick += channel->ptm_toneslide;
}
break;
case IT_OKT_NOTE_SLIDE_DOWN:
case IT_OKT_NOTE_SLIDE_DOWN_ROW:
channel->toneslide = -entry->effectvalue;
channel->okt_toneslide = (entry->effect == IT_OKT_NOTE_SLIDE_DOWN) ? 255 : 1;
break;
case IT_OKT_NOTE_SLIDE_UP:
case IT_OKT_NOTE_SLIDE_UP_ROW:
channel->toneslide = entry->effectvalue;
channel->okt_toneslide = (entry->effect == IT_OKT_NOTE_SLIDE_UP) ? 255 : 1;
break;
case IT_OKT_ARPEGGIO_3:
case IT_OKT_ARPEGGIO_4:
case IT_OKT_ARPEGGIO_5:
{
channel->arpeggio_offsets[0] = 0;
channel->arpeggio_offsets[1] = -(entry->effectvalue >> 4);
channel->arpeggio_offsets[2] = entry->effectvalue & 0x0F;
switch (entry->effect)
{
case IT_OKT_ARPEGGIO_3:
channel->arpeggio_table = (const unsigned char *)&arpeggio_okt_3;
break;
case IT_OKT_ARPEGGIO_4:
channel->arpeggio_table = (const unsigned char *)&arpeggio_okt_4;
break;
case IT_OKT_ARPEGGIO_5:
channel->arpeggio_table = (const unsigned char *)&arpeggio_okt_5;
break;
}
}
break;
case IT_OKT_VOLUME_SLIDE_DOWN:
if ( entry->effectvalue <= 16 ) channel->volslide = -entry->effectvalue;
else
{
channel->volume -= entry->effectvalue - 16;
if (channel->volume > 64) channel->volume = 0;
}
break;
case IT_OKT_VOLUME_SLIDE_UP:
if ( entry->effectvalue <= 16 ) channel->volslide = entry->effectvalue;
else
{
channel->volume += entry->effectvalue - 16;
if (channel->volume > 64) channel->volume = 64;
}
break;
}
}
if (!(sigdata->flags & IT_WAS_AN_XM))
post_process_it_volpan(sigrenderer, entry);
return 0;
}