Delphi-PRAXiS
Seite 26 von 35   « Erste     16242526 2728     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   Virtual Piano (https://www.delphipraxis.net/158944-virtual-piano.html)

EWeiss 20. Mai 2011 15:19

AW: Virtual Piano
 
Zitat:

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.
Warum sollte ich auf Konstruktive vorschläge aggressiv reagieren?
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

EWeiss 20. Mai 2011 15:26

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:
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;
PPQN berechnet sich aus!
Delphi-Quellcode:
Info.MIDINotes[Channel_, N-1].Ppqn := Info.MIDINotes[Channel, N-1].Length / Info.Ticks;
gruss

alfold 20. Mai 2011 15:55

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

EWeiss 20. Mai 2011 16:15

AW: Virtual Piano
 
Zitat:

Zitat von alfold (Beitrag 1102017)
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

Kleinste Note..
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:
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;
gruss

alfold 21. Mai 2011 22:51

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:
// Spielgeschwindigkeit auf default wert setzen
Tempo := round(300 / 127 * MidiNote.Velocity);
Velocity ist doch die Anschlagsdynamic, bzw kann man auch für NoteOn bzw NoteOff benutzten
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:
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;
Es stellen sich also mehr Fragen als Lösungen an:?
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

EWeiss 3. Jun 2011 12:34

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

Namenloser 3. Jun 2011 13:42

AW: Virtual Piano
 
Zitat:

Zitat von EWeiss (Beitrag 1104435)
sorry konnte nicht vorher Antworten.
Lag die letzten zwei wochen mit Gehinblutung im Krankenhaus.

Oha, na dann gute Besserung, auch wenn’s zwei Wochen zu spät kommt...

EWeiss 3. Jun 2011 16:35

AW: Virtual Piano
 
Zitat:

Zitat von NamenLozer (Beitrag 1104454)
Zitat:

Zitat von EWeiss (Beitrag 1104435)
sorry konnte nicht vorher Antworten.
Lag die letzten zwei wochen mit Gehinblutung im Krankenhaus.

Oha, na dann gute Besserung, auch wenn’s zwei Wochen zu spät kommt...

Jo ;)
Danke schön .. jetzt geht es wieder. (Ohne Schmerzen)

gruss

alfold 3. Jun 2011 19:10

AW: Virtual Piano
 
Na, dann wünsch ich Dir auch alles gute:thumb: und alles langsamer angehen:wink:

Zitat:

Velocity = Geschwindigkeit
Original Auszug....
Zitat:

Die Tastennummern bei MIDI reichen von 0-127. #0 steht für C-2,#12 ist demnach C-1,#24 ist C 0,#36 ist C 1,#37 ist C# 1 usw...
$8n Note Off
Statusbyte: $8n,1. Datenbyte Key#,2. Datenbyte Note Off Velocity. Key # ist die Tastennummer 0-127.

$9n Note On
Statusbyte: $9n,1. Datenbyte Key#,2. Datenbyte Note On Velocity. Key # ist die Tastennummer 0-127.

Die Velocity bedeutet die Lautstärke mit der eine Note angeschlagen wird, bzw. losgelassen wird
:gruebel:

Freu mich schon auf die neue(letzte) Version:-D
Gruss alfold

EWeiss 3. Jun 2011 20:10

AW: Virtual Piano
 
Zitat:

Original Auszug....
Muss mich da nochmal schlaumachen.. sowie ich gelesen habe wird es nicht nur für
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.
Seite 26 von 35   « Erste     16242526 2728     Letzte »    

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