Autor Beitrag
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10114
Erhaltene Danke: 1223

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 18.07.11 16:32 
Moin!

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Allerdings gleich ne frage dazu!
[...]
Fange ich also bei meinem 'Grid bei startposition null an steht dann da
ausblenden Delphi-Quelltext
1:
2:
Lied.Add(TTon.Create(72,  0,        480));
Lied.Add(TTon.Create(74,  480,      480));
usw.
Klar, das ist natürlich Blödsinn gewesen, da oben in meinem Beispielcode. Habe ich korrigiert (war wohl schon zu spät gestern... :?).

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Da ich wieder im rechnen blöd bin, was für ein integerwert würde den da stehen wenn die letzte Note erst nach 6 oder 9 Minuten kommt??? Währe das nicht schon > FFFF7F??
Vorsicht Falle! Ich habe hier nur genau das gemacht, was bei MIDI auch so vorgesehen ist: auf Notenwerte skalierte Tonlängen! (Ja, das ist was anderes, als ich weiter oben gefaselt habe, aber da war ich auch noch nicht wieder gut genug im MIDI-Format drin... :oops:)

Ich empfehle also genau das zu tun, wozu das MIDI-Format erfunden wurde: skaliere deine Tonlängen auf MidiTicks (=Notenwerte) und gib das Tempo über das Meta-Event an. :idea: (In meinem Beispiel nicht drin, ich habe hier auf das Standard-Tempo gesetzt und das Metaevent nicht explizit angegeben)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
ALF Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1083
Erhaltene Danke: 53

Win XP, Win7
Delphi 7 Enterprise, XE
BeitragVerfasst: Mo 18.07.11 17:32 
Nene Missverständnis. Ich berechne ja schon im onmousdown/onmousup beim Grid die ticks
Beispiel: eingestellt ist Griddarstellung 1/4note xAchse, also jede Note die ich zeichen hat standart auch die länge 1/4 note. fange ich bei null an käme:
colum 0
note, 0, 480,
nächste note währe colume 1
note, 480, 480,
nächste note colume 2
note, 960, 480,
usw.

Immer bezogen auf den Anfang vom Grid, colume * 480 , usw.
(Da ist noch mehr an Berechnung, aber zur verdeutlichung mal einfach gehalten.)

Ein anderen Bezug kann ich ja beim Zeichnen nicht haben.

Ich stolpere ja auch über den Wert FFFF7F
Theoretisch ergibt FFFF7F ja 16777087/480 ~ 34952 1/4Noten auf der xAchse. Aber der DeltaWert wird ja nur mit 7bit berechnet also wird der Wert noch kleiner.

Oder hab ich hier ein totalfalsche Überlegung.
Darum meine Frage, wie würde der DeltaWert aussehen, bei 6 oder 8 Min oder bei 1000000 columen? Oder ist dies überdimensioniert? Ich weiss es nicht?

PS: Was die anderen Events betrifft, da sehe ich keine Probleme, die zu schreiben oder zu lesen.
Ob nun NoteOn $90 da steht oder Programmchange das prinzip ist immer das selbe im Track.

Allerdings muss ich jetzt erst mal verstehen was Du da in einer Nacht gezaubert hast. Das ist ja weit entfernt von dem was ich kann!
Muss ja noch paar sachen einfügen wie Delete Note oder "insert Note wenn nötig?"
Insert ist nicht Nötig 8) gerade festgestellt!

Ich hoffe Du hast nicht dagegen, wen ich bestimmte Sachen speziell anpasse. Immerhin ist es Dein Wissen und nicht meins.

Sorry: wenn ich jetzt so euphorisch bin. Hab jetzt mal viele Möglichkeiten getestet.
Es ist absolut der Hammer die Unit. :zustimm:
ich hätte Jahre dazu benötigt

Gruss Alf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10114
Erhaltene Danke: 1223

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 18.07.11 21:19 
Moin!

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Ich stolpere ja auch über den Wert FFFF7F
Theoretisch ergibt FFFF7F ja 16777087/480 ~ 34952 1/4Noten auf der xAchse. Aber der DeltaWert wird ja nur mit 7bit berechnet also wird der Wert noch kleiner.
Langsam, du verwechselst da was. Die Obergrenze für die Ereignisse in einem Midi-Track ist der Längenzähler im Track-Header: 4 Bytes = 2^32 = 4GB /~4 Bytes pro Event ~= 1.000.000.000 Midi-Ereignisse :shock: Das ist doch schon was, oder? :zwinker:

Der Maximalwert für ein Delay ist 24 Bit groß, also ~16,7 Millionen Ticks - was aber wieder nix über die Zeit aussagt, die damit abgebildet werden kann, dazu wäre ein Tempo-Metaevent nötig, mit dem man die Miditicks in Zeit umrechnen könnte. :les:

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Darum meine Frage, wie würde der DeltaWert aussehen, bei 6 oder 8 Min
Der Delta-Wert hat (erstmal) noch keine Bedeutung für die Zeitspanne, die er tatsächlich beschreibt, dazu ist auch immer das Tempo nötig! Auch der StartTick in meinen Klassen ist eigentlich nicht notwendig und wird ja im Verlauf der ByteCode-Erzeugung in relative Bezüge umgewandelt. Wenn du tatsächlich mit extrem langen Tracks rechnest, könnte du hier statt Integer auch Int64 nehmen.

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
oder bei 1000000 columen? Oder ist dies überdimensioniert? Ich weiss es nicht?
Was haben die Spalten denn damit zu tun? :gruebel: Also wie gerade oben gesehen, 1.000.000 Midi-Ereignisse sollten pro Track kein Problem darstellen. ;)

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Muss ja noch paar sachen einfügen wie Delete Note
Ansatz: Ich würde in der GUI-Darstellung eine Referenz auf das TBasiston-Objekt vorhalten. Wenn du das löscht, brauchst du nur das referenzierte Objekt per Standard-Methode .Extract() aus der TLied-Liste nehmen, da würde ich nicht mal groß was bauen. :nixweiss:

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Ich hoffe Du hast nicht dagegen, wen ich bestimmte Sachen speziell anpasse. Immerhin ist es Dein Wissen und nicht meins.
Wenn ich was dagegen hätte, würde ich ja die Unit nicht veröffentlichen, oder? ;) Mach mal. :zustimm:

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Es ist absolut der Hammer die Unit. :zustimm:
ich hätte Jahre dazu benötigt
Danke danke :beer: Naja, soo großartig ist das Ding auch wieder nicht, mir sind da schon wieder ein paar Stellen aufgefallen, die man besser machen könnte... :nixweiss: Ist halt ein Quickhack oder TechDemo, wie man´s nimmt. :?

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
ALF Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1083
Erhaltene Danke: 53

Win XP, Win7
Delphi 7 Enterprise, XE
BeitragVerfasst: Mo 18.07.11 22:11 
Ich merk schon, ich kann mich nicht richtig ausdrücken. :oops:
Darum lass ich es erst mal.

Nur eine Frage habe ich noch. Ich müsste jetzt irgendwie an das eigentlich event rankommen.
Dazu muss ich wieder aus dem Track auslesen können. Um also auszulesen bräuchte ich ja den
Deltawert Event Note Dynamik.
Ich versuche es schon, aber blick natürlich bei deiner Unit noch nicht ganz durch.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
type 
TEvent = class(Tobjekt)
 private
  DeltaTime: integer //für getticount delaytime
  Event: Byte        // für MidiOut
  Wert1: Byte
  Wert1: Byte

end;

var
   myLied: TLied;
  myMidiFile: TMidiFile;
...
...
Procedure readevent;
var myevent: TEvent
begin
    myevent:= TEvent.create;
    myevent:= myMidiFile.Track[0].Items[0]);//oder so
...
...

//                     event   Note oder (Wert1)    dynamic(oder Wert2) jenach event   
MIDIOutput1.PutShort($90,    36,                  64); 
    
end;
komme aber nicht klar.
Könntest Du da mal nen Tipp geben?

Ich weiss ich kann nichts, aber trotzdem Danke wenn du da noch ein Tipp hättest.

Gruss Alf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10114
Erhaltene Danke: 1223

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 18.07.11 23:24 
Moin!

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Ich müsste jetzt irgendwie an das eigentlich event rankommen.
Dazu muss ich wieder aus dem Track auslesen können.
Das hast du ja im Wesentlichen schon rausgefunden: ;)
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
  var
    Lied: TLied;
    MidiFile: TMidiFile;
    i: Integer;
    MidiEvent: TMidiEvent;
begin
  Lied := TLied.Create;
  try
    Lied.Add(TTon.Create(72,    0480)); // "Alle meine Entchen..."
    Lied.Add(TTon.Create(74,  480480));
    Lied.Add(TTon.Create(76,  960480));
    Lied.Add(TTon.Create(771440480));
    Lied.Add(TTon.Create(791920960));
    Lied.Add(TTon.Create(792880960));
    Lied.Add(TAkkord.Create(7240001920)); // C-Dur
    MidiFile := TMidiFile.Create;
    try
      MidiFile.AddTrack(TMidiTrack.CreateFromLied(Lied));

      for i := 0 to MidiFile.Track[0].Count-1 do begin
        MidiEvent := TMidiEvent(MidiFile.Track[0].Items[i]);
        ShowMessageFmt('Nr.%d: %s StartTick: %d', [i, MidiEvent.ClassName, MidiEvent.StartTick]);
      end;

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Um also auszulesen bräuchte ich ja den
Deltawert Event Note Dynamik.
Du meinst vermutlich mal wieder was anderes, als zu sagst: Um das an ein Midi-Gerät zu senden brauchst du die Parameter der Ereignisse, oder? ;) Denn sonst macht das hier ja keinen Sinn:
ausblenden Delphi-Quelltext
1:
2:
//                     event   Note oder (Wert1)    dynamic(oder Wert2) jenach event
MIDIOutput1.PutShort($90,    36,                  64);
Den ersten Ansatz hast du oben schon in meinem Code-Beispiel. Allerdings ist der Schlüssel zur Lösung des Problems wohl eher hier zu suchen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
type
  TMidiEvent = class(TObject)
  private
    FStartTick: Integer;
  public
    property StartTick: Integer read FStartTick write FStartTick;
    procedure WriteToStream(AStream: TStream; const ADelay, ATrackNr: Integer); virtualabstract;
    procedure WriteToMIDI(AMIDIDevice: TMIDIDevice; const ADelay: Integer); virtualabstract;
    // Ich habe hier mal TMIDIDevice geschrieben, ich habe keine Ahnung, was das für eine Kompo ist,
    // aber du nutzt das z.B. so: MIDIOutput1.PutShort();
    class procedure WriteDelayToStream(AStream: TStream; const ADelay: Integer);
  end;
Du musst also dem abstrakten Midi-Event beibringen (und später der differenzierten Klasse natürlich die Details), wie man sich selbst (also die Klasse) an ein Midi-Gerät sendet. :idea: Dann brauchst du hier noch eine entsprechende Methode:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
  TMidiTrack = class(TObjectList)
  protected
    procedure SortiereNachStartTick;
  public
    constructor CreateFromLied(ALied: TLied);
    procedure WriteToStream(AStream: TStream; const ATrackNr: Integer);
    procedure WriteToMIDIDevice(AMIDIDevice: TMIDIDevive);
  end;
Hier steckt ja die Schleife drin, die aus den Start-Ticks die Delta-Time berechnet.

Du solltest dieses Objekt hier "entsorgen", damit kommst du nicht weit: :?
user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
type 
TEvent = class(Tobjekt)
 private
  DeltaTime: integer //für getticount delaytime
  Event: Byte        // für MidiOut
  Wert1: Byte
  Wert1: Byte
end;


user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Ich weiss ich kann nichts,
Naja, bei OOP gibt´s wohl noch etwas Nachholbedarf, aber wenn man damit nicht aufgewachsen ist (ist bin´s auch nicht :nixweiss:), sind das erstmal ganz schöne Brocken, diese Konzepte zu verstehen. Aber, die Mächtigkeit von OOP ist einfach den Aufwand wert, wie du siehst. :D

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
ALF Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1083
Erhaltene Danke: 53

Win XP, Win7
Delphi 7 Enterprise, XE
BeitragVerfasst: Di 19.07.11 02:59 
MidiOut ist im Prinzip nichts weiter als vom MMSystem das Handle(+midievents) für die Ausgabe
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
//midiout =  handel vom Mididevice  
//Original sieht es so aus:
procedure PlayOrStopEvent(Event, Wert1, Wert2);
var
  midiMsg: Longint;
begin
     midiMsg := (event + Wert1 + Wert2);
     midiOutShortMsg(midiOut,  midiMsg);
    //MIDIOutput1.PutShort($90, 36, 64);
    //MIDIOutput1.PutShort($80, 36, 0);
end;
Benötige ich ja, wenn ich im Grid ne Note Zeichne, um zu hören ob ich die richtige Note angespielt habe :wink: Das ist das eine.
Wenn das Grid aktuallisiert wird benötige ich ja wieder TTon. Funct ja auch super!
Nun kommt aber play und da benötige ich die originale Reienfolge in meinem Prog.
Deltawert Event;
Deltawert Event,
Deltawert Event,
usw bis Trackende bzw maxtracklänge. so funct jedenfals in mein Prog.
Wie soll ich sonst in meinem Prog die erstellten Noten abspielen?
Im Prinzip liegen sie ja schon so vor im TMIDIFILE wenn ich Deine Unit richtig verstanden habe, natürlich ohne Header den ich ja jetzt noch nicht brauche erst wenn die File erstellt wird.
Aber ich komm da irgenwie nicht ran.

Zitat:
Wenn du tatsächlich mit extrem langen Tracks rechnest, könnte du hier statt Integer auch Int64 nehmen.
Als Midi erschaffen wurde war gerade mal der 8Bit Processor da, glaube kaum das da schon int64 gab. Soweit ich mich erinnere. :wink:
Die längste Midfile die ich mal hatte war glaube ich 20min lang. Soviel ich weiss gibt es aber ganze Konzertelängen :wink:
Gut, solche langen Dinger machen ja auch Profis, mit evtl ne ander technik und nicht mit ein selbstgeschriebenes Prog.
Gruss Alf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10114
Erhaltene Danke: 1223

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Di 19.07.11 11:57 
user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
MidiOut ist im Prinzip nichts weiter als vom MMSystem das Handle(+midievents) für die Ausgabe
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
//midiout =  handel vom Mididevice  
procedure PlayOrStopEvent(Event, Wert1, Wert2);
var
  midiMsg: Longint;
begin
     midiMsg := (event + Wert1 + Wert2);
     midiOutShortMsg(midiOut,  midiMsg);
    //MIDIOutput1.PutShort($90, 36, 64);
    //MIDIOutput1.PutShort($80, 36, 0);
end;
Aha, spannend. Aber irgendwie sieht der Code nicht so wirklich lauffähig aus. :? :gruebel: Kannst du mir mal ein Stück Demo-Code geben, mit dem man eine Note abspielt? Also irgendwie zwei Buttons, NoteOn und NoteOff, die Dauer bestimmte ich dann durch die Klicks. :idea:

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Wie soll ich sonst in meinem Prog die erstellten Noten abspielen?
Einen Ansatz habe ich dir doch oben schon genannt, im Prinzip musst du die ByteCode-Generatormethoden auf Direktausgabe ans MidiDevice umstellen. :nixweiss:

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Im Prinzip liegen sie ja schon so vor im TMIDIFILE wenn ich Deine Unit richtig verstanden habe
Hm, mir scheint, du hast noch etwas Konzeptverständis-Probleme. :? OK, machen wir´s erstmal zu Übungszwecken anders: du hast gesagt, du kannst einen MidiTrack aus einem File lesen, also musst du einen entsprechenden Parser haben. Nimm doch einfach den von meinen Klassen erzeugten Bytecode und wirf ihn deinem Parser vor die Füße, der sollte das dann doch wieder "verstehen" und abspielen können. :idea:

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Zitat:
Wenn du tatsächlich mit extrem langen Tracks rechnest, könnte du hier statt Integer auch Int64 nehmen.
Als Midi erschaffen wurde war gerade mal der 8Bit Processor da, glaube kaum das da schon int64 gab.
Du hast da immer noch was nicht verstanden, fürchte ich. ;) Es geht hier nur um den Start-Tick, dieser Wert taucht ja nie im MidiFile auf, das ist für das Klassenmodell nur eine Krücke, um den (relativen!) Startzeitpunkt absolut zu machen. Im MidiFile ist er ja relativ, da braucht man dann nicht mehr so große Zahlen.

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
ALF Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1083
Erhaltene Danke: 53

Win XP, Win7
Delphi 7 Enterprise, XE
BeitragVerfasst: Di 19.07.11 19:49 
Sorry das es so spät wurde(Urlaub vorbei und schon geht der Stress los) :evil:
Anbei mal wie ich die Noten Abspiele.
Un muss wieder weg, Sorry

EDIT: Hab da Müll Hochgeladen, Jetzt das richtige.

Gruss Alf

Moderiert von user profile iconNarses: Inline- in normalen Anhang konvertiert.
Einloggen, um Attachments anzusehen!
_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10114
Erhaltene Danke: 1223

W2k .. W7pro .. W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 20.07.11 23:34 
Moin!

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Anbei mal wie ich die Noten Abspiele.
Danke. Hatte mir zwar mehr sowas wie das im Anhang vorgestellt, aber dein Beispiel hat´s auch gezeigt. ;)

Jaaa, ich gehe dann mal ein bischen denken wie man das umsetzen kann... :gruebel: Dafür sind wohl ein zwei Änderungen in der UMidiObject-Unit nötig... :? Kann bischen dauern. :nixweiss:

cu
Narses
Einloggen, um Attachments anzusehen!
_________________
There are 10 types of people - those who understand binary and those who don´t.
ALF Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1083
Erhaltene Danke: 53

Win XP, Win7
Delphi 7 Enterprise, XE
BeitragVerfasst: Do 21.07.11 00:17 
mh, wusste nicht das Du ein Klavier bauen wolltest :wink:
Ein fertiges Opensource als NonVCL, allerdings mit XE geschrieben, gibt es hier.
Da bin ich ja dabei den Tracker umzuändern. Er hat leider sein eigenes Systhem dafür geschrieben.
Womit ich nicht zufrieden bin. Darum häng ich ja so ein bischen in der Luft.
Die Graphic des Pianorolleditors, hab ich schon angepasst und zwar so, wie sie sein soll.
Ansonsten ein Prima Teil.
Mit Deiner Untit , währe es genau das was dieses Teil benötigt 8).
Man muss ja das Rad nicht ganz neu erfinden. :mrgreen:

Anbei, ich bin dabei Deine Unit neu zuschreiben, um auf den Mounteverest zu kommen(sie zu verstehn).
Leider seeeehr Complex .

Ps: DeineExe macht bei AVG zicken :shock:

Gruss Alf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
ALF Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1083
Erhaltene Danke: 53

Win XP, Win7
Delphi 7 Enterprise, XE
BeitragVerfasst: Fr 22.07.11 15:03 
So ein kleiner Teil hab ich erst mal für mich umgesetzt.
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
//die Events
    TEvent = class(TObject)
   private
    FDeltaTime: Integer;
    FMidiEvent: Byte;
    FWert1: Byte;
    FWert2: Byte;
   public
    constructor CreateEvent(const ADeltaTime: Integer; const AMidiEvent, AWert1, AWert2: Byte);
    property DeltaTime: Integer read FDeltaTime write FDeltaTime;
    property MidiEvent: Byte read FMidiEvent write FMidiEvent;
    property Wert1: Byte read FWert1 write FWert1;
    property Wert2: Byte read FWert2 write FWert2;

   end;
  //der einzelne Track für die events
  TTrack = class(TObjectList)
  end;
  //alle Tracks in der Liste
  TMidiTracks = class(TObjectList)
  private
    FTracks: TObjectList;
    function GetTrack(const AIndex: Integer): TTrack;
    function GetTrackcount: Integer;
  public
    constructor CreateTrackList;
    destructor  Destroy; override;
    property Track[const AIndex: Integer]: TTrack read GetTrack;
    property TrackCount: Integer read GetTrackcount;
    function AddTrack(ATrack: TTrack): Integer;
    procedure DeleteTrack(AIndex: Integer);
   end;

.....
.....
var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TMidiTracks.CreateTrackList;
begin
  inherited Create;
  FTracks:= TObjectList.Create(True);
end;

destructor TMidiTracks.Destroy;
begin
   FTracks.Free;
   inherited;
end;

constructor TEvent.CreateEvent(const ADeltaTime: Integer; const AMidiEvent, AWert1, AWert2: Byte);
begin
  inherited Create;
  FDeltaTime:= ADeltaTime;
  FMidiEvent:= AMidiEvent;
  FWert1:= AWert1;
  FWert2:= AWert2;
end;

function TMidiTracks.GetTrack(const AIndex: Integer): TTrack;
begin
  Result := TTrack(FTracks.Items[AIndex]);
end;

function TMidiTracks.GetTrackCount: Integer;
begin
  Result := FTracks.Count;
end;

function TMidiTracks.AddTrack(ATrack: TTrack): Integer;
begin
   Result := FTracks.Add(ATrack);
end;

procedure TMidiTracks.DeleteTrack(AIndex: Integer);
begin
  if (FTracks.Count -1 > AIndex) and (AIndex <= FTracks.Capacity) then
    FTracks.Delete(Aindex)
  else
   raise exception.Create('Index überschreitet das Maximum' + IntToStr(FTracks.Count -1));

end;
...
...
Procedure Play;
var
  i: Integer;
  iTrack: Integer;
begin
  PlaySong:= True;
  Label1.Caption:='Player Start';
  Button1.Enabled:= False;
  ComboBox1.Enabled:= False;

  i:= 0;   //der längste bespielte Track ist die Liedlänge
  while i < myMidiTracks.Track[0].Count  do //in diesem Fall ist es der Track 0
  begin
    for iTrack:= 0 to myMidiTracks.TrackCount -1 do// jeden Track holen
    begin
      if i <= myMidiTracks.Track[iTrack].Count -1 then//Track nur lesen wenn noch events vorhanden
      begin
        SpeedTime(TEvent(myMidiTracks.Track[iTrack].Items[i]).Deltatime );
        Tick:= GetTickCount;
        Delay(Tick + TempoWait - GetTickCount);

        PlayOrStopNote(TEvent(myMidiTracks.Track[iTrack].Items[i]).MidiEvent,
             TEvent(myMidiTracks.Track[iTrack].Items[i]).Wert1,
             TEvent(myMidiTracks.Track[iTrack].Items[i]).Wert2);
      end;
    end;

    inc(i);
   end;

  PlaySong:= False;
  Label1.Caption:= 'player stop';
  Button1.Enabled:= True;
  ComboBox1.Enabled:= True;
end;


Was nun fehlt ist natürlich der erste Teil von Dir, TTOn und das ganze sort und Umwandel usw, um es in die Tracks/Trackliste richtig zu machen. (Was jetzt noch manuell passiert)
myMidiTracks.Track[0].Add(TEvent.CreateEvent(0, $C0 + channel, $00, $00));// Event einfügen manuell

Aber diser Teil ist zu komplex, um ihn auseinander zu nehmen :gruebel:
Schnall ich nicht.:bawling:

Denn es müsste eigentlich nur der einzelne Aktive Track, aus der Trackliste, den ich bearbeite, dieses was Du mit(Sort, SortiereNachStartTick, writeDelay)usw machst umsetzten.

Das Speichern selbst, wird ja erst zum Schluss gemacht, wenn man speichern will.
Also Trackende (0,FF,2F,00), MTrk-Header und der MThd-FileHeader brauchen ja erst dann eingefügt werden!
Es reicht also erst mal nur die pure Trackliste(TMidiTracks = class(TObjectList))

Gruss ALf

_________________
Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1185
Erhaltene Danke: 98

Win7
DXE2 Prof, Lazarus
BeitragVerfasst: Fr 22.07.11 18:31 
Ich unterbreche mal eure traute Zweisamkeit und betue mich mal als Besserwisser ;-)
user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
Ich soll was beschreiben ! Ich kanns versuchen.
Eine 1/4note ist fix nicht veränderbar, errechnet sich aus 60000000microsec/120bpm = 500000, wurde mal festgelegt. allerdings werden die 1/4noten mit 480000 geschrieben Warum keine ahnung
Verändere ich den bpm Wert, erhalte ich die zu speichernde Geschwindigkeit für den Header, in diesem Fall währe es auch 500000 microsec.
...

Der Grund warum man auf 480000 kommt ist, das die Basis der 1/4 Note nicht 120bpm sondern 125bpm sind. Rechnet man damit kommt man auch auf den passenden Wert.

_________________
Solange keine Zeile Code geschrieben ist, läuft ein Programm immer fehlerfrei.
Ich teste nicht, weil ich Angst habe Fehler zu finden.