Example #1
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 Editor::midi_edit_event(const EventMidi& ev) {
	
	BlockList *bl = get_blocklist( get_current_blocklist() );
	if (!bl)
		return;
	
	Track_Pattern *pattern_track = dynamic_cast<Track_Pattern*>(bl);
	if (!pattern_track)
		return;
	
	if (ev.midi_type==EventMidi::MIDI_NOTE_ON) {
		
		
		int column=d->pattern_edit.column;
		
		if (d->global_edit.polyphonic_midi_input_enabled) {
			
			column+=d->pattern_edit.poly_input_offset;
			d->pattern_edit.poly_input_offset++;
			if (column>=pattern_track->get_visible_columns())
				return;
		}
		
		if (!pattern_track->is_pos_editable( d->cursor.get_tick_pos() ) )
			return;
		
		int note=ev.data.note.note;
		Tick tickpos=d->cursor.get_tick_pos();
			
		int volume=99;
		
		if (d->pattern_edit.volume_mask_active) {
			volume=d->pattern_edit.volume_mask;
		} else {
				
			Track_Pattern::Note note=pattern_track->get_note(Track_Pattern::Position(tickpos,column));
				
			if (note.is_note())
				volume=note.volume;
		}
			
		d->undo_stream.begin("Set Note");
		SET_NOTE(Track_Pattern::Position(tickpos,column),Track_Pattern::Note(note,volume));
		d->undo_stream.end();
		play_note_at_cursor(column);
		
		if (!d->global_edit.polyphonic_midi_input_enabled)
			d->cursor.set_pos( d->cursor.get_pos() +1 );
			
		if (d->pattern_edit.volume_mask_active)
			d->pattern_edit.volume_mask=volume;
		d->ui_update_notify->volume_mask_changed();
		d->ui_update_notify->notify_action( d->undo_stream.get_current_action_text() );
		
			
	} if (ev.midi_type==EventMidi::MIDI_NOTE_OFF && d->global_edit.polyphonic_midi_input_enabled) {
		
		
		if (d->pattern_edit.poly_input_offset==1)
			d->cursor.set_pos( d->cursor.get_pos() +1 );

		
		d->pattern_edit.poly_input_offset--;
		if (d->pattern_edit.poly_input_offset<0)
			d->pattern_edit.poly_input_offset=0;
		
		
	}
}