in doom_py/src/vizdoom/dumb/src/it/itrender.c [3330:3620]
static void process_xm_note_data(DUMB_IT_SIGRENDERER *sigrenderer, IT_ENTRY *entry)
{
DUMB_IT_SIGDATA *sigdata = sigrenderer->sigdata;
IT_CHANNEL *channel = &sigrenderer->channel[(int)entry->channel];
IT_PLAYING * playing = NULL;
if (entry->mask & IT_ENTRY_INSTRUMENT) {
int oldsample = channel->sample;
channel->inv_loop_offset = 0;
channel->instrument = entry->instrument;
instrument_to_sample(sigdata, channel);
if (channel->playing &&
!((entry->mask & IT_ENTRY_NOTE) && entry->note >= 120) &&
!((entry->mask & IT_ENTRY_EFFECT) && entry->effect == IT_XM_KEY_OFF && entry->effectvalue == 0)) {
playing = dup_playing(channel->playing, channel, channel);
if (!playing) return;
if (!(sigdata->flags & IT_WAS_A_MOD)) {
/* Retrigger vol/pan envelopes if enabled, and cancel fadeout.
* Also reset vol/pan to that of _original_ instrument.
*/
channel->playing->flags &= ~(IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING);
it_playing_update_resamplers(channel->playing);
channel->volume = channel->playing->sample->default_volume;
channel->truepan = 32 + channel->playing->sample->default_pan*64;
retrigger_xm_envelopes(channel->playing);
} else {
/* Switch if sample changed */
if (oldsample != channel->sample) {
int i;
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
if (!sigrenderer->playing[i]) {
channel->playing->declick_stage = 3;
sigrenderer->playing[i] = channel->playing;
channel->playing = NULL;
break;
}
}
if (!channel->sample) {
if (channel->playing)
{
free_playing(sigrenderer, channel->playing);
channel->playing = NULL;
}
} else {
if (channel->playing) {
free_playing(sigrenderer, channel->playing);
}
channel->playing = playing;
playing = NULL;
channel->playing->declick_stage = 0;
channel->playing->sampnum = channel->sample;
channel->playing->sample = &sigdata->sample[channel->sample-1];
it_playing_reset_resamplers(channel->playing, 0);
}
}
get_default_volpan(sigdata, channel);
}
}
}
if (!((entry->mask & IT_ENTRY_EFFECT) && entry->effect == IT_XM_KEY_OFF && entry->effectvalue == 0) &&
(entry->mask & IT_ENTRY_NOTE))
{
if (!(entry->mask & IT_ENTRY_INSTRUMENT))
instrument_to_sample(sigdata, channel);
if (channel->note >= 120)
xm_note_off(sigdata, channel);
else if (channel->sample == 0) {
/** If we get here, one of the following is the case:
** 1. The instrument has never been specified on this channel.
** 2. The specified instrument is invalid.
** 3. The instrument has no sample mapped to the selected note.
** What should happen?
**
** Experimentation shows that any existing note stops and cannot
** be brought back. A subsequent instrument change fixes that.
**/
if (channel->playing) {
int i;
if (playing) {
free_playing(sigrenderer, channel->playing);
channel->playing = playing;
playing = NULL;
}
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
if (!sigrenderer->playing[i]) {
channel->playing->declick_stage = 3;
sigrenderer->playing[i] = channel->playing;
channel->playing = NULL;
break;
}
}
if (channel->playing) {
free_playing(sigrenderer, channel->playing);
channel->playing = NULL;
}
}
if (playing) free_playing(sigrenderer, playing);
return;
} else if (channel->playing && (entry->mask & IT_ENTRY_VOLPAN) && ((entry->volpan>>4) == 0xF)) {
/* Don't retrigger note; portamento in the volume column. */
} else if (channel->playing &&
(entry->mask & IT_ENTRY_EFFECT) &&
(entry->effect == IT_TONE_PORTAMENTO ||
entry->effect == IT_VOLSLIDE_TONEPORTA)) {
/* Don't retrigger note; portamento in the effects column. */
} else {
channel->destnote = IT_NOTE_OFF;
if (!channel->playing) {
channel->playing = new_playing(sigrenderer);
if (!channel->playing) {
if (playing) free_playing(sigrenderer, playing);
return;
}
// Adding the following seems to do the trick for the case where a piece starts with an instrument alone and then some notes alone.
retrigger_xm_envelopes(channel->playing);
}
else if (playing) {
/* volume rampy stuff! move note to NNA */
int i;
IT_PLAYING * ptemp;
if (playing->sample) ptemp = playing;
else ptemp = channel->playing;
if (!ptemp) {
if (playing) free_playing(sigrenderer, playing);
return;
}
playing = NULL;
for (i = 0; i < DUMB_IT_N_NNA_CHANNELS; i++) {
if (!sigrenderer->playing[i]) {
ptemp->declick_stage = 3;
ptemp->flags |= IT_PLAYING_SUSTAINOFF | IT_PLAYING_FADING;
sigrenderer->playing[i] = ptemp;
ptemp = NULL;
break;
}
}
if (ptemp) free_playing(sigrenderer, ptemp);
}
channel->playing->flags = 0;
channel->playing->resampling_quality = sigrenderer->resampling_quality;
channel->playing->channel = channel;
channel->playing->sample = &sigdata->sample[channel->sample-1];
if (sigdata->flags & IT_USE_INSTRUMENTS)
channel->playing->instrument = &sigdata->instrument[channel->instrument-1];
else
channel->playing->instrument = NULL;
channel->playing->env_instrument = channel->playing->instrument;
channel->playing->sampnum = channel->sample;
channel->playing->instnum = channel->instrument;
channel->playing->declick_stage = 0;
channel->playing->channel_volume = channel->channelvolume;
channel->playing->note = channel->truenote;
channel->playing->enabled_envelopes = 0;
channel->playing->volume_offset = 0;
channel->playing->panning_offset = 0;
//channel->playing->output = channel->output;
if (sigdata->flags & IT_USE_INSTRUMENTS) {
IT_PLAYING * playing = channel->playing;
IT_INSTRUMENT * instrument = playing->instrument;
if (instrument->volume_envelope.flags & IT_ENVELOPE_ON) playing->enabled_envelopes |= IT_ENV_VOLUME;
if (instrument->pan_envelope.flags & IT_ENVELOPE_ON) playing->enabled_envelopes |= IT_ENV_PANNING;
//if (instrument->output) playing->output = instrument->output;
}
channel->playing->filter_cutoff = 127;
channel->playing->filter_resonance = 0;
channel->playing->true_filter_cutoff = 127 << 8;
channel->playing->true_filter_resonance = 0;
channel->playing->vibrato_speed = 0;
channel->playing->vibrato_depth = 0;
channel->playing->vibrato_n = 0;
channel->playing->vibrato_time = 0;
channel->playing->vibrato_waveform = 0;
channel->playing->tremolo_speed = 0;
channel->playing->tremolo_depth = 0;
channel->playing->tremolo_time = 0;
channel->playing->tremolo_waveform = 0;
channel->playing->panbrello_speed = 0;
channel->playing->panbrello_depth = 0;
channel->playing->panbrello_time = 0;
channel->playing->panbrello_waveform = 0;
channel->playing->panbrello_random = 0;
channel->playing->sample_vibrato_time = 0;
channel->playing->sample_vibrato_waveform = channel->playing->sample->vibrato_waveform;
channel->playing->sample_vibrato_depth = 0;
channel->playing->slide = 0;
channel->playing->finetune = channel->playing->sample->finetune;
it_reset_filter_state(&channel->playing->filter_state[0]); // Are these
it_reset_filter_state(&channel->playing->filter_state[1]); // necessary?
it_playing_reset_resamplers(channel->playing, 0);
/** WARNING - is everything initialised? */
}
}
if (!((entry->mask & IT_ENTRY_EFFECT) && entry->effect == IT_XM_KEY_OFF && entry->effectvalue == 0) &&
!((entry->mask & IT_ENTRY_NOTE) && entry->note >= 120) &&
(entry->mask & (IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT)) == (IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT))
{
if (channel->playing) retrigger_xm_envelopes(channel->playing);
get_default_volpan(sigdata, channel);
}
if ((entry->mask & IT_ENTRY_VOLPAN) && ((entry->volpan>>4) == 0xF)) {
/* Tone Portamento */
unsigned char v = (entry->volpan & 15) << 4;
if (v == 0)
v = channel->lastG;
channel->lastG = v;
if (entry->mask & IT_ENTRY_NOTE)
if (channel->sample && channel->note < 120)
channel->destnote = channel->truenote;
channel->toneporta = v << 4;
} else if ((entry->mask & IT_ENTRY_EFFECT) &&
(entry->effect == IT_TONE_PORTAMENTO ||
entry->effect == IT_VOLSLIDE_TONEPORTA)) {
unsigned char v;
if (entry->effect == IT_TONE_PORTAMENTO)
v = entry->effectvalue;
else
v = 0;
if (v == 0)
v = channel->lastG;
channel->lastG = v;
if (entry->mask & IT_ENTRY_NOTE)
if (channel->sample && channel->note < 120)
channel->destnote = channel->truenote;
channel->toneporta = v << 4;
}
if (entry->mask & IT_ENTRY_VOLPAN) {
int effect = entry->volpan >> 4;
int value = entry->volpan & 15;
switch (effect) {
case 0x6: /* Volume slide down */
channel->xm_volslide = -value;
break;
case 0x7: /* Volume slide up */
channel->xm_volslide = value;
break;
case 0x8: /* Fine volume slide down */
channel->volume -= value;
if (channel->volume > 64) channel->volume = 0;
break;
case 0x9: /* Fine volume slide up */
channel->volume += value;
if (channel->volume > 64) channel->volume = 64;
break;
case 0xA: /* Set vibrato speed */
if (value)
channel->lastHspeed = value;
if (channel->playing)
channel->playing->vibrato_speed = channel->lastHspeed;
break;
case 0xB: /* Vibrato */
if (value)
channel->lastHdepth = value << 2; /** WARNING: correct ? */
if (channel->playing) {
channel->playing->vibrato_depth = channel->lastHdepth;
channel->playing->vibrato_speed = channel->lastHspeed;
channel->playing->vibrato_n++;
}
break;
case 0xC: /* Set panning */
channel->truepan = 32 + value*(17*64);
break;
case 0xD: /* Pan slide left */
/* -128 is a special case for emulating a 'feature' in FT2.
* As soon as effects are processed, it goes hard left.
*/
channel->panslide = value ? -value : -128;
break;
case 0xE: /* Pan slide Right */
channel->panslide = value;
break;
case 0xF: /* Tone porta */
break;
default: /* Volume */
channel->volume = entry->volpan - 0x10;
break;
}
}
if (playing) free_playing(sigrenderer, playing);
}