summaryrefslogtreecommitdiff
path: root/attic/muse2-oom/muse2/muse/midifile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'attic/muse2-oom/muse2/muse/midifile.cpp')
-rw-r--r--attic/muse2-oom/muse2/muse/midifile.cpp678
1 files changed, 0 insertions, 678 deletions
diff --git a/attic/muse2-oom/muse2/muse/midifile.cpp b/attic/muse2-oom/muse2/muse/midifile.cpp
deleted file mode 100644
index 319152d7..00000000
--- a/attic/muse2-oom/muse2/muse/midifile.cpp
+++ /dev/null
@@ -1,678 +0,0 @@
-//=========================================================
-// MusE
-// Linux Music Editor
-// $Id: midifile.cpp,v 1.17 2004/06/18 08:36:43 wschweer Exp $
-//
-// (C) Copyright 1999-2003 Werner Schweer (ws@seh.de)
-//=========================================================
-
-#include <errno.h>
-#include <values.h>
-#include <assert.h>
-
-#include "song.h"
-#include "midi.h"
-#include "midifile.h"
-#include "drummap.h"
-#include "event.h"
-#include "globals.h"
-#include "midictrl.h"
-#include "marker/marker.h"
-#include "midiport.h"
-#include "midictrl.h"
-#include "mpevent.h"
-#include "gconfig.h"
-
-const char* errString[] = {
- "no Error",
- "unexpected EOF",
- "read Error",
- "write Error",
- "bad midifile: 'MTrk' expected",
- "bad midifile: 'MThd' expected",
- "bad midi fileformat",
- };
-
-enum ERROR {
- MF_NO_ERROR,
- MF_EOF,
- MF_READ,
- MF_WRITE,
- MF_MTRK,
- MF_MTHD,
- MF_FORMAT,
- };
-
-//---------------------------------------------------------
-// error
-//---------------------------------------------------------
-
-QString MidiFile::error()
- {
- return QString(errString[_error]);
- }
-
-//---------------------------------------------------------
-// MidiFile
-//---------------------------------------------------------
-
-MidiFile::MidiFile(FILE* f)
- {
- fp = f;
- curPos = 0;
- _mtype = MT_UNKNOWN;
- _error = MF_NO_ERROR;
- _tracks = new MidiFileTrackList;
- }
-
-MidiFile::~MidiFile()
- {
- delete _tracks;
- }
-
-//---------------------------------------------------------
-// read
-// return true on error
-//---------------------------------------------------------
-
-bool MidiFile::read(void* p, size_t len)
- {
- for (;;) {
- curPos += len;
- size_t rv = fread(p, 1, len, fp);
- if (rv == len)
- return false;
- if (feof(fp)) {
- _error = MF_EOF;
- return true;
- }
- _error = MF_READ;
- return true;
- }
- return false;
- }
-
-//---------------------------------------------------------
-// write
-// return true on error
-//---------------------------------------------------------
-
-bool MidiFile::write(const void* p, size_t len)
- {
- size_t rv = fwrite(p, 1, len, fp);
- if (rv == len)
- return false;
- _error = MF_WRITE;
- return true;
- }
-
-//---------------------------------------------------------
-// writeShort
-// return true on error
-//---------------------------------------------------------
-
-bool MidiFile::writeShort(int i)
- {
- short format = BE_SHORT(i);
- return write(&format, 2);
- }
-
-//---------------------------------------------------------
-// writeLong
-// return true on error
-//---------------------------------------------------------
-
-bool MidiFile::writeLong(int i)
- {
- int format = BE_LONG(i);
- return write(&format, 4);
- }
-
-//---------------------------------------------------------
-// readShort
-//---------------------------------------------------------
-
-int MidiFile::readShort()
- {
- short format;
- read(&format, 2);
- return BE_SHORT(format);
- }
-
-//---------------------------------------------------------
-// readLong
-// writeLong
-//---------------------------------------------------------
-
-int MidiFile::readLong()
- {
- int format;
- read(&format, 4);
- return BE_LONG(format);
- }
-
-/*---------------------------------------------------------
- * skip
- * This is meant for skipping a few bytes in a
- * file or fifo.
- *---------------------------------------------------------*/
-
-bool MidiFile::skip(size_t len)
- {
- char tmp[len];
- return read(tmp, len);
- }
-
-/*---------------------------------------------------------
- * getvl
- * Read variable-length number (7 bits per byte, MSB first)
- *---------------------------------------------------------*/
-
-int MidiFile::getvl()
- {
- int l = 0;
- for (int i = 0; i < 16; i++) {
- uchar c;
- if (read(&c, 1))
- return -1;
- l += (c & 0x7f);
- if (!(c & 0x80))
- return l;
- l <<= 7;
- }
- return -1;
- }
-
-/*---------------------------------------------------------
- * putvl
- * Write variable-length number (7 bits per byte, MSB first)
- *---------------------------------------------------------*/
-
-void MidiFile::putvl(unsigned val)
- {
- unsigned long buf = val & 0x7f;
- while ((val >>= 7) > 0) {
- buf <<= 8;
- buf |= 0x80;
- buf += (val & 0x7f);
- }
- for (;;) {
- put(buf);
- if (buf & 0x80)
- buf >>= 8;
- else
- break;
- }
- }
-
-//---------------------------------------------------------
-// readTrack
-// return true on error
-//---------------------------------------------------------
-
-bool MidiFile::readTrack(MidiFileTrack* t)
- {
- MPEventList* el = &(t->events);
- char tmp[4];
- if (read(tmp, 4))
- return true;
- if (memcmp(tmp, "MTrk", 4)) {
- _error = MF_MTRK;
- return true;
- }
- int len = readLong(); // len
- int endPos = curPos + len;
- status = -1;
- sstatus = -1; // running status, not reset scanning meta or sysex
- click = 0;
-
- int port = 0;
- int channel = 0;
-
- for (;;) {
- MidiPlayEvent event;
- lastport = -1;
- lastchannel = -1;
-
- int rv = readEvent(&event, t);
- if (lastport != -1) {
- port = lastport;
- if (port >= MIDI_PORTS) {
- printf("port %d >= %d, reset to 0\n", port, MIDI_PORTS);
- port = 0;
- }
- }
- if (lastchannel != -1) {
- channel = lastchannel;
- if (channel >= MIDI_CHANNELS) {
- printf("channel %d >= %d, reset to 0\n", port, MIDI_CHANNELS);
- channel = 0;
- }
- }
- if (rv == 0)
- break;
- else if (rv == -1)
- continue;
- else if (rv == -2) // error
- return true;
-
- event.setPort(port);
- if (event.type() == ME_SYSEX || event.type() == ME_META)
- event.setChannel(channel);
- else
- channel = event.channel();
- el->add(event);
- }
- int end = curPos;
- if (end != endPos) {
- printf("MidiFile::readTrack(): TRACKLEN does not fit %d+%d != %d, %d too much\n",
- endPos-len, len, end, endPos-end);
- if (end < endPos)
- skip(endPos - end);
- }
- return false;
- }
-
-//---------------------------------------------------------
-// readEvent
-// returns:
-// 0 End of track
-// -1 Event filtered
-// -2 Error
-//---------------------------------------------------------
-
-int MidiFile::readEvent(MidiPlayEvent* event, MidiFileTrack* t)
- {
- uchar me, type, a, b;
-
- int nclick = getvl();
- if (nclick == -1) {
- printf("readEvent: error 1\n");
- return 0;
- }
- click += nclick;
- for (;;) {
- if (read(&me, 1)) {
- printf("readEvent: error 2\n");
- return 0;
- }
- if (me >= 0xf8 && me <= 0xfe)
- printf("Midi: Real Time Message 0x%02x??\n", me & 0xff);
- else
- break;
- }
-
- event->setTime(click);
- int len;
- unsigned char* buffer;
-
- if ((me & 0xf0) == 0xf0) {
- if (me == 0xf0 || me == 0xf7) {
- //
- // SYSEX
- //
- status = -1; // no running status
- len = getvl();
- if (len == -1) {
- printf("readEvent: error 3\n");
- return -2;
- }
- buffer = new unsigned char[len];
- if (read(buffer, len)) {
- printf("readEvent: error 4\n");
- delete[] buffer;
- return -2;
- }
- if (buffer[len-1] != 0xf7) {
- printf("SYSEX endet nicht mit 0xf7!\n");
- // Forstsetzung folgt?
- }
- else
- --len; // don't count 0xf7
- event->setType(ME_SYSEX);
- event->setData(buffer, len);
- if (((unsigned)len == gmOnMsgLen) && memcmp(buffer, gmOnMsg, gmOnMsgLen) == 0) {
- setMType(MT_GM);
- return -1;
- }
- if (((unsigned)len == gsOnMsgLen) && memcmp(buffer, gsOnMsg, gsOnMsgLen) == 0) {
- setMType(MT_GS);
- return -1;
- }
- if (((unsigned)len == xgOnMsgLen) && memcmp(buffer, xgOnMsg, xgOnMsgLen) == 0) {
- setMType(MT_XG);
- return -1;
- }
- if (buffer[0] == 0x41) { // Roland
- if (mtype() != MT_UNKNOWN)
- setMType(MT_GS);
- }
- else if (buffer[0] == 0x43) { // Yamaha
- if (mtype() == MT_UNKNOWN || mtype() == MT_GM)
- setMType(MT_XG);
- int type = buffer[1] & 0xf0;
- switch (type) {
- case 0x00: // bulk dump
- buffer[1] = 0;
- break;
- case 0x10:
- if (buffer[1] != 0x10) {
- buffer[1] = 0x10; // fix to Device 1
- }
- if (len == 7 && buffer[2] == 0x4c && buffer[3] == 0x08 && buffer[5] == 7) {
- // part mode
- // 0 - normal
- // 1 - DRUM
- // 2 - DRUM 1
- // 3 - DRUM 2
- // 4 - DRUM 3
- // 5 - DRUM 4
- printf("xg set part mode channel %d to %d\n", buffer[4]+1, buffer[6]);
- if (buffer[6] != 0)
- t->isDrumTrack = true;
- }
- break;
- case 0x20:
- printf("YAMAHA DUMP REQUEST\n");
- return -1;
- case 0x30:
- printf("YAMAHA PARAMETER REQUEST\n");
- return -1;
- default:
- printf("YAMAHA unknown SYSEX: data[2]=%02x\n", buffer[1]);
- return -1;
- }
- }
- return 3;
- }
- if (me == 0xff) {
- //
- // META
- //
- status = -1; // no running status
- if (read(&type, 1)) { // read type
- printf("readEvent: error 5\n");
- return -2;
- }
- len = getvl(); // read len
- if (len == -1) {
- printf("readEvent: error 6\n");
- return -2;
- }
- buffer = new unsigned char[len+1];
- if (len) {
- if (read(buffer, len)) {
- printf("readEvent: error 7\n");
- delete[] buffer;
- return -2;
- }
- }
- buffer[len] = 0;
- switch(type) {
- case 0x21: // switch port
- lastport = buffer[0];
- delete[] buffer;
- return -1;
- case 0x20: // switch channel
- lastchannel = buffer[0];
- delete[] buffer;
- return -1;
- case 0x2f: // End of Track
- delete[] buffer;
- return 0;
- default:
- event->setType(ME_META);
- event->setData(buffer, len+1);
- event->setA(type);
- return 3;
- }
- }
- else {
- printf("Midi: unknown Message 0x%02x\n", me & 0xff);
- return -1;
- }
- }
-
- if (me & 0x80) { // status byte
- status = me;
- sstatus = status;
- if (read(&a, 1)) {
- printf("readEvent: error 9\n");
- return -2;
- }
- a &= 0x7F;
- }
- else {
- if (status == -1) {
- printf("readEvent: no running status, read 0x%02x sstatus %x\n", me, sstatus);
- if (sstatus == -1)
- return -1;
- status = sstatus;
- }
- a = me;
- }
- b = 0;
- switch (status & 0xf0) {
- case ME_NOTEOFF:
- case ME_NOTEON:
- case ME_POLYAFTER:
- case ME_CONTROLLER:
- case ME_PITCHBEND:
- if (read(&b, 1)) {
- printf("readEvent: error 15\n");
- return -2;
- }
- event->setB(b & 0x80 ? 0 : b);
- break;
- case ME_PROGRAM:
- case ME_AFTERTOUCH:
- break;
- default: // f1 f2 f3 f4 f5 f6 f7 f8 f9
- printf("BAD STATUS 0x%02x, me 0x%02x\n", status, me);
- return -2;
- }
- event->setA(a & 0x7f);
- event->setType(status & 0xf0);
- event->setChannel(status & 0xf);
- if ((a & 0x80) || (b & 0x80)) {
- printf("8'tes Bit in Daten(%02x %02x): tick %d read 0x%02x status:0x%02x\n",
- a & 0xff, b & 0xff, click, me, status);
- printf("readEvent: error 16\n");
- if (b & 0x80) {
- // Try to fix: interpret as channel byte
- status = b & 0xf0;
- sstatus = status;
- return 3;
- }
- return -1;
- }
- if (event->type() == ME_PITCHBEND) {
- int val = (event->dataB() << 7) + event->dataA();
- val -= 8192;
- event->setA(val);
- }
- return 3;
- }
-
-//---------------------------------------------------------
-// writeTrack
-//---------------------------------------------------------
-
-bool MidiFile::writeTrack(const MidiFileTrack* t)
- {
- //FIXME: By T356 01/19/2010
- // If saving as a compressed file (gz or bz2),
- // the file is a pipe, and pipes can't seek !
- // This results in a corrupted midi file.
- // So exporting compressed midi has been disabled (elsewhere)
- // for now...
-
- const MPEventList* events = &(t->events);
- write("MTrk", 4);
- int lenpos = ftell(fp);
- writeLong(0); // dummy len
-
- status = -1;
- int tick = 0;
- for (iMPEvent i = events->begin(); i != events->end(); ++i) {
- int ntick = i->time();
- if (ntick < tick) {
- printf("MidiFile::writeTrack: ntick %d < tick %d\n", ntick, tick);
- ntick = tick;
- }
- putvl(((ntick - tick) * config.midiDivision + config.division/2)/config.division);
- tick = ntick;
- writeEvent(&(*i));
- }
-
- //---------------------------------------------------
- // write "End Of Track" Meta
- // write Track Len
- //
-
- putvl(0);
- put(0xff); // Meta
- put(0x2f); // EOT
- putvl(0); // len 0
- int endpos = ftell(fp);
- fseek(fp, lenpos, SEEK_SET);
- writeLong(endpos-lenpos-4); // tracklen
- fseek(fp, endpos, SEEK_SET);
- return false;
- }
-
-//---------------------------------------------------------
-// writeEvent
-//---------------------------------------------------------
-
-void MidiFile::writeEvent(const MidiPlayEvent* event)
- {
- int c = event->channel();
- int nstat = event->type();
-
- // we dont save meta data into smf type 0 files:
-
- if (config.smfFormat == 0 && nstat == ME_META)
- return;
-
- nstat |= c;
- //
- // running status; except for Sysex- and Meta Events
- //
- if (((nstat & 0xf0) != 0xf0) && (nstat != status)) {
- status = nstat;
- put(nstat);
- }
- switch (event->type()) {
- case ME_NOTEOFF:
- case ME_NOTEON:
- case ME_POLYAFTER:
- case ME_CONTROLLER:
- case ME_PITCHBEND:
- put(event->dataA());
- put(event->dataB());
- break;
- case ME_PROGRAM: // Program Change
- case ME_AFTERTOUCH: // Channel Aftertouch
- put(event->dataA());
- break;
- case ME_SYSEX:
- put(0xf0);
- putvl(event->len() + 1); // including 0xf7
- write(event->data(), event->len());
- put(0xf7);
- status = -1; // invalidate running status
- break;
- case ME_META:
- put(0xff);
- put(event->dataA());
- putvl(event->len());
- write(event->data(), event->len());
- status = -1;
- break;
- }
- }
-
-//---------------------------------------------------------
-// write
-// returns true on error
-//---------------------------------------------------------
-
-bool MidiFile::write()
- {
- write("MThd", 4);
- writeLong(6); // header len
- writeShort(config.smfFormat);
- if (config.smfFormat == 0) {
- writeShort(1);
- MidiFileTrack dst;
- for (iMidiFileTrack i = _tracks->begin(); i != _tracks->end(); ++i) {
- MPEventList* sl = &((*i)->events);
- for (iMPEvent ie = sl->begin(); ie != sl->end(); ++ie)
- dst.events.add(*ie);
- }
- writeShort(1);
- writeShort(_division);
- writeTrack(&dst);
- }
- else {
- writeShort(ntracks);
-
- writeShort(_division);
- for (ciMidiFileTrack i = _tracks->begin(); i != _tracks->end(); ++i)
- writeTrack(*i);
- }
- return (ferror(fp) != 0);
- }
-
-//---------------------------------------------------------
-// readMidi
-// returns true on error
-//---------------------------------------------------------
-
-bool MidiFile::read()
- {
- _error = MF_NO_ERROR;
- int i;
- char tmp[4];
-
- if (read(tmp, 4))
- return true;
- int len = readLong();
- if (memcmp(tmp, "MThd", 4) || len < 6) {
- _error = MF_MTHD;
- return true;
- }
- format = readShort();
- ntracks = readShort();
- _division = readShort();
-
- if (_division < 0)
- _division = (-(_division/256)) * (_division & 0xff);
- if (len > 6)
- skip(len-6); // skip excess bytes
-
- switch (format) {
- case 0:
- {
- MidiFileTrack* t = new MidiFileTrack;
- _tracks->push_back(t);
- if (readTrack(t))
- return true;
- }
- break;
- case 1:
- for (i = 0; i < ntracks; i++) {
- MidiFileTrack* t = new MidiFileTrack;
- _tracks->push_back(t);
- if (readTrack(t))
- return true;
- }
- break;
- default:
- _error = MF_FORMAT;
- return true;
- }
- return false;
- }
-