A note length represents a note’s duration as a fraction of a whole note. Using `Ratio Natural` keeps these values exact while disallowing negative lengths at the type level. section 10.4.2
Common note lengths and rhythmic modifiers include:
- A dotted note adds half the original duration; repeated dots add progressively smaller extensions. section 10.4.2
- Tuplets multiply a duration by two over their subdivision value, so a triplet uses 2/3 and a quintuplet uses 2/5. section 10.4.2
Calculating modified lengths
With `nl = 1 % 2`, `dotted nl` produces `3 % 4`, while `triplet nl` produces `1 % 3`. Short aliases such as `wn` and `sn` make composed notes more concise.
Listing 10.19 Functions for conversion of note lengths to time
module Composition.Notelength where
import Util.Types (Seconds)
import Data.Ratio (Ratio, (%), denominator, numerator)
...
timePerBeat :: BPM -> Seconds
timePerBeat bpm = 60.0 / bpm #1
timePerNotelength :: TempoInfo -> Notelength -> Seconds
timePerNotelength
(TempoInfo beatsPerMinute beatsPerWholeNote)
noteLength =
let beatsForNoteLength = beatsPerWholeNote *
toDouble noteLength #2
in beatsForNoteLength * timePerBeat beatsPerMinute #3
where
toDouble :: Ratio Natural -> Double
toDouble r = #4
(fromInteger . toInteger $ numerator r)
/ (fromInteger . toInteger $ denominator r)
Convert a note length into seconds by combining its fraction of a whole note with beats per whole note and beats per minute. section 10.4.3
