AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte Virtual Piano
Thema durchsuchen
Ansicht
Themen-Optionen

Virtual Piano

Ein Thema von EWeiss · begonnen am 8. Mär 2011 · letzter Beitrag vom 13. Apr 2019
Antwort Antwort
Seite 26 von 35   « Erste     16242526 2728     Letzte »    
EWeiss
Projekt entfernt..

Geändert von EWeiss (24. Jul 2019 um 05:46 Uhr)
 
EWeiss
 
#251
  Alt 20. Mai 2011, 16:19
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

Geändert von EWeiss (20. Mai 2011 um 16:22 Uhr)
  Mit Zitat antworten Zitat
EWeiss
 
#252
  Alt 20. Mai 2011, 16:26
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!
Info.MIDINotes[Channel_, N-1].Ppqn := Info.MIDINotes[Channel, N-1].Length / Info.Ticks; gruss

Geändert von EWeiss (20. Mai 2011 um 16:29 Uhr)
  Mit Zitat antworten Zitat
alfold

 
Delphi 7 Enterprise
 
#253
  Alt 20. Mai 2011, 16:55
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
  Mit Zitat antworten Zitat
EWeiss
 
#254
  Alt 20. Mai 2011, 17:15
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
Kleinste Note..
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:
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

Geändert von EWeiss (20. Mai 2011 um 17:18 Uhr)
  Mit Zitat antworten Zitat
alfold

 
Delphi 7 Enterprise
 
#255
  Alt 21. Mai 2011, 23:51
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?

EDIT:
Stelle fest das es dochn nicht so einfach ist Deine Variant anzupassen
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
Gruss alfold

Geändert von alfold (22. Mai 2011 um 11:30 Uhr)
  Mit Zitat antworten Zitat
EWeiss
 
#256
  Alt 3. Jun 2011, 13:34
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
  Mit Zitat antworten Zitat
Namenloser

 
FreePascal / Lazarus
 
#257
  Alt 3. Jun 2011, 14:42
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...
  Mit Zitat antworten Zitat
EWeiss
 
#258
  Alt 3. Jun 2011, 17:35
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
  Mit Zitat antworten Zitat
alfold

 
Delphi 7 Enterprise
 
#259
  Alt 3. Jun 2011, 20:10
Na, dann wünsch ich Dir auch alles gute und alles langsamer angehen

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


Freu mich schon auf die neue(letzte) Version
Gruss alfold
  Mit Zitat antworten Zitat
EWeiss
 
#260
  Alt 3. Jun 2011, 21:10
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

Geändert von EWeiss (26. Jun 2011 um 19:21 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 26 von 35   « Erste     16242526 2728     Letzte »    


Forumregeln

Es 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

Gehe zu:

(?)

LinkBack to this Thread

Erstellt von For Type Datum
Delphi-Forum.de - Array statisch/dynamisch oder TList fr Midi-Events This thread Refback 20. Sep 2011 15:59

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:08 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