{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedLists #-} {-# LANGUAGE GADTs #-} module Hypsibius.Data where import Data.Adnot import Data.Sequence (Seq) import Data.Text (Text) import Data.Word (Word8) import Lens.Family2.TH -- | XXX: This is a temporary definition of 'Oscillator' for early -- prototyping purposes. data Oscillator = OscSine | OscSquare deriving (Eq, Show) -- | XXX: This is a temporary definition of 'Instrument' for early -- prototyping purposes. data Instrument = Instrument { _instrSource :: Oscillator } deriving (Eq, Show) $(makeLenses ''Instrument) -- | We'll maintain a list of instruments and refer to them using -- indices. For type safety, here is a wrapper around those -- indices. newtype InstrRef = InstrRef { _fromInstrRef :: Int } deriving (Eq, Show) $(makeLenses ''InstrRef) -- | A 'Note' here is an individual element of a scale, which we'll -- maintain a unique list of on a per-song basis, and most of the time -- we'll use indices into that list. A 'Note' has a frequency represented -- in cents and an appearance that the user will see when running the -- program, which should be no more than a few characters long. data Note = Note { _noteCents :: Double , _noteAppearance :: Text , _noteColor :: Maybe Text } deriving (Eq, Show) instance FromAdnot Note where parseAdnot = withSum "Note" go where go "note" [name, cents] = Note <$> parseAdnot cents <*> parseAdnot name <*> pure Nothing go "note" [name, cents, color] = Note <$> parseAdnot cents <*> parseAdnot name <*> (Just <$> parseAdnot color) go "note" _ = fail "Unknown argument structure" go c _ = fail ("Expected note, got " ++ show c) $(makeLenses ''Note) -- | We'll maintain a list of notes and refer to them using indices. For type -- safety, here is a wrapper around those indices. newtype NoteRef = NoteRef { _fromNoteRef :: Int } deriving (Eq, Show) $(makeLenses ''NoteRef) -- | A 'Scale' has a name, a total number of cents (which will almost always be -- 1200 for traditional scales) and a list of notes associated with it. data Scale = Scale { _scaleName :: Text , _scaleTotalCents :: Double , _scaleNotes :: Seq Note } deriving (Eq, Show) instance FromAdnot Scale where parseAdnot = withProduct "Scale" $ \o -> Scale <$> o .: "name" <*> o .: "size" <*> o .: "notes" $(makeLenses ''Scale) -- | An 'Event' is a typical event associated with a song. data Event = Event deriving (Eq, Show) data Beats = BeatsSimple Word8 | BeatsAdditive [Word8] | BeatsFractional Word8 Word8 deriving (Eq, Show) $(makeTraversals ''Beats) data Signature = Signature { _sigPerBar :: Beats , _sigBeatUnit :: Word8 } deriving (Eq, Show) $(makeLenses ''Signature) data TrackChunk = TrackChunk { _tcSignature :: Signature } deriving (Eq, Show) data Track = Track { } deriving (Eq, Show) data Song = Song { _songScale :: Scale , _songTracks :: Seq Track } deriving (Eq, Show) $(makeLenses ''Song)