Thema: Virtual Piano

Einzelnen Beitrag anzeigen

EWeiss
(Gast)

n/a Beiträge
 
#252

AW: Virtual Piano

  Alt 20. Mai 2011, 15: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 15:29 Uhr)
  Mit Zitat antworten Zitat