Typing keyboard + python = Musical instrument !

In this post I will show you how to do this :

I am not the first to do that, but most people who play their computer on Youtube use either very expensive programs, or programs that won’t run on your computer, or not-so-efficient programs with not-that-much possibilities of extension, or cheap programs with a big lag between pressing the key and actually hearing the note.

So here is a very small Python script which will run fine even on a basic netbook. If you are not familiar with Python, you should take online courses , it is really worth it 🙂 !
If you are faminiliar with Python, then you are welcome to improve the code on its Github page.

Transforming your keyboard into a mixtable

My original idea was to transform my computer keyboard into a mixtable, to make something like in this very awesome video:

So my first move was to make a program that would take a configuration file my_configuration.cf containing this:

q, dog.wav
w, cat.wav
e, tarzan.wav
r, scream.mp3

And then if you hit q you would hear a dog from the dog.wav soundfile, if you hit w you’d hear a cat, etc…
This is pretty easy to do with Python’s pygame package. Here is my code (inspired by similar stuff from the package Mingus):

import pygame as pg
import csv
import time

FPS = 44100
BUFFER = 2**9
def minimix(config_file,mode = 'instrument'):
    Opens an interface that lets you press the keys of your keyboard
    to plays the related soundfiles as sepcified in the provided
    configuration file.
       config_file (str):  A file associating keyboard keys with
                           file names. Each line must be of the form
                           key , filename.
       mode (str) :
            instrument -- causes autorepeat of samples as long
                            as the key is pressed.
            sustain -- causes autorepeat of the samples until its
                       key is pressed again.
            player -- striking the key causes the sound to play once. 
       a list of the (time,events).
    repeat = 0 if (mode is 'player') else (-1)
    screen = pg.display.set_mode((640,480))
    ##### READ CONF FILE
    key2sound = {}
    key2file = {}
    config = csv.reader(open(config_file, 'rb'), delimiter=',')
    for key, soundfile in config:
        key,soundfile = key.strip(' '),soundfile.strip(' ')
        if key is not '#':
            key2file[key] = soundfile
            key2sound[key] = pg.mixer.Sound(soundfile)
    events_list = []
    currently_playing = {k : False for k in key2sound.iterkeys()}
    ##### MAIN LOOP
    while True:
        event =  pg.event.wait()
        if event.type in (pg.KEYDOWN,pg.KEYUP):
            key = pg.key.name(event.key)
            if key in key2sound:
                if event.type == pg.KEYDOWN:
                    if (mode == 'sustain') and currently_playing[key]:
                        currently_playing[key] = False
                        currently_playing[key] = True
                elif event.type == pg.KEYUP and (mode == 'instrument'):
                    currently_playing[key] = False
            elif event.key == pg.K_ESCAPE:
    return events_list

Transforming your keyboard into a musical instrument

If instead of using various noises like cat and dog you use different notes from the same instrument, then you turned your computer into some kind of piano. The problem is that a set of soundfiles with all the notes of an instrument is difficult to find on the internet, so I wrote a script that makes as many notes as you want from just one sound by shifting its pitch up or down. It uses the audio processing program Soundstretch that you will need to install first :

import os

def shift_wav(wavfile,output,shifts,verbose=False):
    Makes new sounds by shifting the pitch of a sound.
    Requires soundstrech installed.
        wavfile : Name of the file containing the original sound
        output: name to use as a prefix for the output files and for
                the output folder name
        shifts (list of int): specifies of how many half-tones the pitch
                shifts should be. For instance [-2,-1,1,2] will produce
                4 files containing the sound 2 half-tones lower, one
                halftone lower, one halftone higher and two halftones
    folder = os.path.dirname(output)
    if not os.path.exists(folder):
    for i,s in enumerate(shifts):
        outputfile = '%s%02d.wav'%(output,i)
        command = 'soundstretch %s %s -pitch=%d'%(wavfile,outputfile,s)
        if verbose:
            print command

Going further

There is so much one could do to improve the program.

On the musical side, for instance, finding configurations of the keyboard that are particularly ergonomic. In the video above I used this configuration:


I called it typewriter because it enables you to play very fast things while moving your hands a minimum (the video is a bad example :P) . But maybe there is better to find !

Also, one could start listing every cool piece of music that can be played on a typing keyboard. I use 46 keys ( almost 4 octaves !), that makes a lot of possibilities !

On the programming side, there is a lot of little things I can think of, like automatizing scale changes, introducing nuances, designing nice interfaces (why not a guitar-hero-like game where you would actually be playing music on a playback ?), writing a script that would take some sheet music (in a nice format, like ABC, MIDI, lylipond) and return the list of the keys you should strike to play it.

I actually wrote a lot more code, for instance to make it easier to write configuration files, for sound processing, etc., but since it is not strictly necessary I am not reporting it here (I’ll certainly put a working version on GitHub, or such, some day).

Philosophy of the musical keyboard

Your typing keyboard is a real instrument. Of course it is not its primary use, but our voice’s primary purpose was not to sing, either. Now do the math : how many people out there have a piano at home ? And how many have a computer ? That gives you an idea of how many people would like to play the piano, cannot, but could play their computers instead.

So promoting computer-keyboardism is ultimately about bringing music to the masses. It is about providing everyone with an instrument that you can practice at home, in the train, at work, and that will be familiar to anyone everywhere in the world.

There is more : how many of you, pianist readers, have started the piano for seduction purposes ? (yeah, sure, me neither…) But public places with a piano on which you could show off your mad skills are getting pretty rare, aren’t they ? Especially since most bars have traded their good old piano for a TV. But think about all these places with a computer at hand ! Yep, time for you to develop a talent that will be useful in real life !

So practice, get good, be one of the first composers for tomorrow’s instrument, impress your friends and spread the good news ! If you are still reading me after so much gibberish , then do not hesitate : you just proved how little you value your free time, you are the right person for the task !

Gipsy-like piano music (with sheet music)

A few days ago I recorded this :

I am aware that the piano has a most un-gipsic sound, but I never had the courage to learn guitar, so I am trying to bring the wonderful repertory of gipsy jazz to my favorite instrument. As I have been asked for the sheet music, I wrote a transcription :

Une Routine Manouche (sheet music)

For the fun I placed this piece of music under a Creative Common licence, which basically lets you free to do whatever you want with it, even make money ( but don’t be too confident about that ! ), without needing my permission.  All I ask is that you cite a certain “A. de la Marmotte” as the author, so that I can google it in ten years and see what has become of my little routine.

In case you are wondering, I edited the music with the free software Lilypond, which is somehow an equivalent of LaTeX for sheet music.  If you want to modify the score, here is the source file I wrote (copy it in a file like “myFile.ly” and run with Lilypond):


\version "2.12.3"

* U N E   R O U T I N E   M A N O U C H E
* Version 0 - 31/03/2012
* Une Routine Manouche by A. de la Marmotte is licensed under a
* Creative Commons Attribution 3.0 Unported License.
* The full text of the licence can be found here:
* http://creativecommons.org/licenses/by/3.0/
* In a nutshell, YOU ARE FREE to share (copy, distribute, transmit),
* to remix or adapt the work, and to make commercial use of the work.
* BUT I ask you to cite "A. de la Marmotte" as the original author
* if you do any of the things above, just so that I can see what this
* little piece is becoming.
* Ideas for improvements are most welcome !

\header {
title = "Une routine manouche"
subtitle = "by A. de Lamarmotte"
subsubtitle = "After the chorus from V. Monti's famous Czardas"
arranger="Grenoble, France, March 2012"
composer = "This is a free work ( licence CC BY 3.0)"
tagline = "Work licenced under licensed a Creative Commons Attribution 3.0 Unported License"

% In what follows, one line represents one bar.

global = {
\key d \minor
\time 4/4

right = \new Voice \with {
\remove "Note_heads_engraver"
\consists "Completion_heads_engraver"
d''4 \grace{b''16[ c''' cis''']} d'''8-5 cis''' c''' b''4-2 bes''-4
a'' gis''8 a'' bes'' a'' f'' d''4.-.-1 a'4.-3 r4
r2. <g-1 cis'-4>8 <a-2 d'-5>4
f'8-3 e' g' f'-1 a' g' bes'
a'-1 d''-3 cis'' e'' d''-1 f'' e'' g''
f''4 g'' f''8 g''16 f''16 e''8 bes'4. r2 r8 bes''-3
\times 2/3 {a''-2 bes'' a''} g'' bes''  \times 2/3 {a'' bes'' a''} g'' bes''
\times 2/3 {a'' bes'' a''} gis'' a'' bes'' a''-1 c''' bes''
\times 2/3 {a'' bes''-3 a''} gis''-2 a'' f'''-. a'' e'''-. a''
es'''-. a'' d'''-. a'' cis'''-. a'' c'''-. a''
b''-4 bes''-3 f'' d'' b'-4 bes' f' d'
e'-2 b' gis' e' d' gis' e' d'-1
cis'-2 e'-1 g' bes' e'-1 g' bes' cis''
g'-1 bes' cis'' e'' bes'-1 cis'' e'' g''
d''4-1 d''' \acciaccatura{gis''16} a''2-3
\times 2/3 {g''8 a'' g''} f''-1 g''-2 \acciaccatura{gis''16-3} a''8-5 f''8-4 d''4-2
{ r4 <c'' d'' f''> <b' d'' f''>2  <c'' d'' f''>8 <c'' d'' f''>4
<b' d'' f''>4.} \\
{ a'1~a'2. }
>>  r8 \times 2/3 {a''16-5 f'' e''}
d''8-1 cis''-3 c'' b' bes'-2 a' d''-4 cis''
c'' b' bes'-2 a' d'' cis'' c'' b'-1
<g'-2 bes'-4>4.-. <g' bes'>4 g'8 bes'4
<g' a'>2. r8 bes''-4

\times 2/3 {g''8-2 bes'' g''} e'' bes'' \times 2/3 {g'' bes'' g''} e'' bes''
\times 2/3 {g'' bes'' g''} e'' g''-4 \times 2/3 {e''-2 g'' e''} cis'' bes''-4
a''-^-3 f'' d'' g''-^-4 e''-2 cis''-1 f''-^-4 d''-2
b'-1 e''-^ cis'' bes' d''-^ a' f' cis''-3
c'' b'-1 bes'-4 a' gis' g' c''-4 b'
bes' a'-1 gis'-2 g' c''-5 b' bes' a'
<e' a' d''>8-^ <e' a' d''>4.-^ <e' a' d''>4-^   <e' a' d''>8-^ <e' a' d''>4.-^

r4 e''-^-3 \times 2/3 {dis''8-^ e'' dis''}
d''4.-^-1 c''8-2 d''-1 e''-2 g''-3 bes''-4
d'''4.-5 \times 2/3 {bes''16 g'' e''} d''4 r4
\ottava #1
r4 \times 2/3 {a'''8-3 c''''-5 a'''} f'''-1 a'''-5 d'''-2 f'''-4
\ottava #0
c'''-1 d'''-5 a'' c''' f''-1 a''-5 d''-1 f''-2
gis''-4 a'' g'' f'' e'' d'' cis''-4 bes'
a' g' f' e' d' cis'-4 bes-2 a-1
e'-4( cis'-2 d'-1) g'-4( e'-2 f'-1) bes' gis'
a' e'' cis'' d'' g'' e'' f'' g''-4
f''4-3 g'' f''8 g''16 f'' e''4
<bes' bes''>4-. r8 <bes' e'' bes''>4. r4
a'8 d'' e'' f'' e''4 d''
<b' a''>8 f''4-. <b' d''>4 f''8 d'' b'-1
bes'4-2 f'' d''8 bes' a'4-1
<< {r4 <d''-4 f''-5> r8 <a' cis'' e''>4 <a' d''>8~<a' d''>4} \\ {gis'2-2 g'4.-1 f'8-1~f'4}>>
r2 e'4-^ \times 2/3 {dis'8-^ e' dis'}
d'4. d'''8 \times 2/3 { bes'' d''' bes'' } g'' bes''
d''2 e'4-^ \times 2/3 {dis'8-^ e' dis'}
d'4 c'8 d' f' a' d'' f''
d'''2 a'4-^ \times 2/3 {gis'8-^ a' gis'}
r8 <bes'' f'''>8 <cis''' g''> r8 <bes' f''> <cis'' g'> r8 gis'
<< {r4 <cis'' f''> r8 <a' cis'' e''>4 r8 <a' d'' f''>4.-^ <a' d'' f''>4.-^ <a' d'' f''>4-^}
\\ {a'2-^ g'4.-^ f'8-^~f'1}>>
r4 d''4 e'' fis''
\times 2/3 {g''8 a'' g''} fis''8 a''8 \times 2/3 {g''8 a'' g''} fis''8 a''8
g'' a'' ais'' b'' c''' d''' b'' d'''
\times 2/3 {c'''8 d''' c'''} b'' d''' \times 2/3 {c'''8 d''' c'''} b'' d'''
\times 4/5 {c'''8-3 d''' c''' a'' f''} \times 4/5 {c''8-3 d'' c'' a' f'}
d'-2 f'-1 g'-3 aes'-4 g' f' d'-1 c'-2
d'-1 f' g' aes' g' f' d'-1 c'-2
<< {r4 <f' a' d''>4.<f' a' d''>4.}\\{d'2.-1 d'4}>>
<f' a' d''>4. <f' a' d''>4. <f' a' d''>4
r8 <d''' f''>8 <gis'' d''> r8 <d'' f'>8 <gis' d'> r8 <d'' f'>
r8 <d''' e''>8 <g'' d''> r8 <d'' e'>8 <g' d'> r4
\times 8/12 {d'16_\markup{ \small \bold Freely } [( f' a' b'   d'' f'' a'' b''
\ottava #1
d''' f''' a''' b'''])} d''''2
\ottava #0
r1 \bar "|."


left = \new Voice \with {
\remove "Note_heads_engraver"
\consists "Completion_heads_engraver"
d4( <f a b>-.) a,( <f a b>-.)
e <g bes d'> cis <e g a>
d-^ <f a b> e-^ <g bes d'>
f-^ <a b d'> a, <cis e>
d <f a b> a, <f a b>
d <f a b> c <f a b>
bes, <g bes d'> g,  <g bes d'>
bes, <g bes d'> g,  <g bes d'>
e <g bes d'> bes,  <g bes d'>
<< {r4 <g bes cis'>2  <g bes cis'>4} \\ {ees1-^} >>
d4-^ <f a b> a, <f a b>
d <f a b> a, <f a b>
<< {r4 <f bes>2 <f bes>4} \\ {d1} >>
e4-^ <gis b> d-^ <gis b>
cis-^ <e g bes> e-^ <g bes cis'>
g-^ <bes cis' e'> bes-^ <cis' e' g'>
\clef treble
d'-^  <f' a' > cis'-^  <f' a' >
c'-^  <f' a' > a-^  <cis' e' g'>
\clef bass
d <f a b> a, <f a b>
d <f a b> a, <f a b>
d-^ <f a b> e-^ < bes d'>
f-^ <bes d'> fis <bes d'>
g <bes d' e'> e <bes d' e'>
g <a d' e'> e <a d' e'>
g <bes cis' e'> e <bes cis' e'>
cis <bes cis' e'>  e <bes cis' e'>
d <f a b> a, <f a b>
d <f a b> a, <f a b>
e <g bes c'> cis <g bes c'>
e <g bes c'> cis <g bes c'>
d <f a b> d <f a b>
d <f a b> <d, d>-^ <dis, dis>-^
<e, e> <g bes c'> c <g bes c'>
d <g bes c'> e <g bes c'>
f < a c' d'> c < a c' d'>
f < a c' d'> c < a c' d'>
cis <e g a> a, <e g a>
b, <e g a> cis, <e g a>
d-^ <f a> cis-^ <f a>
c-^ <f a> b,-^ <f a>
bes,-^ <g bes d' e'> g, <g bes d' e'>
bes,   <g bes d' e'> g, <g bes d' e'>
d <f a b> a, <f a b>
d <f a b> a, <f a b>
bes, <f bes d'> f, <f bes d'>
d <e gis b> cis <e g a>
d <f a b> a, <f a b>
d <f a b> a, <f a b>
e <g bes c'> c <g bes c'>
e <g bes c'> c <g bes c'>
f <a> c <a c'>
f <a c' d'> c <a c' d'>
\clef treble
<g bes cis' g'>4.-^\arpeggio <bes' cis''>4.-. <bes cis'>4-.
\clef bass
a4 <cis' f'> g <a cis' e'>
d <f a b> a, <f a b>
d <f a b> a, <f a b>
e <g bes c'> c <g bes c'>
e <g bes c'> c <g bes c'>
f <a c'> c <a c'>
f <a c' d'> c <a c' d'>
<bes, gis>4 <gis bes d'> <bes, gis> <gis bes d'>
<a, g>4 <g a c'> <a, g> <g a c'>
d <f a b> a, <f a b>
d <f a b> a, <f a b>
<bes, gis>4. <bes gis'>4. <bes, gis>4
<a, g>4. <a g'>4. <a, g>4
<d f a b>2.\arpeggio

\ottava #-1
\acciaccatura {cis,8}  d,4 d,,1
\bar "|."

#(set-global-staff-size 18)

\score {
\new PianoStaff \with {
instrumentName = "Piano"
} <<
\new Staff = "right" \with {
midiInstrument = "acoustic grand"
} \right
\new Staff = "left" \with {
midiInstrument = "acoustic grand"
} { \clef bass \left }
\layout { }
\midi {
\context {
tempoWholesPerMinute = #(ly:make-moment 100 4)


Creative Commons License
Une Routine Manouche by A. de la Marmotte is licensed under a Creative Commons Attribution 3.0 Unported License.