Page 1 of 2

New Midi Keyboard

Posted: Mon Mar 11, 2013 9:12 pm
by einander
As there are some new users interested in Midi, here is an updated version of this oldie.
Cheers!

Code: Select all

;PB MIDI Keyboard  - by Einander
;Updated for PB 5.x 
;Improved PC Keyboard input
;New General MIDI Menu
EnableExplicit
Enumeration
  #Container
  #MouseOver
  #Sustain
  #Sounds
  #ShutUp
  #Volume
  #ShowVolume
  #Img
  #ImGad
  #Quit  
EndEnumeration
#Sust="Sustained "
#KeyPrevState   = $40000000   ; bit  30
;
Structure MIDI
  MIDIIn.A
  MIDIOut.A
  Stat.A
  Dat1.A
  Dat2.A
EndStructure
;
Structure I3: I1.I: I2.I: I3.I:EndStructure
Global _MIDI.MIDI,_hMIDIIn,_HMIDIout,_DrawING,_Keep$,_AutoPan=1
Global _TGMou,_TGkey, _XKbd, _YKbd, W_KBD, _WhiteKeyWidth, _WhiteKeyHeight, _Wid2, _Wid3, _Wid4, _Wid5, _OctaveWidth, _H2
Global Dim _Sounds.S(127), Dim _KNote.B(6), Dim _Pair.I(86)
Global _chromatic$="C C#D EbE F F#G AbA BbB C "     ; mixed # b
Define Font1,Font2,I,Ev,KeySel,MousNote,MouseOver
Define X,Y,Sound$,RGB,KbNT,KBD$,T1,Ti,LParam,K$
Define T$,Finds,Ova,HIWO
Font1=FontID(LoadFont(-1,"arial",10))
Font2=FontID(LoadFont(-1,"wingdings",10))
_KNote(0)=0 : _KNote(1)=2 :_KNote(2)=4 : _KNote(3)=5 :_KNote(4)=7 :_KNote(5)=9 :_KNote(6)=11
;
Macro HIWO(A)  :  ((A>>16)&$FFFF) : EndMacro  ;- HiWord(A)     
;
Macro GadgetBottom(Gad) :  GadgetY(Gad)+GadgetHeight(Gad) : EndMacro ;
;
Macro GadgetRight(Gad)  :  GadgetX(Gad)+GadgetWidth(Gad)  : EndMacro :
;
Macro MMx :  WindowMouseX(EventWindow()) : EndMacro ;
;
Macro MMy :  WindowMouseY(EventWindow()) : EndMacro ;
;
Macro MMk
  Abs(GetAsyncKeyState_(#VK_LBUTTON) +GetAsyncKeyState_(#VK_RBUTTON)*2+GetAsyncKeyState_(#VK_MBUTTON)*3)/$8000   
EndMacro ;
;
Macro GadRGB(Gad,RGB1=#LBLUE,RGB2=#DBLUE)
  SetGadgetColor(Gad,1,RGB1)      
  SetGadgetColor(Gad,2,RGB2)    
EndMacro ;
;
Macro StopDraw  
  If _DrawING:StopDrawing():_DrawING=0:EndIf
EndMacro ;
;
Macro DrawImg(ImgNum) ;- DrawImg(ImgNum)
  StopDraw
  _DrawING=StartDrawing(ImageOutput(ImgNum))
EndMacro ;
;
Macro MIDI_NT(Note)  Name one Note
  Mid(_Chromatic$, (Note % 12) * 2 + 1, 2)
EndMacro ;
;
Macro SetSounds(Channel, Sounds)                                    ;- SetSounds - From 0 to 127
  midiOutShortMsg_(_HMIDIout, $C0 |  Channel | Sounds<< 8 )
EndMacro ;
;
Macro SetPan(Chan,Pan)
  midiOutShortMsg_(_HMIDIout,$B0 |Chan | $A00 | Pan<< 16 )
EndMacro ;
;
Macro PlayNote(Channel, Note, Loudness)                             ;- PlayNote - Loudness 0 = no Sound
  If _AutoPan
    SetPan(Channel,Note)
  EndIf
  midiOutShortMsg_(_HMIDIout,$90 | Channel | Note << 8 | Loudness << 16 )
EndMacro
;
Macro MIDIVolume(Channel,Volume)
  midiOutShortMsg_(_HMIDIout,$B0 | Channel | $700 | Volume << 16 )
EndMacro
;
Procedure AllOff()  ; mute all channels      
  Protected I
  For I=0 To 15
    midiOutShortMsg_(_HMIDIout, $B0 | I | $7B00 )
  Next
EndProcedure 
;
Procedure MIDIInProc(hMIDIIn, WMsg, DuMMy, D1, D2) ; get NoteOn,NoteOff)
  With _MIDI  
    Select WMsg    ; process some MIDI in events; here you can add more events
      Case #MM_MIM_DATA
        If D1 & 255 =144   
          \Stat=(D1 >> 8)  & $FF   ;Note
          \Dat1=(D1 >> 16) & $FF   ;Velocity
;           If \Dat1  :  SetWindowTitle(0,"Note On")
;           Else      :  SetWindowTitle(0,"Note Off")
;           EndIf
        EndIf
    EndSelect
  EndWith
EndProcedure
;
Procedure MIDIinit(*MIDIInProc=-1,Instrument=0) ;MIDIinproc default solo muestra Note on, Note off
  Protected OutDev , InDev
  If *MIDIinproc=-1:*MIDIinproc=@MIDIinproc():EndIf
  If midiInOpen_(@_hMIDIIn, InDev, *MIDIInProc, 0, #CALLBACK_FUNCTION) = #MMSYSERR_NOERROR
    If midiInStart_(_hMIDIIn) <> #MMSYSERR_NOERROR : MessageRequester("Error","Can't start MIDI IN",0) :End:  EndIf
  EndIf
  midiOutOpen_(@_HMIDIout, OutDev, 0, 0, 0) 
  midiOutShortMsg_(_HMIDIout, 192  | Instrument<<8 )
  If _hMIDIIn And _HMIDIout
    If midiConnect_(_hMIDIIn, _HMIDIout, 0)
      MessageRequester("Error","Can't connect MIDI",0) :End
    EndIf
  EndIf
EndProcedure 
;
Procedure MenuSounds()
  Protected GMMenu=CreatePopupMenu(#PB_Any),I, J ,A$
  Restore GeneralMIDISounds
  For J=0 To 127 Step 8
    Read.S A$
    If A$="_Last_":Break:EndIf
    OpenSubMenu(A$)   
    For I=J To J+7
      Read.S A$
      MenuItem(I,Str(I+1)+" "+A$) 
      _Sounds(I)=A$
    Next    
    CloseSubMenu()
  Next
  ProcedureReturn GMMenu
EndProcedure 
;
Procedure.S MIDI_2_Notes(Note$)            ; naming multiple Notes
  Protected I, Note,Nt$
  For I = 0 To Len(Note$) - 1
    Note = PeekA(@Note$ + I)
    Nt$ + Trim(Mid(_Chromatic$, (Note % 12) * 2 + 1, 2)) + Str(Note / 12) + " "
  Next I
  ProcedureReturn Nt$
EndProcedure
;
Procedure GetNote() ; get Selected MIDINote
  Protected R.RECT,Octave,Note,Side
  R\Right=W_KBD-1
  R\Bottom=_WhiteKeyHeight
  If PtInRect_(R,MMx|MMy<<32)
    Octave = (MMx / _WhiteKeyWidth) / 7 * 12                                           ;octave
    Note=Octave+_KNote((MMx / _WhiteKeyWidth) % 7 )                                    ;White Key
    Side= (MMx / _Wid2)%14                                                             ;position on the Left ot Right half of each white Key
    If MMy>_H2 Or Side=0 Or Side=5 Or Side=6 Or Side=13 : ProcedureReturn Note         ;white Key
    ElseIf Side=1 Or Side=3 Or Side=7 Or Side=9 Or Side=11 : ProcedureReturn Note + 1  ;Left black Key
    Else
      ProcedureReturn Note - 1                                                         ;Right black Key
    EndIf
  EndIf
  ProcedureReturn -1
EndProcedure
;
Procedure  DrawKBD(Nt, KeySelected)    ; Draw MIDI Key 
  Protected KeyColor,Octave,Last,A,X
  If Nt < 128
    DrawImg(#Img)
    If KeySelected = #Black : KeyColor = $DCF5FB 
    Else                    : KeyColor = KeySelected 
    EndIf
    Octave = Nt / 12
    Last=Nt
    Nt % 12
    X = Octave * _OctaveWidth
    Select Nt
      Case 1, 3 , 6 , 8, 10 ; black keys
        If Nt > 5 : A = 1 : EndIf
        X + (Nt + A) * _Wid2 + 1
        Box (X + _Wid3-2, 1,_Wid2, _H2-3 ,$AF8F8F)
        Box (X + _Wid3-1, 2, _Wid2-2, _H2 - 5, KeySelected)
      Default              ; white keys
        Select Nt
          Case 0 :                               Box(X + 1, 0, _Wid5, _H2, KeyColor)
          Case 2 : X +   _WhiteKeyWidth     :    Box(X + _Wid3, 0, _Wid4, _H2, KeyColor)
          Case 4 : X +   _WhiteKeyWidth * 2 :    Box(X + _Wid3, 0, _Wid5, _H2, KeyColor)
          Case 5 : X +   _WhiteKeyWidth * 3 :    Box(X + 1, 0, _Wid5, _H2,KeyColor)
          Case 7 : X +   _WhiteKeyWidth * 4 :    Box(X + _Wid3, 0, _Wid4, _H2, KeyColor)
          Case 9 : X +   _WhiteKeyWidth * 5 :    Box(X + _Wid3, 0, _Wid4, _H2, KeyColor)
          Case 11: X +   _WhiteKeyWidth * 6 :    Box(X + _Wid3, 0, _Wid5, _H2, KeyColor)
        EndSelect
        Box (X + 1, _H2, _WhiteKeyWidth - 1, _H2-1, KeyColor)
        Box (X + 2, _H2*2-1, _WhiteKeyWidth - 3, 1, KeyColor)
    EndSelect
    If Last = 127 
      Box(X + _Wid3, 0, _Wid5, _H2, KeyColor) 
    EndIf
    StopDraw
    SetGadgetState(#ImGad,ImageID(#Img))
  EndIf
EndProcedure
;
Procedure.S SortString(A$)
  Protected I,Le = Len(A$) - 1
  Protected Dim Sort.B(Le)
  For I = 0 To Le
    Sort(I) = PeekA(@A$ + I)
  Next
  SortArray(Sort(), 0)
  For I = 0 To Le
    PokeA(@A$ + I, Sort(I))
  Next
  ProcedureReturn A$
EndProcedure
;
Procedure Sustain(Note, Sustain)               ; Add / remove / mute sustained Notes
  Protected A$,I
  If Note > - 1                                ; Add Note
    A$ = Chr(Note)
    If FindString(_Keep$, A$, 1) = 0
      _Keep$ + A$
    EndIf
  EndIf
  If Len(_Keep$) > Sustain  
    For I = 1 To Len(_Keep$) - Sustain
      PlayNote(1, Asc(Mid(_Keep$, I, 1)), 0)  ; mute unwanted Notes
    Next I
    _Keep$ = Right(_Keep$, Sustain)           ; remove Notes
  EndIf
  If Len(_Keep$) :   SetGadgetText(_TGMou, MIDI_2_Notes(SortString(_Keep$)) )
  Else           :   SetGadgetText(_TGMou,"")
  EndIf
EndProcedure
; _______________________________________-
ExamineDesktops()
Define _X = DesktopWidth(0)
_XKbd = 50 : _YKbd = 120                     ; Key width it's up to screen width
_WhiteKeyWidth = (_X - 100) / 77 
_WhiteKeyWidth + (_WhiteKeyWidth & 1)        ; white Key width always even
_WhiteKeyHeight =_X/14                       ; white key Height
w_KBD= _WhiteKeyWidth * 75                   ; Keyboard width
_H2   = _WhiteKeyHeight/ 2                   ; half Key height, to find black or white Keys
_Wid2 = _WhiteKeyWidth / 2                   ; half  Key width, for black Keys
_Wid3 = _WhiteKeyWidth / 3                   ; black Keys position
_Wid4 = _WhiteKeyWidth - _Wid3 * 2 + 1       ; ditto
_Wid5 = _WhiteKeyWidth - _Wid3               ; ditto
_OctaveWidth = _WhiteKeyWidth  * 7           ; 7 Keys = one octave width
Define Sustain = 1
;<<<<<<<<<<<<<<<<<<<<<<<<<<  
Define Title$= "PB MIDI Keyboard    < Ctrl > Or Right MouseButton to Stop Sound."
Define hWnd = OpenWindow(0, _XKbd, _YKbd, W_KBD, _WhiteKeyHeight + 62,Title$, #PB_Window_SystemMenu |#PB_Window_Invisible)
#BKRGB=$C94714
SetWindowColor(0,#BKRGB)
StickyWindow(0,1)
RemoveKeyboardShortcut(0,#PB_Shortcut_Tab)
Define GMMenu=MenuSounds()
CreateImage(#Img,WindowWidth(0),_WhiteKeyHeight)
ImageGadget(#ImGad,0,0,0,0,ImageID(#Img))
Define Sounds=49 ; starting Sound
Define Loudness = 120                               ; Choose From 0 To 127  : Loudness 0 = no Sound
Define MIDIVolume=100
Restore MapKeys ; map keys to MIDInotes : default configuration for Spanish keyboard layout    
; For other layouts some keys may need different values <<<<<<<<<<<<<<<<<<<<<< 
; You can map different pairs to simulate other instruments (like Guitar, bandoneon, concertina...)
Repeat
  Read.I X
  If X=$ACABA:Break:EndIf
  Read.I Y
  _Pair(X)=Y
ForEver
ContainerGadget(#Container, 0, WindowHeight(0) - 60, WindowWidth(0)-100, 24  )
  SetGadgetColor(#Container,2,#BKRGB) 
  Define TGSustain=HyperLinkGadget(#PB_Any,0,2,50,20,"Sustain",#White)
  GadRGB(TGSustain,#White,#BKRGB)
  SpinGadget(#Sustain, 50, 2, 30, 20, 0, 8)
  CheckBoxGadget(#mouseover,GadgetRight(#Sustain)+30,2,100,20,"Mouse Over")
  HyperLinkGadget (#ShutUp,GadgetRight(#MouseOver)+30,2,80,18,"Stop Sound",#Red)
  GadRGB(#ShutUp,#White,#BKRGB)
  HyperLinkGadget (#Sounds,GadgetRight(#ShutUp)+30,2,140,18,"Sound "+Str(Sounds+1)+" : "+_Sounds(Sounds),#Red)
  GadRGB(#Sounds,#White,#BKRGB)
  SetGadgetState(#Sustain, Sustain)
  SetGadgetText(#Sustain, Str(Sustain) )
  TextGadget(#ShowVolume,GadgetRight(#Sounds),2,100,18,"Vol "+Str(MIDIVolume),#PB_Text_Right)
  TrackBarGadget(#Volume,GadgetRight(#ShowVolume)+4,2,100,18,0,127)
  SetGadgetState(#Volume,MIDIVolume)  
CloseGadgetList()
GadRGB(#ShowVolume,#White,#BKRGB)
ButtonGadget (#Quit,GadgetRight(#Container)-70,WindowHeight(0)-20,50,18,"Quit")
GadgetToolTip(TGSustain,"Simultaneous Sounding Notes")
GadgetToolTip(#Sustain,"Simultaneous Sounding Notes")
GadgetToolTip(#MouseOver,"Play notes moving mouse")
GadgetToolTip(#ShutUp,"< Ctrl > Or Right MouseButton to Stop Sound")
GadgetToolTip(#Sounds,"Select 128 General MIDI Sounds")
GadgetToolTip(#Volume,"Volume Control")
_TGMou=HyperLinkGadget(#PB_Any,4,GadgetBottom(#Container)+3,250,20,"",0)
_TGkey=HyperLinkGadget(#PB_Any,GadgetRight(_TGMou)+4,GadgetY(_TGMou),250,20,"",0)
SetGadgetFont(_TGMou,Font1)
SetGadgetFont(_TGkey,Font1)
GadgetToolTip(_TGMou,"Show Notes Played with Mouse")
GadgetToolTip(_TGkey,"Show Notes Played with PC Keyboard")
GadRGB(_TGMou,0,#Red)
GadRGB(_TGkey,0,#Green)
DrawImg(#Img)
Box(0, 0, W_KBD + 1, _WhiteKeyHeight + 2,$673D06)   ; background & space between Keys
For I = 0 To 127                                    ; Draw all keys - full MIDIKeyboard
  DrawKBD(I, #Black)
Next I
MIDIinit()
Define OldNote=-1, LastNote=-1
SetSounds(1, Sounds)  
AddKeyboardShortcut(0,$A1,302)  ;Right shift para MIDINote 67
HideWindow(0,0)
Repeat
  If GetAsyncKeyState_(27)&$8000 :  End : EndIf
  Ev = WaitWindowEvent(1)
  If MMk=2 Or GetAsyncKeyState_(#VK_CONTROL) 
    AllOff()
    For I = 0 To 127                                  
      DrawKBD(I, #Black)
    Next I
    _Keep$=""
    SetGadgetText(_TGkey, "")
    If KeySel :   KeySel=0:    EndIf
    SetGadgetText(_TGMou,"")
   ElseIf MMk=0 And Sustain=0 And OldNote>-1
    AllOff()
    OldNote=-1
  EndIf
  Select Ev
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #Sustain
          Sustain = GetGadgetState(#Sustain)
          SetGadgetText(#Sustain, Str(Sustain))
          If Sustain : Sustain(-1, Sustain)
          Else       : SetGadgetText(_TGkey, "")
          EndIf
          SetActiveGadget(#ImGad)
          WindowEvent()                             ; avoid endless event-Loops
        Case #Sounds
          X=WindowX(0)+GadgetX(#Container)+GadgetX(#Sounds)
          Y=WindowY(0)+GadgetY(#Container)+GadgetY(#Sounds)+46
          DisplayPopupMenu(GMMenu, WindowID(0),X,Y) 
        Case #ShutUp :AllOff()
          SetGadgetText(_TGkey, "")
          If KeySel : DrawKBD(KeySel - 1, #Black)
            KeySel=0
          ElseIf MousNote : DrawKBD(MousNote,#Black)
          EndIf
        Case #Volume
          MIDIVolume=GetGadgetState(#Volume)
          SetGadgetText(#ShowVolume,"Vol "+Str(MIDIVolume))
          MIDIVolume(1,MIDIVolume)
        Case #MouseOver
           MouseOver=GetGadgetState(#mouseover)
          SetGadgetText(_TGMou,"")
          SetActiveGadget(#Container)
        Case #Quit : Break
      EndSelect
    Case  #PB_Event_Menu 
      Select EventMenu()     
        Case 0 To 127
          Sounds=EventMenu()
          SetSounds(1, Sounds)  ; many Sound cards have  Sounds only From 0 to 108, so some keys may be muted
          Sound$=GetMenuItemText(GMMenu,EventMenu())
          SetGadgetText(#Sounds,"Sound "+Str(Sounds+1)+" : "+_Sounds(Sounds))
          AllOff()
        Case 302 :  KbNT=67 ; right shift assigned to "qwerty" line
      EndSelect
    Default
      MousNote=GetNote()
      If MousNote>-1
        If MMk=1 Or MouseOver
          If MousNote<>LastNote
            If Sustain
              PlayNote(1, MousNote, 0)  ; mute MouseNote
            ElseIf OldNote>-1   
              AllOff()
              OldNote=-1
            EndIf
            LastNote=-1
            PlayNote(1, MousNote,Loudness)
            OldNote=MousNote
            If Sustain:Sustain(MousNote, Sustain):EndIf
          EndIf
          LastNote=MousNote
          If MousNote + 1 <> KeySel     ; +1 because 0 is a legal MIDINote
            If KeySel
              DrawKBD(KeySel - 1, #Black)
              If GetGadgetState(#Sustain) = 0 : PlayNote(1, KeySel - 1, 0) : EndIf
            EndIf
            If MouseOver 
              PlayNote(1, MousNote,Loudness) 
              If Sustain : Sustain(MousNote, Sustain) : EndIf
            EndIf
            DrawKBD(MousNote,#Red ) ; Mouse pressed Note
          EndIf
          KeySel = MousNote + 1
        Else
          LastNote=-1   
        EndIf
      EndIf
  EndSelect
  ; in some PC keyboards is possible to hit 2 or more keys siMoultaneously to Play Chords
  If Ev= #WM_KEYDOWN Or Ev= #WM_KEYUP
    LParam=EventlParam()
    If Ev=#WM_KEYDOWN
      If (LParam & #KeyPrevState)=0 ; avoid repeateds
        HIWO=HIWO(LParam)
      Else
        KbNT=-1
      EndIf    
    Else
      HIWO=HIWO(LParam)-$C000
    EndIf   
    Select HIWO
      Case 2 To 28, 30 To 54,58,86
        KbNT=_Pair(HIWO)
        K$=Chr(KbNT)
        Finds=FindString(KBD$,K$,1)
        If Ev=#WM_KEYDOWN  
          RGB=#Green
          If Finds=0
            PlayNote(1,KbNT,Loudness)
            KBD$+K$
          EndIf
        ElseIf Finds 
          PlayNote(1,KbNT,0)
          KBD$=ReplaceString(KBD$,K$,"")
        EndIf
        If Len(KBD$) : SetGadgetText(_TGkey, MIDI_2_Notes(KBD$)) 
        Else : SetGadgetText(_TGkey, "") 
        EndIf                        
        DrawKBD(KbNT,RGB)
      Default
        KbNT=-1
    EndSelect
  Else 
    RGB=#Black
  EndIf
Until Ev = 16 ;#PB_Event_CloseWindow
midiOutClose_(_HMIDIout)
CloseWindow(0)
End
;<<<<<<<<<<<<<<<<<<<<
DataSection
  GeneralMIDISounds:
  Data.S "Keyboards","Piano 1", "Piano 2","Piano 3","Honky-tonk","Electric Piano 1","Electric Piano 2","HarpsiChord","Clavinet",
         "Chromatic Percusion","Celesta","Glockenspiel", "Music Box","Vibraphone","Marimba","Xylophone","Tubular bell","Dulcimer",
         "Organ/Accordion","Organ 1","Organ 2","Organ 3","Church organ 1","Reed Organ","French Accordion","Harmonica","Bandoneon",
         "Guitars","Nylon-string Guitar","Steel-string Guitar","Jazz Guitar","Clean Guitar","Muted Guitar","Overdrive Guitar","Distortion Guitar","Guitar Harmonics",
         "Bass","Acoustic Bass","Fingered Bass","Picked Bass","Fretless Bass","Slap Bass 1","Slap Bass 2","Synth Bass 1","Synth Bass 2",
         "Strings","Violin","Viola","Cello","Contrabass","Tremolo Strings","Pizzicato","Harp","Timpani",
         "Orchestral","Strings","Slow Strings","Synth Strings 1","Synth Strings 2","Choir Aahs","Voice Oohs","SynVox","Orchestra Hit",
         "Brass","Trumpet","Trombone","Tuba","Muted Trumpet","French Horn","Brass  Section","Synth Brass 1","Synth Brass 2",
         "Reed","Soprano Sax","Alto Sax","Tenor Sax","Baritone Sax","Oboe","English Horn","Basson","Clarinet",
         "Woodwinds","Piccolo","Flute","Recorder","Pan Flute","Bottle Blow","Shakuhachi","Whistle","Ocarina",
         "Lead Synth","Square Wave","Saw Wave","Synth Calliope","Chiffer Lead","Charang","Solo Vox","5th Saw Wave","Bass&Lead",
         "Synth Pad","Fantasia","Warm pad","PolySynth","Space Voice","Bowed Glass","Metal pad","Halo pad","Sweep pad",
         "Synth Effects","Ice Rain","Sound Track","Crystal","Atmosphere","BRightness","Goblin","ECho Drops","Star Theme",
         "Ethnic","Sitar","Banjo","Shamisen","Koto","Kalimba","Bag Pipe","Fiddle","Shanai",
         "Percussion","Tinkle bell","Agogo","Steel Drums","Woodblock","Taiko Drum","Melodic Tom 1","Synth Drum","Reverse Cymb",
         "Sound Effects","Guitar FretNoise","Breath Noise","Seashore","Bird","Telephone","Helicopter","Applause","Gun Shot","_Last_"
  ;--------------------------------------------------------------------------------------------------------
  MapKeys:   ; PC Keyboard config ; assign pairs (MIDINotes to each Key) to simulate a Piano Keyboard
  ; This configuration is for Spanish keyboard layout  ; first data=key, 2nd data=midinote   <<<<<<<<<<<<<<<<<<<<<<
  Data.I 41  , 65     ;F ;row 1234...
  Data.I 2   , 66     ;F#   
  Data.I 3   , 68     ;Ab
  Data.I 4   , 70     ;Bb
  Data.I 5   , 72     ;C
  Data.I 6   , 73     ;C#
  Data.I 7   , 75     ;Eb
  Data.I 8   , 77     ;F
  Data.I 9   , 78     ;F#
  Data.I 10  , 80     ;Ab
  Data.I 11  , 82     ;Bb
  Data.I 12  , 84     ;C
  Data.I 13  , 85     ;C#
  Data.I 14  , 87     ;Eb 
  Data.I 15  , 65     ;F  ;row qwerty ; C Scale
  Data.I 16   , 67     ;G 
  Data.I 17   , 69     ;A
  Data.I 18   , 71     ;B
  Data.I 19   , 72     ;C
  Data.I 20   , 74     ;D
  Data.I 21   , 76     ;E
  Data.I 22   , 77     ;F
  Data.I 23   , 79     ;G
  Data.I 24   , 81     ;A
  Data.I 25   , 83     ;B
  Data.I 26   , 84     ;C
  Data.I 27   , 86     ;D
  Data.I 28   , 88     ;E
  Data.I 58   , 48     ;C  ;row asdf ; Db Scale
  Data.I 30   , 49     ;Db  
  Data.I 31   , 51     ;Eb
  Data.I 32   , 53     ;F
  Data.I 33   , 54     ;Gb
  Data.I 34   , 56     ;Ab
  Data.I 35   , 58     ;Bb
  Data.I 36   , 60     ;C
  Data.I 37   , 61     ;Db
  Data.I 38   , 63     ;Eb
  Data.I 39   , 65     ;F
  Data.I 40   , 66     ;Gb
  Data.I 43   , 68     ;Ab 
  Data.I 42   , 47     ;B    ;row zxcv...
  Data.I 86   , 48     ;C    
  Data.I 44   , 50     ;D
  Data.I 45   , 52     ;E
  Data.I 46   , 53     ;F
  Data.I 47   , 55     ;G
  Data.I 48   , 57     ;A
  Data.I 49   , 59     ;B
  Data.I 50   , 60     ;C
  Data.I 51   , 62     ;D
  Data.I 52   , 64     ;E
  Data.I 53   , 65     ;F
  Data.I 54   , 67     ;G  
  Data.I $ACABA
EndDataSection

Re: New Midi Keyboard

Posted: Mon Mar 11, 2013 11:20 pm
by electrochrisso
That is 8) update einander, thanks for sharing. :D

Re: New Midi Keyboard

Posted: Tue Mar 12, 2013 2:43 am
by flaith
:D Really nice, thanks einander

Re: New Midi Keyboard

Posted: Tue Mar 12, 2013 11:26 am
by rsts
Wow - the music maestro!

Thanks for sharing.

Re: New Midi Keyboard

Posted: Tue Mar 12, 2013 11:41 am
by Kwai chang caine
Waooouuhh !! Splendid :shock:
Thanks Einander 8)

Re: New Midi Keyboard

Posted: Wed Mar 13, 2013 12:55 am
by yrreti
wOw! Really neat piece of work Einander. And the range, plus the keyboard layout!
Excellent job!

yrreti

Re: New Midi Keyboard

Posted: Wed Mar 13, 2013 1:02 pm
by einander
Thanks guys!
PC keyboard and mouse are very limited (almost unusable) tools for input music.
To play or investigate Midi, the best choice is a Midi Keyboard.

If someone is interested, here is some info about budget USB keyboards:
http://www.musicradar.com/news/tech/the ... s-565848/1
http://www.akaipro.com/lpk25

I've spent many years playing with them, and I can state that are very useful tools.
Cheers!

Re: New Midi Keyboard

Posted: Wed Mar 20, 2013 9:28 pm
by Psychophanta
Nice, Einander.
Do you know this?
http://www.synthesiagame.com/

I enjoyed it and tried to do a program which worked like it, for midi and also for real sound samples, but i have the project not finished because of i must write other things and programs and no time.
May be you like the idea and as you have good knowledge on MIDI stuff may be you could make something like it.

Re: New Midi Keyboard

Posted: Thu Mar 21, 2013 1:30 am
by einander
Hi Psychophanta: thanks for the link.
For me this program is a good idea spoiled.
I like:
Graphics and smooth scrolling (are far better than the music).
I don't like:
The user interface is not intuitive. I miss standard windows, progress bars, menus and close buttons.
The provided midifiles are too simplified : EG: Beethoven's Moonlight sonata is too far from the original.
I've tried to add some midifiles, but there is oly the option "Stop searching this folder for songs" and nothig happens. Way too long for my patience. :mrgreen:

Re: New Midi Keyboard

Posted: Thu Mar 21, 2013 8:38 am
by Psychophanta
einander wrote:Hi Psychophanta: thanks for the link.
For me this program is a good idea spoiled.
I like:
Graphics and smooth scrolling (are far better than the music).
I don't like:
The user interface is not intuitive. I miss standard windows, progress bars, menus and close buttons.
The provided midifiles are too simplified : EG: Beethoven's Moonlight sonata is too far from the original.
I've tried to add some midifiles, but there is oly the option "Stop searching this folder for songs" and nothig happens. Way too long for my patience. :mrgreen:
Exactly, That's why i gave you the idea, just for you to make the idea in PB and improve it if you see that it is worth! :)

Re: New Midi Keyboard

Posted: Thu Mar 21, 2013 6:54 pm
by einander
just for you to make the idea in PB and improve it if you see that it is worth! :)
Here goes a first approach, without scrolling:
http://www.purebasic.fr/english/viewtop ... 12&t=54039

Re: New Midi Keyboard

Posted: Wed May 08, 2013 1:40 pm
by lelion
I wrote an app dealing with midi and midifile. Currently playing via MCI lib , i especially worked on a very smooth GUI and some harmony "productivity" functions that i needed in my musician work. I have also developped a wav to midi module that should be implemented later.
I'm looking for collaborations in a bigger commercial software project. Is there a better place to post this ?

Maintaining such a project takes too long for a single devlopper. I d like to know if some forum people would be interrested in any kind of collaboration.. PB makes a good midi , thus , good pb midi dev may be hard to find in the real world.. thanks in advance for any idea

Re: New Midi Keyboard

Posted: Wed May 08, 2013 3:05 pm
by davido
Pure magic!

Thanks, very much for sharing.

Re: New Midi Keyboard

Posted: Wed May 08, 2013 4:30 pm
by einander
@ lelion:
I'm looking for collaborations in a bigger commercial software project. Is there a better place to post this ?

The General Discussion board seems the relevant one for this request.

Re: New Midi Keyboard

Posted: Sun Jul 14, 2013 12:20 am
by kenmo
Very cool MIDI example! I was just looking for PB MIDI code. Thanks for sharing this.