![]() |
Hardcode MidiHeader
Habe mich mal im Internet auf diversen Seiten schlau gemacht über die zusammensetzung der Midi Header
Das ist dabei herausgekommen. Wenn sich jemand auskennt .. Sind die Daten so korrekt?
Delphi-Quellcode:
Bin erst am Anfang und ist nicht so leicht umzusetzen.
procedure ExpMidiFile;
var Bytes: array[0..10000] of byte; begin // MIDI File Header Chunk (14 bytes) // MTHD Bytes[1] := ord('M'); Bytes[2] := ord('T'); Bytes[3] := ord('h'); Bytes[4] := ord('d'); // Headerlänge 6 bytes Bytes[5] := 0; Bytes[6] := 0; Bytes[7] := 0; Bytes[8] := 6; // 6 byte Header // 0 - Einzelne Spur // 1 - Mehrere Spuren, Syncron // 2 - Mehrere Spuren, ASyncron Bytes[9] := 0; Bytes[10] := 1; Bytes[11] := 0; Bytes[12] := 9; // Spur Nummer Bytes[13] := 0; Bytes[14] := 48; // Anzahl der Delta-Zeit sekunde pro Viertelnote // Spur 1 // MTRK Bytes[15] := ord('M'); Bytes[16] := ord('T'); Bytes[17] := ord('r'); Bytes[18] := ord('k'); // Anzahl der Bytes in der Spur Bytes[19] := 0; Bytes[20] := 0; Bytes[21] := 0; Bytes[22] := 19; // Geschwindigkeit Bytes[23] := 0; // delta Zeit Bytes[24] := 255; // FF (Meta Befehl) Bytes[25] := 81; // Tempo Befehl Bytes[26] := 3; // 3 bytes für Tempo Beschreibung // Zeit Signatur Bytes[30] := 0; // delta Zeit Bytes[31] := 255; // FF (Meta Befehl) Bytes[32] := 88; // Zeit Signatur Befehl Bytes[33] := 4; // 4 bytes Bytes[34] := 4; // Zähler Bytes[35] := 2; // Nenner (2 = 1/4, 3 = 1/8, 4 = 1/16, etc.) Bytes[36] := 24; // ? Bytes[37] := 8; // 32 Note in einer 4 Note; // Spur Ende Bytes[38] := 0; // delta Zeit Bytes[39] := 255; // Spurende Befehl Bytes[40] := 47; Bytes[41] := 0; Für alle bytes habe ich keine Infos gefunden. Bringt mir ja nichts wenn mein Header falsch ist und die MIDI nachher nicht als Midi erkannt wird. gruss |
AW: Hardcode MidiHeader
das ist eine ungünstige variante:
Delphi-Quellcode:
Du solltest lieber einen Record verweden, welche die einzelnen Feld mit Namen definiert.
Bytes: array[0..10000] of byte;
Pseudocode:
Delphi-Quellcode:
Dann wenn du es nutzt initialisieren -> also in rec.header den String schreiben.
type
midi = packed record // MIDI File Header Chunk Header: array[1..4] of char; // Headerlänge HeaderSize: cardinal; // hier evtl. auf little/big endian achten! [...] end; Wenn du die Daten dann weiter nutzt brauchst du nur den Zeiger auf den Record weiterverarbeiten. Bei dem Datenaufbau, wirst du mehrere Records brauchen bzw. diese sind dann nützlich. |
AW: Hardcode MidiHeader
Bytes[0] hast du vergessen :stupid:
|
AW: Hardcode MidiHeader
Zitat:
Sagte ja Hardcoded und aus Informationen aus dem Net zusammen gesucht. Gibt ja ne Componente hier aber kann ich so nicht verwenden. Zitat:
Muss dann das array halt auf array[1..10000] setzen. Hatte eigentlich vor den Header von Hand aus weiter zu verarbeiten.
Delphi-Quellcode:
Bytes[CurrentByte] := ord('M');
inc(CurrentByte); Bytes[CurrentByte] := ord('T'); inc(CurrentByte); Bytes[CurrentByte] := ord('r'); inc(CurrentByte); Bytes[CurrentByte] := ord('k'); inc(CurrentByte); CurrentByte := CurrentByte + 4; gruss |
AW: Hardcode MidiHeader
Hi,
vielleicht hilft dir ja das hier: ![]() oder das hier: ![]() LG, Frederic |
AW: Hardcode MidiHeader
Zitat:
Der Link oben scheint Interessant zu sein. Danke. gruss |
AW: Hardcode MidiHeader
Jetzt dürft ihr alle nochmal über mich und meinen Programmierstil herziehen.
Delphi-Quellcode:
Und es funktioniert 100% auch ohne Header als Record und der ganze andere Kram
unit uMidi;
interface uses Windows, Classes, SKAeroAPI, Math, SysUtils, uGlobal, uSound; var CurrentByte: Integer; DeltaTime: Integer; LastDeltaTime: Integer; TotalBytes: Integer; MidiInst: Integer; TrackDataStartByte: Integer; MidiIsDrum: BOOL; MidiDrumNum: Integer; Bytes: array[1..10000] of byte; DeltaBinArray: array[0..3] of string; DeltaTimeArray: array[0..3] of byte; DB: Integer; TempZ: Integer; function ConvertToBinary(BInput: Integer): string; procedure ExpMidiFile(MidiFile: string); implementation uses uMidiTracker; procedure MidiFileStartNote(ActiveSpur, ActiveNote: Integer); var Flip: Integer; begin if MidiIsDrum then begin Flip := MidiDrumNum; TempZ := 9; end else begin Flip := 127 - Grid[ActiveSpur, ActiveNote]; TempZ := ActiveSpur; end; // Start Noten Befehl + Channel Bytes[CurrentByte] := 144 + TempZ; inc(CurrentByte); Bytes[CurrentByte] := Flip + Basenote; // Note + Basenote inc(CurrentByte); Bytes[CurrentByte] := 127; // Geschwindigkeit inc(CurrentByte); end; procedure MidiFileStopNote(ActiveSpur: Integer); var Flip: Integer; begin if MidiIsDrum then begin Flip := MidiDrumNum; TempZ := 9; end else begin Flip := 127 - (MidiTracker.OldNote[ActiveSpur] mod 1000); TempZ := ActiveSpur; end; // Stop Noten Befehl + Channel Bytes[CurrentByte] := 128 + TempZ; inc(CurrentByte); Bytes[CurrentByte] := Flip + Basenote; // Note + Basenote inc(CurrentByte); Bytes[CurrentByte] := 0; // Geschwindigkeit inc(CurrentByte); end; procedure ConvertDeltaTime; var DB, DA, DC, DD: Integer; Temp: string; begin // 12 Delta schläge pro 16tel Note DB := DeltaTime * 12; Temp := ConvertToBinary(DB); DA := Length(Temp) mod 7; if DA <> 0 then Temp := StringOfChar('0', 7 - DA) + Temp; DD := Length(Temp) div 7 - 1; for DA := 0 to DD do begin DeltaBinArray[DA] := MidStr(Temp, DA * 7 + 1, 7); if DA = DD then DeltaBinArray[DA] := '0' + DeltaBinArray[DA] else DeltaBinArray[DA] := '1' + DeltaBinArray[DA]; end; // Konvertiere Binärzeichenfolge in DeltaBinArray zu Bytes ins DeltaTimeArray for DA := 0 to DD do begin DB := 0; for DC := 1 to 8 do begin if MidStr(DeltaBinArray[DA], DC, 1) = '1' then DB := DB + trunc(Math.Power(2, (8 - DC))); end; DeltaTimeArray[DA] := DB; end; for DA := 0 to DD do begin Bytes[CurrentByte] := DeltaTimeArray[DA]; inc(CurrentByte); end; end; procedure ConvertTempo; var DB: Integer; DA, DC: Integer; MPQN: Integer; BytesArray: array[0..2] of string; // microsekunden pro viertel Note Temp: string; begin MPQN := 60000000 div MidiTracker.Tempo; DB := MPQN; Temp := ConvertToBinary(DB); Temp := StringOfChar('0', 24 - Length(Temp)) + Temp; for DA := 0 to 2 do BytesArray[DA] := MidStr(Temp, DA * 8 + 1, 8); // Konvertiere Binärzeichenfolge in BytesArray zu Bytes for DA := 0 to 2 do begin DB := 0; for DC := 1 to 8 do begin if MidStr(BytesArray[DA], DC, 1) = '1' then DB := DB + trunc(Math.Power(2, (8 - DC))); end; Bytes[27 + DA] := DB; end; end; function ConvertToBinary(BInput: Integer): string; var Power: Integer; BTemp: string; BNum: Integer; BA, BB: Integer; begin BNum := BInput; Power := 0; while trunc(Math.Power(2, Power)) < BNum do inc(Power); dec(Power); if Power < 0 then Power := 0; BTemp := ''; for BA := Power downto 0 do begin BB := trunc(Math.Power(2, BA)); if BNum >= BB then begin BTemp := BTemp + '1'; BNum := BNum - BB; end else BTemp := BTemp + '0' end; Result := BTemp; end; procedure ConvertTrackLength; var DA, DC: Integer; TotalBytesArray: array[0..3] of string; Temp: string; begin // Ins binär formate konvertieren DB := TotalBytes; Temp := ConvertToBinary(DB); Temp := StringOfChar('0', 32 - length(Temp)) + Temp; for DA := 0 to 3 do TotalBytesArray[DA] := MidStr(Temp, DA * 8 + 1, 8); // Konvertiere Binärzeichenfolge in TotalBytesArray zu Bytes for DA := 0 to 3 do begin DB := 0; for DC := 1 to 8 do begin if MidStr(TotalBytesArray[DA], DC, 1) = '1' then DB := DB + trunc(Math.Power(2, (8 - DC))); end; Bytes[TrackDataStartByte - (4 - DA)] := DB; end; end; procedure ExpMidiFile(MidiFile: string); var IntZ: Integer; IntA: Integer; f: TFileStream; begin // MIDI File Header Chunk (14 bytes) // MTHD Bytes[1] := ord('M'); Bytes[2] := ord('T'); Bytes[3] := ord('h'); Bytes[4] := ord('d'); // Headerlänge 6 bytes Bytes[5] := 0; Bytes[6] := 0; Bytes[7] := 0; Bytes[8] := 6; // 6 byte Header // 0 - Einzelne Spur // 1 - Mehrere Spuren, Syncron // 2 - Mehrere Spuren, ASyncron Bytes[9] := 0; Bytes[10] := 1; Bytes[11] := 0; Bytes[12] := 9; // Spur Nummer Bytes[13] := 0; Bytes[14] := 48; // Anzahl der Delta-Zeit sekunde pro Viertelnote // Spur 1 // MTRK Bytes[15] := ord('M'); Bytes[16] := ord('T'); Bytes[17] := ord('r'); Bytes[18] := ord('k'); // Anzahl der Bytes in der Spur Bytes[19] := 0; Bytes[20] := 0; Bytes[21] := 0; Bytes[22] := 19; // Geschwindigkeit Bytes[23] := 0; // delta Zeit Bytes[24] := 255; // FF (Meta Befehl) Bytes[25] := 81; // Tempo Befehl Bytes[26] := 3; // 3 bytes für Tempo Beschreibung ConvertTempo; // 3 bytes fürs Tempo schreiben // Zeit Signatur Bytes[30] := 0; // delta Zeit Bytes[31] := 255; // FF (Meta Befehl) Bytes[32] := 88; // Zeit Signatur Befehl Bytes[33] := 4; // 4 bytes Bytes[34] := 4; // Zähler Bytes[35] := 2; // Nenner (2 = 1/4, 3 = 1/8, 4 = 1/16, etc.) Bytes[36] := 24; // ? Bytes[37] := 8; // 32 Note in einer 4 Note; // Spur Ende Bytes[38] := 0; // delta Zeit Bytes[39] := 255; // Spurende Befehl Bytes[40] := 47; Bytes[41] := 0; With MidiTracker do begin // Spuren schreiben CurrentByte := 41; MidiTracker.FindEndOfSong; inc(MidiTracker.SongLength); // Spuren einlesen for IntZ := 0 to 7 do begin inc(CurrentByte); OldNote[IntZ] := -1; OldInst[IntZ] := -1; LastDeltaTime := 0; TotalBytes := 0; // MTRK Bytes[CurrentByte] := ord('M'); inc(CurrentByte); Bytes[CurrentByte] := ord('T'); inc(CurrentByte); Bytes[CurrentByte] := ord('r'); inc(CurrentByte); Bytes[CurrentByte] := ord('k'); inc(CurrentByte); CurrentByte := CurrentByte + 4; TrackDataStartByte := CurrentByte; if SKAERO_GetCheckButtonStatus(SKAERO_GetMainItem(MainHandle, IntZ + ID_HIDETRACK_FIRST)) = False then begin for IntA := 0 to SongLength do begin // NotenTyp suchen if OldNote[IntZ] = -1 then OldNoteType := BlankNote; if (OldNote[IntZ] >= 0) and (OldNote[IntZ] < 1000) then OldNoteType := StartingNote; if OldNote[IntZ] >= 1000 then OldNoteType := ContinuingNote; if IntA = SongLength then begin NoteType := BlankNote; end else begin if Grid[IntZ, IntA] = -1 then NoteType := BlankNote; if (Grid[IntZ, IntA] >= 0) and (Grid[IntZ, IntA] < 1000) then NoteType := StartingNote; if Grid[IntZ, IntA] >= 1000 then NoteType := ContinuingNote; end; // Ändere das Instrument wenn nötig // wird eine neue Note gespielt und das Instrument unterscheidet sich vom alten MidiInst := (InstGrid[IntZ, IntA]); if (NoteType = StartingNote) and (MidiInst <> OldInst[IntZ]) then begin // Instrument wählen if MidiInst < 128 then begin DeltaTime := IntA - LastDeltaTime; ConvertDeltaTime; // Intrumenten Befehl + Channel Bytes[CurrentByte] := 192 + IntZ; inc(CurrentByte); Bytes[CurrentByte] := MidiInst; inc(CurrentByte); LastDeltaTime := IntA; MidiIsDrum := False; end else begin // Perkussions Instrument MidiIsDrum := True; MidiDrumNum := MidiInst - 93; end; end; //Stop die Alte Note und starte Neue if (OldNoteType <> BlankNote) and (NoteType = StartingNote) then begin // Stope die Alte Note DeltaTime := IntA - LastDeltaTime; ConvertDeltaTime; MidiFileStopNote(IntZ); // Starte neue Note Bytes[CurrentByte] := 0; // Delta zeit inc(CurrentByte); MidiFileStartNote(IntZ, IntA); LastDeltaTime := IntA; end; // Stop die Alte Note aber keine Neue if (OldNoteType <> BlankNote) and (NoteType = BlankNote) then begin DeltaTime := IntA - LastDeltaTime; ConvertDeltaTime; MidiFileStopNote(IntZ); LastDeltaTime := IntA; end; // Starte neue Note aber stoppe nicht die Alte if (OldNoteType = BlankNote) and (NoteType = StartingNote) then begin DeltaTime := IntA - LastDeltaTime; ConvertDeltaTime; MidiFileStartNote(IntZ, IntA); LastDeltaTime := IntA; end; // Setze die Alte Note als Aktuelle note OldNote[IntZ] := Grid[IntZ, IntA]; // Setze das Alte Instrument als Aktuelles if NoteType = StartingNote then OldInst[IntZ] := InstGrid[IntZ, IntA]; end; // End for IntA end; // End SKAERO_GetCheckButtonStatus // Spur ende DeltaTime := SongLength - LastDeltaTime; // Delta Zeit ConvertDeltaTime; Bytes[CurrentByte] := 255; inc(CurrentByte); Bytes[CurrentByte] := 47; inc(CurrentByte); Bytes[CurrentByte] := 0; TotalBytes := CurrentByte - TrackDataStartByte + 1; ConvertTrackLength; end; // for IntZ end; // End with MidiTracker // Datei schreiben f := TFileStream.Create(MidiFile, fmCreate or fmOpenReadWrite); f.Write(Bytes[1], CurrentByte); f.Free; end; end. der für mich in manchen Situationen uninteressant und unnötig ist. Warum eine Komponente vom 500KB in ein Projekt integrieren wenn es auch anders geht. gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:28 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz