peter rademaker & robert stremler. preview 1.introduction 2.the basics 3.simple examples...
TRANSCRIPT
Peter Rademaker & Robert Stremler
Preview
1. Introduction2. The Basics3. Simple Examples4. Interpretation and Performance5. MIDI6. Algebraic Properties7. Conclusions
Introduction
• Developed by Paul Hudak, Yale University, 1997
• Modules for expressing musical structures
• Music rather than sound
• Algebra of music
• Objects represent both abstract musical ideas and their concrete implementations
Haskore Architecture
The Basics
module Basics whereinfixr 5 :+:, :=:
type Pitch = (PitchClass, Octave)data PitchClass = Cf | C | Cs | Df | D | Ds | Ef | E | Es | Ff | F | Fs |
Gf | G | Gs | Af | A | As | Bf | B | Bs deriving (Eq,Ord,Ix,Show)type Octave = Int
The Basics
module Basics whereinfixr 5 :+:, :=:
type Pitch = (PitchClass, Octave)data PitchClass = Cf | C | Cs | Df | D | Ds | Ef | E | Es | Ff | F | Fs |
Gf | G | Gs | Af | A | As | Bf | B | Bs deriving (Eq,Ord,Ix,Show)type Octave = Int data Music = Note Pitch Dur [NoteAttribute] | Rest Dur | Music :+: Music | Music :=: Music | Tempo Int Int Music | Trans Int Music | Instr IName Music | Player PName Music | Phrase [PhraseAttribute] Music deriving Show
type Dur = Float type IName = Stringtype PName = String
Some helpers
c,d ... :: Octave → Dur → [NoteAttribute] → Musicc o = Note (Cf,o) d o = Note (C,o) …
wn, hn, qn, ... :: Durwn = 1 hn = 1/2 qn = ¼…
wnr, hnr, qnr, ... :: Musicwnr = Rest wnhnr = Rest hnqnr = Rest qn…
Some Simple Examples
line, chord :: [Music] → Musicline = foldr (:+:) (Rest 0) chord = foldr (:=:) (Rest 0)
cMaj = map (λf → f 4 qn []) [c, e, g]cMajArp = line cMajcMajChd = chord cMaj
Some Simple Examples
line, chord :: [Music] → Musicline = foldr (:+:) (Rest 0) chord = foldr (:=:) (Rest 0)
cMaj = map (λf → f 4 qn []) [c, e, g]cMajArp = line cMajcMajChd = chord cMaj
delay :: Dur → Music → Musicdelay d m = Rest d :+: m
repeatM :: Music → MusicrepeatM m = m :+: repeatM m
withIdenticalVoice = m1 :=: Trans 7 m2
Attributes
Interpretation Overview
Music Player
Perfomance
MIDI
Phrasing and Articulationdata NoteAttribute = Volume Float | Fingering Int | Dynamics String
data PhraseAttribute = Dyn Dynamic | Art Articulation | Orn Ornament
data Dynamic = Accent Float | Crescendo Float | Diminuendo Float | PPP | PP | P | MP | SF | MF | NF | FF | FFF | Loudness Float | Ritardando Float | Accelerando Float
data Articulation = Staccato Float | Legato Float | Slurred Float | Tenuto | Marcato | Pedal | Fermata | FermataDown | Breath | DownBow | UpBow | Harmonic | Pizzicato | LeftPizz | BartokPizz | Swell | Wedge | Thumb | Stopped
data Ornament = Trill | Mordent | InvMordent | DoubleMordent | Turn | TrilledTurn | ShortTrill | Arpeggio | ArpeggioUp | ArpeggioDown | Instruction String | Head NoteHead
data NoteHead = DiamondHead | SquareHead | XHead | TriangleHead | TremoloHead | SlashHead | ArtHarmonic | NoHead
Interpretation and Performance
type Performance = [Event]
data Event = Event Time IName AbsPitch DurT Volume
type Time = Floattype DurT = Floattype Volume = Float
Interpretation and Performance
perform :: PMap → Context → Music → Performance
type PMap = PName → Playertype Context = (Time,Player,IName,DurT,Key,Volume)type Key = AbsPitch
Interpretation and Performance
perform :: PMap → Context → Music → Performance
type PMap = PName → Playertype Context = (Time,Player,IName,DurT,Key,Volume)type Key = AbsPitch
perform pmap c@(t,pl,i,dt,k,v) m = case m of Note p d nas → playNote pl c p d nas Rest d → [] Tempo a b m → perform pmap (setTempo c (dt * float b / float a))m Trans p m → perform pmap (setTrans c (k+p)) m Instr nm m → perform pmap (setInstr c nm ) m Player nm m → perform pmap (setPlayer c (pmap nm)) m Phrase pas m → interpPhrase pl pmap c pas m
Interpretation and Performanceperform :: PMap → Context → Music → Performance
type PMap = PName → Playertype Context = (Time,Player,IName,DurT,Key,Volume)type Key = AbsPitch
perform pmap c@(t,pl,i,dt,k,v) m = case m of Note p d nas → playNote pl c p d nas Rest d → [] Tempo a b m → perform pmap (setTempo c (dt * float b / float a))m Trans p m → perform pmap (setTrans c (k+p)) m Instr nm m → perform pmap (setInstr c nm ) m Player nm m → perform pmap (setPlayer c (pmap nm)) m Phrase pas m → interpPhrase pl pmap c pas m
m1 :+: m2 → perform pmap c m1 ++ perform pmap (setTime c (t+(dur m1)*dt)) m2 m1 :=: m2 → merge (perform pmap c m1) (perform pmap c m2)
Interpretation and Performance
merge :: Performance → Performance → Performance
merge a@(e1:es1) b@(e2:es2) = if e1 < e2 then e1 : merge es1 b else e2 : merge a es2merge [] es2 = es2merge es1 [] = es1
Players
data Player = MkPlayer PName NoteFun PhraseFun NotateFun
type NoteFun = Context → Pitch → Dur → [NoteAttribute] →Performance
type PhraseFun = PMap → Context → [PhraseAttribute] → Music → (Performance,Dur)
type NotateFun = ()
Example PlayerdefPlayNote :: (Context → NoteAttribute → Event → Event) -NoteFundefPlayNote nasHandler c@(t,pl,i,dt,k,v) p d nas = [ foldr (nasHandler c) (Event t i (absPitch p + k) (d*dt) v) nas ]
defNasHandler :: Context → NoteAttribute → Event → EventdefNasHandler (_,_,_,_,_,v) (Volume v') ev = setEventVol ev (v*v'/100.0)defNasHandler _ _ ev = ev
defInterpPhrase :: (PhraseAttribute → Performance → Performance) → PhraseFundefInterpPhrase pasHandler pmap c@(t,pl,i,dt,k,v) pas m =
let (pf,dur) = perf pmap c m in (foldr pasHandler pf pas, dur)
defPasHandler :: PhraseAttribute → Performance → PerformancedefPasHandler (Dyn (Accent x)) pf = map (\e → setEventVol e (x * getEventVol e)) pfdefPasHandler (Art (Staccato x))pf =map (\e → setEventDur e (x * getEventDur e)) pfdefPasHandler (Art (Legato x)) pf =map (\e → setEventDur e (x * getEventDur e)) pfdefPasHandler _ pf = pf
def fancy
Midi
• Musical Instrument Digital Interface
• Protocol for communicating musical events and meta-events
Conversion to a Midi file
type UserPatchMap = [(IName,GenMidiName,MidiChannel)]
performToMidi :: Performance → UserPatchMap → MidiFileperformToMidi pf pMap = MidiFile mfType (Ticks division) (map (performToMEvs pMap) (splitByInst pf))
Algebraic Properties
(m1 :+: m2) :+: (m3 :+: m4) m1 :+: m2 :+: m3 :+: m4
m1 ≡ m2 iff(forall imap,c) perform imap c m1 ≡ perform imap c m2
Definition
Algebraic Properties
For any r1, r2, r3, r4, and m: Tempo r1 r2 (Tempo r3 r4 m) ≡ Tempo (r1*r3) (r2*r4) m
Proof: perform dt (Tempo r1 r2 (Tempo r3 r4 m))≡ perform (r2*dt/r1) (Tempo r3 r4 m)≡ perform (r4*(r2*dt/r1)/r3) m≡ perform ((r2*r4)*dt/(r1*r3)) m≡ perform dt (Tempo (r1*r3) (r2*r4) m)
Algebraic Properties
For any r1, r2, m1, and m2:
Tempo r1 r2 (m1 :+: m2) ≡ Tempo r1 r2 m1 :+: Tempo r1 r2 m2
Proof: perform (t,dt) (Tempo r1 r2 (m1 :+: m2))≡ perform (t,r2*dt/r1) (m1 :+: m2) ≡ perform (t,r2*dt/r1) m1 ++ perform (t',r2*dt/r1) m2 ≡ perform (t,dt) (Tempo r1 r2 m1) ++ perform (t',dt) (Tempo r1 r2 m2) ≡ perform (t,dt) (Tempo r1 r2 m1) ++ perform (t'',dt) (Tempo r1 r2 m2) ≡ perform (t,dt) (Tempo r1 r2 m1 :+: Tempo r1 r2 m2)
where t' = t + (dur m1)*r2*dt/r1t'' = t + (dur (Tempo r1 r2 m1))*dt
Conclusions
• Clear distinction between music and performance
• Algebra of music
• GUI lacking
• Maintenance
• Haskell well suited as an executable specification language