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.
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.
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
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.
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?
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?
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?
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.
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?
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)
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.
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.
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?
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.