synthesizer-alsa-0.3: src/Synthesizer/Dimensional/MIDIValue.hs
{-# LANGUAGE NoImplicitPrelude #-}
{- |
Functions for converting MIDI controller and key values
to something meaningful for signal processing.
-}
module Synthesizer.Dimensional.MIDIValue where
import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg
import qualified Algebra.DimensionTerm as Dim
import qualified Number.DimensionTerm as DN
import qualified Algebra.Transcendental as Trans
import qualified Algebra.Field as Field
import qualified Algebra.Additive as Additive
import NumericPrelude.Numeric
-- import NumericPrelude.Base
{-# INLINE controllerLinear #-}
controllerLinear ::
(Field.C y, Dim.C v) =>
DN.T v y -> (DN.T v y, DN.T v y) -> Int -> y
controllerLinear amp (lower,upper) n =
let k = fromIntegral n / 127
in DN.divToScalar (DN.scale (1-k) lower + DN.scale k upper) amp
{-# INLINE controllerExponential #-}
controllerExponential ::
(Trans.C y, Dim.C v) =>
DN.T v y -> (DN.T v y, DN.T v y) -> Int -> y
controllerExponential amp (lower,upper) n =
let k = fromIntegral n / 127
in DN.divToScalar lower amp ** (1-k) *
DN.divToScalar upper amp ** k
{-# INLINE pitchBend #-}
pitchBend ::
(Trans.C y, Dim.C v) =>
DN.T v y -> y -> DN.T v y -> Int -> y
pitchBend amp range center n =
DN.divToScalar center amp * range ** (fromIntegral n / 8192)
{- |
Convert pitch to frequency according to the default tuning
in MIDI 1.0 Detailed Specification.
-}
{-# INLINE frequencyFromPitch #-}
frequencyFromPitch ::
(Trans.C y) =>
VoiceMsg.Pitch -> DN.Frequency y
frequencyFromPitch pitch =
DN.scale
(2 ^? (fromIntegral (VoiceMsg.fromPitch pitch + 3 - 6*12) / 12))
(DN.frequency 440)