Autor |
Beitrag |
Narses
Beiträge: 10181
Erhaltene Danke: 1254
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 18.07.11 16:32
Moin!
ALF hat folgendes geschrieben : | Allerdings gleich ne frage dazu!
[...]
Fange ich also bei meinem 'Grid bei startposition null an steht dann da
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... ).
ALF hat folgendes geschrieben : | 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... )
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. (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
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: 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 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.
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
Beiträge: 10181
Erhaltene Danke: 1254
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 18.07.11 21:19
Moin!
ALF hat folgendes geschrieben : | 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 Das ist doch schon was, oder?
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.
ALF hat folgendes geschrieben : | 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.
ALF hat folgendes geschrieben : | oder bei 1000000 columen? Oder ist dies überdimensioniert? Ich weiss es nicht? |
Was haben die Spalten denn damit zu tun? Also wie gerade oben gesehen, 1.000.000 Midi-Ereignisse sollten pro Track kein Problem darstellen.
ALF hat folgendes geschrieben : | 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.
ALF hat folgendes geschrieben : | 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.
ALF hat folgendes geschrieben : | Es ist absolut der Hammer die Unit.
ich hätte Jahre dazu benötigt |
Danke danke 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... 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
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: Mo 18.07.11 22:11
Ich merk schon, ich kann mich nicht richtig ausdrücken.
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.
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 Event: Byte 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]);... ...
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
Beiträge: 10181
Erhaltene Danke: 1254
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mo 18.07.11 23:24
Moin!
ALF hat folgendes geschrieben : | 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:
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, 0, 480)); Lied.Add(TTon.Create(74, 480, 480)); Lied.Add(TTon.Create(76, 960, 480)); Lied.Add(TTon.Create(77, 1440, 480)); Lied.Add(TTon.Create(79, 1920, 960)); Lied.Add(TTon.Create(79, 2880, 960)); Lied.Add(TAkkord.Create(72, 4000, 1920)); 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; |
ALF hat folgendes geschrieben : | 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:
Delphi-Quelltext 1: 2:
| 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:
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); virtual; abstract; procedure WriteToMIDI(AMIDIDevice: TMIDIDevice; const ADelay: Integer); virtual; abstract; 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. Dann brauchst du hier noch eine entsprechende Methode:
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:
ALF hat folgendes geschrieben : | Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| type TEvent = class(Tobjekt) private DeltaTime: integer Event: Byte Wert1: Byte Wert1: Byte end; | |
ALF hat folgendes geschrieben : | 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 ), 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.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
ALF
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: Di 19.07.11 02:59
MidiOut ist im Prinzip nichts weiter als vom MMSystem das Handle(+midievents) für die Ausgabe
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure PlayOrStopEvent(Event, Wert1, Wert2); var midiMsg: Longint; begin midiMsg := (event + Wert1 + Wert2); midiOutShortMsg(midiOut, midiMsg); end; | Benötige ich ja, wenn ich im Grid ne Note Zeichne, um zu hören ob ich die richtige Note angespielt habe 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.
Die längste Midfile die ich mal hatte war glaube ich 20min lang. Soviel ich weiss gibt es aber ganze Konzertelängen
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
Beiträge: 10181
Erhaltene Danke: 1254
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Di 19.07.11 11:57
ALF hat folgendes geschrieben : | MidiOut ist im Prinzip nichts weiter als vom MMSystem das Handle(+midievents) für die Ausgabe
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| procedure PlayOrStopEvent(Event, Wert1, Wert2); var midiMsg: Longint; begin midiMsg := (event + Wert1 + Wert2); midiOutShortMsg(midiOut, midiMsg); end; | |
Aha, spannend. Aber irgendwie sieht der Code nicht so wirklich lauffähig aus. 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.
ALF hat folgendes geschrieben : | 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.
ALF hat folgendes geschrieben : | 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.
ALF hat folgendes geschrieben : | 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
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: Di 19.07.11 19:49
Sorry das es so spät wurde(Urlaub vorbei und schon geht der Stress los)
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 Narses: 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
Beiträge: 10181
Erhaltene Danke: 1254
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 20.07.11 23:34
Moin!
ALF hat folgendes geschrieben : | 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... Dafür sind wohl ein zwei Änderungen in der UMidiObject-Unit nötig... Kann bischen dauern.
cu
Narses
Einloggen, um Attachments anzusehen!
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
ALF
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: Do 21.07.11 00:17
mh, wusste nicht das Du ein Klavier bauen wolltest
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 .
Man muss ja das Rad nicht ganz neu erfinden.
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
Gruss Alf
_________________ Wenn jeder alles kann oder wüsste und keiner hätt' ne Frage mehr, omg, währe dieses Forum leer!
|
|
ALF
Beiträge: 1085
Erhaltene Danke: 53
WinXP, Win7, Win10
Delphi 7 Enterprise, XE
|
Verfasst: Fr 22.07.11 15:03
So ein kleiner Teil hab ich erst mal für mich umgesetzt.
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:
| 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; TTrack = class(TObjectList) end; 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; while i < myMidiTracks.Track[0].Count do begin for iTrack:= 0 to myMidiTracks.TrackCount -1 do begin if i <= myMidiTracks.Track[iTrack].Count -1 then 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
Schnall ich nicht.
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
Beiträge: 1322
Erhaltene Danke: 117
Win 10
RIO, CE, Lazarus
|
Verfasst: Fr 22.07.11 18:31
Ich unterbreche mal eure traute Zweisamkeit und betue mich mal als Besserwisser
ALF hat folgendes geschrieben : | 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.
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
|