summaryrefslogtreecommitdiff
path: root/attic/muse_qt4_evolution/muse/midi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'attic/muse_qt4_evolution/muse/midi.cpp')
-rw-r--r--attic/muse_qt4_evolution/muse/midi.cpp633
1 files changed, 0 insertions, 633 deletions
diff --git a/attic/muse_qt4_evolution/muse/midi.cpp b/attic/muse_qt4_evolution/muse/midi.cpp
deleted file mode 100644
index a182fe4a..00000000
--- a/attic/muse_qt4_evolution/muse/midi.cpp
+++ /dev/null
@@ -1,633 +0,0 @@
-//=============================================================================
-// MusE
-// Linux Music Editor
-// $Id:$
-//
-// Copyright (C) 2002-2006 by Werner Schweer and others
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// 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.
-//=============================================================================
-
-#include "song.h"
-#include "midi.h"
-#include "midiedit/drummap.h"
-#include "event.h"
-#include "globals.h"
-#include "midictrl.h"
-#include "midictrl.h"
-#include "audio.h"
-#include "audiodev.h"
-#include "wave.h"
-#include "synth.h"
-#include "sync.h"
-#include "gconfig.h"
-#include "ticksynth.h"
-#include "al/tempo.h"
-#include "al/sig.h"
-#include "part.h"
-#include "midiplugin.h"
-#include "midiinport.h"
-#include "midioutport.h"
-#include "instruments/minstrument.h"
-
-extern void dump(const unsigned char* p, int n);
-
-unsigned const char gmOnMsg[] = {
- 0x7e, // Non-Real Time header
- 0x7f, // ID of target device (7f = all devices)
- 0x09,
- 0x01
- };
-unsigned const char gsOnMsg[] = {
- 0x41, // roland id
- 0x10, // Id of target device (default = 10h for roland)
- 0x42, // model id (42h = gs devices)
- 0x12, // command id (12h = data set)
- 0x40, // address & value
- 0x00,
- 0x7f,
- 0x00,
- 0x41 // checksum?
- };
-unsigned const char xgOnMsg[] = {
- 0x43, // yamaha id
- 0x10, // device number (0)
- 0x4c, // model id
- 0x00, // address (high, mid, low)
- 0x00,
- 0x7e,
- 0x00 // data
- };
-unsigned const int gmOnMsgLen = sizeof(gmOnMsg);
-unsigned const int gsOnMsgLen = sizeof(gsOnMsg);
-unsigned const int xgOnMsgLen = sizeof(xgOnMsg);
-
-/*---------------------------------------------------------
- * midi_meta_name
- *---------------------------------------------------------*/
-
-QString midiMetaName(int meta)
- {
- const char* s = "";
- switch (meta) {
- case 0: s = "Sequence Number"; break;
- case 1: s = "Text Event"; break;
- case 2: s = "Copyright"; break;
- case 3: s = "Sequence/Track Name"; break;
- case 4: s = "Instrument Name"; break;
- case 5: s = "Lyric"; break;
- case 6: s = "Marker"; break;
- case 7: s = "Cue Point"; break;
- case 8:
- case 9:
- case 0x0a:
- case 0x0b:
- case 0x0c:
- case 0x0d:
- case 0x0e:
- case 0x0f: s = "Text"; break;
- case 0x20: s = "Channel Prefix"; break;
- case 0x21: s = "Port Change"; break;
- case 0x2f: s = "End of Track"; break;
- case 0x51: s = "Set Tempo"; break;
- case 0x54: s = "SMPTE Offset"; break;
- case 0x58: s = "Time Signature"; break;
- case 0x59: s = "Key Signature"; break;
- case 0x74: s = "Sequencer-Specific1"; break;
- case 0x7f: s = "Sequencer-Specific2"; break;
- default:
- break;
- }
- return QString(s);
- }
-
-//---------------------------------------------------------
-// QString nameSysex
-//---------------------------------------------------------
-
-QString nameSysex(unsigned int len, const unsigned char* buf)
- {
- QString s;
- switch(buf[0]) {
- case 0x00:
- if (buf[1] == 0 && buf[2] == 0x41)
- s = "Microsoft";
- break;
- case 0x01: s = "Sequential Circuits: "; break;
- case 0x02: s = "Big Briar: "; break;
- case 0x03: s = "Octave / Plateau: "; break;
- case 0x04: s = "Moog: "; break;
- case 0x05: s = "Passport Designs: "; break;
- case 0x06: s = "Lexicon: "; break;
- case 0x07: s = "Kurzweil"; break;
- case 0x08: s = "Fender"; break;
- case 0x09: s = "Gulbransen"; break;
- case 0x0a: s = "Delta Labas"; break;
- case 0x0b: s = "Sound Comp."; break;
- case 0x0c: s = "General Electro"; break;
- case 0x0d: s = "Techmar"; break;
- case 0x0e: s = "Matthews Research"; break;
- case 0x10: s = "Oberheim"; break;
- case 0x11: s = "PAIA: "; break;
- case 0x12: s = "Simmons: "; break;
- case 0x13: s = "DigiDesign"; break;
- case 0x14: s = "Fairlight: "; break;
- case 0x15: s = "JL Cooper"; break;
- case 0x16: s = "Lowery"; break;
- case 0x17: s = "Lin"; break;
- case 0x18: s = "Emu"; break;
- case 0x1b: s = "Peavy"; break;
- case 0x20: s = "Bon Tempi: "; break;
- case 0x21: s = "S.I.E.L: "; break;
- case 0x23: s = "SyntheAxe: "; break;
- case 0x24: s = "Hohner"; break;
- case 0x25: s = "Crumar"; break;
- case 0x26: s = "Solton"; break;
- case 0x27: s = "Jellinghaus Ms"; break;
- case 0x28: s = "CTS"; break;
- case 0x29: s = "PPG"; break;
- case 0x2f: s = "Elka"; break;
- case 0x36: s = "Cheetah"; break;
- case 0x3e: s = "Waldorf"; break;
- case 0x40: s = "Kawai: "; break;
- case 0x41: s = "Roland: "; break;
- case 0x42: s = "Korg: "; break;
- case 0x43: s = "Yamaha: "; break;
- case 0x44: s = "Casio"; break;
- case 0x45: s = "Akai"; break;
- case 0x7c: s = "MusE Soft Synth"; break;
- case 0x7d: s = "Educational Use"; break;
- case 0x7e: s = "Universal: Non Real Time"; break;
- case 0x7f: s = "Universal: Real Time"; break;
- default: s = "??: "; break;
- }
- //
- // following messages should not show up in event list
- // they are filtered while importing midi files
- //
- if ((len == gmOnMsgLen) && memcmp(buf, gmOnMsg, gmOnMsgLen) == 0)
- s += "GM-ON";
- else if ((len == gsOnMsgLen) && memcmp(buf, gsOnMsg, gsOnMsgLen) == 0)
- s += "GS-ON";
- else if ((len == xgOnMsgLen) && memcmp(buf, xgOnMsg, xgOnMsgLen) == 0)
- s += "XG-ON";
- return s;
- }
-
-//---------------------------------------------------------
-// buildMidiEventList
-// TODO:
-// parse data increment/decrement controller
-// NRPN/RPN fine/course data 7/14 Bit
-// must we set datah/datal to zero after change
-// of NRPN/RPN register?
-// generally: how to handle incomplete messages?
-//---------------------------------------------------------
-
-void buildMidiEventList(EventList* del, const MidiEventList* el, MidiTrack* track, int channel,
- int div, bool addSysexMeta)
- {
- QString tname;
- int hbank = 0xff;
- int lbank = 0xff;
- int rpnh = -1;
- int rpnl = -1;
- int datah = 0;
- int datal = 0;
- int dataType = 0; // 0 : disabled, 0x20000 : rpn, 0x30000 : nrpn
-
- EventList mel;
- int metaChannel = -1;
- for (iMidiEvent i = el->begin(); i != el->end(); ++i) {
- MidiEvent ev = *i;
- if (ev.type() == ME_META) {
- if (ev.dataA() == 0x20) {
- metaChannel = ((char*)(ev.data()))[0];
- }
- if (metaChannel == channel) {
- if (ev.dataA() == 0x4) {
- tname = (char*)(ev.data());
- }
- }
- }
- if (!addSysexMeta && (ev.type() == ME_SYSEX || ev.type() == ME_META))
- continue;
- if (!(ev.type() == ME_SYSEX || ev.type() == ME_META || (ev.channel() == channel)))
- continue;
- int tick = ev.time();
- Event e;
- switch(ev.type()) {
- case ME_NOTEON:
- e.setType(Note);
-
- if (track->useDrumMap()) {
- int instr = track->drumMap()->inmap(ev.dataA());
- e.setPitch(instr);
- }
- else
- e.setPitch(ev.dataA());
-
- e.setVelo(ev.dataB());
- e.setLenTick(0);
- break;
- case ME_NOTEOFF:
- e.setType(Note);
- if (track->useDrumMap()) {
- int instr = track->drumMap()->inmap(ev.dataA());
- e.setPitch(instr);
- }
- else
- e.setPitch(ev.dataA());
- e.setVelo(0);
- e.setVeloOff(ev.dataB());
- e.setLenTick(0);
- break;
- case ME_POLYAFTER:
- e.setType(PAfter);
- e.setA(ev.dataA());
- e.setB(ev.dataB());
- break;
- case ME_CONTROLLER:
- {
- int val = ev.dataB();
- switch(ev.dataA()) {
- case CTRL_HBANK:
- hbank = val;
- break;
-
- case CTRL_LBANK:
- lbank = val;
- break;
-
- case CTRL_HDATA:
- datah = val;
- // check if a CTRL_LDATA follows
- // e.g. wie have a 14 bit controller:
- {
- iMidiEvent ii = i;
- ++ii;
- bool found = false;
- for (; ii != el->end(); ++ii) {
- MidiEvent ev = *ii;
- if (ev.type() == ME_CONTROLLER) {
- if (ev.dataA() == CTRL_LDATA) {
- // handle later
- found = true;
- }
- break;
- }
- }
- if (!found) {
- if (rpnh == -1 || rpnl == -1) {
- printf("parameter number not defined, data 0x%x\n", datah);
- }
- else {
- int ctrl = dataType | (rpnh << 8) | rpnl;
- e.setType(Controller);
- e.setA(ctrl);
- e.setB(datah);
- }
- }
- }
- break;
-
- case CTRL_LDATA:
- datal = val;
-
- if (rpnh == -1 || rpnl == -1) {
- printf("parameter number not defined, data 0x%x 0x%x, tick %d, channel %d\n",
- datah, datal, tick, channel);
- break;
- }
- // assume that the sequence is always
- // CTRL_HDATA - CTRL_LDATA
- // eg. that LDATA is always send last
-
- e.setType(Controller);
- // 14 Bit RPN/NRPN
- e.setA((dataType+0x30000) | (rpnh << 8) | rpnl);
- e.setB((datah << 7) | datal);
- break;
-
- case CTRL_HNRPN:
- rpnh = val;
- dataType = 0x30000;
- break;
-
- case CTRL_LNRPN:
- rpnl = val;
- dataType = 0x30000;
- break;
-
- case CTRL_HRPN:
- rpnh = val;
- dataType = 0x20000;
- break;
-
- case CTRL_LRPN:
- rpnl = val;
- dataType = 0x20000;
- break;
-
- default:
- e.setType(Controller);
- e.setA(ev.dataA());
- e.setB(val);
- break;
- }
- }
- break;
-
- case ME_PROGRAM:
- e.setType(Controller);
- e.setA(CTRL_PROGRAM);
- e.setB((hbank << 16) | (lbank << 8) | ev.dataA());
- break;
-
- case ME_AFTERTOUCH:
- e.setType(CAfter);
- e.setA(ev.dataA());
- break;
-
- case ME_PITCHBEND:
- e.setType(Controller);
- e.setA(CTRL_PITCH);
- e.setB(ev.dataA());
- break;
-
- case ME_SYSEX:
- e.setType(Sysex);
- e.setData(ev.data(), ev.len());
- break;
-
- case ME_META:
- {
- const unsigned char* data = ev.data();
- switch (ev.dataA()) {
- case 0x01: // Text
- if (track->comment().isEmpty())
- track->setComment(QString((const char*)data));
- else
- track->setComment(track->comment() + "\n" + QString((const char*)data));
- break;
- case 0x02: // Copyright
- config.copyright = (char*)data;
- break;
- case 0x03: // Sequence-/TrackName
- tname = (char*)data;
- break;
- case 0x6: // Marker
- {
- Pos pos((tick * config.division + div/2) / div, AL::TICKS);
- song->addMarker(QString((const char*)(data)), pos);
- }
- break;
- case 0x4: // Instrument Name
- case 0x5: // Lyrics
- case 0x8: // text
- case 0x9:
- case 0xa:
- case 0x20: // channel prefix
- case 0x21: // port change
- break;
-
- case 0x0f: // Track Comment
- track->setComment(QString((char*)data));
- break;
-
- case 0x51: // Tempo
- {
- int tempo = data[2] + (data[1] << 8) + (data[0] <<16);
- int ltick = (tick * config.division + div/2) / div;
- AL::tempomap.addTempo(ltick, tempo);
- }
- break;
-
- case 0x58: // Time Signature
- {
- int timesig_z = data[0];
- int n = data[1];
- int timesig_n = 1;
- for (int i = 0; i < n; i++)
- timesig_n *= 2;
- int ltick = (tick * config.division + div/2) / div;
- AL::sigmap.add(ltick, AL::TimeSignature(timesig_z, timesig_n));
- }
- break;
-
- case 0x59: // Key Signature
- printf("Meta: Key Signature %d %d\n", data[0], data[1]);
- // track->scale.set(data[0]);
- // track->scale.setMajorMinor(data[1]);
- break;
-
- case 0x7f: // Sequencer Specific
- printf("Meta: Seq specific:len %d\n", ev.len());
- break;
-
- default:
- printf("unknown Meta 0x%x %d\n", ev.dataA(), ev.dataA());
- }
- }
- break;
- } // switch(ev.type()
- if (!e.empty()) {
- e.setTick(tick);
- mel.add(e);
- }
- } // i != el->end()
-
- //---------------------------------------------------
- // resolve NoteOff events
- //---------------------------------------------------
-
- for (iEvent i = mel.begin(); i != mel.end(); ++i) {
- Event ev = i->second;
- if (!ev.isNote())
- continue;
- if (ev.lenTick())
- continue;
-// printf("%d note %d %d\n", ev.tick(), ev.pitch(), ev.velo());
- if (ev.isNoteOff()) {
- bool found = false;
- iEvent k = i;
-// printf(" start with note off\n");
- for (++k; k != mel.end(); ++k) {
- Event event = k->second;
- if (event.tick() > ev.tick())
- break;
- if (event.isNote() && event.velo() && event.pitch() == ev.pitch()) {
- ev.setLenTick(1);
- ev.setVelo(event.velo());
- ev.setVeloOff(0);
- found = true;
-// printf(" found on: %d\n", event.tick());
- break;
- }
- }
- if (!found) {
- // maybe found note with velocity zero is really a
- // note-on !
- k = i;
- found = true;
- for (++k; k != mel.end(); ++k) {
- Event event = k->second;
- if (!event.isNote())
- continue;
- if (event.pitch() == ev.pitch()) {
- if (event.velo() == 0) {
- found = true;
- int t = event.tick() - ev.tick();
- ev.setLenTick(t);
- ev.setVelo(1);
- ev.setVeloOff(0);
- mel.erase(k);
- i = mel.begin();
- }
- break;
- }
- }
- if (!found) {
- printf("NOTE OFF without Note ON tick %d type %d %d %d\n",
- ev.tick(), ev.type(), ev.pitch(), ev.velo());
- }
- else
- continue;
- }
- else {
- mel.erase(k);
- i = mel.begin(); // DEBUG
- continue;
- }
- }
- iEvent k;
- // ev is noteOn
- for (k = mel.lower_bound(ev.tick()); k != mel.end(); ++k) {
- Event event = k->second;
-// printf(" - %d(%d,%d)\n", event.tick(), event.pitch(), event.velo());
- if (ev.isNoteOff(event)) {
- int t = k->first - i->first;
- if (t <= 0) {
- if (debugMsg) {
- printf("Note len is (%d-%d)=%d, set to 1\n",
- k->first, i->first, k->first - i->first);
- ev.dump();
- event.dump();
- }
- t = 1;
- }
- ev.setLenTick(t);
- ev.setVeloOff(event.veloOff());
- break;
- }
- }
- if (k == mel.end()) {
- printf(" -no note-off! %d pitch %d velo %d\n",
- ev.tick(), ev.pitch(), ev.velo());
- //
- // switch off at end of measure
- //
- int endTick = song->roundUpBar(ev.tick()+1);
- ev.setLenTick(endTick-ev.tick());
- }
- else {
- mel.erase(k);
- i = mel.begin();
- }
- }
-
- for (iEvent i = mel.begin(); i != mel.end(); ++i) {
- Event ev = i->second;
- if (ev.isNoteOff()) {
- printf("+extra note-off! %d pitch %d velo %d\n",
- i->first, ev.pitch(), ev.velo());
-// ev.dump();
- continue;
- }
- int tick = (ev.tick() * config.division + div/2) / div;
- if (ev.isNote()) {
- int lenTick = (ev.lenTick() * config.division + div/2) / div;
- ev.setLenTick(lenTick);
- }
- ev.setTick(tick);
- if (ev.type() == Controller) {
- int id = ev.dataA();
- CVal val;
- val.i = ev.dataB();
-
-// bool found = false;
- Ctrl* c = track->getController(id);
- if (c)
- c->add(tick, val);
- else
- // if no managed controller, store as event
- del->add(ev);
- }
- else
- del->add(ev);
- }
- if (!tname.isEmpty())
- track->setName(tname);
- }
-
-//---------------------------------------------------------
-// initMidiDevices
-//---------------------------------------------------------
-
-void Audio::initMidiDevices()
- {
- //
- // test for explicit instrument initialization
- //
- MidiOutPortList* mpl = song->midiOutPorts();
- for (iMidiOutPort i = mpl->begin(); i != mpl->end(); ++i) {
- MidiOutPort* mp = *i;
- MidiInstrument* instr = mp->instrument();
- if (!instr)
- continue; // TODO: use default instrument?
- EventList* events = instr->midiInit();
- for (iEvent ie = events->begin(); ie != events->end(); ++ie) {
- MidiEvent ev(0, 0, ie->second);
- mp->playMidiEvent(&ev);
- }
- }
- }
-
-//---------------------------------------------------------
-// resetMidiDevices
-//---------------------------------------------------------
-
-void Audio::resetMidiDevices()
- {
- MidiTrackList* mcl = song->midis();
- for (iMidiTrack i = mcl->begin(); i != mcl->end(); ++i) {
- MidiTrack* mc = *i;
- if (!mc->mute() && mc->autoRead()) {
- CtrlList* cl = mc->controller();
- for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) {
- ic->second->setCurVal(CTRL_VAL_UNKNOWN);
- }
- }
- }
- MidiOutPortList* mpl = song->midiOutPorts();
- for (iMidiOutPort i = mpl->begin(); i != mpl->end(); ++i) {
- MidiOutPort* mp = *i;
- if (!mp->mute() && mp->autoRead()) {
- CtrlList* cl = mp->controller();
- for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) {
- ic->second->setCurVal(CTRL_VAL_UNKNOWN);
- }
- }
- }
- }
-