![]() |
AW: TMIDIPlayer2
Zitat:
Zitat:
Bedenke das ist ein Freeware Projekt ist also nicht ausgelegt für den Professionellen Bereich. Und nein ich möchte mir das nicht antun meine Zeit (gegen Bares) in das Projekt zu stecken es würde sich einfach nicht lohnen. Ich ändere etwas dran wenn ich zeit finde oder Lust dazu habe das soll nicht in MÜSSEN ausarten ;) gruss |
AW: TMIDIPlayer2 SysEx
Liste der Anhänge anzeigen (Anzahl: 3)
Hallo, sorry für mein Deutsch übersetzt mit Google Trans.
Ich hatte auch Probleme mit den SysEx und ich schaffte es, durch Änderung der Code TMidiPlayer2.pas beheben. Ich bin kein professioneller Programmierer, aber jetzt SysEx-Funktion. Ich lege Bearbeitungsverfahren TMidiDriver.DoOnMidiTimer. Ich habe Änderungen in Version 0.9.5.1 durchgeführt. Sicher wird es auch in den folgenden Versionen. Änderungen werden durch (****** JV *****) hervorgehoben. Einen schönen Tag noch. wolfmusic Modifizierten Code:
Delphi-Quellcode:
procedure TMidiDriver.DoOnMidiTimer;
var (****************************JV ******************************************) i, n: Integer; (****************************JV ******************************************) TickTime: LongWord; DeltaTime: LongWord; AMidiTrack: TMidiTrack; pEvent: pMidiEvent; EventCode: byte; ChannelNo: byte; ActiveNoteRemains: boolean; OutNote: byte; EventPositon: LongWord; (****************************JV ******************************************) SysExJv: array of Byte; (*Word*) (****************************JV ******************************************) begin if not Assigned(MidiFile) then Exit; TickTime := GetTickCount; if LastOutputTime = 0 then begin DeltaTime := TickTime - FStartTime; FCurrentTime := round(DeltaTime * FSpeed); end else begin DeltaTime := TickTime - LastOutputTime; FCurrentTime := FCurrentTime + round(DeltaTime * FSpeed); end; LastOutputTime := TickTime; FCurrentPos := MidiFile.Time2TickPos(FCurrentTime); // I have found a MIDI file which does not have the end of track mark. // Following sentences are for the case to stop playing forcibly. if FCurrentTime > (MidiFile.Duration + 300) then begin Suspend := true; // to prohibit calling DoOnMidiTimer in PlayThread if FStepMode then SendMessage(FPlayerHandle, WM_MIDI_EndOfTrack, 0, 1) else PostMessage(FPlayerHandle, WM_MIDI_EndOfTrack, 0, 1); exit; end; for i := 0 to MidiFile.TrackCount - 1 do begin AMidiTrack := MidiFile.GetTrack(i); if not AMidiTrack.EndOfTrack then with AMidiTrack do begin while (AMidiTrack.PlayPos < AMidiTrack.EventCount) do begin pEvent := GetEvent(PlayPos); EventPositon := pEvent^.Positon; if (Round(FCurrentPos) <= EventPositon) then break; if PEvent.Event = $FF then ProcessEvent(i, pEvent) else if AMidiTrack.Active then begin EventCode := pEvent^.Event and $F0; ChannelNo := pEvent^.Event and $0F; if pEvent^.Msg = '' then // Not a System Exclusive Message ? begin ActiveNoteRemains := IsActiveNote(ChannelNo); // The note number for drum channel defines the different percussion instruments, // So, we should not change that. if ChannelNo = DrumChannel then // Drum channel ? OutNote := pEvent^.Data1 // Output the adjusted note number for the Note On, Note Off and Note Aftertouch Events // by FPitch value. else if (EventCode = $80) or (EventCode = $90) or (EventCode = $A0) then begin OutNote := pEvent^.Data1 + FPitch; if (EventCode = $80) or ((EventCode = $90) and (pEvent^.Data2 = 0)) then begin if FChannelState[ChannelNo] then DeleteConvRecord(pEvent^.Event and $0F, pEvent^.Data1, OutNote) end else if FChannelState[ChannelNo] then AddConvRecord(pEvent^.Event and $0F, pEvent^.Data1, OutNote); end else OutNote := pEvent^.Data1; if FChannelState[ChannelNo] then MidiOut.PutShort(pEvent^.Event, OutNote, pEvent^.Data2) else begin if ActiveNoteRemains then begin // $B0 + ChannelNo : Control change, 123 : All Notes Off MidiOut.PutShort($B0 + ChannelNo, 123, pEvent^.Data2); ClearChannelRecord(ChannelNo); end; // Activate following 2 lines if we want to process Control change messages and // Program change messages regardless of channel's On/Off state. if (EventCode = $B0) or (EventCode = $C0) then MidiOut.PutShort(pEvent^.Event, pEvent^.Data1, pEvent^.Data2); end; end else if (not NoExclusiveMsg) then // if FChannelState[ChannelNo] then (********************************************JV ******************************************) // original MidiOut.PutLong(pAnsiChar(pEvent^.Msg), Length(pEvent^.Msg)); if (EventCode = $F0) and (pEvent^.Msg <> '') then {if pEvent^.Msg <> '' then} begin SetLength(SysExJv, 0); SetLength(SysExJv, Length(pEvent^.Msg) + 1); SysExJv[0]:= $F0; for n:= 0 to Length(pEvent^.Msg) - 1 do begin SysExJv[N + 1]:= Byte(pEvent^.Msg[N + 1]); end; MidiOut.PutLong(@SysExJv[0], Length(SysExJv)); end; (********************************************JV ******************************************) // if FChannelState[ChannelNo] then if FChannelState[ChannelNo] or (pEvent^.Msg <> '') or (EventCode = $B0) or (EventCode = $C0) then if FStepMode then SendMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent)) else PostMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent)); end; // Messages for meta event are posted in the procedure ProcessEvent. { if FStepMode then SendMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent)) else PostMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent)); } PlayPos := PlayPos + 1; end; end; end; if FStepMode then SendMessage(FPlayerHandle, WM_MIDI_PosUpdate, FCurrentTime, FCurrentPos) else PostMessage(FPlayerHandle, WM_MIDI_PosUpdate, FCurrentTime, FCurrentPos); end; |
AW: TMIDIPlayer2
Danke!
Ersetzt mal bitte die procedure TMidiDriver.DoOnMidiTimer in der MidiPlayer2.pas
Delphi-Quellcode:
Sollten dann immer noch Probleme auftauchen in Verbindung mit den Sytem Exclusiven Messagen..
procedure TMidiDriver.DoOnMidiTimer;
var i: Integer; TickTime: LongWord; DeltaTime: LongWord; AMidiTrack: TMidiTrack; pEvent: pMidiEvent; EventCode: byte; ChannelNo: byte; ActiveNoteRemains: boolean; OutNote: byte; EventPositon: LongWord; tmpSuspend: boolean; SysExMsg: AnsiString; begin if not Assigned(MidiFile) then Exit; TickTime := GetTickCount; if LastOutputTime = 0 then begin DeltaTime := TickTime - FStartTime; FCurrentTime := round(DeltaTime * FSpeed); end else begin DeltaTime := TickTime - LastOutputTime; FCurrentTime := FCurrentTime + round(DeltaTime * FSpeed); end; LastOutputTime := TickTime; FCurrentPos := MidiFile.Time2TickPos(FCurrentTime); if FFirePosition > 0 then // if we set to fire on specified Position begin if FCurrentPos >= FFirePosition then begin if not FFired then // to suppress multiple events on specified Position begin FFired := true; // exit if return value is not 0 if SendMessage(FPlayerHandle, WM_MIDI_ArrivedAtFirePos, FCurrentTime, FCurrentPos) <> 0 then exit; end; end else if FFired then FFired := false; end; // Set back to the start position of specified interval, when player reachs the end position // of specified interval, if we activated repeat-interval function. tmpSuspend := false; if FRepeatSection then if FCurrentPos >= FEndPos then begin tmpSuspend := true; Suspend := true; MidiOut.SentAllNotesOff; SetCurrentPos(FBeginPos); // PostMessage(FPlayerHandle, WM_MIDI_PosChangeByRepeat, FBeginPos, FCurrentPos); end; // I have found a MIDI file which does not have the end of track mark. // Following sentences are for the case to stop playing forcibly. if FCurrentTime > (MidiFile.Duration + 300) then begin Suspend := true; // to prohibit calling DoOnMidiTimer in PlayThread if FStepMode then SendMessage(FPlayerHandle, WM_MIDI_EndOfTrack, 0, 1) else PostMessage(FPlayerHandle, WM_MIDI_EndOfTrack, 0, 1); exit; end; for i := 0 to MidiFile.TrackCount - 1 do begin AMidiTrack := MidiFile.GetTrack(i); if not AMidiTrack.EndOfTrack then with AMidiTrack do begin while (AMidiTrack.PlayPos < AMidiTrack.EventCount) do begin pEvent := GetEvent(PlayPos); EventPositon := pEvent^.Positon; if (Round(FCurrentPos) <= EventPositon) then break; // Got the verse change event ? // ( * This is not a standard MIDI event, It's just to support custom specification) if (pEvent^.Event = $B0) and (pEvent^.Data1 = $14) then // verse change event ? begin if FVerseNum <> pEvent^.Data2 then begin PostMessage(FPlayerHandle, WM_MIDI_VerseChange, FVerseNum, pEvent^.Data2); FVerseNum := pEvent^.Data2; end; PlayPos := PlayPos + 1; continue; end; if PEvent.Event = $FF then ProcessEvent(i, pEvent) else if AMidiTrack.Active then begin EventCode := pEvent^.Event and $F0; ChannelNo := pEvent^.Event and $0F; if pEvent^.Msg = '' then // Not a System Exclusive Message ? begin ActiveNoteRemains := IsActiveNote(ChannelNo); // The note number for drum channel defines the different percussion instruments, // So, we should not change that. if ChannelNo = DrumChannel then // Drum channel ? OutNote := pEvent^.Data1 // Output the adjusted note number for the Note On, Note Off and Note Aftertouch Events // by FPitch value. else if (EventCode = $80) or (EventCode = $90) or (EventCode = $A0) then begin OutNote := pEvent^.Data1 + FPitch; if (EventCode = $80) or ((EventCode = $90) and (pEvent^.Data2 = 0)) then begin if FChannelState[ChannelNo] then DeleteConvRecord(pEvent^.Event and $0F, pEvent^.Data1, OutNote) end else if FChannelState[ChannelNo] then AddConvRecord(pEvent^.Event and $0F, pEvent^.Data1, OutNote); end else OutNote := pEvent^.Data1; if FChannelState[ChannelNo] then begin // if event code is Bank select or Program change, Skip if pre-assigned instrument // should be applied if (EventCode <> $B0) and (EventCode <> $C0) then MidiOut.PutShort(pEvent^.Event, OutNote, pEvent^.Data2) else if CanOutput(pEvent) then MidiOut.PutShort(pEvent^.Event, OutNote, pEvent^.Data2); end else begin if ActiveNoteRemains then begin // $B0 + ChannelNo : Control change, 123 : All Notes Off MidiOut.PutShort($B0 + ChannelNo, 123, pEvent^.Data2); ClearChannelRecord(ChannelNo); end; // Activate following 2 lines if we want to process Control change messages and // Program change messages regardless of channel's On/Off state. if (EventCode = $B0) or (EventCode = $C0) then // if event code is Bank select or Program change, Skip if pre-assigned instrument // should be applied if CanOutput(pEvent) then MidiOut.PutShort(pEvent^.Event, pEvent^.Data1, pEvent^.Data2); end; end else if (not NoExclusiveMsg) then // for (pEvent^.Msg <> '') if (EventCode = $F0) or (EventCode = $F7) then // $F7 - used as a Message continuation mark begin // if FChannelState[ChannelNo] then // MidiOut.PutLong(pAnsiChar(pEvent^.Msg), Length(pEvent^.Msg)); // * missed event code // * Bug fix : correction for missed event code (01 Jun 2015) SysExMsg := AnsiChar(EventCode) + pEvent^.Msg; MidiOut.PutLong(@SysExMsg[1], Length(SysExMsg)); end; // if FChannelState[ChannelNo] then if (FChannelState[ChannelNo] or (pEvent^.Msg <> '')) and (EventCode <> $B0) and (EventCode <> $C0) then begin if FStepMode then SendMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent)) else PostMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent)); end else if (EventCode = $B0) or (EventCode = $C0) then if CanOutput(pEvent) then if FStepMode then SendMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent)) else PostMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent)); end; // Messages for meta event are posted in the procedure ProcessEvent. { if FStepMode then SendMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent)) else PostMessage(FPlayerHandle, WM_MIDI_Event, i, integer(pEvent)); } PlayPos := PlayPos + 1; end; end; end; if FStepMode then SendMessage(FPlayerHandle, WM_MIDI_PosUpdate, FCurrentTime, FCurrentPos) else PostMessage(FPlayerHandle, WM_MIDI_PosUpdate, FCurrentTime, FCurrentPos); if tmpSuspend then Suspend := false; end; Dann bitte eine/die Datei hochladen wo das Problem auftritt. Wenn die Problem durch die Änderung behoben sein sollten lade ich ein neues Archiv hoch. gruss |
AW: TMIDIPlayer2
Hallo,
gestern war bei uns Feiertag und darum blieb mal etwas Zeit für den MidiPlayer. Neue Erkenntniss: Das von mir geschilderte Problem hat nicht nur mit den SysEx zu tun - das habe ich jetzt übrigens durch Priority=HIGHEST verbessern können - sondern mit langen Noten. Besonders wenn sie sich überschneiden, was bei Flächensounds (Streicher, Orgel...) schon mal vorkommt, scheint es so zu sein, dass die Note-Off's nicht am Soundmodul ankommen. Ein Indiz dafür ist unter Anderem: Wenn ein Flächensound durch z.B. ein Piano ersetzt wird, dann ist das Phänomen weg. Weil das Problem nur schwer mit dem Debugger lösbar ist, bräuchte man jetzt mal ein Tool, das die im Midifile vorhandenen Events und die am Expander tatsächlich ankommenden Events vergleicht. Dann wäre es auch eine gesicherte Aussage. Den Quellcode habe ich mir zwar angesehen, aber da steige ich momentan noch nicht bzw. zu wenig durch. Alternative: Vielleicht hat Silhwan Hyun ja eine Idee? Wie schon gesagt, wenn es funktioniert bezahle ich auch gerne dafür. |
AW: TMIDIPlayer2
Zitat:
Kein Problem.. :) Zitat:
Zitat:
Bisher wurde auch kein Feedback bezüglich der Änderung im TMidiDriver.DoOnMidiTimer gegeben. Von dir die Aussagen sind etwas undurchsichtig (Ein Indiz).. Was haben unsere Änderungen bzgl. SysEx denn nun ergeben? gruss |
AW: TMIDIPlayer2
Zitat:
Ich bin heute schon den ganzen Tag am Quellcode lesen und verstehen. Dabei bin ich auf ein paar Ungereimtheiten gestoßen die ich noch nicht zuordnen oder eindeutig beurteilen kann. Beispielsweise die Property Pitch in v0.9.4 vom 27 May 2012. FPitch wird nirgendwo initialisiert. Ist vielleicht auch nicht nötig, weil man davon ausgehen kann, dass es normalerweise "0" ist. Aber kann man auch sicher sein? Nachdem ich in den beiden constructoren mal "FPitch := 0" ergänzt habe, laufen wieder ein paar Midifiles mehr d.h. ein paar Notenhänger sind verschwunden. SysEx: Verlorene SysEx habe ich heute mit MidiOx keine mehr gefunden. Zumindest nicht auf meinem Entwickler-PC und meinem Test-PC. Wie schon gesagt, die Priority hat in der Hinsicht geholfen. Aber nicht auf meinem Auftritt-PC mit einem 1.6-er Atom. Der ist davon unbeeindruckt :stupid: Es sind aber immer noch etwa 1/3 meiner Midi's die nicht laufen. Sorry, aber ich werde mich jetzt vorerst mal ausklinken weil die Freizeit derzeit eh sehr knapp ist. Die (Musik-)Saison hat begonnen und Brötchen verdienen muss ich auch noch so nebenbei :) |
AW: TMIDIPlayer2
Bzgl. FPitch
Zitat:
Zitat:
Zitat:
An den Änderungen oder ausschließlich an der Priority. Ich behaupte einfach mal das es daran lag weil wir die SysExMsg (Events) nicht behandelt haben. Zitat:
gruss |
AW: TMIDIPlayer2
Zitat:
Hast du keinen MidiOx oder etwas Vergleichbares? Dann könntest du das auch kontrollieren bzw. nachvollziehen: Der MidiPlayer sendet bei einem im Midifile enthaltenen SysEx nur ein einziges Byte. Ein Bug den ich noch nicht gefunden habe, denn PutLong funktioniert prinzipiell. Mit der Erhöhung der Priorität wird wohl lediglich der SysEx etwas schneller verarbeitet (sprich die Routine kommt etwas schneller zurück) und dann passt das auch besser im Timing, denn in einem SysEx wird z.B. das KanalRouting geändert, was natürlich vor der ersten Note schon erledigt sein muss. Zitat:
Hier öffentlich als Dateianlage geht nicht, weil meine Midi's natürlich ganz reell gekauft wurden und somit dem Copyright des Herstellers unterliegen. Ich müsste sie also z.B. nach 15 Sekunden abschneiden, dann wären sie für den normalen Einsatz unbrauchbar und mein Gewissen wäre beruhigt. |
AW: TMIDIPlayer2
Zitat:
Mich interessiert es weniger ob du etwas geändert hast, sondern ob unsere Änderung im vergleich zu vorher irgendwelche Auswirkungen auf deine nicht funktionierenden Midi-Dateien hat. Wie schon gesagt haben wir die SysEx Events vorher nicht behandelt. Die Änderung! Nochmal zur Veranschaulichung.
Delphi-Quellcode:
if (not NoExclusiveMsg) then // for (pEvent^.Msg <> '')
if (EventCode = $F0) or (EventCode = $F7) then // $F7 - used as a Message continuation mark begin // if FChannelState[ChannelNo] then // MidiOut.PutLong(pAnsiChar(pEvent^.Msg), Length(pEvent^.Msg)); // * missed event code // * Bug fix : correction for missed event code (01 Jun 2015) SysExMsg := AnsiChar(EventCode) + pEvent^.Msg; MidiOut.PutLong(@SysExMsg[1], Length(SysExMsg)); end; Zitat:
Aber verstehe bitte auch das so keine "Fehler?" behoben werden können. Ohne das wir einen Vergleich ziehen können. (Datei.. analysieren) gruss |
AW: TMIDIPlayer2
Hallo,
erst gestern habe ich mir die aktuelle Version nochmals runtergeladen. Selbst da ist der von dir zitierte Codeausschnitt nicht enthalten. Ich werde es heute bei Gelegenheit ändern und dann testen. |
AW: TMIDIPlayer2
Zitat:
Hatte aber darum gebeten... Zitat:
![]() gruss |
AW: TMIDIPlayerComp
Neue Version online unter GNU General Public License.
Bitte die alte Komponente wegen Versions Konflikt vorher deinstallieren. TMIDIFile2, TMIDIPlayer2 und TSheetMusic. Silhwan hat die "Midi Sheet Music" class, written in c# by Madhav Vaidyanathan, nach der Delphi Komponente "TSheetMusic" portiert. Mein Dank geht also an ihm. gruss |
AW: TMIDIPlayerComp
Neue Version..
Änderungen siehe v0.9.1 gruss |
AW: TMIDIPlayerComp
Neue Version..
Änderungen siehe v0.9.1.1 gruss |
AW: TMIDIPlayerComp
Hallo Midifreunde und Delphianer,
ich habe an MidiCompPackage etwas weitergeschrieben und ein paar wichtige Features dem Ganzen spendiert. Im Übrigen, danke an EWeiss für die Arbeitsgrundlage. Änderungen: - PosDisplay - Taktwechsel - Bindenoten über Taktende mit Bezierkurven - Noten Font - Transport Steuerung - Noten-Eventanzeige Fertig ist das noch lange nicht und es können durchaus noch Fehler d'rin sein. Weiter entwickelt habe ich in Delphi 5, so dass ich viele Elemente (Hash Dictionaries) ersetzen musste. Am Ende habe ich noch mal alles in D2009 kompiliert und bei mir läuft das unter Win7-64, hoffe bei Euch auch. Umgeschrieben habe ich auch auf dynamische Erzeugung der Komponenten, so dass man nichts erst installieren muss und vieles andere mehr. Nun zu meinem Problem: Es gibt zwei SplitChannels Funktionen in MidiFile2.pas und MidiFile.pas. Diese erzeugen unterschiedliche Anzahlen von Tracks, siehe beigelegte Midi-Files von mir. Die Funktion SetupMenus bezieht die Tracks von MidiFile.pas und MenuMuteTrackClick von MidiFile2.pas. Das Muten eines Tracks wird dann falsch zugeordnet. Hier komme ich nicht weiter. Es wäre nett, wenn EWeiss mir sagen könnte, wie das gedacht war, danke. PS.: Bitte die Portierung nach D5 nicht ernst nehmen. Wie gesagt, am Ende habe ich in D2009 kompiliert. Freundliche Grüße Klaus Schaaff |
AW: TMIDIPlayerComp
MidiFile.pas gehört zur Komponente Sheetmusic (Sheetmusic ist eine Komponente in der Komponente MIDIPlayerComp)
Diese soll eigentlich nur in Verbindung mit Sheetmusic verwendet werden. MididFile2 ist teil der Hauptkomponente MIDIPlayerComp. Kann aber nochmal bei Silhwan nachfragen. Denke aber das es mit der Portierung zu tun hat und er den Player nicht mit Sheetmusic kombinieren wollte. Zitat:
Aber egal.. PS: Ansonsten super Arbeit Klaus ;) Dein Demo gefällt mir sehr gut. gruss |
AW: TMIDIPlayerComp
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo EWeiss,
danke für die schnelle Antwort und Deine Hinweise. Bei mir existiert ein älteres Projekt "MidiPlayer" aus Delphi 5 siehe Anhang, deshalb die Portierung nach D5. Mir ist noch unklar welche Intension besteht hinsichtlich Deines Projekts. Will man ein einfaches Werkzeug entwickeln das im Wesentlichen die Grundfunktionen für Karaokebearbeitung enthält, oder eine Expertensoftware für Musiker, ein echtes Sequenzerprogram. Speziell hier habe ich festgestellt, dass die Grundstruktur von MidiComPackage Hindernisse enthält, um weitere Features einzuarbeiten. Beispiel: Vielleicht hast Du mal eine Note angeklickt in meiner Version. Dann werden die Werte in den kleinen Editoren unterhalb der Transportsteuerung mit den Werten der Note belegt. Mein Ziel wäre, ändert man den Anfang der Note, sollte MusicSheet darauf reagieren und die Note an neuem Platz darstellen. Die Grundstruktur von MusikSheet berechnet aber immer nur einen kompletten Score. Für seqmentierte Berechnungen hat die Unit keine Grundlagenstruktur. Genauso ändere ich Velocity einer Note, sollte bei Play das hörbar werden. All das, rückwärtige Zugriffe, Schnittstellen auf die Midi-Daten, sind in der bisherigen Struktur nur schwer zu realisieren. Dennoch ist der Score an sich eine hervorragende Leistung. Grund genug, um daran weiter zu arbeiten. Hier fehlen noch Features, die das Notenbild einem echten Notenbild und der Arbeitsweise eines Musikers entsprechen und annähern. Das sind: - Quantisierung des Notenbilds - Korrekte Darstellung von Triolen und n-Tolen - Kanalbasierte Mehrstimmigkeit eines Notensystems. Channel 1 = Oberstimme, Channel 2 = Mittelstimme Channel 3 = Bassstimme diese beliebig zuweisbar - Akkoladen - Textdarstellung der Systeme System 1 = Viola System 2 = Continuo - Weitere Notenschlüssel Violin hoch 8 Violin unter 8, Sopran, Tenor etc. - Legatobögen - Korrekte Notengruppierungen, 8tel, 16tel Balken. Das sind Ansprüche, wo man mir zur Antwort geben kann: Kauf dir doch Cubase. Ich hab Cubase und acht andere. Keins genügt mir für alles. Manchmal schreibe ich mir eigene Midi-Funktionen in meinen MidiPlayer damit ich bestimmte Dinge realisieren kann. Da ist es auch, warum diese Arbeit von Dir so viel wert ist. Den PianoRoll schaue ich mir mal an, das kann aber dauern. Momentan hadere ich an der Grundstruktur, um überhaupt weitere Features einzubauen zu können. Ich hänge mal meinen MidiPlayer an, wo nicht alles funktioniert, wo man aber sehen kann, wo ich hin will und wo bei mir schon fertige Komponenten existieren. Meine bisherige Erweiterung von Editoren: Laufanzeige, Locatoren, Taktanzeige, Tempo usw. ist noch unfertig. Die Unit CbEdit.pas sollte nicht als Komponente in Delphi installiert werden, da der Designmodus vollkommen fehlt. Hier war meine Intension den Traffic von Messages in der VCL so weit zu minimieren, das nie Störungen der Midi-Wiedergabe entstehen. Bisher ist das nicht vollständig von mir. Sequenzerprogramme sind neben CAD-CAM Systemen das Aufwendigste was Programmierer machen können. Dagegen sind Datenbankanwendungen steuerungstechnisch nur ein kleiner Kühlschrank und Sequenzersoftware ein Atomkraftwerk. Mal so weit Klaus Schaaff |
AW: TMIDIPlayerComp
Ok..
Der Unterschied ist folgender. TMidiFile2 enthält einen NICHT Notentrack Track 0 enthält keine Noten NUR Steuerereignisse. Ein nicht Noten Track ist notwendig um Midi Dateien abspielen zu können. TMidiFile: schließt den Track ohne Noten aus weil ein NICHT Noten Track für die Anzeige auf dem Midi\Notenblatt nutzlos ist. Hoffe das hilft weiter. PS: Ich sehe aber bei deinen Antworten das du über große Kenntnisse hinsichtlich Midi(Sequenzer) verfügst. Verbesserungen sind immer willkommen. In dem Sinne :) Zitat:
Es hat sich mit der Zeit so Entwickelt wie es ist. Aber wie gesagt Verbesserungen oder Erweiterungen steht nichts im Wege. Zitat:
Ich müsste dazu Midi Standards verwenden also explicit für den Miditracker Würde bedeuten das ich mein eigenes Format entfernen muss da bin ich noch am hadern. gruss |
AW: TMIDIPlayerComp
Hallo EWeiss,
danke für die Info. Meine Absicht war nur zu der hervorragenden Arbeit etwas beizusteuern, von der ich sehr profitiert habe. Ich hoffe Ihr könnt es verwenden. Grüße Klaus Schaaff |
AW: TMIDIPlayerComp
Zitat:
Davon ausgenommen Siehe! §1 ![]() PN.. Habe ich bzgl. des Vermerks an dich gesendet. gruss |
AW: TMIDIPlayerComp
Hallo EWeiss,
sorry, das habe ich nicht bedacht. Mein selbst geschriebener Code-Formater hat das per Voreinstellung (alles was vor unit steht löschen) entfernt. Tut mir leid. Ich hoffe es ist kein Schaden entstanden. Das zip Archiv "08 MidiCompPackage D5.zip" habe ich wieder gelöscht. Ich wüßte auch ehrlich nicht wie und welche Änderungen ich da kennzeichnen müsste. Wichtig war mir, dass Du meine Version im Quelltext hast. Aber da hängen ja noch andere im GNU PBL d'rin, stimmt vollkommen. In meiner Info.txt habe ich skizzenartig für mich selbst die Änderungen festgehalten. Wichtigste Änderung von er Du profitieren solltest: function TMidiFile.ReadTrack(...): TListMidiEvent; Diese wurde komplett neu geschrieben, da sie Fehler verursacht. Bitte entschuldige meinen Lapsus, es war keine Absicht. Klaus Schaaff |
AW: TMIDIPlayerComp
Zitat:
Und akzeptiere die Entschuldigung. Mir ist das aufgefallen als ich versucht habe die Änderungen zu vergleichen und sie als neue Version der Community zur Verfügung stellen wollte.. Mit deinen Änderungen im Header vermerkt natürlich. Allerdings war mir das nicht möglich da wie schon angemerkt (über PN) alle Urheberrechte entfernt wurden. Ich bin zwar NUR ein mittelmäßiger Schreiber(Programmierer) destotrotz behalte ich mir vor das mein Copyright bzw.. Mitarbeit aus den Headern nicht entfernt wird. Wie andere das Handhaben ist ihre Sache.. Ich allerdings bin da eigen. Gut vergessen wir das da es ein versehen "Code-Formater bedingt" war. Hätte deine Änderungen gern übernommen aber so nach der Formatierung ist das auffinden der geänderten Passagen leider nicht möglich. gruss |
AW: TMIDIPlayerComp
Hallo EWeiss,
Die Übernahme meiner Änderungen bedeuten sehr viel Arbeit. Denn es erfordert all das nachzuvollziehen, wie es mir mit deinem Quelltext erging. Andererseits bedarf es einer persönlichen Abschätzung, wie viel einem selbst diese Änderungen wert sind. Das ist ganz unverbindlich Deine Entscheidung. Das könnte weiter helfen: ![]() Das Tool ist hervorragend und reduziert den Aufwand veränderte Quelltexte auf einen Blick zu vergleichen. Ich habe das weiter ausgebaut zu einem universellen Verwaltungstool für Pascal. Code-Formatieren, Dateien suchen, Ausdrücke suchen, Ersetzen usw. Damit reduziert sich die Arbeit auf weniger als 5% und man lernt, wie Pascal Texte aussehen sollten, um mit ihnen archivtechnisch, sowie prozessoptimiert arbeiten zu können - das ist aber Pascal Philosophie und ein anderes Thema. Weiter habe ich mittlerweile erkannt, ohne Änderungen der Grundstruktur an MidiCompPackage, kann ich weitere Features nicht einbauen. Ich werde deshalb je nach Zeit die Grundstruktur erst mal überarbeiten und verabschiede mich vorerst von diesem Thread. Liebe Grüße Klaus Schaaff |
AW: TMIDIPlayerComp
Zitat:
Zitat:
gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:13 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-2025 by Thomas Breitkreuz