One of the most satisfying sounds for us, programmers, to hear is a keyboard sound. Apart from the underlying switch mechanism, a keyboard’s sound is beauty itself. In this tutorial, we will build a fairly small Keyboard Sound Simulator using Python. The program will play a random sound from a collection of your choice every time you press a key.
Prerequisites
First of all, we need to install a couple of packages and Python modules. We need sox
package to play sounds and python-xlib
package for pyxhook
to work properly. Use the package manager of your system to install these packages. For example:
- On Ubuntu:
sudo apt install sox python-xlib
- On Arch:
sudo pacman -S sox python-xlib
We also need pyxhook
Python module, so pip install pyxhook
. Now we are good to go.
Coding Time
First, let’s create a file and name it kb_sound_simulator.py
. Then, let’s import the modules we are going to use.
A Little Pause
Before we continue, here is how the program will go. A path to a directory containing sounds we want to play will be provided to the program. The program will go through the files in that directory looking for at least one file with sound for each of enter
, space
, and other keys. Then on any keypress, the program will play the corresponding sound. Pretty easy, isn’t it?
Getting Paths for Sound Files
So, as discussed, we need to get paths for sound files.
We define some variables to store paths for sound files later if found. We get a list of files in the provided directory on line 6. On lines 8-10, we define Regular Expressions (RegEx) to use later to match file names we are expecting. On line 8, we define a Regex that matches a string that starts with the word enter
, followed by a dot .
, and ending with either mp3
or wav
. The same goes for line 9, but for the word space
. And same goes for line 10, but instead of matching a string starting with enter
or space
, we match a string starting with any one or more characters (.+). Then we loop through the filenames list, check for matches with any of the RegExes, and assign matched filenames to the corresponding variable. For example, on line 13, we match the enter_re
Regex against the filename, and if the result is not None
, meaning there is a match, we store that filename in the enter_path
variable. In the end, if we don’t find any of the required files, we print an error message and exit.
Handling Key Presses
To handle key presses, we will first define a function to handle pressing a key down. This function takes in an event
object which, lucky for us, contains the name of the key that was pressed. So, on lines 9-15 we assign the file path corresponding to the key pressed, in case of enter
, or space
, or a random file path from the others_paths
array, in case of any other key, to the sound
variable. Now, this is a tricky part. On lines 1and 2, we declared 2 variables, continuous
and last_key
. These variables are meant to help us fix issues that appear as keys are held down. So, on lines 17-20, we make sure that we are either not in continuous mode or the current key is different from the last one. This helps avoid replaying key sound when the same key is pressed down and held without interruption. Then, we set the last key to be the current one, play the sound using the os.system()
function to execute a shell command, and set continuous to True
to indicate that the key is not yet released.
NOTE: We pass the sound file path as the first argument to the play command.
Hooking Everything Up
Now, we need to actually initiate a hook manager and attach a keyboard hook, so that the program can listen to key presses.
We started the hook manager on line 1, assigned the KeyDown
and KeyUp
callback handlers on lines 2 and 3, attached the keyboard hook on line 4, and started the hook manager on line 6. And that’s it. We are done!
Conclusion
First, we used regular expressions
and os
module and its helper functions to look for the files we needed. Then, we used os.system()
along with the play
shell command to play sounds. Finally, we used pyhook
module to listen for and act upon keyboard events. Now, this program is complete, but it lacks somethings, for example, we can add a command-line option to control the volume of the played sounds. We may then add a help message to make it easier to use. To learn how to do this, you can read Getting Started with Python’s Argparse.
NOTE: The source code for this tutorial can be found here.