Esempio n. 1
0
void process_fx(struct context_data *ctx, struct channel_data *xc, int chn,
                uint8 note, uint8 fxt, uint8 fxp, int fnum)
{
    struct player_data *p = &ctx->p;
    struct module_data *m = &ctx->m;
    struct xmp_module *mod = &m->mod;
    struct flow_control *f = &p->flow;
    int h, l;

    switch (fxt) {
    case FX_ARPEGGIO:
fx_arpeggio:
        if (fxp != 0) {
            xc->arpeggio.val[0] = 0;
            xc->arpeggio.val[1] = MSN(fxp);
            xc->arpeggio.val[2] = LSN(fxp);
            xc->arpeggio.size = 3;
        }
        break;
    case FX_S3M_ARPEGGIO:
        EFFECT_MEMORY(fxp, xc->arpeggio.memory);
        goto fx_arpeggio;
#ifndef LIBXMP_CORE_PLAYER
    case FX_OKT_ARP3:
        if (fxp != 0) {
            xc->arpeggio.val[0] = -MSN(fxp);
            xc->arpeggio.val[1] = 0;
            xc->arpeggio.val[2] = LSN(fxp);
            xc->arpeggio.size = 3;
        }
        break;
    case FX_OKT_ARP4:
        if (fxp != 0) {
            xc->arpeggio.val[0] = 0;
            xc->arpeggio.val[1] = LSN(fxp);
            xc->arpeggio.val[2] = 0;
            xc->arpeggio.val[3] = -MSN(fxp);
            xc->arpeggio.size = 4;
        }
        break;
    case FX_OKT_ARP5:
        if (fxp != 0) {
            xc->arpeggio.val[0] = LSN(fxp);
            xc->arpeggio.val[1] = LSN(fxp);
            xc->arpeggio.val[2] = 0;
            xc->arpeggio.size = 3;
        }
        break;
#endif
    case FX_PORTA_UP:	/* Portamento up */
        EFFECT_MEMORY(fxp, xc->freq.memory);

        if (HAS_QUIRK(QUIRK_FINEFX)
                && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) {
            switch (MSN(fxp)) {
            case 0xf:
                fxp &= 0x0f;
                goto fx_f_porta_up;
            case 0xe:
                fxp &= 0x0f;
                fxp |= 0x10;
                goto fx_xf_porta;
            }
        }

        SET(PITCHBEND);

        if (fxp != 0) {
            xc->freq.slide = -fxp;
            if (HAS_QUIRK(QUIRK_UNISLD))
                xc->porta.memory = fxp;
        } else if (xc->freq.slide > 0) {
            xc->freq.slide *= -1;
        }
        break;
    case FX_PORTA_DN:	/* Portamento down */
        EFFECT_MEMORY(fxp, xc->freq.memory);

        if (HAS_QUIRK(QUIRK_FINEFX)
                && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) {
            switch (MSN(fxp)) {
            case 0xf:
                fxp &= 0x0f;
                goto fx_f_porta_dn;
            case 0xe:
                fxp &= 0x0f;
                fxp |= 0x20;
                goto fx_xf_porta;
            }
        }

        SET(PITCHBEND);

        if (fxp != 0) {
            xc->freq.slide = fxp;
            if (HAS_QUIRK(QUIRK_UNISLD))
                xc->porta.memory = fxp;
        } else if (xc->freq.slide < 0) {
            xc->freq.slide *= -1;
        }
        break;
    case FX_TONEPORTA:	/* Tone portamento */
        if (HAS_QUIRK(QUIRK_IGSTPOR)) {
            if (note == 0 && xc->porta.dir == 0)
                break;
        }
        if (!IS_VALID_INSTRUMENT(xc->ins))
            break;

        do_toneporta(m, xc, note);

        EFFECT_MEMORY_SETONLY(fxp, xc->porta.memory);

        if (fxp != 0) {
            if (HAS_QUIRK(QUIRK_UNISLD)) /* IT compatible Gxx off */
                xc->freq.memory = fxp;
            xc->porta.slide = fxp;
        }
        SET(TONEPORTA);
        break;

    case FX_VIBRATO:	/* Vibrato */
        EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory);

        SET(VIBRATO);
        SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp) << 2, MSN(fxp));
        break;
    case FX_FINE_VIBRATO:	/* Fine vibrato */
        EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory);

        SET(VIBRATO);
        SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp), MSN(fxp));
        break;

    case FX_TONE_VSLIDE:	/* Toneporta + vol slide */
        if (!IS_VALID_INSTRUMENT(xc->ins))
            break;
        do_toneporta(m, xc, note);
        SET(TONEPORTA);
        goto fx_volslide;
    case FX_VIBRA_VSLIDE:	/* Vibrato + vol slide */
        SET(VIBRATO);
        goto fx_volslide;

    case FX_TREMOLO:	/* Tremolo */
        EFFECT_MEMORY_SETONLY(fxp, xc->tremolo.memory);
        SET(TREMOLO);
        SET_LFO_NOTZERO(&xc->tremolo.lfo, LSN(fxp), MSN(fxp));
        break;

    case FX_SETPAN:		/* Set pan */
        xc->pan.val = fxp;
        break;
    case FX_OFFSET:		/* Set sample offset */
        SET(OFFSET);
        if (fxp) {
            xc->offset_val = xc->offset = fxp << 8;
        } else {
            xc->offset_val = xc->offset;
        }
        break;
    case FX_VOLSLIDE:	/* Volume slide */
fx_volslide:
        /* S3M file volume slide note:
         * DFy  Fine volume down by y (...) If y is 0, the command will
         *      be treated as a volume slide up with a value of f (15).
         *      If a DFF command is specified, the volume will be slid
         *      up.
         */
        if (HAS_QUIRK(QUIRK_FINEFX)) {
            h = MSN(fxp);
            l = LSN(fxp);
            if (l == 0xf && h != 0) {
                xc->vol.memory = fxp;
                fxp >>= 4;
                goto fx_f_vslide_up;
            } else if (h == 0xf && l != 0) {
                xc->vol.memory = fxp;
                fxp &= 0x0f;
                goto fx_f_vslide_dn;
            }
        }
Esempio n. 2
0
void process_fx(struct context_data *ctx, struct channel_data *xc, int chn,
		struct xmp_event *e, int fnum)
{
	struct player_data *p = &ctx->p;
	struct module_data *m = &ctx->m;
	struct xmp_module *mod = &m->mod;
	struct flow_control *f = &p->flow;
	uint8 note, fxp, fxt;
	int h, l;

	/* key_porta is IT only */
	if (m->read_event_type != READ_EVENT_IT) {
		xc->key_porta = xc->key;
	}

	note = e->note;
	if (fnum == 0) {
		fxt = e->fxt;
		fxp = e->fxp;
	} else {
		fxt = e->f2t;
		fxp = e->f2p;
	}

	switch (fxt) {
	case FX_ARPEGGIO:
	      fx_arpeggio:
		if (fxp != 0) {
			xc->arpeggio.val[0] = 0;
			xc->arpeggio.val[1] = MSN(fxp);
			xc->arpeggio.val[2] = LSN(fxp);
			xc->arpeggio.size = 3;
		}
		break;
	case FX_S3M_ARPEGGIO:
		EFFECT_MEMORY(fxp, xc->arpeggio.memory);
		goto fx_arpeggio;
#ifndef LIBXMP_CORE_PLAYER
	case FX_OKT_ARP3:
		if (fxp != 0) {
			xc->arpeggio.val[0] = -MSN(fxp);
			xc->arpeggio.val[1] = 0;
			xc->arpeggio.val[2] = LSN(fxp);
			xc->arpeggio.size = 3;
		}
		break;
	case FX_OKT_ARP4:
		if (fxp != 0) {
			xc->arpeggio.val[0] = 0;
			xc->arpeggio.val[1] = LSN(fxp);
			xc->arpeggio.val[2] = 0;
			xc->arpeggio.val[3] = -MSN(fxp);
			xc->arpeggio.size = 4;
		}
		break;
	case FX_OKT_ARP5:
		if (fxp != 0) {
			xc->arpeggio.val[0] = LSN(fxp);
			xc->arpeggio.val[1] = LSN(fxp);
			xc->arpeggio.val[2] = 0;
			xc->arpeggio.size = 3;
		}
		break;
#endif
	case FX_PORTA_UP:	/* Portamento up */
		EFFECT_MEMORY(fxp, xc->freq.memory);

		if (HAS_QUIRK(QUIRK_FINEFX)
		    && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) {
			switch (MSN(fxp)) {
			case 0xf:
				fxp &= 0x0f;
				goto fx_f_porta_up;
			case 0xe:
				fxp &= 0x0f;
				fxp |= 0x10;
				goto fx_xf_porta;
			}
		}

		SET(PITCHBEND);

		if (fxp != 0) {
			xc->freq.slide = -fxp;
			if (HAS_QUIRK(QUIRK_UNISLD))
				xc->porta.memory = fxp;
		} else if (xc->freq.slide > 0) {
			xc->freq.slide *= -1;
		}
		break;
	case FX_PORTA_DN:	/* Portamento down */
		EFFECT_MEMORY(fxp, xc->freq.memory);

		if (HAS_QUIRK(QUIRK_FINEFX)
		    && (fnum == 0 || !HAS_QUIRK(QUIRK_ITVPOR))) {
			switch (MSN(fxp)) {
			case 0xf:
				fxp &= 0x0f;
				goto fx_f_porta_dn;
			case 0xe:
				fxp &= 0x0f;
				fxp |= 0x20;
				goto fx_xf_porta;
			}
		}

		SET(PITCHBEND);

		if (fxp != 0) {
			xc->freq.slide = fxp;
			if (HAS_QUIRK(QUIRK_UNISLD))
				xc->porta.memory = fxp;
		} else if (xc->freq.slide < 0) {
			xc->freq.slide *= -1;
		}
		break;
	case FX_TONEPORTA:	/* Tone portamento */
		if (HAS_QUIRK(QUIRK_IGSTPOR)) {
			if (note == 0 && xc->porta.dir == 0)
				break;
		}
		if (!IS_VALID_INSTRUMENT(xc->ins))
			break;

		do_toneporta(m, xc, note);

		EFFECT_MEMORY_SETONLY(fxp, xc->porta.memory);

		if (fxp != 0) {
			if (HAS_QUIRK(QUIRK_UNISLD)) /* IT compatible Gxx off */
				xc->freq.memory = fxp;
			xc->porta.slide = fxp;
		}
		SET(TONEPORTA);
		break;

	case FX_VIBRATO:	/* Vibrato */
		EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory);

		SET(VIBRATO);
		SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp) << 2, MSN(fxp));
		break;
	case FX_FINE_VIBRATO:	/* Fine vibrato */
		EFFECT_MEMORY_SETONLY(fxp, xc->vibrato.memory);

		SET(VIBRATO);
		SET_LFO_NOTZERO(&xc->vibrato.lfo, LSN(fxp), MSN(fxp));
		break;

	case FX_TONE_VSLIDE:	/* Toneporta + vol slide */
		if (!IS_VALID_INSTRUMENT(xc->ins))
			break;
		do_toneporta(m, xc, note);
		SET(TONEPORTA);
		goto fx_volslide;
	case FX_VIBRA_VSLIDE:	/* Vibrato + vol slide */
		SET(VIBRATO);
		goto fx_volslide;

	case FX_TREMOLO:	/* Tremolo */
		EFFECT_MEMORY_SETONLY(fxp, xc->tremolo.memory);
		SET(TREMOLO);
		SET_LFO_NOTZERO(&xc->tremolo.lfo, LSN(fxp), MSN(fxp));
		break;

	case FX_SETPAN:		/* Set pan */
		/* From OpenMPT PanOff.xm:
		 * "Another chapter of weird FT2 bugs: Note-Off + Note Delay
		 *  + Volume Column Panning = Panning effect is ignored."
		 */
		if (!HAS_QUIRK(QUIRK_FT2BUGS)		/* If not FT2 */
		    || fnum == 0			/* or not vol column */
		    || e->note != XMP_KEY_OFF		/* or not keyoff */
		    || e->fxt != FX_EXTENDED		/* or not delay */
		    || MSN(e->fxp) != EX_DELAY) {
			xc->pan.val = fxp;
			xc->pan.surround = 0;
		}
		break;
	case FX_OFFSET:		/* Set sample offset */
		EFFECT_MEMORY(fxp, xc->offset.memory);
		SET(OFFSET);
		if (note) {
			xc->offset.val &= xc->offset.val & ~0xffff;
			xc->offset.val |= fxp << 8;
			xc->offset.val2 = fxp << 8;
		}
		if (e->ins) {
			xc->offset.val2 = fxp << 8;
		}
		break;
	case FX_VOLSLIDE:	/* Volume slide */
	      fx_volslide:
		/* S3M file volume slide note:
		 * DFy  Fine volume down by y (...) If y is 0, the command will
		 *      be treated as a volume slide up with a value of f (15).
		 *      If a DFF command is specified, the volume will be slid
		 *      up.
		 */
		if (HAS_QUIRK(QUIRK_FINEFX)) {
			h = MSN(fxp);
			l = LSN(fxp);
			if (l == 0xf && h != 0) {
				xc->vol.memory = fxp;
				fxp >>= 4;
				goto fx_f_vslide_up;
			} else if (h == 0xf && l != 0) {
				xc->vol.memory = fxp;
				fxp &= 0x0f;
				goto fx_f_vslide_dn;
			}
		}