|
![]() |
|
Registriert seit: 29. Jun 2010 Ort: Neustrelitz 393 Beiträge Delphi 7 Enterprise |
#1
![]() Habe ich dir doch oben ausführlich beschrieben
![]() Wenn ich es richtig verstanden habe, speicherst du die gezeichnete Notenlänge in Deiner Datei ab? Hast Du dir mal diesen ![]() ![]() Wie soll ich die Daten vom Grid trennen?
Also das ist beim besten willen nicht möglich. Wie willst du sonst die Arrays mit Daten füttern wenn du quasi nichts hast? .... Wie also soll ich ohne das Grid das Array füllen? Wie soll ich ohne Grid die Noten Visualisieren ? Wie willst du ohne Grid festlegen wann und welche Note gespielt wird? Du liest eine Mid ein! Was ist jetzt das Problem, die Noten kannst du in ein normales Array laden, auch ohne Grid. Takt und BPM liegen auch vor. Aus diesen Daten und noch andere, errechnet sich was eine 4tel note ist, halbe oder 16. als reiner Zahlenwert! Würdest Du nun ne visualisierug mit Notenlienen machen ist es auch egal ob Du 40pixel für eine Note nimmst oder nur 10pixel. Enscheident ist jetzt, welche Note wo gezeichnet wird! Ok zum Grid! Wenn du beim einlesen von Middateien nun die reinen Notenwerte hast (die liegen in ein Array) kannst Du nun die Anzeige machen wie du willst! weil Du das Array nicht änderst sondern nur die Anzeige! Ok editieren: auch hier gibst Du Takt und BPM vor, Zeichnest die Note, egal in welcher Auflösung, siehe mein simpel Beispiel. Selbst daraus errechnet sich jetzt welche Note und wie lang sie ist. Diesen wert speicherst Du im array, wie beim einlesen! Änderst Du jetzt die Auflösung wird die Note aus denm array geholt und gezeichnet! Auch hier wieder mein simpel Beispiel. Das selbe gilt für das speichern deines Formates, du must nicht die Darstellung speichern(wenn ich es richtig verstanden habe) sondern nur die Note und ihre länge zum Takt und nicht wie lang sie gezeichnet werden muss! Der rest ist dann so wie ich es beschrieben habe. Ich befürchte aber das das umstellen schwerer sein wird als es so zu lassen! Weil Du dich auf 12x12 fixierst hast! Gruss alfold Geändert von alfold (19. Mai 2011 um 22:37 Uhr) |
![]() |
EWeiss
(Gast)
n/a Beiträge |
#2
![]() OK fangen wir hinten an!
Du liest eine Mid ein! Was ist jetzt das Problem, die Noten kannst du in ein normales Array laden, auch ohne Grid. Takt und BPM liegen auch vor. Nur das ich Sie nach dem einlesen in mein Array auf meinen DateiTyp anpasse (Parsen). ![]() ist es auch egal ob Du 40pixel für eine Note nimmst oder nur 10pixel.
Enscheident ist jetzt, welche Note wo gezeichnet wird! das mußt du doch sehen wenn du in einer reihe im Grid Klickst. Nochmal.. 0..15 Spur die legst du fest indem du auf EditTrack 1 klickst 0..1000 Noten.. Scroll das grid ganz runter wenn du nun in der Spalte 0 und Letzte Reihe(72) klickst dann wird im Array Grid die Note "C0" gespeichert Wird diese erweitert also als halbe Note ausgelegt dann wird dem Array eine (1000 + 72) = 1072 hinzugefügt. Im Array steht jetzt also 72, 1072. Start und Fortlaufende Note = eine 2/4 Note bei einem 4/4 Takt. Diese Daten werden dann in der *.mtf Datei abgespeichert. ![]() kannst Du nun die Anzeige machen wie du willst! weil Du das Array nicht änderst sondern nur die Anzeige!
Die Anzeige ist vorgegeben pro Note 12x12 ![]() Das selbe gilt für das speichern deines Formates, du must nicht die Darstellung speichern(wenn ich es richtig verstanden habe) sondern nur die Note und ihre länge zum Takt und nicht wie lang sie gezeichnet werden muss!
Aber du scheinst da irgend etwas nicht zu verstehen. Ob ich meine Note nun in Hex oder Dezimal in meine Datei schreibe ist doch wurscht. Die Frage ist doch wie ich die Daten nachher wieder einlese (Parse). Und das es funktioniert wenn du mein Format liest siehst du doch. ![]() Ich befürchte aber das das umstellen schwerer sein wird als es so zu lassen! Weil Du dich auf 12x12 fixierst hast!
Ich habe das Prog so ausgelegt das die Noten nicht in Pixeln sondern in Quadern gezeichnet werden und um das umzulegen auf Pixel da kann ich direkt alles wieder neu machen. Und das scheinst du nicht zu verstehen. Habe dir das schon 20 Beiträge vorher mitgeteilt. Das ich im moment grenzen unterliege weil meine Grafik(Grid) auf eine feste größe ausgelegt ist. Vielleicht verstehst du eins nicht das ist NonVCL es gibt keine komponente die man mal ebend auf die Form klatscht sondern es ist alles Handgemacht mit GDI+. Nur für das grid ca. 4 Wochen Arbeit(na ja ist Hobby). Wenn ich das ändere muss ich quasi alles neu machen angefangen bei den Tool Button. Im moment geht es eh nicht.. Da ich mit einer 6 Segment Anzeige von hand gezeichnet GDI+ beschäftigt bin. Das hat vorrang da ich damit die Zeitanzeige verwirklichen will. Passend zu meinem Design natürlich. Das bedeutet Bilder zeichnen Quelltext schreiben und dann muss es auch noch funktionieren ![]() gruss Geändert von EWeiss (20. Mai 2011 um 01:31 Uhr) |
![]() |
Registriert seit: 29. Jun 2010 Ort: Neustrelitz 393 Beiträge Delphi 7 Enterprise |
#3
![]() Eine Note.. bsp. 50
Erweiterst du diese dann bekommst du einen Eintrag von "50, 1050" 1050 steht für Fortgesetzte Note(rede jetzt nur vom Grid) in dem Fall hättest du dann 2x48 Ticks also ein halbe note 2/4. Wobei 50 die StartNote und mit 1000 addiert die Folgenden sind. "50, 1050, 1050, 1050" wäre dann eine ganze. Wenn du dich nun im 1/16 Grid befindest und dort eine ganze Note zeichnest sieht das ganze so aus. "91,1091,1091,1091,1091,1091,1091,1091,1091,10 91,1 091,1091,1091,1091,1091,1091" So jetzt schalte mal zurück nach 1/8 Note.. Was denkst du wie es dann aussieht Dann halbiert ich das ganze schaltest du nun nach 1/4 dann wird alles das abgeschnitten was im 1/4 Grid nicht mehr Anzeigbar ist so wie die 1/16 Note. Es ist einfach mit meiner Grid auflösung nicht möglich in einem 1/4 grid 1/16 noten anzeigen zu lassen. '...Fall hättest du dann 2x48 Ticks also ein halbe note 2/4.' eine 32tel hat 3ticks eine 16tel hat 6ticks eine 8tel hat 12ticks Eine 4tel hätte 24 ticks eine halbe hätte 48 ticks eine ganze hat 96 ticks eine Punktierte 4tel hätte demzufolge auch 48ticks nur so am rande So speichern tutst Du nun 50 12 für ne 8tel oder 50 24 für ne 4tel oder 50 48 für ne halbe oder 50 96 für ne ganze so sollten die dan in deinem Array drin stehen. Das sind die tatsächliche gehörte länge einer Note! Grid Ausgabe: 1/4 diesen wert musst Du ja auch irgendwo stehen haben! nun kommt die Berechnung und dies hat nix mit VCL oder nonvcl zu tun Deine graphiche länge ist 12, (die höhe lass ich mal weg)
Delphi-Quellcode:
usw.
if 1/4 and (notenticks >=24) then zeichnen
notenticks 24 zeichne 12 notenticks 48 zeichne 2x12 notenticks 96 zeichne 4x12 if 1/8 and (notenticks >= 12 then zeichnen notenticks 12 zeichne 12 notenticks 24 zeichne 2x12 notenticks 48 zeichne 4x12 if 1/16 and (notenticks >=6) then zeichnen notenticks 6 zeichne 12 notenticks 12 zeichne 2x12 notenticks 24 zeichne 4x12 notenticks 48 zeichne 8x12 Sieht im ersten Moment natürlich blöd aus, erklärt aber wie die Umsetzung vom prinzip geht! Und jetzt sage mir das geht nicht! Denn dies hat weder was mit vcl oder nonvcl zu tun Das auslesen(beim editieren) was Du also irgend wo mit der Mouse gemacht hast, must Du ja auch irgenwo herbekommen. Da steht auch irgenwo der Wert 1/4 oder 1/16 dann Zeichnest Du (oder wie du es bei nonvcl nennst)und diesen Wert rechnest Du zurück und speicherst es so ab wie oben beschrieben! Das brauchst Du also nicht speichern "91,1091,1091,1091,1091,1091,1091,1091,1091,10 91,1 091,1091,1091,1091,1091,1091" bei einer Auflösung von 1/16 sondern so wie es sein sollte 91 96, entspricht eine ganze Note. Du siehst also das dein eigener Ansatzt des speichern, falsch ist. Sorry Bitte, wenn ich diesen Ansatz von Dir kritisiere. Kannst mich jetzt auch Steinigen oder mir verbieten auf dieses Thema noch zu Antworten, würde ich sogar verstehen. Gruss alfold Geändert von alfold (20. Mai 2011 um 15:15 Uhr) |
![]() |
EWeiss
(Gast)
n/a Beiträge |
#4
![]() Du siehst also das dein eigener Ansatzt des speichern, falsch ist.
Sorry Bitte, wenn ich diesen Ansatz von Dir kritisiere. Kannst mich jetzt auch Steinigen oder mir verbieten auf dieses Thema noch zu Antworten, würde ich sogar verstehen. Ich werde mir deinen vorschlag mal notieren genau durchgehen und wenn ich zu dem Schluss komme das es einfacher, Übersichtlicher ist es so zu machen dann tue ich es. Solange wie ich im "moment" nicht meine Grid Operationen dadurch gefährde. Meine aber das es letztendlich nicht von bedeutung ist was im array steht und wie die Daten gespeichert werden. Sondern nur wie lese ich sie ein bzw .. parse sie korrekt auf das MidiFormat(NOTE) Theoretisch könnte ich sie für dich unleserlich machen A,AB,AB,AB aber am ende stehen die Daten in einem für mein Grid bzw.. MidiDaten lauffähigen Format nach dem parsen. ob ich jetzt 91 96 Note/Notenlänge so interpretiere oder auf meiner weise 91, 1091, 1091 spielt dabei absolut keine rolle das ergebniss zählt was letztendlich heraus kommt. ![]() Auf die eine oder andere Weise. PS: Meine Funktion zum Parsen ist Ausschlaggebend und nicht die art wie ich die Daten ablege. gruss Geändert von EWeiss (20. Mai 2011 um 15:22 Uhr) |
![]() |
EWeiss
(Gast)
n/a Beiträge |
#5
Hier meine Parse Funktion
Delphi-Quellcode:
function TMidiTracker.ConvertMidiNote(MidiNote: TMIDINote; Ticks: Word; FirstNote: Bool) : Integer;
var TickValue: Integer; begin Result := -1; TickValue := Ticks div SmallNoteData[SmallNDSelected].Value; if MidiNote.NoteNo > 0 then if (MidiNote.Length = TickValue) or (FirstNote = True) then begin Result := MidiNote.NoteNo; MidStartNote := False; end else if (MidiNote.Length > TickValue) then Result := 1000 + MidiNote.NoteNo else Result := MidiNote.NoteNo; end;
Delphi-Quellcode:
PPQN berechnet sich aus!
procedure TMidiTracker.ImpMidiFile(MidiFile: Widestring);
var MIDIFileInfo: TMIDIFileInfo; MIDINote: TMIDINote; IntI: Integer; IntA: Integer; IntB: Integer; IntC: Integer; NewNote: Integer; TimeGap: DWORD; Ticks: Word; TmpGrid: array of integer; TmpInstGrid: array of integer; PPQN: Double; st: string; begin if not ReadMIDIFile(MidiFile, MIDIFileInfo) then begin MessageBox(Self.Handle, 'Not a valid MIDI file.', 'Confirm', MB_OK); exit; end; ClearGrids; Ticks := MIDIFileInfo.Ticks; // Array länge setzen SetLength(TmpGrid, MaxNotes); SetLength(TmpInstGrid, MaxNotes); // Blanke Noten einfügen for IntB := 0 to High(TmpGrid) do begin TmpGrid[IntB] := -1; TmpInstGrid[IntB] := 0; end; // erste Note Initialisieren NewNote := -1; for IntI := 0 to High(SmallNoteData) do begin if SmallNoteData[IntI].Ticks = Ticks then begin SmallNDSelected := IntI; SKAERO_SetCTLText(SKAERO_GetMainItem(MainHandle, ID_SMALLESTNOTELABELVAL), WideString(SmallNoteData[SmallNDSelected].Name)); break; end; end; for IntI := 1 to MIDIFileInfo.Channels do begin for IntA := 0 to MIDIFileInfo.ChannelAttr[IntI].NoteCounter -1 do begin // Note einlesen MidiNote := MIDIFileInfo.MIDINotes[IntI, IntA]; PPQN := MidiNote.Ppqn * 2; // Note Umdrehen MidiNote.NoteNo := (127 - MidiNote.NoteNo) + basenote; // Erste Note nicht an position 0 // Blanke Noten einfügen if (IntA = 0) and (MIDIFileInfo.MIDINotes[IntI, IntA].StartTime > 0) then begin TimeGap := MidiNote.StartTime; IntB := (TimeGap div 12); if IntB > 0 then begin for IntC := 1 to IntB do begin inc(NewNote); TmpGrid[NewNote] := -1; TmpInstGrid[NewNote] := 0; end; end end; // Prüfen ob StartNote if not MidStartNote then MidStartNote := MidiNote.Length > (Ticks div SmallNoteData[SmallNDSelected].Value); // StartNote gefunden if MidStartNote then begin for IntB := 1 to round(PPQN) do begin Grid[IntI - 1, IntA] := ConvertMidiNote(MidiNote, Ticks, MidStartNote); SKAERO_SetTrackValue(TrackBarVol[IntI].Handle, MIDIFileInfo.ChannelAttr[IntI].Volume); inc(NewNote); if Grid[IntI - 1, IntA] < 1000 then begin TmpGrid[NewNote] := Grid[IntI - 1, IntA]; TmpInstGrid[NewNote] := MidiNote.Instrument;; end; if Grid[IntI - 1, IntA] > 1000 then begin TmpGrid[NewNote] := Grid[IntI - 1, IntA]; TmpInstGrid[NewNote] := MidiNote.Instrument; end; end; end else begin Grid[IntI - 1, IntA] := ConvertMidiNote(MidiNote, Ticks, MidStartNote); InstGrid[IntI - 1, IntA] := MidiNote.Instrument; SKAERO_SetTrackValue(TrackBarVol[IntI].Handle, MIDIFileInfo.ChannelAttr[IntI].Volume); inc(NewNote); TmpGrid[NewNote] := Grid[IntI - 1, IntA]; TmpInstGrid[NewNote] := MidiNote.Instrument; end; if IntA < MIDIFileInfo.ChannelAttr[IntI].NoteCounter -1 then begin TimeGap := MIDIFileInfo.MIDINotes[IntI, IntA + 1].StartTime - (MidiNote.StartTime + MidiNote.Length); if TimeGap > 0 then begin IntB := (TimeGap div 12); if IntB > 0 then begin for IntC := 1 to IntB do begin inc(NewNote); TmpGrid[NewNote] := -1; TmpInstGrid[NewNote] := 0; end; end end; end; end; for IntA := 0 to High(TmpGrid) do begin Grid[IntI - 1, IntA] := TmpGrid[IntA]; InstGrid[IntI - 1, IntA] := TmpInstGrid[IntA]; end; // Blanke Noten für neu einlesenden Track einfügen for IntB := 0 to High(TmpGrid) do begin TmpGrid[IntB] := -1; TmpInstGrid[NewNote] := 0; end; NewNote := -1; end; // Temp Array löschen Fillchar(TmpGrid, sizeOf(TmpGrid), 0); // Default werte für das Grid setzen StartX := 0; EndX := XSize; ColumnX := 0; // Grid zeichnen DrawGrid(Handle); // Spielgeschwindigkeit auf default wert setzen Tempo := round(300 / 127 * MidiNote.Velocity); SKAERO_SetKnobValue(SKAERO_GetMainItem(MainHandle, ID_KNOB_SPEED), trunc(Tempo)); SKAERO_SetCTLText(SKAERO_GetMainItem(MainHandle, ID_SPEEDVALLABEL), WideString(IntToStr(trunc(Tempo)))); MidiTracker.Tempo := Tempo; MidiTracker.ChangeVelocity; MidiTracker.SetTime(round(MIDIFileInfo.PlayTime)); st := Format ('%02d:%02.2d:%02.2d.%02.2d', [fHours, fMins, fSecs, fCS]); MediaTimer.SetTime(trunc(MIDIFileInfo.PlayTime)); SKAERO_SetCTLText(SKAERO_GetMainItem(MainHandle, ID_SOUNDTIME), WideString(st)); //SetTimer(Handle, SONGTIME_TIMER, 250, nil); end; Info.MIDINotes[Channel_, N-1].Ppqn := Info.MIDINotes[Channel, N-1].Length / Info.Ticks; gruss Geändert von EWeiss (20. Mai 2011 um 15:29 Uhr) |
![]() |
Registriert seit: 29. Jun 2010 Ort: Neustrelitz 393 Beiträge Delphi 7 Enterprise |
#6
2 Fragen dazu
![]() An welcher Stelle berücksichtigst Du die Auflösung? (1/4 - 1/32) Was passiert wenn man die Auflösung ändert? Wird die Datei neu eingelesene oder wie wird es bei Dir gemacht? Das währe erstmal alles dazu. Hab zwr noch nicht alles kappiert, ist klar, aber ich denke damit kommt man zurecht, um es nach meinem Vorschlag umzusetzten.(versuch) ![]() Gruss alfold |
![]() |
EWeiss
(Gast)
n/a Beiträge |
#7
2 Fragen dazu
![]() An welcher Stelle berücksichtigst Du die Auflösung? (1/4 - 1/32) Was passiert wenn man die Auflösung ändert? Wird die Datei neu eingelesene oder wie wird es bei Dir gemacht? Das währe erstmal alles dazu. Hab zwr noch nicht alles kappiert, ist klar, aber ich denke damit kommt man zurecht, um es nach meinem Vorschlag umzusetzten.(versuch) ![]() Gruss alfold SmallNoteData[SmallNDSelected].Value);
Delphi-Quellcode:
// Kleinste Noten
SmallNoteData[0].Name := '1/4 Note'; SmallNoteData[0].Value := 1; SmallNoteData[0].Nenner := 2; SmallNoteData[0].Ticks := 48; SmallNoteData[1].Name := '1/8 Note'; SmallNoteData[1].Value := 2; SmallNoteData[1].Nenner := 3; SmallNoteData[1].Ticks := 24; SmallNoteData[2].Name := '1/16 Note'; SmallNoteData[2].Value := 4; SmallNoteData[2].Nenner := 4; SmallNoteData[2].Ticks := 12; SmallNoteData[3].Name := '1/32 Note'; SmallNoteData[3].Value := 8; SmallNoteData[3].Nenner := 5; SmallNoteData[3].Ticks := 6; Wenn die Auflösung geändert wird passiert folgendes.. bzw wird diese Funktion aufgerufen. MidiTracker.SetNewNoteLength(SmallNoteData[SmallNDSelected].Value);
Delphi-Quellcode:
gruss
procedure TMidiTracker.SetNewNoteLength(NewLenght: Integer);
var TmpGrid: array of Integer; Note: Integer; IntA: integer; IntB: Integer; IntC: Integer; NewNote: Integer; begin FindEndOfSong; if SongLength > 0 then begin SetLength(TmpGrid, MaxNotes); MidiTracker.ChangeVelocity; NewNote:= -1; //if NewLenght div 2 = 0 then // exit; // Altes Grid Speichern if not bOldGrid then begin for IntA := 0 to 15 do for IntB := 0 to High(TmpGrid) do OldGrid[IntA, IntB] := Grid[IntA, IntB]; bOldGrid := True; end; if bOldGrid then begin // Altes Grid füllen zum erneuten Parsen for IntA := 0 to 15 do for IntB := 0 to High(TmpGrid) do begin Grid[IntA, IntB] := OldGrid[IntA, IntB]; TmpGrid[IntB] := -1; end; end; for IntA := 0 to 15 do begin for IntB := 0 to SongLength do begin Note := Grid[IntA, IntB]; if Note < 1000 then begin for IntC := 0 to NewLenght - 1 do begin if NewNote < High(TmpGrid) then begin inc(NewNote); TmpGrid[NewNote] := Note; if Note < 0 then Note := -1 else Note := 1000 + Note; end; end; end else begin if Note > 1000 then for IntC := 0 to NewLenght - 1 do begin if NewNote < High(TmpGrid) then begin inc(NewNote); TmpGrid[NewNote] := Note; end; end; end; end; for IntB := 0 to High(TmpGrid) do Grid[IntA, IntB] := TmpGrid[IntB]; // Blanke Noten einfügen for IntB := 0 to High(TmpGrid) do TmpGrid[IntB] := -1; NewNote:= -1; end; end; end; Geändert von EWeiss (20. Mai 2011 um 16:18 Uhr) |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Erstellt von | For | Type | Datum |
Delphi-Forum.de - Array statisch/dynamisch oder TList fr Midi-Events | This thread | Refback | 20. Sep 2011 14:59 |
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |