{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}

module Language.Shifts
  ( (#)
  , (^)
  ) where

import Debug.Trace           (trace)
import Language.Notes        (Note (getTone), Octave, Tone, getIntFromOctave,
                              getIntFromTone, getOctave, getOctaveFromInt,
                              getToneFromInt, tones)
import Prelude               hiding ((^))
import Synthesizer.Structure (Frequency)

type OctaveShift = Int
class ShiftOctave a where
  (^) :: a -> OctaveShift -> a

instance ShiftOctave Note where
  ^ :: Note -> OctaveShift -> Note
(^) Note
note OctaveShift
octaveShift = Note
note { getOctave :: Octave
getOctave = Octave
newOctave }
    where
      newOctave :: Octave
newOctave = OctaveShift -> Octave
getOctaveFromInt (OctaveShift -> Octave) -> OctaveShift -> Octave
forall a b. (a -> b) -> a -> b
$ Octave -> OctaveShift
getIntFromOctave (Note -> Octave
getOctave Note
note) OctaveShift -> OctaveShift -> OctaveShift
forall a. Num a => a -> a -> a
+ OctaveShift
octaveShift

instance ShiftOctave [Note] where
  ^ :: [Note] -> OctaveShift -> [Note]
(^) [Note]
notes OctaveShift
octaveShift = (Note -> Note) -> [Note] -> [Note]
forall a b. (a -> b) -> [a] -> [b]
map (Note -> OctaveShift -> Note
forall a. ShiftOctave a => a -> OctaveShift -> a
^ OctaveShift
octaveShift) [Note]
notes

type ToneShift = Int

class ShiftTone a where
  (#) :: a -> ToneShift -> a

instance ShiftTone Note where
  # :: Note -> OctaveShift -> Note
(#) Note
note OctaveShift
toneShift = Note
note { getTone :: Tone
getTone = OctaveShift -> Tone
getToneFromInt OctaveShift
newTone } Note -> OctaveShift -> Note
forall a. ShiftOctave a => a -> OctaveShift -> a
^ OctaveShift
octaveShift
    where
      previousTone :: OctaveShift
previousTone = Tone -> OctaveShift
getIntFromTone (Note -> Tone
getTone Note
note)
      tonesTotal :: OctaveShift
tonesTotal = [Tone] -> OctaveShift
forall (t :: * -> *) a. Foldable t => t a -> OctaveShift
length [Tone]
tones
      tonesTillNextOctave :: OctaveShift
tonesTillNextOctave = OctaveShift
tonesTotal OctaveShift -> OctaveShift -> OctaveShift
forall a. Num a => a -> a -> a
- OctaveShift
previousTone

      octaveShift :: OctaveShift
octaveShift = (OctaveShift
previousTone OctaveShift -> OctaveShift -> OctaveShift
forall a. Num a => a -> a -> a
+ OctaveShift
toneShift) OctaveShift -> OctaveShift -> OctaveShift
forall a. Integral a => a -> a -> a
`div` OctaveShift
tonesTotal
      newTone :: OctaveShift
newTone = (OctaveShift
previousTone OctaveShift -> OctaveShift -> OctaveShift
forall a. Num a => a -> a -> a
+ OctaveShift
toneShift) OctaveShift -> OctaveShift -> OctaveShift
forall a. Integral a => a -> a -> a
`mod` OctaveShift
tonesTotal

instance ShiftTone [Note] where
  # :: [Note] -> OctaveShift -> [Note]
(#) [Note]
notes OctaveShift
toneShift = (Note -> Note) -> [Note] -> [Note]
forall a b. (a -> b) -> [a] -> [b]
map (Note -> OctaveShift -> Note
forall a. ShiftTone a => a -> OctaveShift -> a
# OctaveShift
toneShift) [Note]
notes