Generating Music Notation in Real Time
Listing 6. Script Fragment to Capture User Data
import cgi, re form = cgi.FieldStorage() formS = '<pre>\n' for field in form: formS += field + ' = ' formS += form[field].value + '\n' formS += '</pre>\n'
The script then inserts the formS string at the appropriate point within the feedback file. The variables are integers representing percentage chances that a given note will have a given characteristic. I chose to list the values within <pre> tags to allow easy observation of changes to variables during a performance using a Web browser. The scripts always write the most recent data immediately after a <!-- begin --> comment.
In addition to the audience data variables, the processing script also incorporates a second-order Markov chain (see the “Markov Chains” sidebar). This allows all pages of music after the first to share characteristics of the first page while still being shaped by the audience feedback.
Markov Chains, named after Russian Mathematician A.A. Markov, are ordered collections of data based on samples. For each set element x, we find all transitions from it to any element, including a repetition of itself. From those data, we find the probability that x leads to each element that follows it. We then can use those probabilities to reconstruct a randomly generated set that resembles the source set without necessarily being identical to it.
The user then continues to run the noclergy.py script for as long as desired. Another wrapper shell script could keep the piece running until a specific condition is met, such one of the pc variables reaching a given minimum or maximum. It also could have a set number of iterations. It even could run as a long-term installation. No performer relishes the thought of sitting for eight or more hours and playing whatever appears on a screen in front of him or her. Therefore, for very long runs, I should alter the program such that it does not require performers. One option would be to output to a synthesizer such as Csound. Another option would be to display the notation for visual demonstration only.
Future plans for this project include a port to the Ruby language. This is mainly for self education, but there are other reasons. Ruby code tends to be more compact—the advantages of features like the each method add up with enough code. In informal benchmarking, I've also found Ruby faster than Python for some tasks. I'd like to test this more scientifically, with and without Python bytecode optimization. Finally, by porting, I'll learn both Python and Ruby better—always a good thing.
As mentioned previously, the scripts store previous runs of the piece in the MusicXML format. There is no reason that other music in that same format couldn't be run through the script. By using other source music, the mutate.py script can create Markovian blends of Charlie Parker and Bartok, or whatever suits the user's tastes.
Finally, here's some technical trivia that may interest readers. I achieved much faster XML access when I did “dumb” file/string readline operations with my own convention for placement of \n characters. Conversion to standard DOM-aware XML libraries slowed the program down noticeably but made it both more robust and more usable by others. For a while, I even kept both versions of XML reading available. Eventually, I decided to use only the DOM-based reading, even thought it has become the slowest portion of the script by far.
In the end, I felt that arguments for using an HTTP-based audience interface had merit for the XML access issue. Using the standard DOM library made the script available to a wider user base. The XML read runs fast enough for usability today and will be even faster in the future with faster hardware. Therefore, I decided to comply with existing standards in the interest of robustness.
I plan to have a performance at the University at Buffalo in late 2004. Obviously, the program's collision with a real-world test should provide a great deal of useful information about how to improve it. The specifics of the performance are still in question, but I may try to use wireless browsers for the audience, which I hope will provide a less intimidating interface for them and will improve the overall experience for both performers and audience members.
Resources for this article: www.linuxjournal.com/article/7815.
Kevin Baird is pursuing a PhD in Music Composition at the University at Buffalo in Buffalo, New York. He is on-line at kevinbaird.net.
- Tech Tip: Really Simple HTTP Server with Python
- My Childhood in a Cigar Box
- Papa's Got a Brand New NAS
- Applied Expert Systems, Inc.'s CleverView for TCP/IP on Linux
- Returning Values from Bash Functions
- Rogue Wave Software's TotalView for HPC and CodeDynamics
- Panther MPC, Inc.'s Panther Alpha
- Simplenote, Simply Awesome!
- NethServer: Linux without All That Linux Stuff