This piano has a realistic action and sound and was designed to use the Canvas
TouchDown event block for determining which 'key' was pressed.
It is not
polyphonic, and like many cheap toy keyboards, can play one note at a time (but has a great sound :).
This is done by using two canvases contained in a HorizontalScreenArrangement: one for the ivory keys and one for the ebony keys.
Using an
image mapping technique the location of the user's touch is translated to an offset for a specific piano key on each of the canvases.
A single ImageSprite is used in each canvas to highlight where the user touched and a single Player component is used to play a midi note if the area touched contains a piano key (1) .
Also, this project features a scrolling piano keyboard -- allowing access to piano keys that are not currently visible on the Screen.
(1) there are empty areas on the ebony keys row which can be touched, but must be ignored
Open the lrn_Canvas_TouchDown_advanced project.
Screen Designer:
Two keyboard images and a key highlight were created with
GIMP image editor:
- ivories816.png: ivory keys: 816x50; 17 keys; each 50x48
- ebonies816.png: ebony keys: 816x50; 12 keys; each 50x48 and filled areas representing the backs of the ivory keys
- touched.png: key highlight; 50x48; Android blue, 50% opacity
Twenty-nine
midi files were created with the
Anvil Studio midi sequencer.
Each file contains one measure containing one whole note played at 120 bps.
The voice used was Acoustic Grand Piano.
The notes range from C4 to E6.
All of these files are included in the Media list of the Screen Designer.
Screen1:
AlignHorizontal: Center
AlignVertical: Center
BackgroundColor: Dark Gray
ScreenOrientation: Portrait
Scrollable: (checked)
- This allows maximum visibility to of the piano keys and access to all keys by scrolling.
For touched_ivory_spr and touched_ebony_spr:
Picture: touched.png
X: 0
Visible: (uncheck)
Width: 50
Height: 48
note_ply:
Volume: 100
---
Blocks Editor:
The ivory_notes global variable contains a list of midi file names which are played by the ivory keys.

The ebony_notes global variable contains a list of midi file names which are played by the ebony keys and empty text items where no key is present.
Key_index holds the index to the midi file item in the ivory_notes and ebony_notes lists.
In the ebony_notes list it also may index an empty text item where there is no key at that position.

ivories_cnv.TouchDown plays the midi sound of the key and displays a highlight showing which key was pressed.

- in case an ebony key is highlighted, touched_ebony_spr.Visible is set to false
- key_index is set to the index of the midi file to play based on the y value of the area touched (ivories_cnv.TouchDown, ivories_td_y)
- the note is played from the ivory_notes list using key_index
- the touched_ivory_spr highlight y position is calculated based on key_index
- the touched_ivory_spr highlight is displayed
ebonies_cnv.TouchDown plays the midi sound of an ebony key and displays a highlight showing which key was pressed.

- the index to the note in the ebony_notes list is calculated, offsetting y by 24 pixels as the first ebony key is located at y=24px
- if the item in ebony_notes list at the key_index position is not empty text, then continue with the following steps:
- hide touched_ivory_spr
- play the note based on key_index to the ebony_notes list
- set touched_ebony_spr.Y to the position where the the key was touched
- show touched_ebony_spr
About the Math block quotient: quotient returns the quotient of a division and discards the remainder.
This is comparable to the int() function in other programming languages.
Test the project.
Challenge:
Enhancements to this project might include:
- adjustable volume or other options
- UI refinement (colorful background image, animations, etc.)
(I have not been able to get multi-touch to work in AI yet. To play more than one note at a time (polyphony) in AI you can statically record each key pressed for a chord, then play each corresponding note back with multiple players at the same time. Positioning multiple sprites so that they collide with a sprite cursor at the same time can produce chords as well when those sprite's event blocks play a specific note.)