STEM

An interactive musical keyboard player (Python)

In this post, I am sharing my Python code for creating a simple musical keyboard player that can be played using a standard computer keyboard. The app will generate specific musical notes as you press keys A-Z on your keyboard. You can increase a note by half-step or full-step by each press. So, increasing by half-step twice will effectively increase it to full-step and so on. There’s no limit to how much you increase by but your speaker range may limit the sound from being heard at extremely high or low ranges. Similarly, you can decrease a note by a half or full-step with each press of a key (the command keys are shown below in this post). You can also increase or decrease the pitch by an octave by press of a key and it’s also cumulative, meaning, at each press, it’ll go up by an octave from the previous octave.

The other things the app is doing is save all your notes in memory during a session. To copy which notes (standard musical note names) were played and at what frequency (in hertz), and for how long (duration in seconds), just press F5 key anytime and the history will be copied to the clipboard, then you can open Notepad or any editor and simply paste. And voila! All your play history is pasted in the order you played them. If you want to also see the actual frequency and duration, the app also prints out that information in the console/Shell window (same time when you press F5 key)…from where you can simply copy the text and save it in a document for your reference.

An example history may look like this:

f:D4,d:C4,f:D4,g:D#4/Eb4,f:D4,d:C4,a:A3,f:D4,d:C4,f:D4,d:C4,f:D4,d:C4,f:D4,g:D#4/Eb4,f:D4,d:C4,a:A3

The format is a pair for each note showing the computer keyboard key that was pressed followed by the music note that was played when it was pressed separated by a colon; and all notes pairs are comma-separated and can be saved as a text or CSV file.

The history output in the console/Shell provides frequency and duration history, and it may look like this:

Frequeny history: [146.84, 130.8, 146.84, 155.56, 146.84, 130.8, 110.0, 146.84, 130.8, 146.84, 130.8, 146.84, 130.8, 146.84, 155.56, 146.84, 130.8, 110.0]
Duration history: [0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25]

The notes history can be saved in a text file, and I have another app that can read back a saved file and will play back all the notes exactly as saved and can even be fine-tuned; see Related Posts section below for that blog post.

Also note that in the code below, I have set a limit of 400 notes for the history after which, it’ll automatically start over the history —this is an arbitrary limit and you can increase or decrease it to your needs.

Limitations:

Due to the nature of how computer keyboards are designed, it’s not possible for me to actually detect the pressure exerted on the keys while playing, so it’ll simply be either pressed or not pressed. That means, the app will not record varying durations in-between key presses…the duration between presses will remain constant. Also, due to the limitations of a standard keyboard, if you try to play consecutive notes to fast, it may fail to register and play some notes. So, keep these limitations in mind when you play with the app.

To generate a musical note, you press a letter key a to z on your keyboard. Those letters are actually mapped to real musical notes as below. On the left side of colon is the key on the physical computer keyboard, and in parenthesis are the canonical musical note name and the frequency in hertz (as tuned in a standard USA piano):

'a': ('A3', 220.00),
'b': ('A#3/Bb3', 233.08),
'c': ('B3', 246.96),
'd': ('C4', 261.60),
'e': ('C#4/Db4', 277.20),
'f': ('D4', 293.68),
'g': ('D#4/Eb4', 311.12),
'h': ('E4', 329.60),
'i': ('F4', 349.20),
'j': ('F#4/Gb4', 370.00),
'k': ('G4', 392.00),
'l': ('G#4/Ab4', 415.28),

'm': ('A4', 440.00),
'n': ('A#4/Bb4', 466.16),
'o': ('B4', 493.92),
'p': ('C5', 523.20),
'q': ('C#5/Db5', 554.40),
'r': ('D5', 587.36),    
's': ('D#5/Eb5', 622.24),
't': ('E5', 659.20),
'u': ('F5', 698.40),
'v': ('F#5/Gb5', 740.00),
'w': ('G5', 784.00),
'x': ('G#5/Ab5', 830.56),

'y': ('A5', 880.00),
'z': ('A#5/Bb5', 932.32)

The command keys:
You can press F1 anytime to bring up on-screen help, which shows which keys to press in increase pitch, how to copy play history to clipboard, and clear history, etc. The help text is shown below:

As you press a key on your keyboard, both the actual musical note that the key is mapped to along with the frequency are shown on screen, as well as the key pressed on the keyboard. Pressing ‘D’ for example on the keyboard will look like this at default frequency:

To increase it by a half-step, you’d press the “+” or “=” key (they’re the same key on your keyboard) and so on. And as you change a note’s pitch the new frequency will appear on screen.

The application cannot be executed on this page, nor in the embed widget below…that is because it requires access to your local speakers attached to the machine you’re running the application on during the session, also trinket.io does not yet support sounddevice library that is required for this. So, if you want to actually run the application, you’ll need to run it in your favorite Python IDE and environment. Be sure to install these libraries: sounddevice, numpy, pygame, pyperclip via pip install so they’re actually on your development machine. Then the import statements in code will import and use those binaries for proper real-time execution of the app.

A Sample Session (Video): Let’s take a quick look at a sample session where some keys are pressed to generate music, then the pitches are changed, and then the history is copied to clipboard. Press Play in the widget below to see the video clip.

With all that preview, let me share the code. Remember, you cannot run it here on this page…you’ll need to save the code, and run it in your own Python environment.

I hope you have fun with this! Happy coding and playing.


Related Posts:

Leave a Reply

Your email address will not be published. Required fields are marked *

Back To Top