📄 seq.c
字号:
register event_type insert_before; if (!seq->current) { seq->current = seq_eventlist(seq); } if (event->ntime >= seq->current->ntime) { /* insertion point is after current */ previous = seq->current; insert_before = previous->next; } else { /* insertion point is before current; start at beginning */ /* assume: not inserting at very head of list; that would * have been taken care of above */ previous = seq_events(seq); insert_before = previous->next; } while ((insert_before != NULL) && (event->ntime >= insert_before->ntime)) { previous = insert_before; insert_before = insert_before->next; } previous->next = event; event->next = insert_before; seq->current = event; }}/* insert_macctrl -- add a control to the seq *//**/event_type insert_macctrl(seq, ctime, cline, ctrl, voice, value) seq_type seq; time_type ctime; int cline; int ctrl; int voice; int value;{ register event_type event = event_create(seq, macctrlsize, ctime, cline); if (seq_print) { gprintf(TRANS, "macctrl(%lx): time %ld, line %d, ctrl %d, voice %d, value %d\n", event, ctime, cline, ctrl, voice, value); } if (event) { seq_used_mask(seq) |= 1 << (voice - 1); event->nvoice = ctrl_voice(ESC_CTRL, voice); event->value = MACCTRL_VALUE; event->u.macctrl.ctrl_number = ctrl; event->u.macctrl.value = value; seq_ctrlcount(seq)++; } return event;}/* insert_macro -- insert a macro call seq *//**/event_type insert_macro(seq, ctime, cline, def, voice, nparms, parms) seq_type seq; time_type ctime; int cline; def_type def; int voice; int nparms; short *parms;{ register event_type event = event_create(seq, macrosize, ctime, cline); if (seq_print) { int i; gprintf(TRANS, "macro(%lx): time %ld, line %d, def %ld, voice %d, parms", event, ctime, cline, def, voice); for (i = 0; i < nparms; i++) gprintf(TRANS, " %d", parms[i]); gprintf(TRANS, "\n"); } if (event) { seq_used_mask(seq) |= 1 << (voice - 1); event->nvoice = ctrl_voice(ESC_CTRL, voice); event->value = MACRO_VALUE; event->u.macro.definition = def->definition; while (nparms-- > 0) { event->u.macro.parameter[nparms] = parms[nparms]; } seq_ctrlcount(seq)++; } return event;}/* insert_note -- add a note to the seq *//**/event_type insert_note(seq, ntime, nline, voice, pitch, dur, loud) seq_type seq; time_type ntime; int nline; int voice; int pitch; time_type dur; int loud;{ register event_type event = event_create(seq, notesize, ntime, nline); if (seq_print) { gprintf(TRANS, "note(%lx): time %ld, line %d, dur %ld, pitch %d, voice %d, loudness %d\n", event, ntime, nline, dur, pitch, voice, loud); } if (event) { seq_used_mask(seq) |= 1 << (voice - 1); event->nvoice = voice - 1; event->value = pitch; event->u.note.ndur = (dur << 8) + loud; seq_notecount(seq)++; seq_duration(seq) = MAX(seq_duration(seq), ntime + dur); } return event;}/* insert_seti -- add a seti event to the seq *//**/event_type insert_seti(seq, stime, sline, voice, addr, value) seq_type seq; time_type stime; int sline; int voice; int *addr; int value;{ register event_type event = event_create(seq, setisize, stime, sline); if (seq_print) { gprintf(TRANS, "seti(%ld): time %ld, line %d, voice %d, addr %ld, value %d\n", event, stime, sline, voice, addr, value); } if (event) { event->nvoice = ctrl_voice(ESC_CTRL, voice); event->value = SETI_VALUE; event->u.seti.int_to_set = addr; event->u.seti.value = value; seq_ctrlcount(seq)++; } return event; }/* noop -- just returns, the default stopfunc for sequences *//**/void noop(seq_type seq) {}private void process_event(seq) seq_type seq;{ register event_type event; if (!seq->runflag) return; while ((event = seq->current) && (event->ntime <= virttime)) { int voice; /* process all current (and earlier) events */ if (is_note(event)) { /*** play a note or rest ***/ /* if this note is not a rest, play it and schedule an off event */ if (event->value != NO_PITCH && (seq_channel_mask(seq) & (1 << ((voice = vc_voice(event->nvoice)) - 1)))) { seq_noteon(seq, voice, event->value, (int) event->u.note.ndur & 0xFF); if (debug) { gprintf(TRANS, "play pitch %d at %ld\n", event->value, event->ntime); } seq_cause_noteoff(seq, (event->u.note.ndur) >> 8, voice, event->value); } } else { /*** send a control command ***/ int n; time_type step; int delta; long increment; int voice = vc_voice(event->nvoice); ulong enabled = seq_channel_mask(seq) & (1 << (voice - 1)); switch (vc_ctrl(event->nvoice)) { case PSWITCH_CTRL: if (!enabled) break; seq_midi_ctrl(seq, voice, PORTASWITCH, event->value); break; case MODWHEEL_CTRL: if (!enabled) break; seq_midi_ctrl(seq, voice, MODWHEEL, event->value); break; case TOUCH_CTRL: if (!enabled) break; seq_midi_touch(seq, voice, event->value); break; case VOLUME_CTRL: if (!enabled) break; seq_midi_ctrl(seq, voice, VOLUME, event->value); break; case BEND_CTRL: if (!enabled) break; seq_midi_bend(seq, voice, (event->value << 6)); break; case PROGRAM_CTRL: if (!enabled) break; seq_midi_program(seq, voice, event->value + 1); break; case ESC_CTRL: switch (event->value) { case CALL_VALUE: sequence = seq; (*(event->u.call.routine))(event->u.call.args); break; case CLOCK_VALUE: clock_ticksize = event->u.clock.ticksize; if (!clock_running && !suppress_midi_clock && !external_midi_clock) { clock_running = TRUE; midi_start(); clock_tick(seq, 0L); } break; case MACCTRL_VALUE: if (!enabled) break; seq_midi_ctrl(seq, voice, event->u.macctrl.ctrl_number, event->u.macctrl.value); break; case MACRO_VALUE: { if (!enabled) break; send_macro(event->u.macro.definition, voice, event->u.macro.parameter, -1, 0, event->nline); break; } case CTRLRAMP_VALUE: case DEFRAMP_VALUE: { int from, to; if (!enabled) break; step = event->u.ramp.step; if (event->value == CTRLRAMP_VALUE) { from = event->u.ramp.u.ctrl.from_value; to = event->u.ramp.u.ctrl.to_value; } else { from = event->u.ramp.u.def.parameter[ event->u.ramp.u.def.parm_num]; to = event->u.ramp.u.def.to_value; } delta = to - from; increment = delta; if (delta < 0) delta = -delta; /* Note: Step is always non-zero */ n = event->u.ramp.dur / step; increment = (increment << 8) / n; ramp_event(seq, event, from << 8, to << 8, (int) increment, step, n); seq->noteoff_count++; break; } case SETI_VALUE: *(event->u.seti.int_to_set) = event->u.seti.value; break; default: gprintf(TRANS, "unexpected ESC_CTRL value\n"); break; } break; default: gprintf(TRANS, "unexpected seq data\n"); break; } } seq->current = event->next; } if (seq->current) { cause((delay_type)(event->ntime - virttime), process_event, seq); } else if (seq->noteoff_count == 0 && seq->note_enable) { /* if we're just advancing to a start point, note_enable will be * FALSE and this won't get called: */ if (seq->stopfunc) { (*(seq->stopfunc))(seq); } }}/* ramp_event -- generate a ramp *//**/private void ramp_event(seq, event, value, to_value, increment, step, n) seq_type seq; register event_type event; unsigned int value; unsigned int to_value; int increment; time_type step; int n;{ if (seq->runflag) { int voice = vc_voice(event->nvoice);/* printf("ramp_event: value %d to_value %d increment %d step %d n %d time %d\n", value, to_value, increment, step, n, virttime); */ if (n == 0) value = to_value; else { causepri((delay_type)step, 5, ramp_event, seq, event, value + increment, to_value, increment, step, n - 1); } if (event->value == CTRLRAMP_VALUE) { int ctrl = event->u.ramp.ctrl; if (ctrl == -TOUCH_CTRL) midi_touch(voice, value >> 8); else if (ctrl == -BEND_CTRL) midi_bend(voice, value >> 2); else midi_ctrl(voice, ctrl, value >> 8); } else { /* must be DEFRAMP_VALUE */ send_macro(event->u.ramp.u.def.definition, vc_voice(event->nvoice), event->u.ramp.u.def.parameter, event->u.ramp.u.def.parm_num, value >> 8, event->nline); } if (n == 0) seq_end_event(seq); }}/* report_enabled_channels -- print out concise listing of channels *//* * to fit on one line, write out ranges, e.g. 1-5 9-11 */void report_enabled_channels(seq) seq_type seq;{ ulong mask = seq_channel_mask(seq); int i, range_open_at = 0; for (i = 1; i <= MAX_CHANNELS; i++) { if (!range_open_at && (mask & 1)) { gprintf(TRANS, " %d", i); range_open_at = i; } else if (range_open_at && !(mask & 1)) { if (i > (range_open_at + 1)) { gprintf(TRANS, "-%d", i - 1); } range_open_at = 0; /* FALSE */ } mask = mask >> 1; } if (range_open_at) gprintf(TRANS, "-%d", MAX_CHANNELS);}/* send_macro -- instantiate macro and send it *//* * note: to support ramping, "value" is used in place of * parameter["parm_num"] *//*private*/void send_macro(ptr, voice, parameter, parm_num, value, nline) register unsigned char *ptr; int voice; short parameter[]; int parm_num; int value; int nline;{ register unsigned char code, *loc; while ((code = *ptr++)) { loc = ptr + *ptr; ptr++; if (code <= nmacroparms) { code--; *loc = (code == parm_num ? value : parameter[code]) & 0x7f; } else if (code == nmacroparms + 1) { /* take old high order bits and OR in 4 voice bits */ *loc = (*loc & 0xF0) | ((voice - 1) & 0xF); } else { code -= (nmacroparms + 2); *loc = ((code == parm_num ? value : parameter[code]) >> 7) & 0x7F; } } if (ptr[1] == MIDI_SYSEX) { midi_exclusive(ptr + 1); } else { /* make sure user didn't try to send more than 3 bytes. This test * could be done at sequence read time, but it's tricky because the * first byte could be a parameter, so in general you need to * plug the actual parameters into the message and then do the test. * Currently, this is the only place parameters are plugged in. */ if (*ptr > 3) { gprintf(ERROR, "Non-sysex macro longer than 3 bytes ignored, line %d.\n", nline); } else { midi_write((int) *ptr, MIDI_PORT(voice), ptr[1], ptr[2], ptr[3]); } }}/* seq_alloc -- a utility function to allocate a seq struct *//**/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -