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.