The Problem
I love to learn new music, but I experience difficulty reading notes that lie high above or below the staff fast enough. Being into programming I thought I'd create something to help me, and while doing so learned some neat things.Requirements
- I imagine a kind of flash card system: a program that displays random music notes, lets me guess the note names and then tells me how long it took to finish all the assignments as a simple way of tracking my progress in reading notes faster.
- I want to be able to configure which notes I'm questioned about: one day I may want to practice low notes, another day I want to practice high notes. And I can imagine beginning musicians would be happy to practice "easier" notes as well.
- The system should support at least the g-clef and the f-clef (the two most commonly used clefs).
- To quickly reach some result, I want to prerender all the graphics. This also allows me to use software to generate professional looking graphics. The icons that go on the buttons must be automatically generated too, as I'm not interested in manually creating and maintaining icons.
- Finally, I want the program to run on at least linux and windows systems. I don't have a Mac to test on, but preferably it should be easily portable to Mac's too.
Technology choices
- The program is written in python 2.x and pyqt4. The code is available under GPLv3 license. To create the graphics
- I first programmatically generate lilypond files.
- I then render those .ly files to scalable vector graphics (svg) format. Display of the assignment can immediately use the .svg format. SVG being a vector format, this will ensure maximum quality.
- The icons on the buttons to the best of my knowledge must be in bitmap format. First, I render the SVG files to portable network graphics (.png) using inkscape. Inkscape provides some convenient command line options that allow just that. Inkscape allows me to export the SVG bounding box to a .png.
- I wanted to have a very general way to do postprocessing on the icons, and found Imagemagick. Imagemagick is like a swiss knife of bitmap processing, and best of all it allows to specify all the operations programmatically. I know to some of you this doesn't sound very exciting, but that's usually because you don't fully realize what incredible possibilities Imagemagick has. It's quite hard to overestimate the awesomeness of Imagemagick! I use Imagemagick to automatically make the icon size 64x64, with the graphics nicely centered. (That is to say: the icons are only displayed at 48x48 right now, with the resizing done in Qt - I may revise these settings in the future. The nice thing about having everything automated is that it becomes easy to make experiments with different settings).
- The build system: GNU make (for now). As I've used it before it seemed like the quickest way to get something. In retrospect, I probably should look out for something else. As I found out the hard way, GNU make has some serious trouble when it comes to dealing with filenames containing whitespace. It also is less than ideal for cross-platform development. Sure, there's a native win32 version of GNU make available, but one of the things bothers me is how its internal variable $(RM) on windows platforms still is defined as
rm -f
, making it harder than needed to implement amake clean
on windows.
The code
The code can be found on http://speedsightread.sourceforge.net/. It also contains an .nsis file to generate a nullsoft installshield (setup.exe) for windows systems. The make clean target for now only works on linux systems. There are no pre-built versions available yet.
Building the code
- To build the program you need: python 2.x (I used python 2.7), pyqt4, lilypond, imagemagick, GNU make
- To build an installshield you additionally need: py2exe, nullsoft nsis
- To run the program, once it's built, you only need python 2.x and pyqt4. If you build the windows setup.exe using the nullsoft nsis script, you don't need anything else but the setup.exe.
Looks very useful, thanks!
ReplyDeleteHow difficult would it be to copy the end score time also into the clipboard? Background is in a multi-player environment, with your friends at home you might want to create a small tournament, e.g. using some other tournament management software, then the result in the clipboard could be pasted directly in this software and the next person could 'play', and the better player wins this match and so on. Simple but funny tournament, especially, if you would make it quite easy and the typing speed also counts. :)
ReplyDelete/*
ReplyDeleteThis is a small helper for this cool program. You can start using left-control + space. Also for all the notes input, it adds the ENTER key automatically.
What is missing now is only copying the result time into the clipboard. But for this there is also a solution, using some OCR software, in a next version.
*/
#NoEnv
#SingleInstance force
#InstallKeybdHook
SetTitleMatchMode, 2
SendMode Input
DetectHiddenWindows, On
#IfWinActive, Sight Read Trainer ahk_class QWidget
{
c::
{
Send, c{enter}
return
}
d::
{
Send, d{enter}
return
}
e::
{
Send, e{enter}
return
}
f::
{
Send, f{enter}
return
}
g::
{
Send, g{enter}
return
}
a::
{
Send, a{enter}
return
}
b::
{
Send, b{enter}
return
}
lcontrol & space::
{
Click, 50,526
return
}
Imagining one match as a 100 hurdle sprinting, the analysis output could contain a few more nice elements. All timings between all 20 steps, a nice plots showing those timings as a visual summary. A few more extrax like 'weakest 3 notes', 'best 3 notes'. Later being able to start matches based on 'weakest n notes'.
ReplyDelete