module Sound.SC3.Lang.Math.Pitch where data Pitch a = Pitch { mtranspose :: a , gtranspose :: a , ctranspose :: a , octave :: a , root :: a , scale :: [a] , degree :: a , stepsPerOctave :: a , detune :: a , harmonic :: a , freq_f :: Pitch a -> a , midinote_f :: Pitch a -> a , note_f :: Pitch a -> a } midi_cps :: (Floating a) => a -> a midi_cps a = 440.0 * (2.0 ** ((a - 69.0) * (1.0 / 12.0))) defaultPitch :: (Floating a, RealFrac a) => Pitch a defaultPitch = Pitch { mtranspose = 0 , gtranspose = 0 , ctranspose = 0 , octave = 5 , root = 0 , degree = 0 , scale = [0, 2, 4, 5, 7, 9, 11] , stepsPerOctave = 12 , detune = 0 , harmonic = 1 , freq_f = default_freq_f , midinote_f = default_midinote_f , note_f = default_note_f } default_freq_f :: (Floating a) => Pitch a -> a default_freq_f e = midi_cps (midinote e + ctranspose e) * harmonic e default_midinote_f :: (Fractional a) => Pitch a -> a default_midinote_f e = let n = note e + gtranspose e + root e in (n / stepsPerOctave e + octave e) * 12 default_note_f :: (RealFrac a) => Pitch a -> a default_note_f e = let d = degree e + mtranspose e in degree_to_key d (scale e) (stepsPerOctave e) degree_to_key :: (RealFrac a) => a -> [a] -> a -> a degree_to_key d s n = let l = length s d' = round d a = (d - fromIntegral d') * 10.0 * (n / 12.0) in (n * fromIntegral (d' `div` l)) + (s !! (d' `mod` l)) + a note :: Pitch a -> a note e = note_f e e midinote :: Pitch a -> a midinote e = midinote_f e e freq :: Pitch a -> a freq e = freq_f e e detunedFreq :: (Num a) => Pitch a -> a detunedFreq e = freq e + detune e