📄 midifns.c
字号:
int c = getc(stdin); ungetc(c, stdin); } return;}#elsevoid eventwait(timeout) long timeout;{ while (timeout > gettime() || timeout == -1) { if (check_ascii() || check_midi()) return; }}#endif /* WINDOWS */#endif /* UNIX */#endif /* AMIGA *//***************************************************************************** exclusive* Inputs:* boolean onflag -- set to TRUE to receive midi exclusive data* Effect: * Tells module to read exclusive messages into buffer****************************************************************************/void exclusive(boolean onflag){ if (!initialized) fixup(); if (musictrace) gprintf(TRANS, "exclusive: %d\n", onflag);#ifdef AMIGA if (onflag) SetMidiFilters(cmt_mi, cmt_mi->PortFilter, cmt_mi->TypeFilter | CMF_SysEx, cmt_mi->ChanFilter); else SetMidiFilters(cmt_mi, cmt_mi->PortFilter, cmt_mi->TypeFilter & ~CMF_SysEx, cmt_mi->ChanFilter);#endif#ifdef MACINTOSH_OR_DOS exclFilter = !onflag;#endif}/***************************************************************************** fixup* Effect: * Print error message and call musicinit****************************************************************************/private void fixup(){ gprintf(ERROR, "You forgot to call musicinit. I'll do it for you.\n"); musicinit();}#ifdef UNIX_IRIX_MIDIFNSprivate void flush_sysex(void);#endiflong get_excl(byte *buffer, long len){ long ret = 0;#ifdef UNIX_IRIX_MIDIFNS byte *sxp = sysex_p; long l = len;#endif#ifdef UNIX_ITC /* was ITC */ ret = mi_getx(midiconn, FALSE, len, (char *) buffer);#endif#ifdef UNIX_MACH ret = mi_getx(midiconn, FALSE, len, (unsigned char *)buffer);#endif#ifdef UNIX_IRIX_MIDIFNS if (!sysex_p) return 0; if (len > sysex_n) len = sysex_n; while (l--) { *buffer = *(sxp++); if (*(buffer++) == CMT_MIDI_EOX) { flush_sysex(); break; } } ret = len - l - 1;#endif#ifdef AMIGA ret = GetSysEx(cmt_mi, (UBYTE *) buffer, len); AMIGA_ERROR_CHECK;#endif#ifdef MACINTOSH_OR_DOS#ifndef WINDOWS /* I'm not sure the following line is a good thing: it forces the * caller to wait until a full sysex message is received and the * 1st 4 bytes are fetched via getbuf() before a sysex message can * be read via get_excl(). Without this, both mm.c and exget.c * were fetching ahead and getting out of sync with getbuf(). I * fixed mm.c and exget.c to work (by checking for EOX), but I added * this line (which should never have any effect) just to make the * DOS interface behave more like the Amiga and Mac interfaces. The * drawback is that you can't fetch bytes until the EOX is seen, * because nothing goes into the getbuf() buffer until then. */ if (!sysex_pending) return 0; while (len-- && (xbufhead != xbuftail)) { *buffer = xbuff[xbufhead++]; ret++; if (*buffer == MIDI_EOX) { sysex_pending = FALSE; break; } buffer++; xbufhead &= xbufmask; }#endif#endif return ret;}/***************************************************************************** getbuf* Inputs:* boolean waitflag: TRUE if routine should wait for data* byte * p: Pointer to data destination* Result: boolean* TRUE if data was written to *p* FALSE if data not written to *p* Effect: * copies data from buffer to *p* will wait for buffer to become nonempty if waitflag is TRUE** Modified 24 May 1988 for AMIGA (JCD)****************************************************************************/#ifdef UNIX_IRIX_MIDIFNS private void setup_sysex(MDevent *event, u_char *buffer);#endif /* UNIX_IRIX */boolean getbuf(boolean waitflag, unsigned char * p){#ifdef UNIX_IRIX_MIDIFNS MDevent event; int ret;#endif /* UNIX_IRIX */ if (!initialized) fixup();#ifdef UNIX#ifdef UNIX_IRIX_MIDIFNS/* current IRIX version ignores the waitflag (it never waits) */ if (sysex_p) flush_sysex(); if (ignore_realtime == 0) { ret = mdReceive(miport, &event, 1); if (ret) { if (event.msg[0] != 0xF0) { *((u_long*) p) = *((u_long*) event.msg); } else { setup_sysex(&event, p); } } return ret; } else { do /* skip realtime messages */ { ret = mdReceive(miport, &event, 1); if (ret == -1) return ret; } while (event.msg[0] == 0xf8); if (event.msg[0] != 0xF0) { *((u_long*) p) = *((u_long*) event.msg); } else { setup_sysex(&event, p); } return ret; }#endif /* UNIX_IRIX */#ifdef UNIX_ITC if (ignore_realtime == 0) { return(mi_get(midiconn, waitflag, (char *) p)); } else { boolean ret=false; /* filter out realtime msgs */ do { ret = mi_get(midiconn, waitflag, (char *) p); if (ret == FALSE) return(ret); } while(p[0] == 0xf8); return(ret); }#else /* UNIX_ITC */#ifndef UNIX_IRIX if (waitflag) { gprintf(ERROR, "getbuf called with waitflag!"); EXIT(1); } return FALSE;#endif /* UNIX_IRIX */#endif /* UNIX_ITC */#endif /* UNIX */#ifdef MACINTOSH_OR_DOS#ifndef WINDOWS if (sysex_pending) { /* flush sysex to keep buffers in sync */ while (xbuff[xbufhead++] != MIDI_EOX) { xbufhead &= xbufmask; if (xbufhead == xbuftail) break; } sysex_pending = FALSE; } if (waitflag) while (buffhead == bufftail) /* wait */ ; else if (buffhead == bufftail) return(false); *(long *)p = *(long *)(((char *)buff)+buffhead); buffhead = (buffhead + 4) & BUFF_MASK; if (*p == MIDI_SYSEX) { /* if sys-ex, remember to fetch from xbuff */ sysex_pending = TRUE; } return(true);#else return FALSE;#endif /* WINDOWS */#endif /* MACINTOSH_OR_DOS */#ifdef AMIGA if (waitflag) { do { WaitMidi(cmt_mi, &cmt_msg); AMIGA_ERROR_CHECK; } while (amigaerrflags); } else { AMIGA_ERROR_CHECK; if (!GetMidi(cmt_mi, &cmt_msg)) return(false); } *(long *)p = *(long *)&cmt_msg; clearmsg(cmt_msg); return(true);#endif /* AMIGA */}#ifdef UNIX_IRIX_MIDIFNSprivate void setup_sysex(MDevent *event, u_char *buffer)/* N.B. do not leak memory remember to call free(sysex_p) */{ u_char *sxp = (u_char *) event->sysexmsg; int i; for (i=0;i<4;i++) *(buffer++) = *(sxp++); sysex_p = event->sysexmsg; sysex_n = event->msglen;}private void flush_sysex(){ mdFree(sysex_p); sysex_p = 0; sysex_n = 0;}#endif#ifdef MACINTOSH_OR_DOS#ifndef WINDOWSpublic boolean check_midi(){ if (buffhead == bufftail) return FALSE; else return TRUE;}#endif#endif/***************************************************************************** getkey* Inputs:* boolean waitflag: TRUE if wait until key depression, FALSE if* return immediately* Result: int* key number of key which has been depressed* It returns -1 if waitflag is FALSE and no key has been pressed* If waitflag is TRUE this routine will block until a key is pressed* Effect: * reads a key****************************************************************************//*DMH: in previous version, macmidi.c subtracted 12 from msg to get key at each occurence...*/short getkey(boolean waitflag){ byte msg[4]; short k; if (!initialized) fixup(); while (TRUE) { /* process data until you find a note */ /* look for data and exit if none found */ /* NOTE: waitflag will force waiting until data arrives */ if (!getbuf(waitflag, msg)) { /* nothing there */ k = -1; break; } else if ((msg[0] & MIDI_CODE_MASK) == MIDI_ON_NOTE) { if (msg[2] == 0) { /* velocity 0 -> note off */ keyloud = 0; k = msg[1] + 128; } else { keyloud = msg[2]; k = msg[1]; } break; } else if ((msg[0] & MIDI_CODE_MASK) == MIDI_OFF_NOTE) { keyloud = 0; k = msg[1] + 128; break; } } if (musictrace) { if (k != -1) gprintf(TRANS,"getkey got %d\n", k); } return k;}/***************************************************************************** gettime* Result: ulong* current timestamp since the last call to* musicinit or timereset* Effect: * fakes it****************************************************************************/ulong gettime() /*DMH: ulong is from mpu->midifns conversion, for Mac*/{#if HAS_GETTIMEOFDAY struct timeval timeval;#endif#if HAS_FTIME struct timeb ftime_res;#endif register ulong ticks = 0L; BREAKTEST /* abort if user typed Ctrl Break */ if (!initialized) fixup();#ifdef MACINTOSH#ifdef MIDIMGR ticks = MIDIGetCurTime(OutputRefNum) - ticksAtStart;#else ticks = TickCount() - ticksAtStart;#endif if (initialized) abort_check(); /* give user a chance to abort */ ticks = TICKS_TO_MS(ticks);#endif#ifdef AMIGA ticks = (*camdtime - timeoffset) << 1; /* return milliseconds */#endif#ifdef DOS#ifndef WINDOWS ticks = elapsedtime(timeoffset, readtimer()); /* return milliseconds */ /* gprintf(TRANS, "currtime = %ld, timeoffset = %ld\n", currtime, timeoffset); */#endif#endif /* ifdef DOS */#if HAS_GETTIMEOFDAY gettimeofday(&timeval, 0); ticks = timeval.tv_sec * 1000 + timeval.tv_usec / 1000 - timeoffset;#endif#if HAS_FTIME ftime(&ftime_res); ticks = ((ftime_res.time - timeoffset) * 1000) + ftime_res.millitm;#endif /* if (miditrace) gprintf(TRANS, "."); */ return(ticks);}/***************************************************************************** l_rest* Inputs:* long time: Amount of time to rest* Effect: * Waits until the amount of time specified has lapsed****************************************************************************/void l_rest(time)long time;{ if (!initialized) fixup(); l_restuntil(time + gettime()); }/***************************************************************************** l_restuntil* Inputs:* long time: Event time to rest until* Effect: * Waits until the specified time has been reached (absolute time)****************************************************************************/void l_restuntil(time)long time;{#ifdef MACINTOSH ulong now = gettime(); ulong junk; /* changed from ulong for ThinkC 7, back to ulong for CW5 */#endif#ifdef AMIGA while (time > gettime()) eventwait(time);#else for(; (time_type) time > gettime(););#endif#ifdef MACINTOSH now = gettime(); if (time > now) Delay(MS_TO_TICKS(time - now), &junk); /* else time <= now, so return immediately */#endif}/***************************************************************************** metronome* Inputs:* boolean onflag: TRUE or FALSE* Effect:* enables (true) or disables (false) MPU-401 metronome function.* must be called before musicinit****************************************************************************/void metronome(boolean onflag){#ifdef DOSmetroflag = onflag;#endif}/***************************************************************************** midi_bend* Inputs:* int channel: midi channel on which to send data* int value: pitch bend value* Effect: * Sends a midi pitch bend message****************************************************************************/void midi_bend(int channel, int value){ if (!initialized) fixup(); if (musictrace) gprintf(TRANS,"midi_bend: ch %d, val %d\n", channel, value - (1 << 13)); bend[MIDI_CHANNEL(channel)] = value; midi_write(3, MIDI_PORT(channel), (byte) (MIDI_BEND | MIDI_CHANNEL(channel)), (byte) MIDI_DATA(value), (byte) MIDI_DATA(value >> 7));}/***************************************************************************** midi_buffer* Inputs:* byte * buffer: the buffer address* int size: number of bytes in buffer* Returns:* FALSE if size is less than 16 or buffer is NULL, otherwise TRUE* Effect: DOS, MAC:* tells interrupt routine to store system exclusive messages in
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -