GUI: piano keyboard

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

GUI: piano keyboard

27 Dec 2017, 20:41

- Does anybody have any good AHK links for a piano keyboard GUI?
- I'd be interested in any existing or new scripts, simple or complex. Thanks.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: GUI: piano keyboard

28 Dec 2017, 05:37

I'd guess you've already checked :arrow: [this] and :arrow: [that] as a starting point?
Probably another option, to use your keyboard already connected to :arrow: [this] (its sounds are not that distortet)
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

28 Dec 2017, 06:08

- Many thanks for the links.
- The zip for OnScreenPiano isn't available (and the link is unsafe). In case anyone has the zip.
- I have code regarding playing MIDIs from rommmcek (that I need to investigate), although people are welcome to post any sound/MIDI related links to this thread also.
- I'm wondering how best to handle images, to indicate that a key is held down. E.g. change keys to red as they are played.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: GUI: piano keyboard

28 Dec 2017, 06:40

Not sure if you've checked [the online piano] already ("Load Piano Keyboard". It sounds are great, and its keys are changing its color the way you've descriped it)
Odlanir
Posts: 659
Joined: 20 Oct 2016, 08:20

Re: GUI: piano keyboard

28 Dec 2017, 09:04

I've played around the GUI part of your goal. Can be a little starting point really far from being perfect.
Cheers.

Code: Select all

notesFull := ["C","D","E","F","G","A","B"]
notesHalf := ["C#","D#","F#","G#","A#"]
Gui,+AlwaysOnTop 
cnt := 0, cols := 6, WS_CLIPSIBLINGS := +0x4000000 ; https://autohotkey.com/boards/viewtopic.php?t=227
octave := 1, i := 1
Gui, add, Button,% " w25 x28 y10 h80 v" notesHalf[i] octave " gBut hwnd" notesHalf[i] octave
loop, 22{
	if (a_index = 2 || a_index  = 6 || a_index  = 9 || a_index  = 13 || a_index  = 16  || a_index  = 20 )
		Gui, add, Button,% " w25 xp+31 yp h80 hidden"
	else  {
		if ( Mod(a_index, 7) = 0 )
			++octave, i:=0
		varx := notesHalf[++i] octave
		Gui, add, Button,% " w25 xp+31 yp h80 v" varx " gBut hwnd" varx
	}
}
octave := 1, i := 1
Gui, add, Button,% WS_CLIPSIBLINGS " w30 x10 yp h140 v" notesFull[i] octave " gBut hwnd" notesFull[i] octave
loop, 23{
	if ( Mod(a_index, 7) = 0 )
		++octave, i:=0
	varx := notesFull[++i] octave
	Gui, add, Button,% WS_CLIPSIBLINGS " w30 x+1 yp h140 v" varx " gBut hwnd" varx
}
Gui, Show
return
____________________________________________________________________________
Windows 10 Pro 64 bit - Autohotkey v1.1.30.01 64-bit Unicode
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

28 Dec 2017, 10:48

- @Odlanir: Thanks, that's really nice. Hmm, it's relatively simple, you just need buttons that overlap, you don't need 3 images for 3 different types of white key. I suppose, fundamentally, all that needs to be done is to create some rectangular controls, and change the colour.
- Btw, to get it working I added:

Code: Select all

But:
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Odlanir
Posts: 659
Joined: 20 Oct 2016, 08:20

Re: GUI: piano keyboard

28 Dec 2017, 14:12

My bad. I forgot to paste the code which shows the selected note.
I've coded an updated gui with coloured keys, hope you like it.

Code: Select all

notesFull := ["C","D","E","F","G","A","B"]
notesHalf := ["C#","D#","F#","G#","A#"]
Gui,+AlwaysOnTop 
;~ Gui, Color, EEAA99

cnt := 0, cols := 6, WS_CLIPSIBLINGS := +0x4000000 ; https://autohotkey.com/boards/viewtopic.php?t=227
octave := 1, i := 1
Gui, add, text,% " w25 x28 y10 h80 v" notesHalf[i] octave " gBut border hwnd" notesHalf[i] octave
loop, 22{
	if (a_index = 2 || a_index  = 6 || a_index  = 9 || a_index  = 13 || a_index  = 16  || a_index  = 20 )
		Gui, add, text,% " w25 xp+31 yp h80 hidden "
	else  {
		if ( Mod(a_index, 7) = 0 )
			++octave, i:=0
		varx := notesHalf[++i] octave
		Gui, add, text,% " w25 xp+31 yp h80 v" varx " gBut border hwnd" varx		
	}
}
octave := 1, i := 1
Gui, add, text,% WS_CLIPSIBLINGS " w30 x10 yp h140 v" notesFull[i] octave " gBut border hwnd" notesFull[i] octave
loop, 23{
	if ( Mod(a_index, 7) = 0 )
		++octave, i:=0
	varx := notesFull[++i] octave
	Gui, add, text,% WS_CLIPSIBLINGS " w30 x+1 yp h140 v" varx " gBut border hwnd" varx	
}
Gui, Show
notes := [C1,D1,E1,F1,G1,A1,B1,C2,D2,E2,F2,G2,A2,B2,C3,D3,E3,F3,G3,A3,B3,C4,D4,E4] 
loop % notes.Maxindex() {
	SetStaticColor(notes[a_index], 0xFFFFFF)
}
notes := [C#1,D#1,F#1,G#1,A#1,C#2,D#2,F#2,G#2,A#2,C#3,D#3,F#3,G#3,A#3,C#4,D#4] 
loop % notes.Maxindex() {
	SetStaticColor(notes[a_index], 0x000000)
}
return

ExitApp

But:
	ToolTip % A_GuiControl
return

esc::
GuiClose:
GuiEscape:
	exitapp




SetStaticColor(hStatic, b_color, f_color := 0)
{
   static arr := [], GWL_WNDPROC := -4
   b_color := DllCall("Ws2_32\ntohl", UInt, b_color << 8, UInt)
   f_color := DllCall("Ws2_32\ntohl", UInt, f_color << 8, UInt)
   hGui := DllCall("GetParent", Ptr, hStatic, Ptr)
   if !arr.HasKey(hGui)  {
      arr[hGui] := {}, arr[hGui].Statics := []
      arr[hGui].ProcOld := DllCall("SetWindowLong" . (A_PtrSize = 8 ? "Ptr" : ""), Ptr, hGui, Int, GWL_WNDPROC
                                    , Ptr, RegisterCallback("WindowProc", "", 4, Object(arr[hGui])), Ptr)
   }
   else if arr[hGui].Statics.HasKey(hStatic)
      DllCall("DeleteObject", Ptr, arr[hGui].Statics[hStatic].hBrush)
   arr[hGui].Statics[hStatic] := { b_color: b_color, f_color: f_color
                                 , hBrush: DllCall("CreateSolidBrush", UInt, b_color, Ptr) }
   WinSet, Redraw,, ahk_id %hStatic%
}

WindowProc(hwnd, uMsg, wParam, lParam)
{
   Critical
   static WM_CTLCOLORSTATIC := 0x138
   obj := Object(A_EventInfo)
   if (uMsg = WM_CTLCOLORSTATIC && k := obj.Statics[lParam])  {
      DllCall("SetBkColor", Ptr, wParam, UInt, k.b_color)
      DllCall("SetTextColor", Ptr, wParam, UInt, k.f_color)
      Return k.hBrush
   }
   Return DllCall("CallWindowProc", Ptr, obj.ProcOld, Ptr, hwnd, UInt, uMsg, Ptr, wParam, Ptr, lParam)
}
____________________________________________________________________________
Windows 10 Pro 64 bit - Autohotkey v1.1.30.01 64-bit Unicode
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

28 Dec 2017, 18:21

- Looks great, thanks so much!
- Btw for the 'notes' arrays you probably want "C1","D1" ..., or, easier than that, use StrSplit.
- Is it easy to say, have a hotkey that changes a specific key's colour. If I can do that, then that's all the GUI I need. (I did try to fiddle about with the script a bit.)

- Actually, one other GUI, if anyone has any ideas, would be to show squares/horizontal lines corresponding to notes as they're played, which would be more complicated.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: GUI: piano keyboard

28 Dec 2017, 20:33

I took the first GUI from Odlanir (thanks for sharing!) and changed the Buttons to ListViews for coloring.
I also added an Icon, a timer for the Tooltips and SoundBeeps. (All keys play the note for 250ms, need to improve here)
You can choose between "Pythagoras' tuning" and "equal temperament". Or rather my understanding thereof.

Code: Select all

#NoEnv
#SingleInstance, Force

    Menu, Tray, Icon, Piano.ico
    Temperament := "Pythagoras" ; comment this line for equal temperament

    PythRatio ; integer ratios = Pythagoras' tuning
    := { "C" :   1 /   1
       , "C#":  17 /  16
       , "D" :   9 /   8
       , "D#": 153 / 128
       , "E" :  81 /  64
       , "F" :   4 /   3
       , "F#":  17 /  12
       , "G" :   3 /   2
       , "G#":  51 /  32
       , "A" :  27 /  16
       , "A#": 459 / 256
       , "B" : 243 / 128 }

    Equal ; 12th roots = equal temperament
    := { "C" : 2**( 0/12)
       , "C#": 2**( 1/12)
       , "D" : 2**( 2/12)
       , "D#": 2**( 3/12)
       , "E" : 2**( 4/12)
       , "F" : 2**( 5/12)
       , "F#": 2**( 6/12)
       , "G" : 2**( 7/12)
       , "G#": 2**( 8/12)
       , "A" : 2**( 9/12)
       , "A#": 2**(10/12)
       , "B" : 2**(11/12) }

    Gosub, GuiCreate
    Gui, Show,, Piano

Return ; end of auto-execute section



GuiClose:
ExitApp



;-------------------------------------------------------------------------------
GuiCreate: ; draw piano keys (thx to Odlanir)
;-------------------------------------------------------------------------------
    ; https://autohotkey.com/boards/viewtopic.php?p=191212#p191212
    ;---------------------------------------------------------------------------

    Clip := 0x4000000 ; WS_CLIPSIBLINGS
    NotesHalf := [  "C#","D#",     "F#","G#","A#"  ]
    NotesFull := ["C", "D", "E", "F", "G", "A", "B"]

    Gui, +AlwaysOnTop
    Gui, Margin, 0, 0

    ; black keys
    Octave := 1, i := 1, varx := NotesHalf[i] Octave
    Gui, Add, ListView, x18 w25 h80 gBut v%varx% Background AltSubmit
    loop, 22 {
        If A_Index in 2,6,9,13,16,20
            Gui, Add, Button, xp+31 yp wp hp Hidden ; use plain buttons here
        Else {
            If Mod(A_Index, 7) = 0
                ++Octave, i := 0
            varx := NotesHalf[++i] Octave
            Gui, Add, ListView, xp+31 yp wp hp gBut v%varx% Background AltSubmit
        }
    }

    ; white keys
    Octave := 1, i := 1, varx := NotesFull[i] Octave
    Gui, Add, ListView, x0 yp w30 h140 gBut v%varx% AltSubmit %Clip%
    loop, 23 {
        If Mod(A_Index, 7) = 0
            ++Octave, i := 0
        varx := NotesFull[++i] Octave
        Gui, Add, ListView, x+1 yp wp hp gBut v%varx% AltSubmit %Clip%
    }

Return



;-------------------------------------------------------------------------------
But: ; all the keys come here
;-------------------------------------------------------------------------------
    If (A_GuiEvent = "Normal") {
        Note   := SubStr(A_GuiControl, 1, StrLen(A_GuiControl) - 1)
        Octave := SubStr(A_GuiControl, 0) ; last char
        Tuning := (Temperament = "Pythagoras") ? PythRatio[Note] : Equal[Note]
        Freq   := Round(2**(Octave+7) * Tuning)
        SoundBeep, Freq, 250
        ToolTipEx(A_GuiControl "`n" Freq)
    }

Return



;-------------------------------------------------------------------------------
ToolTipEx(Text) { ; w/ auto-off
;-------------------------------------------------------------------------------
    ToolTip, %Text%
    SetTimer, ToolTipOff, -1000
    Return, Text

    ToolTipOff:
        ToolTip ; off
    Return
}
Attachments
icon.zip
(234 Bytes) Downloaded 274 times
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

28 Dec 2017, 21:44

- @wolf_II: Looks nice, the icon makes it look very sleek.
- Btw sometimes when clicking, if you click a border, it doesn't play a sound.
- Anybody had a go at keys that change colour? E.g. when you click them, or when you press a key.
- Thanks so much for both scripts.
- My plan, should I get there, is to display MIDI files on the keyboard. But I would do things like miss out certain notes, shift the pitch, or change the key.
- Pythagorean comma. Hmm.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: GUI: piano keyboard

28 Dec 2017, 21:51

I added two hotkeys in order to see if I am able to hear a difference between the two temperaments. I could not.

Code: Select all



;-------------------------------------------------------------------------------
F11:: ; switch between temperaments
;-------------------------------------------------------------------------------
    Temperament := (Temperament = "Equal") ? "Pythagoras" : "Equal"
    Gui, Show,, Piano - %Temperament%

Return



;-------------------------------------------------------------------------------
F12:: Play("CDEFG G AAAAG AAAAG GFFFFEEEEDEDCEG GFFFFEEEEDEDC") ; nice song
;-------------------------------------------------------------------------------



;-------------------------------------------------------------------------------
Play(Song) { ; support only full notes in 1st octave
;-------------------------------------------------------------------------------
    global Temperament, PythRatio, Equal

    While Song {
        Note   := SubStr(Song, 1, 1)
        Song   := SubStr(Song, 2)
        Tuning := (Temperament = "Pythagoras") ? PythRatio[Note] : Equal[Note]
        Freq   := Round(256 * Tuning)
        SoundBeep, Freq, 250
    }
}
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: GUI: piano keyboard

28 Dec 2017, 22:12

My attempt at keys changing color needs a sleep: :(

Code: Select all



;-------------------------------------------------------------------------------
But: ; all the keys come here
;-------------------------------------------------------------------------------
    If (A_GuiEvent = "Normal") {
        Note   := SubStr(A_GuiControl, 1, StrLen(A_GuiControl) - 1)
        Octave := SubStr(A_GuiControl, 0) ; last char
        Tuning := (Temperament = "Pythagoras") ? PythRatio[Note] : Equal[Note]
        Freq   := Round(2**(Octave+7) * Tuning)
        Color  := InStr(Note, "#") ? "Black" : "White"
        GuiControl, +BackgroundRed, %A_GuiControl%
        SoundBeep, Freq, 250
        Sleep, 100
        ToolTipEx(A_GuiControl "`n" Freq)
        GuiControl, +Background%Color%, %A_GuiControl%
    }

Return
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: GUI: piano keyboard

28 Dec 2017, 22:15

jeeswg wrote:- Pythagorean comma. Hmm.
I don't understand this, is it about a typo I made?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

28 Dec 2017, 22:23

- Re. Pythagorean comma, it's a concept, you reminded me of it. Wondered if you'd come across it.
- Thanks for providing both temperaments. That table of ratios looks nice. As do the colour-changing keys.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: GUI: piano keyboard

28 Dec 2017, 22:39

Re: Pythagorean comma

I have first come across the term a few months ago here:
https://de.wikipedia.org/wiki/Pythagoreische_Stimmung
https://de.wikipedia.org/wiki/Gleichstufige_Stimmung
In German there seem to be a lot of different words for the same thing. :(
All I understand about it is reflected in my code. Do you have anything of interest?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

28 Dec 2017, 22:43

I just remember it from something I listened to once. It was amusing, a special number, like pi, e or i, a very small pitch difference.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
wolf_II
Posts: 2688
Joined: 08 Feb 2015, 20:55

Re: GUI: piano keyboard

28 Dec 2017, 22:59

I somehow associate "make a song with the number pi" with Brady Haran from Numberphile.
I could not find what I was looking for, but I found this nice piece of music:
https://www.youtube.com/watch?v=OMq9he-5HUU
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

25 Mar 2018, 15:49

This is great:
Piano Player - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=45330
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
rommmcek
Posts: 1473
Joined: 15 Aug 2014, 15:18

Re: GUI: piano keyboard

26 Mar 2018, 09:45

@jeeswg: I answered to you this morning via PM with zip file attached. Now I see the message got stuck in Outbox. Did you receive my message?
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: piano keyboard

26 Mar 2018, 09:56

Yes I did, messages in the Outbox, are messages that the recipient hasn't read yet. The problem was simply that I'm not logged in and active 24/7 on the AutoHotkey website. Cheers.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Anput, ShatterCoder and 112 guests