📄 playevents.c
字号:
/************************************************************************ playevents.c -- actually sends sorted list of events to device Copyright (C) 1994-1996 Nathan I. Laredo This program is modifiable/redistributable under the terms of the GNU General Public Licence. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Send your comments and all your spare pocket change to laredo@gnu.ai.mit.edu (Nathan Laredo) or to PSC 1, BOX 709, 2401 Kelly Drive, Lackland AFB, TX 78236-5128, USA. *************************************************************************//* edited by Peter Kutak *//* email : kutak@stonline.sk */#if defined(linux) || defined(__FreeBSD__)#include "playmidi.h"#include <sys/time.h>extern int seq_set_patch(int, int);extern void seq_key_pressure(int, int, int, int);extern void seq_start_note(int, int, int, int);extern void seq_stop_note(int, int, int, int);extern void seq_control(int, int, int, int);extern void seq_chn_pressure(int, int, int);extern void seq_bender(int, int, int, int);extern void seq_reset();SEQ_USE_EXTBUF();extern int division, ntrks, format;extern int gus_dev, ext_dev, sb_dev, awe_dev, perc, seqfd, p_remap;extern int play_gus, play_fm, play_ext, play_awe, reverb, chorus, chanmask;extern int usevol[16];extern struct miditrack seq[MAXTRKS];extern float skew;extern unsigned long int default_tempo;extern char ImPlaying,StopPlease;extern void load_sysex(int, unsigned char *, int);unsigned long int ticks, tempo;struct timeval start_time;unsigned long int rvl(s)struct miditrack *s;{ register unsigned long int value = 0; register unsigned char c; if (s->index < s->length && ((value = s->data[(s->index)++]) & 0x80)) { value &= 0x7f; do { if (s->index >= s->length) c = 0; else value = (value << 7) + ((c = s->data[(s->index)++]) & 0x7f); } while (c & 0x80); } return (value);}/* indexed by high nibble of command */int cmdlen[16] ={0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0};#define CMD seq[track].running_st#define TIME seq[track].ticks#define CHN (CMD & 0xf)#define NOTE data[0]#define VEL data[1]int playevents(){ unsigned long int tempo = default_tempo, lasttime = 0; unsigned int lowtime, track, best, length, loaded; unsigned char *data; double current = 0.0, dtime = 0.0; int use_dev, play_status, playing = 1; seq_reset(); gettimeofday(&start_time, NULL); /* for synchronization */ for (track = 0; track < ntrks; track++) { seq[track].index = seq[track].running_st = 0; seq[track].ticks = rvl(&seq[track]); } for (best = 0; best < 16; best++) { if (ISAWE(best)) use_dev = awe_dev; else if (ISGUS(best)) use_dev = gus_dev; else if (ISFM(best)) use_dev = sb_dev; else use_dev = ext_dev; seq_control(use_dev, best, CTL_BANK_SELECT, 0); seq_control(use_dev, best, CTL_EXT_EFF_DEPTH, reverb); seq_control(use_dev, best, CTL_CHORUS_DEPTH, chorus); seq_control(use_dev, best, CTL_MAIN_VOLUME, 127); seq_chn_pressure(use_dev, best, 127); seq_control(use_dev, best, 0x4a, 127); } SEQ_START_TIMER(); SEQ_DUMPBUF(); while (playing) { lowtime = ~0; for (best = track = 0; track < ntrks; track++) if (seq[track].ticks < lowtime) { best = track; lowtime = TIME; } if (lowtime == ~0) break; /* no more data to read */ track = best; if (ISMIDI(CHN)) use_dev = ext_dev; else if (ISAWE(CHN)) use_dev = awe_dev; else if (ISGUS(CHN)) use_dev = gus_dev; else use_dev = sb_dev; /* this section parses data in midi file buffer */ if ((seq[track].data[seq[track].index] & 0x80) && (seq[track].index < seq[track].length)) CMD = seq[track].data[seq[track].index++]; if (CMD == 0xff && seq[track].index < seq[track].length) CMD = seq[track].data[seq[track].index++]; if (CMD > 0xf7) /* midi real-time message (ignored) */ length = 0; else if (!(length = cmdlen[(CMD & 0xf0) >> 4])) length = rvl(&seq[track]); if (seq[track].index + length < seq[track].length) { /* use the parsed midi data */ data = &(seq[track].data[seq[track].index]); if (CMD == set_tempo) tempo = ((*(data) << 16) | (data[1] << 8) | data[2]); if (TIME > lasttime) { if (division > 0) { dtime = ((double) ((TIME - lasttime) * (tempo / 10000)) / (double) (division)) * skew; current += dtime; lasttime = TIME; } else if (division < 0) current = ((double) TIME / ((double) ((division & 0xff00 >> 8) * (division & 0xff)) * 10000.0)) * skew; /* stop if there's more than 40 seconds of nothing */ if (dtime > 4096.0) playing = 0; else if ((int) current > ticks) { SEQ_WAIT_TIME((ticks = (int) current)); SEQ_DUMPBUF(); } } if (CMD > 0x7f && CMD < 0xf0 && ISPERC(CHN) && p_remap) { CMD &= 0xf0; CMD |= (p_remap - 1); } loaded = 0; /* for patch setting failures */ if (playing && CMD > 0x7f && ISPLAYING(CHN)) switch (CMD & 0xf0) { case MIDI_KEY_PRESSURE: if (ISPERC(CHN) && VEL && (!ISMIDI(CHN)&&!ISAWE(CHN))) loaded = seq_set_patch(CHN, NOTE + 128); if (loaded != -1) seq_key_pressure(use_dev, CHN, NOTE, VEL); break; case MIDI_NOTEON: if (ISPERC(CHN) && VEL && (!ISMIDI(CHN)&&!ISAWE(CHN))) loaded = seq_set_patch(CHN, NOTE + 128); if (VEL && usevol[CHN]) VEL = usevol[CHN]; if (loaded != -1) seq_start_note(use_dev, CHN, NOTE, VEL); break; case MIDI_NOTEOFF: seq_stop_note(use_dev, CHN, NOTE, VEL); break; case MIDI_CTL_CHANGE: seq_control(use_dev, CHN, NOTE, VEL); break; case MIDI_CHN_PRESSURE: seq_chn_pressure(use_dev, CHN, NOTE); break; case MIDI_PITCH_BEND: seq_bender(use_dev, CHN, NOTE, VEL); break; case MIDI_PGM_CHANGE: if (ISMIDI(CHN) || ISAWE(CHN) || !ISPERC(CHN)) NOTE = seq_set_patch(CHN, NOTE); break; case MIDI_SYSTEM_PREFIX: if (length > 1) load_sysex(length, data, CMD); break; default: break; } } /* this last little part queues up the next event time */ seq[track].index += length; if (seq[track].index >= seq[track].length) seq[track].ticks = ~0; /* mark track complete */ else seq[track].ticks += rvl(&seq[track]); } SEQ_DUMPBUF(); ImPlaying = 0; return 1;}#endif /* linux || FreeBSD */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -