{-# LANGUAGE GeneralizedNewtypeDeriving #-} ------------------------------------------------------------------------------------- -- | -- Copyright : (c) Hans Hoglund 2012 -- -- License : BSD-style -- -- Maintainer : hans@hanshoglund.se -- Stability : experimental -- Portability : portable -- -- Absolute representation of loudness, or dynamics. -- -- The canonical loudness representation is 'Amplitude'. For conversion, see 'HasAmplitude'. -- ------------------------------------------------------------------------------------- module Music.Dynamics.Absolute ( Amplitude(..), Decibel, Bel, HasAmplitude(..), decibel, bel, ) where import Data.Maybe import Data.Either import Data.Semigroup import Control.Monad import Control.Applicative -- | -- Amplitude level, where @0@ is silent and @1@ is peak. -- newtype Amplitude = Amplitude { getAmplitude :: Double } deriving (Read, Show, Eq, Enum, Num, Ord, Fractional, Floating, Real, RealFrac) -- | -- A logarithmic representation of amplitude such that -- -- > -- > x * 10 = amplitude (bel x + 1) -- newtype Bel = Bel { getBel :: Amplitude } deriving (Read, Show, Eq, Enum, Num, Ord, Fractional, Floating, Real, RealFrac) -- | -- A logarithmic representation of amplitude such that -- -- > -- > x * 10 = amplitude (decibel x + 10) -- newtype Decibel = Decibel { getDecibel :: Amplitude } deriving (Read, Show, Eq, Enum, Num, Ord, Fractional, Floating, Real, RealFrac) instance Semigroup Amplitude where (<>) = (*) instance Semigroup Decibel where (<>) = (+) instance Semigroup Bel where (<>) = (+) instance Monoid Amplitude where { mempty = 1 ; mappend = (*) } instance Monoid Decibel where { mempty = 0 ; mappend = (+) } instance Monoid Bel where { mempty = 0 ; mappend = (+) } class HasAmplitude a where amplitude :: a -> Amplitude instance HasAmplitude Amplitude where amplitude = id instance HasAmplitude Decibel where amplitude (Decibel f) = (10/1) ** (f / 10) instance HasAmplitude Bel where amplitude (Bel f) = (10/1) ** (f / 1) decibel :: HasAmplitude a => a -> Decibel decibel a = Decibel $ logBase (10/1) (amplitude a) * 10 bel :: HasAmplitude a => a -> Bel bel a = Bel $ logBase (10/1) (amplitude a) * 1