📄 seq.c
字号:
seq_type seq_alloc(){ seq_type seq; seq = (seq_type) memget(sizeof(seq_node)); return seq;} /* seq_at_end -- set the function to be called at sequence end *//**/void seq_at_end(seq, fn) seq_type seq; void (*fn)(seq_type);{ if (!fn) fn = noop; seq->stopfunc = fn;}/* seq_cause_noteoff_meth -- turn off a note in the future *//**/void seq_cause_noteoff_meth(seq, delay, voice, pitch) seq_type seq; time_type delay; int voice; int pitch;{ if (seq->note_enable) { pitch += seq->transpose; while (pitch < 0) pitch += 12; while (pitch > 127) pitch -= 12; seq->noteoff_count++; causepri((delay_type) delay, 10, seq->noteoff_fn, seq, voice, pitch); }}/* seq_copy -- copy a sequence, share the eventlist *//**/seq_type seq_copy(from_seq) seq_type from_seq;{ register seq_type seq = seq_init(seq_alloc(), FALSE); if (!seq) return NULL; seq->chunklist = from_seq->chunklist; seq->current = seq_events(seq); seq->chunklist->u.info.refcount++; seq->transpose = from_seq->transpose; seq->loudness = from_seq->loudness; seq->rate = from_seq->rate; seq->paused = from_seq->paused; seq->noteoff_count = 0; return seq;}/* seq_create -- create a seq structure and an initial event chunk *//**/seq_type seq_create(){ return seq_init(seq_alloc(), TRUE);}/* seq_cycle -- set parameters for cycling a sequence *//**/void seq_cycle(seq_type seq, boolean flag, time_type dur){ seq->cycleflag = flag; seq->cycledur = dur;}/* seq_end_event -- call this when an score-generated event ends *//* * Assumes that noteoff_count was incremented when event started. */void seq_end_event(seq) seq_type seq;{ /*gprintf(TRANS, "nd");*/ seq->noteoff_count--; if (seq->current == NULL /* finished seq */ && seq->noteoff_count == 0 /* finished noteoff's */ && seq->runflag /* we've not been stopped */) { if (seq->cycleflag) { cause((delay_type) (seq->cycledur - virttime), cycle, seq); } else if (seq->stopfunc) { (*(seq->stopfunc))(seq); } }}/***************************************************************************** seq_free_meth* Input: a seq_type* Effect:* frees storage occupied by a seq****************************************************************************/private void seq_free_meth(seq) seq_type seq;{ seq_free_chunks(seq); if (seq->timebase) timebase_free(seq->timebase); memfree((void *) seq, sizeof(seq_node));}/* seq_free_chunks -- free storage for note list *//* * NOTE: in its original form, this routine was perhaps more readable, * but would not compile under Microsoft C V7.00 due to a compiler bug. * I rewrote the code until the bug disappeared, hopefully without * changing the semantics! If you change this code, make sure it still * compiles under Microsoft C. * * This module frees chunks from a seq_type in preparation for freeing * the seq_type itself. Reference counts are checked and chunks are * only freed when the last reference is removed. */public void seq_free_chunks(seq) seq_type seq;{ chunk_type tail; chunk_type head; head = seq->chunklist; if (((head->u.info.refcount)--) != 0) return; while (head != NULL) { tail = head->next; memfree((void *) head, sizeof(chunk_node)); head = tail; seq->chunklist = head; }}seq_type seq_init(seq, create_chunk) seq_type seq; int create_chunk;{ if (!seq || !(seq->timebase = timebase_create(50))) { return NULL; } seq->chunklist = NULL; if (create_chunk) { seq->chunklist = chunk_create(TRUE); if (!seq->chunklist) { seq_free(seq); return NULL; } } seq->cause_noteoff_fn = seq_cause_noteoff_meth; seq->midi_bend_fn = seq_midi_bend_meth; seq->midi_ctrl_fn = seq_midi_ctrl_meth; seq->midi_program_fn = seq_midi_program_meth; seq->midi_touch_fn = seq_midi_touch_meth; seq->noteoff_fn = seq_noteoff_meth; seq->noteon_fn = seq_noteon_meth; seq->free_fn = seq_free_meth; seq->reset_fn = seq_reset_meth; seq->current = NULL; seq->transpose = 0; seq->loudness = 0; seq->cycleflag = FALSE; seq->cycledur = 0L; seq->rate = 256L; seq->paused = FALSE; seq->stopfunc = noop; seq->channel_mask = 0xFFFFFFFFL; seq->runflag = seq->note_enable = FALSE; return seq;}/* seq_midi_bend_meth -- send a midi bend *//**/void seq_midi_bend_meth(seq_type seq, int voice, int value){ midi_bend(voice, value);}/* seq_midi_ctrl_meth -- send a midi ctrl change *//**/void seq_midi_ctrl_meth(seq_type seq, int voice, int ctrl, int value){ midi_ctrl(voice, ctrl, value);}/* seq_midi_program_meth -- send a midi program change *//**/void seq_midi_program_meth(seq_type seq, int voice, int prog){ midi_bend(voice, prog);}/* seq_midi_touch_meth -- send a midi touch *//**/void seq_midi_touch_meth(seq_type seq, int voice, int value){ midi_touch(voice, value);}/* seq_noteoff_meth -- turn a seq note off *//**/void seq_noteoff_meth(seq, voice, pitch) seq_type seq; int voice; int pitch;{ midi_note(voice, pitch, 0); /*gprintf(TRANS, "_e");*/ seq_end_event(seq);}/* seq_noteon_meth -- play a note with transformations *//**/void seq_noteon_meth(seq, chan, pitch, vel) seq_type seq; int chan, pitch, vel;{ if (seq->note_enable) { pitch += seq->transpose; while (pitch < 0) pitch += 12; while (pitch > 127) pitch -= 12; vel += seq->loudness; if (vel <= 0) vel = 1; else if (vel > 127) vel = 127; midi_note(chan, pitch, vel); }}/* seq_pause -- stop playing momentarily or resume playing *//**/time_type seq_pause(seq_type seq, boolean flag){ if (!seq->paused && flag) { seq->paused = TRUE; seq->rate = seq->timebase->rate; set_rate(seq->timebase, STOPRATE); } else if (seq->paused && !flag) { seq_play(seq); } return (time_type) seq->timebase->virt_base;}/* seq_play -- play a sequence from the current event forward *//**/void seq_play(seq) seq_type seq;{ timebase_type prev_timebase = timebase; register timebase_type reg_timebase = seq->timebase; if (!seq->runflag) { seq_reset(seq); } if (!seq->paused) return; eventtime = gettime(); /* assume that virt_base is correct virtual time as the result of seq_start_time or seq_reset */ timebase = reg_timebase; virttime = reg_timebase->virt_base; /* note that set_rate will set reg_timebase->real_base to eventtime */ set_rate(reg_timebase, seq->rate); seq->paused = FALSE; /* in case the score had been paused; note that seq_pause() has no effect if paused is TRUE */ seq->runflag = TRUE; seq->note_enable = TRUE; /* restore previous timebase */ timebase_use(prev_timebase);}/* seq_reset_meth -- reset a sequence to start back at the first event *//**/void seq_reset_meth(seq) seq_type seq;{ timebase_type old_timebase = timebase; if (seq->runflag) { /* maybe this seq is already reset, and process_event is * already scheduled. If so, don't schedule another one. */ if ((seq->timebase->virt_base == 0) && (seq->timebase->rate == STOPRATE)) { /* in case the reader just iterated through the list without * cause'ing events, reset the event list */ seq->current = seq_events(seq); return; } /* Otherwise, the seq is running, so stop it. */ seq_stop(seq); } timebase_use(seq->timebase); set_rate(seq->timebase, STOPRATE); set_virttime(seq->timebase, 0L); seq->current = seq_events(seq); seq->noteoff_count = 0L; seq->runflag = TRUE; seq->paused = TRUE; if (seq->current) cause((delay_type)(seq->current->ntime - virttime), process_event, seq); timebase_use(old_timebase);}/* seq_set_loudness -- set the loudness offset of a sequence *//**/void seq_set_loudness(seq, loud) seq_type seq; int loud;{ seq->loudness = loud;}/* seq_set_rate -- set the rate of a sequence *//**/void seq_set_rate(seq, rate) seq_type seq; time_type rate;{ seq->rate = rate; if (!seq->paused) set_rate(seq->timebase, rate);}/* seq_set_transpose -- set the sequence transposition *//**/void seq_set_transpose(seq, trans) seq_type seq; int trans;{ seq->transpose = trans;}/* seq_start_time -- set the current pointer so the sequence starts here *//**/void seq_start_time(seq, start_time) seq_type seq; time_type start_time;{ timebase_type prev_timebase = timebase; if (!seq->runflag) { seq_reset(seq); } if (real_to_virt(seq->timebase, eventtime) > start_time) { seq_reset(seq); } timebase_use(seq->timebase); seq->note_enable = FALSE; /* prime the pump */ set_rate(timebase, STOPRATE); set_virttime(timebase, start_time); catchup(); seq->note_enable = TRUE; seq->paused = TRUE; /* restore previous timebase */ timebase_use(prev_timebase);}/* seq_stop -- stop a sequence, clear out all pending events *//**/void seq_stop(seq) seq_type seq;{ timebase_type prev_timebase = timebase; if (seq->runflag) { if (moxcdebug) gprintf(TRANS, "seq_reset swap from timebase 0x%x to 0x%x\n", timebase, seq->timebase); timebase = seq->timebase; seq->runflag = FALSE; set_rate(timebase, STOPRATE); set_virttime(timebase, MAXTIME); catchup(); } timebase_use(prev_timebase);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -