A performance is a list of musical events with start times. It forms the bridge between a composed NoteStructure and playable sound: events can be passed to an Oscillator or another performer. section 11.1.2 section 11.2
A performance supports several practical operations:
- Convert notes and pauses using tempo, elapsed time, pitch frequency, and duration. section 11.2
- Sort generated events by their start times before playback. section 11.2
- Represent overlapping events so multiple sounds can play polyphonically. section 11.2.1
- Transform the event list into a signal through the Performer type class. section 11.2.1
Converting a note structure
Define `type Performance = [Event]`. Then use `toPerformance tempoInfo` to recursively interpret a NoteStructure from time zero, producing Tone and Silence events and sorting them by start time. section 11.1.2 section 11.2
Listing 11.4 Wrapper function for converting note structures into a performance
...
import Data.List (sortBy, foldl')
...
toPerformance :: TempoInfo -> NoteStructure -> Performance
toPerformance tempoInfo =
sortBy (\x y -> compare (start x) (start y)) #1
. snd #2
. structureToPerformance tempoInfo 0 #3
The wrapper shows how recursive interpretation becomes a clean `TempoInfo -> NoteStructure -> Performance` interface. section 11.2
Listing 11.5 Type class for transforming performances into a signal
module Sound.Sound where import Util.Types import Composition.Performance class Performer p where play :: p -> Performance -> Signal
The performer abstraction shows how the same performance can be sent to different sound-producing implementations. section 11.2.1
