This is SPUR ("Scheduled Player Using Racket"), a poor man's version of Andrew Sorensen's Impromptu , ported to Racket Scheme . It also uses the idea of musical phrases from Tim Thompson's KeyKit . The package uses the pc-ivl-lib from Impromptu, and extends the Racket coremidi package by Evan Hanson . See what.txt for a quick overview of the main ideas. -------------------------------------------------------------------------- CONTENTS This package contains the following files: - README.txt This file - what.txt The three main ideas behind SPUR - guide.txt Instructions on programming SPUR - spur.scm The main implementation file - phrase.scm Library that defines musical phrases - scale.scm Glue for Andrew Sorensen's pc-ivl-lib.scm library - midiout.scm Glue for Evan Hanson's CoreMIDI package - testmidi.scm Test file for midiout functions - piano-phase.scm Example SPUR file - glass.scm Example SPUR file - bnd.scm Example SPUR file - loop.scm Example SPUR file - spur-emacs.el For using SPUR with Emacs - portmidi-output.c Code for using PortMidi instead of CoreMIDI - portmidi-output.scm Code for using PortMidi instead of CoreMIDI -------------------------------------------------------------------------- SYSTEM REQUIREMENTS In addition to Racket Scheme (and Emacs, if you intend to use it), this package needs to be able to send bytes to MIDI out to produce sounds. I use Evan Hanson's CoreMIDI package under Mac OS X to do this, as described below. For Linux or Windows systems, it should be possible to run SPUR by plugging in a replacement for CoreMIDI. It need only provide three Scheme functions: midi-open, midi-close, and message; the rest of SPUR should then work as is. One way is to use PortMidi with some Racket glue. I was able to get this to work fine under Mac OS X, but I have not tried elsewhere. Here is what is involved: install PortMidi; compile "portmidi-output.c" to produce a dynamic library; edit "portmidi-output.scm" to point to this new dynamic library; and finally change midiout.scm to load "portmidi-output.scm" instead of "evhan-coremidi.scm". It just may work. Another possibility is to adapt . -------------------------------------------------------------------------- INSTALLATION FOR OS X 1) Make sure that Racket Scheme is installed properly: > racket -e '(+ 3 4)' 7 2) Obtain a copy of the coremidi.rkt source file from the repository at . Replace the final expression in it (provide-contract ...) by (provide midi-open midi-close message) and save the resulting file as "evhan-coremidi.scm" in the SPUR directory. 3) Make sure that MIDI out is now working properly: > racket -fm testmidi.scm This should play a C major scale on MIDI channel 1. If no MIDI instrument is connected, the IAC Driver (under OS X) should be used to send MIDI to some other application that will produce the sound. Midipipe is a free application that can connect IAC to the yucky QuickTime music synthesizer. Garageband can also be used over IAC and has better sounding instruments, but is limited to a single MIDI channel. Logic is better, but my version does not respond to the "all-notes-off" message. Maybe the best option is to use VST instruments (free or commercial) and run a VST host such as the free MuLab . 4) (Optional) If you intend to try examples from the Impromptu site (and you should), you will want the pc-ivl-lib library that defines scales, chords, etc. Get the file from . Fix two bugs: replace the second definition of "ivl:expand/contract" by "pc:expand/contract"; and within the body of "pc:from-intervals", replace "ivls" by "intervals". Finally, comment out the definition of "*pc:chord-syms-dict*" and "pc:diatonic-dict". Save the resulting file as "andrew-pc-ivl-lib.scm" in the SPUR directory. Then you can include (require (file "scale.scm")) in your files to load the pc-ivl-lib file. -------------------------------------------------------------------------- RUNNING A SPUR FILE NON-INTERACTIVELY A SPUR file typically looks like the following: (require (file "/path/to/spur.scm")) ; optionally (require (file "/path/to/phrase.scm")) for phrases ; optionally (require (file "/path/to/scale.scm")) for pc-ivl-lib ... auxilliary definitions ... (define (main) (with-midi-schedule ... schedule some events ... )) See the guide.txt for how to do the scheduling. To run your file, do this: > racket -fm myfile.scm Try piano-phase.scm as an example. Stop the playing with ^C. A more complex example is glass.scm. And for something completely different, try bnd.scm. -------------------------------------------------------------------------- RUNNING A SPUR FILE INTERACTIVELY To simply play musical phrases typed in interactively (see the guide.txt): > racket -t phrase.scm -e '(rppl)' To interact with a running SPUR program, one way is the following: > racket -i -f myfile.scm -e '(thread main)' This will run the main function in myfile.scm as a thread but also invoke a read-eval-print loop where Scheme expressions can be evaluated interactively to modify the ongoing execution. (It is best not to use the Racket "readline" library in this case, as it appears to cause nasty delays in the execution.) Try piano-phase.scm as an example: > racket -i -f piano-phase.scm -e '(thread main)' ;; change the playing to staccato > (set! phrase (map (lambda (n) (set-note-length n 20)) phrase)) ;; play the phrases faster but then wait as usual to start over > (set! bpm (* 1.4 bpm)) -------------------------------------------------------------------------- INTERACTING WITH SPUR FROM EMACS To interact with a running SPUR program, it is much better to use Emacs in the style of Impromptu (see one of Andrew Sorensen's many performance videos). There are various packages for communicating between Scheme and an Emacs buffer, but the included spur-emacs.el is a very simple one based on the standard Emacs cmuscheme library. To install it, make sure that *.scm files are edited in Emacs scheme-mode, and add (autoload 'run-spur "/path/to/spur-emacs.el" "" t) to your .emacs file. Then visit a SPUR file in an Emacs buffer and use these commands: M-x run-spur ;; start the function main as a thread M-x kill-spur ;; kill the thread running main While the SPUR program is running, expressions can be sent from Emacs to Racket Scheme to modify the ongoing execution. In particular, ^c ^e ;; send the current enclosing expression ^c ^r ;; send the current region ^x ^e ;; send the expression just before point See the cmuscheme library for the full set of available commands. To check that all this is working, edit the file loop.scm in scheme-mode in Emacs, and then execute the "run-spur" command. A loop should start playing: seven notes randomly chosen from E and F, and then the root C. Now replace "(rand '(4 5))" in the buffer by "(rand major)". Nothing changes yet. But with the cursor within the body of the pitch function, type ^c ^e. The new definition of the pitch function will be sent to Racket, and the notes will be selected from the full scale of C. Execute "kill-spur" to stop the playing.