MidiShare: Das neue Midi-Betriebssystem

Ob MultiTOS, Multi-Finder, OS/2 oder Unix — alle Multitasking-Systeme haben eines gemeinsam: Für Midi-Anwendungen sind sie völlig ungeeignet. Ein Midi-Entwicklerpaket wie »MidiShare« war also längst fällig!

Midi-Programme verwenden häufig kritische Elemente wie Timer, Interrupts oder serielle Schnittstellen, die sich normalerweise nicht von mehreren Applikationen gleichzeitig nutzen lassen. Da sind auch moderne Multitasking-Betriebssysteme keine Garantie dafür, daß Midi-Programme tatsächlich in Echtzeit simultan laufen.

Mit MidiShare verfügen ST-Programmierer über ein Entwicklungspaket, das multitaskingfähige Midi-Programme ermöglicht, die auch bei zeitkritischen Situationen garantiert in Echtzeit arbeiten.

Das gesamte System basiert auf der Verarbeitung von Midi-Ereignissen (Events). Jedes eingehende Ereignis wird zusammen mit einem Datum in den Speicher geschrieben. Ein 32 Bit großes Feld definiert in einer Auflösung von Millisekunden die Ein- bzw. Ausgabezeit eines Events.

Bereits beim Eintreffen der Midi-Nachrichten ist eine normale Speicherverwaltung auf Dauer überfordert. Sie arbeitet nämlich nur mit relativ großen Blöcken effektiv. Für kleine Zellen mit einer Größe von 16 Byte, wie sie Midi-Events belegen, sind konventionelle Speicherverwaltungen nicht eingerichtet. Da benötigt allein die Anweisung zur Allocation (Zuweisen von Speicherplatz) eines neuen Blocks zwölf und mehr Bytes. Darüber hinaus hängt die Zeit, die für eine Allocation nötig ist, von unvorhersehbaren Faktoren ab. Bei einem stark fragmentierten Speicher kann dies z.B. recht lange dauern — ist der Speicher leer, geht’s relativ schnell. Kurze Reaktionszeiten kann eine traditionelle Speicherverwaltung nicht garantieren. Darüber hinaus ist eine traditionelle Speicherverwaltung nicht re-entrant, d.h. nicht beliebig im Speicher verschiebbar. Im Interrupt lassen sich deshalb weder direkt noch indirekt Routinen verwenden, die auf die Speicherverwaltung zurückgreifen.

MidiShare arbeitet mit einer eigenen dynamischen Speicherverwaltung (Dynamic Memory Allocation). Damit lassen sich — auch im Interrupt — bei extrem kurzer Reaktionszeit neue Events kreieren, ändern oder löschen.

Inter-Actors: eine neue Generation Midi-Controller.

Daneben unterstützt MidiShare ein eigenes Kommunikationssystem. Jede Midi-Applikation erhält ein FIFO-Eingangsmodul (Datenverwaltung nach dem First In/First Out-Prinzip). Das Programm kann dort jederzeit Daten auslesen und bearbeiten. Viele Midi-Programme organisieren Daten in Sequenzen, die nach einer zeitlichen Ordnung zusammengestellt werden. Für solche Fälle ist MidiShare bestens gerüstet: Die Funktion »MidiNewSeq« eröffnet beispielsweise eine neue, leere Sequenz. Mit der Prozedur »MidiAddSeq« lassen sich dort Events einfügen, die sich automatisch in eine zeitlich aufsteigende Rangfolge einordnen.

Zum Transfer von Midi-Daten genügt die Angabe eines bestimmten Datums. Organisiert wird die Datenkommunikation nach dem Alarm-Prinzip. Ein Alarm besteht aus einer Prozedur, deren Adresse an das Midi-Share-Hauptmodul übermittelt wird. Diese Prozedur kann nun in Echtzeit oder im Interrupt ausgeführt werden. Befindet sich beispielsweise eine neue Midi-Note im FIFO-Eingangs-Modul, sendet das Programm automatisch einen »MidiSetRec-Alarm«. Dabei lassen sich über 256 verschiedene Ports mit jeweils 32 Midi-Kanälen ansprechen, also insgesamt 8192 verschiedene Channels. Maximal verwaltet MidiShare 63 simultan laufende Programme.

Am ST unterstützt MidiShare bislang ausschließlich die Programmentwicklung unter Turbo-C bzw. Pure-C. MidiShare besteht aus einer Betriebssystemerweiterung — ähnlich wie Steinbergs M-ROS — sowie einem systemunabhängigen Entwicklungspaket. Das bekannteste Vorzeigeprodukt, das unter MidiShare läuft, ist Geer-des modularer Sequenzer »Startrack«. Auch C-Labs »Notator-Logic« (Mac) wurde mit MidiShare entwickelt.

Sämtliche Midi-Events sind als Datentypen vordefiniert. Die Speicherverwaltung organisiert alle Events in 16 Byte großen Zellen, wobei normalerweise eine Zelle pro Event genügt. Ausnahmen bilden die System-Exklusiven, die eine beliebige Länge haben. Zellen bestehen aus einem Kopf — dem Header —, einem 32 Bit großen Datumsfeld mit einem Zahlenbereich von 0 bis (2Ä3131—1. Das ebenfalls 32 Bit große Link-Feld ermöglicht beliebige Verbindungen zwischen den einzelnen Zellen. Vier 8-Bit-Felder speichern die Referenznummer der betreffenden Applikation, die Codenummer des Event-Typs, die Nummer des Ausgangsports sowie den Midi-Kanal. Diese sechs Standardfelder sind in jeder Event-Zelle vorhanden. Ein weiteres 32 Bit großes Infofeld beinhaltet ergänzende Daten oder — falls ein Event aus mehreren Zellen besteht — einen Zeiger auf die folgende Zelle. Midi-Events vom Type typeNote speichern im Infofeld z.B. die Notennummer, Anschlagsdynamik und Notendauer.

Anwendungsbeispiel: eine neue Methode zur Soundsteuerung.

Neue Midi-Noten lassen sich mit einer einfachen Anweisung kreieren:

Beispiel: MidiEvPtr

Als Ergebnis gibt diese Funktion einen Zeiger auf das neue Midi-Ereignis aus. Ist der Speicher voll und kann deshalb kein neues Event erzeugt werden, erhält der Zeiger den Wert NIL. Interessant ist die Behandlung von Notenlängen. Neben den üblichen Midi-Anweisungen kennt Midi-Share spezielle typeNote-Events, die — entgegen der Midi-Spezifikationen — ein Feld für die Notenlänge besitzen. Ein NoteOff-Befehl muß somit nicht explizit ausgegeben werden, das besorgt MidiShare automatisch. Dadurch lassen sich die oft schwer zu kontrollierenden Notenhänger vermeiden.

MidiEvPtr Note(long date, short pitch, 
	short vcl, lang dur, short chan, 
	short port)
{
	MidiEvPtr c;
	if (e = MidiNewEv(typeNote))
	{
		Date(e) = date,
		Pitch(e) = pitch 
		Vcl(e) = vel,
		Dur(e) = dur,
		Chan(e) = Chan;
		Port(e) = port;
	}
return e
}

Die Ausgabe von Midi-Daten erfolgt über das interne Kommunikationssystem. Jede Applikation verfügt über ein Ein- und Ausgangsmodul — auch die physikalische Midi-Schnittstelle wird dabei wie eine Anwendung behandelt.

Um bei der Ausgabe von Midi-Daten ein möglichst genaues Timing zu gewährleisten, stellt MidiShare verschiedene Typen von Send-Anweisungen zur Verfügung. Der Befehl »MidiSend-At« kopiert ein Ereignis und schreibt den Sendetermin ins Datumsfeld. Zum vereinbarten Zeitpunkt wird das Event automatisch an die Zielapplikation — das kann auch die Midi-Schnittstelle sein — verschickt. Dabei lassen sich Aktionen — bis zu mehreren Tagen im voraus — exakt bestimmen. MidiSendAt(refNum__a, e, d)

Dabei ist refNum_a die Referenznummer der sendenden Applikation, e ein Zeiger auf das MidiEvent und d das Sendedatum. Soll eine Midi-Anweisung sofort verschickt werden, verwendet man die »MidiSendlm«-Anweisung.

MidiSendIm(refNum__a, e);

Die dritte Variante »Midi-Send« wird zusammen mit dem internen Alarmsystem benutzt. Unten ein Beispiel, das jede eingehende Midi-Information eine Sekunde später wieder ausgibt (Midi-Echo).

Midi-Ereignisse werden in der Regel im Interrupt ausgeführt. Deshalb sind weder direkte noch indirekte Systemaufrufe gestattet. MidiShare umgeht diese Einschränkung mit Hilfe des internen Alarmsystems, das es Applikationen ermöglicht, zeitabhängige Prozesse selbst auszulösen.

Fazit: MidiShare verfügt über ein praxisorientiertes Entwicklerpaket. Es existieren neben der Atari-Version auch Portierungen für den Apple Macintosh. Programme, die unter MidiShare laufen, lassen sich dadurch auch recht schnell auf ein anderes System übertragen. Die großen Vorteile von MidiShare sind seine Multitasking-Features. Viele Routineaufgaben sind gelöst und der Entwickler kann sich den wesentlichen, kreativen Aufgaben widmen. Der Nachteil: MidiShare läßt sich nicht in den Programmcode integrieren und muß immer eigens im System installiert werden.

WERTUNG

MidiShare

Hersteller: TimeTech
Preis: 358 Mark
Vorteile: Multitasking, Echtzeitverarbeitung, vordefinierte Midi-Routinen, 256 Port zu 32 Channels, automatische Organisation von Midi Sequenzen

Einschränkungen:
läßt sich nicht in den Programmcode integrieren, Lizenzgebühren für kommerzielle Programme, unterstützt nur Turbo/Pure-C

Vertrieb: Geerdes midisystems, Bismarckstr 84, 1000 Berlin 1

void OncSecDelay (short refNum a)
/* ALARM-Routine*/
{
	MidiPtr	e;
	long		n;
	for (n = MidiCountEvs (refNum_a); 
	n > 0, -n;
	{
		c = MidiGetEv (refNum a);
		/* Holt ein Event aus dem FIFO-Modul*/
		Date(e) +=1000;
		/* addiert zum Datum1000 ms*/ 
		MidiSend(refNum a,c 
		/* und verschickt das Event*/
	}
}
MidiSetRevAlarm (refNum_a, OneSecDelay),
/* und Installation des ALARMS */

Manfred Neumayer
Aus: ST-Magazin 10 / 1992, Seite 48

Links

Copyright-Bestimmungen: siehe Über diese Seite