void release_module_extras(struct context_data *ctx) { struct module_data *m = &ctx->m; if (HAS_MED_MODULE_EXTRAS(*m)) med_release_module_extras(m); else if (HAS_HMN_MODULE_EXTRAS(*m)) hmn_release_module_extras(m); }
int new_channel_extras(struct context_data *ctx, struct channel_data *xc) { struct module_data *m = &ctx->m; if (HAS_MED_MODULE_EXTRAS(*m)) { if (med_new_channel_extras(xc) < 0) return -1; } else if (HAS_HMN_MODULE_EXTRAS(*m)) { if (hmn_new_channel_extras(xc) < 0) return -1; } return 0; }
void med_play_extras(struct context_data *ctx, struct channel_data *xc, int chn) { struct module_data *m = &ctx->m; struct player_data *p = &ctx->p; struct xmp_module *mod = &m->mod; struct med_module_extras *me; struct med_channel_extras *ce; struct med_instrument_extras *ie; int b, jws = 0, jvs = 0, loop; int temp; if (!HAS_MED_MODULE_EXTRAS(*m)) return; me = (struct med_module_extras *)m->extra; ce = (struct med_channel_extras *)xc->extra; ie = MED_INSTRUMENT_EXTRAS(m->mod.xxi[xc->ins]); /* Handle hold/decay */ /* on the first row of a held note, continue note if ce->hold is 2 * (this is set after pre-fetching the next row and see if we * continue to hold. On remaining rows with hold on, we have the * FX_MED_HOLD effect and ce->hold set to 1. On the last row, see * if ce->hold_count is set (meaning that a note was held) and * ce->hold is 0 (meaning that it's not held anymore). Then * procceed with normal frame counting until decay. */ if (ce->hold_count) { /* was held in the past */ if (!ce->hold && p->frame >= ie->hold) { /* but not now */ SET_NOTE(NOTE_FADEOUT); ce->hold_count = 0; } } else if (ie->hold) { /* has instrument hold */ if (p->frame >= ie->hold && ce->hold == 0) { SET_NOTE(NOTE_FADEOUT); } } if (p->frame == (p->speed - 1) && ce->hold != 2) { ce->hold = 0; } /* Handle synth */ if (me->vol_table[xc->ins] == NULL || me->wav_table[xc->ins] == NULL) { ce->volume = 64; /* we need this in extras_get_volume() */ return; } if (p->frame == 0 && TEST(NEW_NOTE)) { ce->period = xc->period; if (TEST(NEW_INS)) { ce->arp = ce->aidx = 0; ce->vp = ce->vc = ce->vw = 0; ce->wp = ce->wc = ce->ww = 0; ce->env_wav = -1; ce->env_idx = 0; ce->flags &= ~MED_SYNTH_ENV_LOOP; ce->vv = 0; ce->wv = 0; ce->vs = ie->vts; ce->ws = ie->wts; } } if (ce->vs > 0 && ce->vc-- == 0) { ce->vc = ce->vs - 1; if (ce->vw > 0) { ce->vw--; goto skip_vol; } loop = jws = 0; /* Volume commands */ next_vt: switch (b = VT) { case 0xff: /* END */ case 0xfb: /* HLT */ ce->vp--; break; case 0xfe: /* JMP */ if (loop) /* avoid infinite loop */ break; temp = VT; ce->vp = temp; loop = 1; goto next_vt; break; case 0xfa: /* JWS */ jws = VT; break; case 0xf5: /* EN2 */ ce->env_wav = VT; ce->flags |= MED_SYNTH_ENV_LOOP; break; case 0xf4: /* EN1 */ ce->env_wav = VT; break; case 0xf3: /* CHU */ ce->vv = VT; break; case 0xf2: /* CHD */ ce->vv = -VT; break; case 0xf1: /* WAI */ ce->vw = VT; break; case 0xf0: /* SPD */ ce->vs = VT; break; default: if (b >= 0x00 && b <= 0x40) ce->volume = b; } skip_vol: /* volume envelope */ if (ce->env_wav >= 0) { int sid = mod->xxi[xc->ins].sub[ce->env_wav].sid; struct xmp_sample *xxs = &mod->xxs[sid]; if (xxs->len == 0x80) { /* sanity check */ ce->volume = ((int8)xxs->data[ce->env_idx] + 0x80) >> 2; ce->env_idx++; if (ce->env_idx >= 0x80) { if (~ce->flags & MED_SYNTH_ENV_LOOP) { ce->env_wav = -1; } ce->env_idx = 0; } }
void med_play_extras(struct context_data *ctx, struct channel_data *xc, int chn, int new_note) { struct module_data *m = &ctx->m; struct med_module_extras *me; struct med_channel_extras *ce; int b, jws = 0, jvs = 0, loop; int temp; if (!HAS_MED_MODULE_EXTRAS(*m)) return; me = (struct med_module_extras *)m->extra; ce = (struct med_channel_extras *)xc->extra; if (me->vol_table[xc->ins] == NULL || me->wav_table[xc->ins] == NULL) return; if (new_note) { ce->arp = ce->aidx = 0; ce->period = xc->period; ce->vp = ce->vc = ce->vw = 0; ce->wp = ce->wc = ce->ww = 0; ce->vv = 0; ce->vs = MED_INSTRUMENT_EXTRAS(m->mod.xxi[xc->ins])->vts; ce->ws = MED_INSTRUMENT_EXTRAS(m->mod.xxi[xc->ins])->wts; } if (ce->vs > 0 && ce->vc-- == 0) { ce->vc = ce->vs - 1; if (ce->vw > 0) { ce->vw--; goto skip_vol; } loop = jws = 0; next_vt: switch (b = VT) { case 0xff: /* END */ case 0xfb: /* HLT */ ce->vp--; break; case 0xfe: /* JMP */ if (loop) /* avoid infinite loop */ break; temp = VT; ce->vp = temp; loop = 1; goto next_vt; break; case 0xfa: /* JWS */ jws = VT; break; case 0xf5: /* EN2 */ case 0xf4: /* EN1 */ VT_SKIP; /* Not implemented */ break; case 0xf3: /* CHU */ ce->vv = VT; break; case 0xf2: /* CHD */ ce->vv = -VT; break; case 0xf1: /* WAI */ ce->vw = VT; break; case 0xf0: /* SPD */ ce->vs = VT; break; default: if (b >= 0x00 && b <= 0x40) ce->volume = b; } ce->volume += ce->vv; CLAMP(ce->volume, 0, 64); skip_vol: if (ce->ww > 0) { ce->ww--; goto skip_wav; } loop = jvs = 0; next_wt: switch (b = WT) { struct xmp_instrument *xxi; case 0xff: /* END */ case 0xfb: /* HLT */ ce->wp--; break; case 0xfe: /* JMP */ if (loop) /* avoid infinite loop */ break; temp = WT; if (temp == 0xff) { /* handle JMP END case */ ce->wp--; /* see lepeltheme ins 0x02 */ break; } ce->wp = temp; loop = 1; goto next_wt; case 0xfd: /* ARE */ break; case 0xfc: /* ARP */ ce->arp = ce->aidx = ce->wp++; while (WT != 0xfd) ; break; case 0xfa: /* JVS */ jws = WT; break; case 0xf7: /* VWF */ ce->vwf = WT; break; case 0xf6: /* RES */ xc->period = ce->period; break; case 0xf5: /* VBS */ ce->vib_speed = WT; break; case 0xf4: /* VBD */ ce->vib_depth = WT; break; case 0xf3: /* CHU */ ce->wv = -WT; break; case 0xf2: /* CHD */ ce->wv = WT; break; case 0xf1: /* WAI */ ce->ww = WT; break; case 0xf0: /* SPD */ ce->ws = WT; break; default: xxi = &m->mod.xxi[xc->ins]; if (b < xxi->nsm && xxi->sub[b].sid != xc->smp) { xc->smp = xxi->sub[b].sid; virt_setsmp(ctx, chn, xc->smp); } } skip_wav: ; /* xc->period += ce->wv; */ } if (jws) { ce->wp = jws; jws = 0; } if (jvs) { ce->vp = jvs; jvs = 0; } }