Midi-Programm schreiben (Grundausführungen &so)

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Benutzeravatar
SimonSimCity
Beiträge: 132
Registriert: 14.01.2007 00:49

Midi-Programm schreiben (Grundausführungen &so)

Beitrag von SimonSimCity »

Hi, Leute

Ich hab mir hier einiges zum Thema MIDI angeschaut, aber ich bin leider nicht so richtig schlau geworden...

Wie geht das so richtig?
Wie macht man dass, wenn man da die Noten anzeigen will?
.
.
.


Ich will einen Midi-Editor schreiben, der sehr viele Funktionen unterstützt wie z.B. aus einer Melodiestimme und Hauptakkorden einen kompletten harmonischen Stimmsatz zu schreiben.

Aber jetzt bitte nur Dinge, die mit der Einbindung des MIDI in das Programm zu tun haben!

Ein Midi-Gadget wäre auch sehr hilfreich :) -> für das Anzeigen...

EDIT: Ich hab mir auch schon mal diesen ca 900-Zeilen Code von NicTheQuick angeschaut... Leider kann ich nur den Code aus dem Forum verwenden, da die Links nicht mehr funktionieren...
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Willst du eine vorhandene MIDI-Datei öffnen und bearbeiten oder willst du
nur die MIDI-Schnittstelle nutzen?

Ich schau mal, wieso mein Code nicht mehr verlinkt ist und werde ihn
demnächst mal erneuern. Kann aber bis Montag dauern.

Mein Interface beinhaltet im Grunde alles zur MIDI-Ansteuerung und alles
zum Auslesen ankommender MIDI-Daten. Außerdem hab ich fast alle
YAMAHA-XG SysEx-Messages als einfache Befehle eingebaut. Für Roland
Synthesizer hatte ich noch keine ausreichende Dokumentation aller Messages
gefunden und daher noch nicht eingebaut.
Achja: .mid-Dateien kann das Interface nicht lesen, schreiben oder
abspielen.
Benutzeravatar
SimonSimCity
Beiträge: 132
Registriert: 14.01.2007 00:49

Beitrag von SimonSimCity »

Willst du eine vorhandene MIDI-Datei öffnen und bearbeiten oder willst du
nur die MIDI-Schnittstelle nutzen?
Beides.

Wie kann man das denn mit dem Noten anzeigen machen?
Gibt es da ein Midi-Gadget oder so was oder muss man sich da was selber schreiben?

Ich weiß nur, das Programme wie NothWorthyComposer & Finale eine .TTF-Datei verwenden...
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Das Darstellen von Noten musst du selbst in die Hand nehmen. Dazu erstellst
du am besten ein Image mit 'CreateImage()', das du dann in einem
'ImageGadget()' anzeigst. Dann nimmst du dir eine passende Schriftart
(.TTF), die Noten-Symbole enthält und schreibst sie an die richtige Position
mit 'DrawText()' auf das Image.

Ich hatte auch mal sowas wie ein MIDI- bzw. Noten-Gadget vor, aber nie
damit angefangen, weil ich dann doch zu faul war.

Um MIDI-Dateien zu lesen und zu schreiben, solltest du dir mal das
MIDI-Format genauer anschauen. Dazu findest du vielleicht auf folgender
Seite die passenden Informationen: Wotsit
Mach dich aber darauf gefasst, das wohl das meiste in Englisch beschrieben
ist.
Benutzeravatar
SimonSimCity
Beiträge: 132
Registriert: 14.01.2007 00:49

Beitrag von SimonSimCity »

NicTheQuick hat geschrieben:Um MIDI-Dateien zu lesen und zu schreiben, solltest du dir mal das
MIDI-Format genauer anschauen. Dazu findest du vielleicht auf folgender
Seite die passenden Informationen: Wotsit
Mach dich aber darauf gefasst, das wohl das meiste in Englisch beschrieben
ist.
Ok...
Ich mach das doch anders:

Ich hab ja Finale..
Damit kann man ja auch als XML exportieren...
Dann umgehe ich diesen Format-Blubb.

Ich find das einfacher...
p.s. NicTheQuick
Kannst du mir nen Ansatz für das Gadget geben, sodass das hier doch was wird?
Benutzeravatar
SimonSimCity
Beiträge: 132
Registriert: 14.01.2007 00:49

Beitrag von SimonSimCity »

Ich hab mich mal im englischen Forum umbeschaut:

Midi-Monitor
http://www.purebasic.fr/english/viewtopic.php?p=40540 -> PB 3.93 & 4.0
EDIT: Hier ist der Code für ein KeyBoard, was die Noten spielt :)
Aber ist das normal, dass die Noten nur von F0 bis C9 normal klingen? (Reicht auch...)

Midi-File Decoder
http://www.purebasic.fr/english/viewtop ... light=midi -> PB 3.93

Und der letzte Link (hätte ich fast vergessen :) )
http://www.purearea.net/pb/CodeArchiv/German.html
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

SimonSimCity hat geschrieben:p.s. NicTheQuick
Kannst du mir nen Ansatz für das Gadget geben, sodass das hier doch was wird?
Naja, ich weiß ja nicht, wie weit du dich mit PB auskennst und wie weit du mit
dem NotenGadget gehen willst. Ich würde da vielleicht so anfangen:

Code: Alles auswählen

Structure NotesGadget
  SAG.l     ;ScrollAreaGadget
  ImgG.l    ;ImageGadget
  IMG.l     ;Image
  width.l
  height.l
  Notes.s   ;String mit Noten (z.B. Alle meine Entchen "4cdef2gg4aaaa1g4aaaa1g4ffff2ee4gggg1c")
EndStructure
NewList NotesGadget.NotesGadget()

Procedure NotesGadget(x.l, y.l, width.l, height.l, ScrollWidth.l, ScrollHeight.l)
  If AddElement(NotesGadget())
    With NotesGadget()
      \IMG = CreateImage(#PB_Any, ScrollWidth, ScrollHeight)
      StartDrawing(ImageOutput(\IMG))
        Box(0, 0, ScrollWidth, ScrollHeight, $FFFFFF)
      StopDrawing()
      If \IMG
        \SAG = ScrollAreaGadget(#PB_Any, x, y, width, height, ScrollWidth, ScrollHeight, 1)
        \ImgG = ImageGadget(#PB_Any, 0, 0, ScrollWidth, ScrollHeight, ImageID(\IMG))
        \width = ScrollWidth
        \height = ScrollHeight
        
        ProcedureReturn @NotesGadget()
      Else
        DeleteElement(NotesGadget())
        ProcedureReturn #False
      EndIf
    EndWith
  EndIf
EndProcedure

Procedure SetNotes(*Gadget.NotesGadget, Notes.s)
  Protected z.s, length.l = -1, a.l, slength.l, pos.l = -1
  
  With *Gadget
    \Notes = Notes
    StartDrawing(ImageOutput(\IMG))
      slength = Len(Notes)
      For a = 1 To slength
        z = Mid(Notes, a, 1)
        If z >= "0" And z <= "9"
          length = Val(z)
        Else
          Select LCase(z)
            Case "c" : pos = 0
            Case "d" : pos = 1
            Case "e" : pos = 2
            Case "f" : pos = 3
            ;...
          EndSelect
          ;Mal Note mit DrawText()
        EndIf
      Next
    StopDrawing()
    SetGadgetState(\ImgG, ImageID(\IMG))
  EndWith
EndProcedure

Procedure FreeNotesGadget(*Gadget.NotesGadget)
  With *Gadget
    FreeGadget(\ImgG)
    FreeGadget(\SAG)
    FreeImage(\IMG)
    ChangeCurrentElement(NotesGadget(), *Gadget)
    DeleteElement(NotesGadget())
  EndWith
EndProcedure
Benutzeravatar
SimonSimCity
Beiträge: 132
Registriert: 14.01.2007 00:49

Beitrag von SimonSimCity »

Kann mir jemand sagen, was die im englischen Forum bei diesem Encoder mit der Variable "Delta_time" aussagen wollen??
Wenn ich die 1. Note beginne ist die =0 und wenn ich irgendeine Note beende ist die 160 und wenn ich eine Note beginne, die nicht die 1. ist, dann ist die Variable =32
Warum weiß ich nicht...
Die Noten sind alle gleich hoch, gleich schnell...


@NIC:
Das fängt gleich mit nem Fehler an :(

Ich bekomme diesen DEBUG-Fehler:
[13:38:47] Warte auf den Start des Executable...
[13:38:47] Executable gestartet.
[13:38:47] [Debug] 4199275
[13:38:47] [ERROR] Line: 37
[13:38:47] [ERROR] Invalid memory access.
[13:38:50] Das Programm wurde beendet.
Kann das wieder an meinem PB 4.10 Beta3 liegen??

Code: Alles auswählen

Structure NotesGadget
  SAG.l     ;ScrollAreaGadget
  ImgG.l    ;ImageGadget
  IMG.l     ;Image
  width.l
  height.l
  Notes.s   ;String mit Noten (z.B. Alle meine Entchen "4cdef2gg4aaaa1g4aaaa1g4ffff2ee4gggg1c")
EndStructure
Global NewList _NotesGadget.NotesGadget()

Procedure NotesGadget(x.l, y.l, width.l, height.l, ScrollWidth.l, ScrollHeight.l)
  If AddElement(_NotesGadget())
    With _NotesGadget()
      \IMG = CreateImage(#PB_Any, ScrollWidth, ScrollHeight)
      StartDrawing(ImageOutput(\IMG))
        Box(0, 0, ScrollWidth, ScrollHeight, $FFFFFF)
      StopDrawing()
      If \IMG
        \SAG = ScrollAreaGadget(#PB_Any, x, y, width, height, ScrollWidth, ScrollHeight, 1)
        \ImgG = ImageGadget(#PB_Any, 0, 0, ScrollWidth, ScrollHeight, ImageID(\IMG))
        \width = ScrollWidth
        \height = ScrollHeight
       
        ProcedureReturn @NotesGadget()
      Else
        DeleteElement(_NotesGadget())
        ProcedureReturn #False
      EndIf
    EndWith
  EndIf
EndProcedure

Procedure SetNotes(*Gadget.NotesGadget, Notes.s)
  Protected z.s, length.l = -1, a.l, slength.l, pos.l = -1
 
  With *Gadget
    \Notes = Notes
    StartDrawing(ImageOutput(\IMG))
      slength = Len(Notes)
      For a = 1 To slength
        z = Mid(Notes, a, 1)
        If z >= "0" And z <= "9"
          length = Val(z)
        Else
          Select LCase(z)
            Case "c" : pos = 0
            Case "d" : pos = 1
            Case "e" : pos = 2
            Case "f" : pos = 3
            ;...
          EndSelect
          ;Mal Note mit DrawText()
        EndIf
      Next
    StopDrawing()
    SetGadgetState(\ImgG, ImageID(\IMG))
  EndWith
EndProcedure

Procedure FreeNotesGadget(*Gadget.NotesGadget)
  With *Gadget
    FreeGadget(\ImgG)
    FreeGadget(\SAG)
    FreeImage(\IMG)
    ChangeCurrentElement(_NotesGadget(), *Gadget)
    DeleteElement(_NotesGadget())
  EndWith
EndProcedure

;//////////////////////////////////////////////////////////////

Enumeration 0 ;/ #Window_*
  #Window_0
EndEnumeration

OpenWindow(#Window_0, 0, 0, 600/2, 480/2, "<title>", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CreateGadgetList(WindowID(#Window_0))

*gadget.NotesGadget = NotesGadget(10, 10, 200, 150, 200, 150)
Debug *gadget

SetNotes(*gadget, "4cdef2gg4aaaa1g4aaaa1g4ffff2ee4gggg1c")

Define lWindowEvent.l
Repeat
  lWindowEvent = WaitWindowEvent()
  
  Select lWindowEvent
    Case #PB_Event_CloseWindow
      Break
  EndSelect
ForEver

FreeNotesGadget(*gadget)

End
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ich hatte den Code nicht getestet und deshalb nicht gemerkt, dass man eine
LinkedList nicht so nennen darf wie eine Procedure. Deswegen hast du ja fast
überall den Unterstrich davor gesetzt. Nur in Zeile 24 hast du es vergessen.
:wink:

Aber so wie der Code jetzt ist, sieht man eh noch nichts außer einer weißen
Fläche in einem 'ScrollAreaGadget()'. Es fehlt natürlich noch das Laden eine
Schriftart, mit der man Noten darstellen kann und die Notendarstellung
selbst. Außerdem muss man beachten, dass ein Image eine
Größenbegrenzung hat, bei mehreren Stimmen muss man auch wieder was
ändern, usw.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8812
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Hier ist übrigens meine DirectMidi.pbi-Include .
Ich hab auch die Links in meinem alten Thread erneuert.
Antworten