MIDI Zeit - Verständnissproblem


Orbit

Erfahrenes Mitglied
Hallo,
habe da so ein Problem aus 100 Quellen zusammenzupflücken wie die Zeiten im Midiformat angegeben werden.
Es gibt da verschiedene Begriffe von denen ich nicht weiß wie ich sie trennen soll:
ticks_per_quarter im MThd header (in den von meinem Programm erzeugten Dateien = 1024). Wenn ich das wörtlich nehme bekomme ich etwa nen viertel von meinem Tempo.
(Also wenn ich jedes Viertel mit 1024 ticks versehe).

Außerdem noch den Midiclock. Hier wird gesagt dass es pro Viertel 24 Midiclocks gibt. Wenn ich aber schon festgelegt habe dass ich 1024 ticks habe; wozu dann 24 clocks?

Die deltatimeevents verarbeite ich im Moment durch angabe der ticks. Also ich weiß ich habe 120 Viiertel pro minute, 1024 ticks pro Viertel (macht 120/60*1024 = 2048 ticks pro sekunde).

Wo ist denn da der Zusammenhang bezw. wo liegt mein Denkfehler (warum habe ich unter Angabe der Ticks ein falsches Tempo?)

Hoffe mir kann jemand helfen habe inzwischen an die 100 Seiten im Netz über dieses doofe Midiformat durchforstet und hab soweit auch die komplette Implementierung fertig muss nur noch das mit den Zeiten hinkriegen...

Grüße,
Orbit

EDIT: hier ein paar Zitate aus den Quellen:
FF 58 04 nn dd cc bb Time Signature
The time signature is expressed as four numbers. nn and dd represent the numerator and denominator of the time signature as it would be notated. The denominator is a negative power of two: 2 represents a quarter-note, 3 represents an eighth-note, etc. The cc parameter expresses the number of MIDI clocks in a metronome click. The bb parameter expresses the number of notated 32nd-notes in a MIDI quarter- note (24 MIDI Clocks). This was added because there are already multiple programs which allow the user to specify that what MIDI thinks of as a quarter-note (24 clocks) is to be notated as, or related to in terms of, something else.

Therefore, the complete event for 6/8 time, where the metronome clicks every three eighth-notes, but there are 24 clocks per quarter-note, 72 to the bar, would be (in hex):

FF 58 04 06 03 24 08

That is, 6/8 time (8 is 2 to the 3rd power, so this is 06 03), 32 MIDI clocks per dotted-quarter (24 hex!), and eight notated 32nd-notes per MIDI quarter note.
Mhh ich vermute mit den "32 MIDI clocks per dotted-quarter " sind wohl 36 gemeint....

0001 0002 00C0 = Datenbytes des MThd Tracks
0001 = Midiformat 0
0000 = Eine Spur beinhaltet alle 16 Kanäle
0001 = Mehrere Spuren können alle 16 Kanäle beinhalten
0002 = Mehrere Spuren können unterschiedliche Kanäle beinhalten
0002 = Es folgen 2 MTrk Tracks
00C0 = Die Basisgeschwindigkeit einer Viertelnote = 192

FF58 0404 0218 0800 = Time Signature
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
Wozu einerseits ticks und wozu andererseits die midiclocks/midizyklen?

So und hier nochmal ein Ausschnitt einer Midifiole der mein Probnlem verständlich machen sollte:
8813 (hex) ist mein delay zwischen An-und Ausschalten einer Viertel.
Entspricht nach MIDI 2067.
Im header steht
0400(hex)
als beats pro Viertel. das sind nur 1024.
Da muss doch irgendwas kaputt sein? wieso spuielt jeder normale Midiplayer das dann richtig?
Also muss das ding dann ja 2 mal so langsam spielen^^ Den anderen Faktor zwei habe ich beraits gefunden und entfernt aber dieser liegt wohl an nix anderm als am Verständnisproblem..
Danke für eure Hilfe!
 
Zuletzt bearbeitet:

chmee

verstaubtes inventar
Premium-User
ich kome in der Eile noch nicht ganz mit, aber

1. Die Klicks beschreiben die höchstmögliche Auflösung für MIDI-Events
2. Der Midiclock beschreibt die Taktart ( 4/4 oder 6/8 etc.. ), nebenbei der Takt-Master/Sync für angeschlossene Geräte ( Video, Midi-Player etc..)

Vielleicht komme ich später nochmal hierzu.. Sitze noch auf Arbeit.
mfg chmee

**EDIT**
Header chunk - 4D 54 68 64 00 00 00 06 ff ff nn nn dd dd
ff - fileformat, nn - number of tracks, dd - deltatime ticks
zB 4D 54 68 64 00 00 00 06 00 01 00 05 04 00

Note Befehl C5 an, 1/4 Takt laufen(1024 Ticks), Note C5 Off
00 90 3C 64 88 00 80 3C 00

Infos aus http://www.inf.fu-berlin.de/lehre/WS02/multimedia/Synthetisieren_von_Musik.ppt - Seiten 15ff
 

Orbit

Erfahrenes Mitglied
Hallo, danke für deine Hilfe!
Genauso habe ich die Datei bisher auch interpretiert. Leider geht es nicht ganz so schön auf wie bei Deiner Variante:

Mein Header:
4D 54 68 64 00 00 00 06 00 01 00 02 04 00
Heißt:
1024 Beat / Quarter.

Später folgt (Tempo Track)
FF 51 03 07 A1 20
Heißt:
500000 ms pro Viertel.
Also:
6000000/500000 = 120 Viertel pro Minute

Damit müsste sich für das deltatime von Anschalten zu Ausschalten einer Viertel im Bereich 1024 Ticks bewegen.

Später:
(eben ein solches Viertel)
90 48 45 (an)
88 13 (delta time = 2067)
80 48 00 (aus)

Also habe ich doch eigentlich eine Viertel die exakt eine Sekunde dauert oder?
Ich verstehe nicht was ich da für einen Fehler drinhaben soll.
Das delttime habe ich doch richtig ausgerechnet oder?
(erstes byte:
1. Bit gesetzt -> erstes Bit 0 setzen, Zahl shift 7
2 Byte:
1. Bit nicht gesetzt (== letztes Byte)
einfach draufaddieren.

Grüße,
Orbit

EDIT:
oder verstehe ich das ganz falsch und das deltatime im header heißt nicht pro Viertel sondern pro Viertlesekunde?
Also dieser Mensch hier schreibt dazu:
00C0 = Die Basisgeschwindigkeit einer Viertelnote = 192
Hmm geht man dfavon aus dass das richtig ist?


Hmm ok die Folie sagt auch dass es pro Viertelnote sein soll.
Geht in dem Beispiel auch gut auf (betas_per_quarter = 1024, delta_time für ein quarter = 1024.
Obwohl das Tempo da auch auf 120 Quarters/Minute steht.
Wieso hab ich nen doppelt so großes daltatime drin?
 
Zuletzt bearbeitet:

chmee

verstaubtes inventar
Premium-User
Habe oben den Fehler Sekunde/Takt berichtigt.

Hast Du denn schon einen Minimal-Export getestet, also ähnlich meinem Auswurf ? Daran könnte man erkennen, ob die Implementation an sich ( Header ) oder die Ticksberechnung (deltatime ) fehlerhaft ist.
Time Division
The third and final word in the MIDI header chunk is a bit more complicated than the first two. It contains the time division used to decode the track event delta times into "real" time. This value is represents either ticks per beat or frames per second. If the top bit of the word (bit mask 0x8000) is 0, the following 15 bits describe the time division in ticks per beat. Otherwise the following 15 bits (bit mask 0x7FFF) describe the time division in frames per second. Ticks per beat translate to the number of clock ticks or track delta positions (described in the Track Chunk section) in every quarter note of music. Common values range from 48 to 960, although newer sequencers go far beyond this range to ease working with MIDI and digital audio together. Frames per second is defined by breaking the remaining 15 bytes into two values. The top 7 bits (bit mask 0x7F00) define a value for the number of SMPTE frames and can be 24, 25, 29 (for 29.97 fps) or 30. The remaining byte (bit mask 0x00FF) defines how many clock ticks or track delta positions there are per frame. So a time division example of 0x9978 could be broken down into it's three parts: the top bit is one, so it is in SMPTE frames per second format, the following 7 bits have a value of 25 (0x19) and the bottom byte has a value of 120 (0x78). This means the example plays at 24 frames per second SMPTE time and has 120 ticks per frame.
aus http://www.sonicspot.com/guide/midifiles.html

mfg chmee

**EDIT**
Hmm, irgendwas in Deinen Zeit-Berechnungen macht mich stutzig. Bei 120bpm ist 1/4 Takt eine halbe Sekunde ( 1024 Ticks ), 1 Sekunde entspricht 2/4 also 2048 Ticks. Die krumme Zahl deltatime=2067 ist auch komisch.

Die Berechnung V=(Zeit pro Viertel in Sekunden) zu B=Bpm wäre wohl :

B = 1/V*60 oder V= 60/B

mfg chmee
 

Orbit

Erfahrenes Mitglied
Hallo,
also ich baue kein Programm dass einen Export erstelle sondern lese eine MIDIfile von einer SD-Karte in einen Mikrocontrolelr ein der das Zeitsignal auslesen und dann die Befehle Noteon etc. an ein Midigerät schickt.

Die zititierte Datei stammt aus dem Programm Finale und wird von zB Winamp korrekt gespielt.

Hmm, irgendwas in Deinen Zeit-Berechnungen macht mich stutzig. Bei 120bpm ist 1/4 Takt eine halbe Sekunde ( 1024 Ticks ), 1 Sekunde entspricht 2/4 also 2048 Ticks. Die krumme Zahl deltatime=2067 ist auch komisch.
Eben das ist es ja gerade. (Abgesehen von der krummen Zahl).
Der sagt mir im header ich soll 1024 ticks / quarter machen.
Eine Viertel hat aber eingetragene 2067 ~ 2048 ticks. Aber wieso spielt Winamp das nicht in halbem Tempo?

his value is represents either ticks per beat or frames per second. If the top bit of the word (bit mask 0x8000) is 0, the following 15 bits describe the time division in ticks per beat.
bei 0400hex ist ja Genau der Fall gesetzt also habe ich 1024 ticks per beat, das sehe ich schon richtig oder?
und dass ein beat wirklich ein Viertel sein soll istr auch richtig?

Grüße,
Orbit
 

chmee

verstaubtes inventar
Premium-User
Könntest Du nen Hex-Ausschnitt hier reinstellen ? Header und Track-Daten ? Ruhig n bissel länger, 5-10 Noten, damit ich es im Zusammenhang verstehen versuche :D

Hab auch überlegt, ob Winamp sich über simple Fehler hinwegsetzt und es "scheinbar" richtig abspielt, ähnlich wie der Quirks-Modus im IE.

mfg chmee
 

Orbit

Erfahrenes Mitglied
Args.
Tut mir leid, ich hatte nen Denkfehler drin. Bzw. einen rechenfehler.
88 13 (delta time = 2067)
Ist natürlich Unsinn. Das sind exakt 1043. Hmm nen bisschen Fehler ist da immer noch drin (sollten 1024 sein) aber nagut^^
Wobei die doppelte Länge sehr gut in mein halbes Abspieltempo gepasst hätte...

Hmm einlesen tu ich die Zahl so:

Code:
uint32_t get_next_delta_time(uint8_t *length){
	/* Die Anzahl an Ticks ausrechnen */
	uint32_t timer = 0;
	uint8_t byte;
	(*length) = 0;
	do {
		byte = sd_next_byte();
		/* Um 7 Bit verschieben, Platz für neue 7 Bit */
		timer<<=7;
		timer+=(byte&0b01111111);
		(*length)++;
	} while(byte & (1<<7));
	return timer;
}
Wobei sd_next_byte() (überraschenderweise) das nächste BYte der SD-Karte ließt.
Eigentlich müsste die Variante korrekt sein oder?
 

MarcDuSoleil

Grünschnabel
Nachdem ich auch ein massives Problem damit hatte und ich jetzt die Lösung gefunden habe, hier meine Lösung in Excel:
1575995631488.png
Alle Rechnungen bezeihen sich auf Spalten P bis U und Zeilen 27 bis 31
Hier nochmal alles als Text zum Kopieren:
1.Byte (binär)=HEXINBIN(LINKS(P27;2);8)
2.Byte (binär)=HEXINBIN(RECHTS(P27;2);8)
DeltaTime=RECHTS(TEXT(Q27;"00000000");7) & RECHTS(TEXT(R27;"00000000");7) (siehe Grafik unter der folgenden URL)
http://www.inf.fu-berlin.de/lehre/WS02/multimedia/Synthetisieren_von_Musik.ppt - Seite 28
Ticks=BinstrToLng(T27)
DeltaMS = Ticks * ( (60.0 / ((BPM) * PPQ)))
Function BinstrToLng(strBin As String) As Long
Dim i, i_col As Integer
BinstrToLng = 0
i = Len(strBin) - 1
i_col = 1
Do While i >= 0
If Mid(strBin, i_col, 1) = "1" Then
BinstrToLng = BinstrToLng + 2 ^ i
End If
i = i - 1
i_col = i_col + 1
Loop
End Function
 

Neue Beiträge