📄 seqmwrite.c
字号:
/* created by DMH (damonhorowitz): write seq_type as standard midifile *//**************************************************************************** Change Log* Date | Change*-----------+---------------------------------------------------------------* 11-Mar-94 | Created Change Log* 11-Mar-94 | PLu : Added private to function defs.* 28-Apr-03 | DM : Change #include's for portability****************************************************************************/#include "switches.h"#include <stdio.h>#include "cext.h"#include "userio.h"#include "midicode.h"#include "mfmidi.h"#include "midifns.h"#include "timebase.h"#include "moxc.h"#include "seq.h"#include "seqread.h" /* to get scale() */#include "seqmwrite.h"long chunk_size_marker;int seti_counter;extern time_type a_start_time;long last_event; /*time from last_clock_event to the last event*/time_type last_clock_event;time_type last_tick_size; /* millisec per tick shifted 16 bits */struct smf_write_seq { seq_type seq; int track; FILE *outfile; } smfw_seq;extern seq_type sequence; /* this is a global to be accessed by * routines called from the sequence *//* clock state: */extern time_type clock_ticksize; /* millisec per tick shifted 16 bits */extern boolean clock_running; /* TRUE if clock is running */extern boolean use_midi_clock;private void smfw_bend();private void smfw_cause_noteoff();private void smfw_ctrl();private void smfw_deltatime();private void smfw_dotrack();private void smfw_exclusive();private void smfw_noteoff();private void smfw_noteon();private void smfw_process_event();private void smfw_ramp_event(seq_type seq, event_type event, unsigned int value, unsigned int to_value, int increment, time_type step, int n);private void smfw_send_macro();private void smfw_touch(seq_type seq, int voice, int value);private void writevarlen();/* smfw_bend -- write a pitch bend to a midi file *//**/private void smfw_bend(seq_type seq, int voice, int value){ if(debug) gprintf(TRANS, "smfw_bend %d\n", value); smfw_deltatime(); putc(MIDI_BEND | (voice - 1), smfw_seq.outfile); putc(0xFF & ((value & 0x1) << 6) , smfw_seq.outfile); putc(0xFF & (value >> 1), smfw_seq.outfile);}/* smfw_cause_noteoff -- schedule a noteoff for midi file *//* * NOTE: this is called by smfw_process_event when it handles a note * event node in a seq_type's event list. The ordinary moxc scheduler * is used to "schedule" the noteoff in the future. In reality, the * output is done as fast as possible (by attempting an infinite rate), * so no real timing delays occur. The effect is to sort events by their * specified time. */private void smfw_cause_noteoff(seq, delay, voice, pitch) seq_type seq; time_type delay; int voice; int pitch;{ if(debug) gprintf(TRANS, "cause noteoff at %ld...", virttime + delay); 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); }private void smfw_clock_event(old_ticksize, new_ticksize) time_type old_ticksize, new_ticksize;{ time_type temp_ticksize = new_ticksize; new_ticksize = scale(new_ticksize, 375L, 1024L);/* (new_ticksize >> 16) * 24000 ms/clock becomes us/midiquarter */ if(debug) gprintf(TRANS, "smfw_clock: write %ld (time:%ld) ->->->tempo %ld\n", new_ticksize, virttime, 2500L / (new_ticksize / 24000)); /*use old ticksize to write the delta for the clock event*/ last_tick_size = old_ticksize; smfw_deltatime(); last_tick_size = temp_ticksize;/* reset to = new_tick_size */ putc(0xFF, smfw_seq.outfile); putc(0x51, smfw_seq.outfile); putc(0x03, smfw_seq.outfile); putc((int) ((new_ticksize >> 16) & 0xFF), smfw_seq.outfile); putc((int) ((new_ticksize >> 8) & 0xFF), smfw_seq.outfile); putc((int) (new_ticksize & 0xFF), smfw_seq.outfile); last_clock_event = virttime; last_event = 0L; /*no time expired between last clockevent and last event(they are the same).*/ /*next clock event will be exactly the next this_event from last_clock_event*/}/* smfw_ctrl -- write a control change to a midi file *//**/private void smfw_ctrl(seq_type seq, int voice, int ctrl_name, int value){ if(debug) gprintf(TRANS, "smfw_ctrl %d: %d\n", ctrl_name, value); smfw_deltatime(); putc(MIDI_CTRL | (voice - 1), smfw_seq.outfile); putc(ctrl_name, smfw_seq.outfile); putc(value, smfw_seq.outfile);}/* smfw_deltatime -- write the time difference between now an previous event *//**/private void smfw_deltatime(){ /* if last_ and clock_ are different, use last_ for clock deltatime*/ time_type use_ticksize = (clock_ticksize != last_tick_size) ? last_tick_size : clock_ticksize; time_type this_event = virttime - last_clock_event; if(debug) gprintf(TRANS, "delta! ticksize: %lu Lastev: %ld ThisevScaled: %lu Thisev: %lu ", clock_ticksize, last_event, (this_event * ((2500L << 16) / use_ticksize)) / 100, this_event); this_event = ((virttime - last_clock_event) * ((2500L << 16) / use_ticksize)) / 100; if(debug) gprintf(TRANS, "--- deltatime: %lu\n", this_event - last_event); writevarlen((long) (this_event - last_event)); last_event = this_event; }/* smfw_dotrack -- write the remainder of a track */private void smfw_dotrack(seq) seq_type seq;{ long end_marker; timebase_type old_timebase = timebase; unsigned long chunk_size; if (seq->runflag) { if ((seq->timebase->virt_base == 0) && (seq->timebase->rate == STOPRATE)) /*we just set these last time through... do nothing*/; 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; last_clock_event = 0L; last_event = 0L; if(debug) gprintf(TRANS, "dotrack (reset) %d %ld (%lu) \n", smfw_seq.track, last_event, virttime); if (seq->current) cause((delay_type)(seq->current->ntime - virttime), smfw_process_event, seq); set_virttime(timebase, MAXTIME); catchup(); putc(0x00, smfw_seq.outfile); putc(0xFF, smfw_seq.outfile);/*end of track chunk*/ putc(0x2F, smfw_seq.outfile); putc(0x00, smfw_seq.outfile); end_marker = ftell(smfw_seq.outfile); fseek(smfw_seq.outfile, chunk_size_marker, 0);/*go back to enter chunksize*/ chunk_size = (end_marker - chunk_size_marker) - 4;/* - 4 for 4 size bytes*/ if(debug) gprintf(TRANS, "bytes written in previous track: %ld \n\n", chunk_size); putc((int) ((0xFF & (chunk_size >> 24))), smfw_seq.outfile); putc((int) ((0xFF & (chunk_size >> 16))), smfw_seq.outfile); putc((int) ((0xFF & (chunk_size >> 8))), smfw_seq.outfile); putc((int) ((0xFF & chunk_size)), smfw_seq.outfile); fseek(smfw_seq.outfile, end_marker, 0);/*return file pointer to end of track*/ timebase_use(old_timebase);}/* smfw_exclusive -- write a system excl. msg to midi file */private void smfw_exclusive(length, msg)int length;unsigned char *msg; { int length_count = 0; if(debug) gprintf(TRANS, "SYSEX (time:%ld)\n", virttime); smfw_deltatime(); while (length > length_count){ /* *(msg-1) != MIDI_EOX) { */ putc(*msg++, smfw_seq.outfile); length_count++; } if(*(--msg) != MIDI_EOX) gprintf(TRANS, "ERROR: no end of sysex\n");}private void smfw_msg_write(n,c1,c2,c3) int n; unsigned char c1,c2,c3;{ if(debug) gprintf(TRANS, "MSGWRITE %d bytes (time:%ld)\n", n, virttime); smfw_deltatime(); switch(n) { case 1: putc(c1, smfw_seq.outfile); break; case 2: putc(c1, smfw_seq.outfile); putc(c2, smfw_seq.outfile); break; case 3: putc(c1, smfw_seq.outfile); putc(c2, smfw_seq.outfile); putc(c3, smfw_seq.outfile); break; }}/* smfw_noteoff -- write noteoff to midi file *//**/private void smfw_noteoff(seq_type seq, int voice, int pitch){ if(debug) gprintf(TRANS, "smfw_noteoff %d: %d (time:%ld)\n", voice, pitch, virttime); smfw_deltatime(); putc(NOTEOFF | (voice - 1), smfw_seq.outfile); putc(pitch, smfw_seq.outfile); putc(0x40, smfw_seq.outfile);} /* smfw_noteon -- write noteon to midi file *//* * NOTE: the seq parameter is not used here, but is passed in by the * seq_noteon macro, so we have to have a placeholder for it. */private void smfw_noteon(seq, voice, pitch, vel) seq_type seq; int voice, pitch, vel;{ if(debug) gprintf(TRANS, "smfw_noteon %d: %d %d(time:%ld)\n", voice, pitch, vel, virttime); smfw_deltatime(); putc(NOTEON | (voice - 1), smfw_seq.outfile); putc(pitch, smfw_seq.outfile); putc(vel, smfw_seq.outfile);}/* smfw_process_event -- write a seq event to a midi file *//**/private void smfw_process_event(seq) seq_type seq;{ register event_type event; if (!seq->runflag) return; while ((event = seq->current) && (event->ntime <= virttime)) { unsigned int voice; if ((vc_voice(event->nvoice) == smfw_seq.track) || /*if on current track*/ (((vc_voice(event->nvoice) - 16) == smfw_seq.track) && (smfw_seq.track > 0)) || /* acknowledge clock change on all tracks*/ (event->value == CLOCK_VALUE)) { /* 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, (0xFF & event->value), (int) (event->u.note.ndur & 0xFF)); seq_cause_noteoff(seq, (event->u.note.ndur) >> 8, voice, (0xFF & event->value)); } } else { /*** send a control command ***/ int n; time_type step; int delta; int 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; if(debug) gprintf(TRANS, "porta %d (time:%ld)... ", event->value, virttime); seq_midi_ctrl(seq, voice, PORTASWITCH, 0xFF & event->value); break; case MODWHEEL_CTRL: if (!enabled) break; if(debug) gprintf(TRANS, "modw %d (time:%ld)...", event->value, virttime); seq_midi_ctrl(seq, voice, MODWHEEL, 0xFF & event->value); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -