AW: Virtual Piano
Zitat:
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 |
AW: Virtual Piano
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;
Delphi-Quellcode:
gruss
Info.MIDINotes[Channel_, N-1].Ppqn := Info.MIDINotes[Channel, N-1].Length / Info.Ticks;
|
AW: Virtual Piano
2 Fragen dazu:wink:
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):wink: Gruss alfold |
AW: Virtual Piano
Zitat:
Delphi-Quellcode:
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.
Delphi-Quellcode:
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; |
AW: Virtual Piano
So bin wieder da.
Muss doch noch nachfragen. Will ja nur das umändern was du nicht brauchst, bei meinem Vorschlag. MIDIFileInfo MidiNote Währe schön wenn Du mir die den Aufbau gibst. Ist es MIDIFileInfo wo Du alles ablegst und zur Laufzeit für die Audioausgabe ausliest, vermute ich mal.
Code:
Velocity ist doch die Anschlagsdynamic, bzw kann man auch für NoteOn bzw NoteOff benutzten
// Spielgeschwindigkeit auf default wert setzen
Tempo := round(300 / 127 * MidiNote.Velocity); Frage mich wie dies mit dem Tempo zusammenhängt?:gruebel: EDIT: Stelle fest das es dochn nicht so einfach ist Deine Variant anzupassen:gruebel: Bei meinem Vorschlag muss ich ja nicht Prufen ob eine note >1000 ist ConvertMidiNote? warscheinlich auch nicht!
Code:
Es stellen sich also mehr Fragen als Lösungen an:?
for IntA := 0 to High(TmpGrid) do
begin Grid[IntI - 1, IntA] := TmpGrid[IntA];//<--Grid[array] füllen, Was zur anzeige kommt? InstGrid[IntI - 1, IntA] := TmpInstGrid[IntA];//<---???? end; Denn // Grid zeichnen DrawGrid(Handle); müsste ja auch angepasst werden! Auch wenn es bei mir nicht läuft, währe es besser ich könnte den code sehen, als hier tausend Fragen zu stellen. dann passe ich es als demo an mit meinem Vorschlag und Du kannst es testen:wink: Gruss alfold |
AW: Virtual Piano
sorry konnte nicht vorher Antworten.
Lag die letzten zwei wochen mit Gehinblutung im Krankenhaus. Velocity = Geschwindigkeit ;) Werde den Quelltext die Tage hochladen muss meine 6 Segment Anzeige erst noch fertig machen kam ja leider zu nichts mehr. gruss |
AW: Virtual Piano
Zitat:
|
AW: Virtual Piano
Zitat:
Danke schön .. jetzt geht es wieder. (Ohne Schmerzen) gruss |
AW: Virtual Piano
Na, dann wünsch ich Dir auch alles gute:thumb: und alles langsamer angehen:wink:
Zitat:
Zitat:
Freu mich schon auf die neue(letzte) Version:-D Gruss alfold |
AW: Virtual Piano
Zitat:
Anschlagdynamic verwendet. Im Anhang der Source und fehlende Bitmaps für Nummern. Der Quelltext funktioniert nur mit oben ängehängten "Binären Archiv" gruss |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:31 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz