Forum: PC-Programmierung MIDI-Format zeitlicher Ablauf


von Sam .. (sam1994)


Lesenswert?

Hi

Ich schreibe gerade einen Midiconverter für meinen Selbstbausynthesizer, 
allerdings verstehe ich nicht wie Midi die Zeit bestimmt, wann einen 
Note angeht und wann aus. Ich orientiere mich an diesem Beispiel: 
http://jakob-werner.de/Midi/Dateiaufbau.htm

Es gibt folgende Befehle die damit etwas zutun haben könnten:


FF 51 03 tt tt tt   Tempowechsel   Tempo = 60.000.000/ tt tt tt
Nur weiß ich hier nicht was diese neue Zahl genau bestimmmt, eine 
Erklärung ist auf der Seite auch nicht beschrieben.

FF 58 04 aa bb cc dd   Time Signature   aa = Numerator

bb = Denominator

Demonitator: 2=4 3=8 usw.

z.B. 4/4 = 04 02

cc = Anzahl der Midiclocks

zum Metronom

dd = Anzahl von 32’st Noten in
einer ¼ Note

Alles verständlich, aber was ist ein Midiclock?


In einer Mididatei stehen die Befehle nacheinandert. Wenn es nun eine 
Zeiteinheit gäbe, welche sagt, dass alle x ms der nächste Befehl 
eingelesen wird, müsste es haufenweise nop Befehle geben.

Ich hab keine Ahnung wie die Mididatei am Ende zeitlich korrekt 
gesteuert abgespielt werden soll. Vielleicht kann mir einer auf die 
Sprünge helfen oder es gibt eine Ausführlichere Seit.

von Karl H. (kbuchegg)


Lesenswert?

Da du die Software für einen Synthesizer schreibst, interessiert dich 
doch das alles nicht.
Du musst die Protokolldefinition implementieren und nicht das 
Dateiformat!

Dein Synthesizer kriegt:

  Note ein

  Note aus

bei "Note ein" fängt er zu dudeln an, bei "Note aus" hört er damit auf. 
Timing und Takt sind nicht dein Problem sondern ein Problem des 
ansteuernden Programms auf der anderen Seite der Leitung.

von Karl H. (kbuchegg)


Lesenswert?

Samuel K. schrieb:

> Es gibt folgende Befehle die damit etwas zutun haben könnten:
>
>
> FF 51 03 tt tt tt   Tempowechsel   Tempo = 60.000.000/ tt tt tt
> Nur weiß ich hier nicht was diese neue Zahl genau bestimmmt, eine
> Erklärung ist auf der Seite auch nicht beschrieben.

Hmm.
AUf genau der von dir angegebenen Seite findet sich

FF 5103 07A1 2000 = Tempowechsel (siehe Tabelle 6:)
FF 5103 = Message für Tempowechsel
07A1 20 = neues Tempo
Berechnung: 07A120= 500.000
60.000.000 / 500.000 = 120 Schläge pro Minute für 1/4 Note

von Karl H. (kbuchegg)


Lesenswert?

Samuel K. schrieb:

>
> FF 58 04 aa bb cc dd   Time Signature   aa = Numerator
>
> bb = Denominator
>
> Demonitator: 2=4 3=8 usw.
>
> z.B. 4/4 = 04 02
>
> cc = Anzahl der Midiclocks
>
> zum Metronom
>
> dd = Anzahl von 32’st Noten in
> einer ¼ Note
>
> Alles verständlich, aber was ist ein Midiclock?

Wieder auf der von dir verlinkten Seite

FF58 0404 0218 0800 = Time Signature (siehe Tabelle6:)
FF58 04 = Message für Key Signature
04 02 = 4/4 Takt (zweites Byte: 01=2 02=4 03=8 usw.)
18 = 24 Midizyclen pro Metronomschlag
08 = Anzahl der 32stel Noten in einer Viertelnote


Eine Midiclock ist also eine Unterteilung eines Metronomschlages in eine 
feinere Einheit. Midi bestimmt ja nicht, wie schnell du dein Metronom 
einstellst, das machst du schon selber. Aber MIDI möchte etwas feiner 
als nur auf ganze Metronomschläge synchronisieren können.

von Sam .. (sam1994)


Lesenswert?

Danke für deine Antworten!

Karl Heinz Buchegger schrieb:
> Da du die Software für einen Synthesizer schreibst, interessiert dich
> doch das alles nicht.
> Du musst die Protokolldefinition implementieren und nicht das
> Dateiformat!
>
> Dein Synthesizer kriegt:
>
>   Note ein
>
>   Note aus

Das Problem ist, es ist ein Selbstbausynthesizer mit µC: 
Beitrag "AVR Synthesizer Konzept"

Der bekommt bisher folgendes Format:

Befehl Daten
Z.B: Ton, nr. 45, 100 (dauer in Samplerate / 256)

Das selbst per .db einzutragen ist wirklich ätzend. Deswegen möchte ich 
den Konverter dafür programmieren. MIDI gibts zum glück zu Haufen im 
Netz.


Gut in der Midi wird definiert wie schnell die 4tel sind. Aber der Ton 
an Befehl enthält nicht die Tonlänge. In der Datei steht etwas von:

Ton X an ... Ton X aus.

Diese Befehle können direkt hintereinander stehen. Woher weiß man wann 
der Ton X aus sein soll?

von Karl H. (kbuchegg)


Lesenswert?

Samuel K. schrieb:

> Gut in der Midi wird definiert wie schnell die 4tel sind. Aber der Ton
> an Befehl enthält nicht die Tonlänge.

Laut den Protokolldefinitionen die ich im Web gefunden habe, steht im 
Note On Befehl sehr wohl die Länge des Tones drinnen.



Aber ich denke, ich habe noch nicht verstanden, auf welcher Seite vom 
Midi du programmierst


           PC
   +-------------------+
   |  Midi- Reader     |
   |                   |       Übertragung     +-----------------+
   |             o---------------------------->| Synthesizer     |
   |                   |                       |                 |
   |                   |                       |                 |
   +------^------------+                       +-----------------+
          |
          |
        File


Ich bin bisher davon ausgegangen, dass du im rechten Block zu Hause 
bist, also beim Synthi selber. Der hat aber mit dem Timing an sich gar 
nichts mehr zu tun. Das Timing wird doch schon komplett vom Midi-Reader 
am PC erledigt, der das File liest, es aufbereitet und den Synthi 
mittels Note-On bzw. Note-Off Befehlen ansteuert. Das muss auch so sein, 
weil ja an diesem zentralen Bauteil durchaus mehrere Midi-Geräte hängen 
könnten, die alle eine gemeinsame Vorstellung vom Timing haben müssen. 
Am einfachsten erreicht man das, indem eben diese zentrale Stelle 
bereits sich um das Timing kümmert und die Satelliten nur noch 
Befehlsausführer sind.

Derartige Midi-Reader gibt es wie Sand am Meer, so dass es Sinn macht 
die Midi File Interpretation auch dort zu lassen und am Synthi eine 
entsprechende Schnittstelle zu implementieren. Die hat es aber viel 
einfacher, weil sie sich ums Timing nicht mehr kümmern muss. Sie bekommt 
ja nur noch ein/aus Kommandos für die Noten. Das erkennt man zb am PC 
ganz leicht daran, dass zb ein Software-Sythesizer weiterhin seine 
letzten Töne vor sich hinpfeift, wenn man den Reader einfach abwürgt: er 
hat nie die Note-Off Befehle erhalten und hält daher den letzten Ton auf 
Biegen und Brechen.

Du musst unterscheiden zwischen dem Format, das in Midi Files vorliegt 
(die der Reader einliest) und dem was dann tatsächlich zum Sysnthesizer 
geschickt wird. Das ist nicht dasselbe.

Oder liege ich da jetzt komplett falsch?

von Sam .. (sam1994)


Lesenswert?

Vielen dank, das hat mir sehr geholfen. Ich habe nicht unterschieden zw. 
MIDI-Format(PC) und midi Protokoll zum Synthesizer.
Das hat mich die ganze Zeit verwirrt.

Nur eine Frage habe ich noch. Die Dauer der Note wird von 0-255 
angegeben (00-FF), Sind das Midizyklen? Welche Einheit ist das?

von Karl H. (kbuchegg)


Lesenswert?

Mein Fehler.
Im Note-On ist keine Länge enthalten, wie du richtig gesagt hast.

Dort ist die Velocity enthalten, also wie schnell die 'Taste' 
angeschlagen wurde.



Im File-Format ist das die Einheit, die sich hierauf bezieht
1
0001 0002 00C0 = Datenbytes des MThd Tracks
2
0001 = Midiformat 0
3
   0000 = Eine Spur beinhaltet alle 16 Kanäle
4
   0001 = Mehrere Spuren können alle 16 Kanäle beinhalten
5
   0002 = Mehrere Spuren können unterschiedliche Kanäle beinhalten
6
0002 = Es folgen 2 MTrk Tracks
7
00C0 = Die Basisgeschwindigkeit einer Viertelnote = 192
der letzte Eintrag legt fest, welche Zahl einer Viertelnote entspricht. 
Wenn also bei der Note im File eine Länge von 81 steht, dann handelt es 
sich um eine 1/8 Note. Wie lang das tatsächlich ist, hängt jetzt wieder 
von anderen Faktoren ab, unter anderem auch davon, ob der Benutzer an 
dieser Einstellung gedreht hat (und sich zb für Übungszwecke das 
Metronom auf langsamer gestellt hat)

Aber wieder zurück zum Midi-Protokoll:

Achte zb auch darauf, dass dein Synthi den sog "Running Status" 
unterstützt. Bei dem wird implizit das letzte Kommando (oder nur bei 
Note On?) wiederholt, wenn man Datenbytes ohne vorhergehendes Kommando 
erhält. Aus genau diesem Grund gilt zb ein "Note On" mit einer Velocity 
von 0 als "Note Off" damit man nicht zwischendurch ein anderes Kommando 
braucht um eine Note wieder abzuschalten etc, etc.

Für dich interessant ist wie gesagt nicht das File-Format, sondern alles 
was zb hier
http://www.gweep.net/~prefect/eng/reference/protocol/midispec.html
beschrieben ist. Das sind die Bytes, so wie du sie vom Reader 
(Sequenzer) bekommst.




Beim googlen darauf achten wonach du googelst.

"Midi Format" bezieht sich meistens auf das File-Format. Das ist aber 
nicht das was dich interessiert.
"Midi Protokoll" bezieht sich meistens auf den Transfer zum Synthi. Das 
ist das was du brauchst. Dort kreist das meiste um "Note On" und "Note 
Off" und natürlich um diverse Channel und sonstige Kommandos.

Und immer auch daran denken, dass über Midi nicht nur Klangerzeugung 
gestuert wird, sondern auch Sequenzer. Nicht alle Kommandos sind daher 
für einen Synthesizer sinnvoll.

von Sam .. (sam1994)


Lesenswert?

Später wird mich das Protokoll wahrscheinlich schon interessieren. Aber 
jetzt möchte ich erstmal den Synthesizer mit einem eigenen Dateiformat 
testen. Deswegen brauch ich erstmal das Dateiformat.

9045 6E81 20 Spiele Note A in der 5 Oktave
(siehe Tabelle 4:)
9 = Note ein 0=Kanal 1
45 = Note A in der 5 Oktave
6E = Anschlagstärke
81 = Dauer der Note

90 4500 20 = Schalte Note 45 aus
9 = Note ein 0=Kanal 1
45 = Note A in der 5 Oktave
00 = Anschlagdynamik (Lautstärke 0)
Erklärung: Schalte Note mit
Lautstärke 0 ein hat die gleiche
Bedeutung wie Note off.

Warum wird hier Note aus extra noch einmal geschrieben? Die Dauer ist 
doch schon in der ersten verankert. Dem Synthesizer wird das gesendet, 
aber in der Mididatei hat das doch nichts zu suchen?

von Karl H. (kbuchegg)


Lesenswert?

Samuel K. schrieb:
> Später wird mich das Protokoll wahrscheinlich schon interessieren. Aber
> jetzt möchte ich erstmal den Synthesizer mit einem eigenen Dateiformat
> testen. Deswegen brauch ich erstmal das Dateiformat.

Mir ist ehrlich nicht ganz klar, wozu das gut sein soll.
Midi Player gibt es für den PC wie Sand am Meer. Dem gibst du ein File 
und der streamt dir am seriellen Port die Midi Daten zeitlich richtig 
raus.
Aufwand: 0 (abgesehen von ein bischen googeln, download und 
ausprobieren)

Und ob du jetzt dein eigenes Protokoll implementierst, oder Midi 
Note-On/Note-Off interpretierst ... da ist letzteres wahrscheinlich 
sogar weniger Aufwand (den Rest kann man ja erst mal ignorieren)

von Karl H. (kbuchegg)


Lesenswert?

Ich muss mich entschuldigen. Ich hab dich scheinbar in eine falsche 
Richtung gelockt.

Als ich das letzte mal mit Midi was gemacht habe, war die Sache noch 
einfach. Ist aber auch schon lange her.

Scheinbar ist es unter Windows gar nicht mehr so einfach, dem Windows 
eine serielle Schnittstelle als Midi-Port unterzujubeln. Zumindest 
konnte ich jetzt inh 15 Minuten nichts dergleichen ergoogeln.

von Sam .. (sam1994)


Lesenswert?

Du brauchst dich nicht entschuldigen, ich bin dir dankbar dass ich es 
jetzt verstanden habe.

Wir reden aber immernoch aneinander vorbei:

Ich programmiere geraed einen Atmega88, dieser z.b. diesen Befehl an:
1
;Spuranfänge
2
.dw 0, 4, 7, 7
3
SMIDI:
4
.db TONE, C4, 255, END, TONE, G4, 255, END
D.h. Ton C4 an, 255 Zyklen, dann ist die Spur zu Ende.

Nun möchte ich einen Konverter schreiben, der die Mididatei in dieses 
(noch) einfache Format konvertiert.


Übrigens: Wer noch einen alten PC mit 15pol D-Sub anschluss hat, kann 
unter Sound in der Systemsteuerung einstellen, das Midi darüber 
ausgegeben wird. Neuere Keyboard machen das über usb.

von Sam .. (sam1994)


Lesenswert?

Ich muss den Thread doch noch mal ausgraben...

Der Konverter gräbt sich schon durch die ersten Midifiles durch, jedoch 
ist mir die Länge der Note nicht ganz klar. Sie wird zwar angegeben, bei 
der Testmididatei (http://jakob-werner.de/Midi/Dateiaufbau.htm) ist das 
129, allerdings sind es nur 120 Schläge pro Minuten.

Warum sind es nicht genau 1/4 Noten? Das passt doch gar nicht.


2. Bei Vielen Befehlen ist ein 0x00 drangehängt. Bei den Noten sogar z.T 
0x20. Welchen Sinn hat das?

von Sam .. (sam1994)


Lesenswert?

Die Testmididatei hat der Konverter wunderbar geschluckt. Doch alles 
andere bringt Fehlermeldungen:

Hier mal die Ausgabe
1
Länge des Headers: 6
2
Format: 1
3
MTrkTracks: 2
4
Basisgeschwindigkeit einer Viertelnote: 1024
5
Tracklänge: 285
6
Cmd: FF58
7
2/4, 24, 8
8
Cmd: FF59
9
Cmd: FF51
10
Tempo: 120
11
Cmd: E000
12
Cmd: FF58
13
1/2, 48, 8
14
Cmd: A000
15
Cmd: FF58
16
1/4, 24, 8
17
Cmd: 9000
18
New Tone: 0 | dur/dyn: 88 / 255
19
9000 58 4
20
Cmd: 202
21
Unknow Command: 202| Data: 18

Ich fang mal bei Cmd: A000 an:
Bei diesem lese ich das Nachfolgende Datenbyte nicht, da er sonst den 
Befehl 0x5804 nicht kennt.

Nach New Tone: 0 | dur/dyn: 88 / 255 kommt der erste Fehler.
Die Hexdaten 9000 FF 58 04 deuten auf eine Pause hin (Ton aus obwohl 
keiner an ist?), danach kommt aber 020218 was kein bekannter Befehl ist.

Ich würde es so zerlegen, verstehe aber nicht warum:
1
9000       Befehl 90 Ton aus. Warum aber nur ein Byte Daten?
2
FF58       Hier fängt der nächste Befehl an (Time Signature)
3
04         Länge 4
4
01 0130 08 Daten
5
81         Ton an, Kanal 1
6
F000       Note F0, Dynamik 00 also Ton aus
7
FF58 0401...

Das Format kann einen echt zum verzweifeln bringen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.