chapter 22
Download
Skip this Video
Download Presentation
Chapter 22

Loading in 2 Seconds...

play fullscreen
1 / 8

Chapter 22 - PowerPoint PPT Presentation


  • 228 Views
  • Uploaded on

Chapter 22. From Performance to MIDI. Motivation. Abstractly, an MDL program denotes a Performance . But a Performance is just a Haskell data structure – we can analyze it, but we cannot hear it! To remedy this, we will convert a Performance into a MIDI File.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Chapter 22' - ivanbritt


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
chapter 22

Chapter 22

From Performance to MIDI

motivation
Motivation
  • Abstractly, an MDL program denotes a Performance.
  • But a Performance is just a Haskell data structure – we can analyze it, but we cannot hear it!
  • To remedy this, we will convert a Performance into a MIDI File.
  • MIDI (Musical Instrument Digital Interface) is a standard protocol for describing electronic music.
  • The MIDI file format is part of this standard, and all consumer PC’s are capable of playing them through the PC’s sound card.
  • In addition, General MIDI standardizes instrument and percussion names as used in MDL.
our goal
Our Goal
  • We need to define a function (called “test” in text): musicToMidi :: Music -> IO () musicToMidi = outputMidiFile "test.mid“ . performToMidi . perform defCon
  • “perform” was defined in the previous chapter, and “defCon” is just the default Context.
  • So additionally we need: performToMidi :: Performance -> MidiFile outputMidiFile :: String -> MidiFile -> IO ()
  • “MidiFile” and “outputMidiFile” are imported from Haskore. Our main job is to define “performToMidi”.
midifile data type
MidiFile Data Type
  • The MidiFile data type (imported from Haskore) captures the essence of a Midi file: data MidiFile = MidiFile MFType Division [Track] deriving (Show, Eq) type MFType = Int type Track = [MEvent] data Division = Ticks Int | SMPTE Int Int deriving (Show,Eq) data MEvent = MidiEvent ElapsedTime MidiEvent | MetaEvent ElapsedTime MetaEvent | NoEvent deriving (Show,Eq) type ElapsedTime = Int

[ see text for details ]

midi events
MIDI Events
  • MIDI events are like MDL events, except that there are events for both start and end of a note: data MidiEvent = | NoteOff MidiChannel MPitch Velocity | NoteOn MidiChannel MPitch Velocity | ProgChange MidiChannel ProgNum | ... deriving (Show, Eq)type MPitch = Int; type Velocity = Int type ProgNum = Int; type MidiChannel = Int data MetaEvent = SetTempo MTempo | ... deriving (Show, Eq)type MTempo = Int
performtomidi
performToMidi
  • To convert a Performance into a MidiFile value: performToMidi :: Performance -> MidiFile performToMidi pf = MidiFile mfType (Ticks division) (map performToMEvs (splitByInst pf)) mfType = 1 :: Int division = 96 :: Int
  • This leaves two functions:splitByInst :: Performance -> [(MidiChannel,ProgNum,Performance)]performToMEvs :: (MidiChannel,ProgNum,Performance) -> [MEvent]
  • In a Type 1 MIDI file, each instrument is associated with a separate track. splitByInst splits the Performance to achieve this (see text for details).
performtomevs
performToMEvs

performToMEvs :: (MidiChannel,ProgNum,Performance) -> [MEvent]

performToMEvs (ch,pn,perf)= let setupInst = MidiEvent 0 (ProgChange ch pn) setTempo = MetaEvent 0 (SetTempo tempo) loop [] = [] loop (e:es) = let (mev1,mev2) = mkMEvents ch e in mev1 : insertMEvent mev2 (loop es) in setupInst : setTempo : loop perf

tempo = 500000 :: Int -- number of microsecs in one beat

insertMEvent :: MEvent -> [MEvent] -> [MEvent]insertMEvent ev1 [] = [ev1]insertMEvent [email protected](MidiEvent t1 _) [email protected]([email protected](MidiEvent t2 _) : evs\') = if t1 <= t2 then ev1 : evs else ev2 : insertMEvent ev1 evs\'

mkmevents
mkMEvents
  • Finally, we convert individual notes:mkMEvents :: MidiChannel -> Event -> (MEvent,MEvent)mkMEvents mChan (Event { eTime = t, ePitch = p, eDur = d }) = ( MidiEvent (toDelta t) (NoteOn mChan p 127), MidiEvent (toDelta (t+d)) (NoteOff mChan p 127) )toDelta t = round (t * 4.0 * intToFloat division)
ad