-- cf. SuperCollider.SoundMap -- this module shall replace InstrumentMap in the long term module Haskore.Interface.CSound.SoundMap where import qualified Haskore.Interface.CSound.Orchestra as Orchestra import Haskore.Interface.CSound.Orchestra (SigExp, noteDur, noteVel, notePit, pField) import Haskore.Interface.CSound (PField, Instrument) import Haskore.General.Utility (toMaybe) import Data.Maybe (mapMaybe) type SoundId = Instrument type InstrumentId = SoundId type DrumId = SoundId type Attribute = PField type AttributeList = [Attribute] type ToSound instr = instr -> (AttributeList, SoundId) attributeControl :: Int -> SigExp attributeControl n = pField (6+n) type InstrumentTable out instr = [(instr, InstrumentSigExp out)] type InstrumentTableWithAttributes out instr = [InstrumentAssociation out instr] type InstrumentSigExp out = SigExp -> SigExp -> SigExp -> out data InstrumentAssociation out instr = InstrumentAssociation InstrumentId (instr -> Maybe AttributeList) out lookupInstrument :: InstrumentTableWithAttributes out instr -> ToSound instr lookupInstrument table instr = case mapMaybe (\(InstrumentAssociation name toAttributes _) -> fmap (\ps -> (ps,name)) (toAttributes instr)) table of [] -> error "SuperCollider.InstrumentMap.lookup: instrument not found" [x] -> x _ -> error "SuperCollider.InstrumentMap.lookup: multiple instruments found" instrumentTableToInstrBlocks :: InstrumentTableWithAttributes out instr -> [Orchestra.InstrBlock out] instrumentTableToInstrBlocks = map (\(InstrumentAssociation i _ out) -> Orchestra.InstrBlock i 0 out []) addInstrumentControls :: InstrumentSigExp out -> out addInstrumentControls graph = graph noteDur noteVel notePit instrumentAssociation :: (parameterTuple -> AttributeList) -> (graph -> InstrumentSigExp out) -> InstrumentId -> (instr -> Maybe parameterTuple) -> graph -> InstrumentAssociation out instr instrumentAssociation makeAttributeList makeInstrumentSigExp name select graph = InstrumentAssociation name (fmap makeAttributeList . select) (addInstrumentControls $ makeInstrumentSigExp graph) instrument :: InstrumentId -> (instr -> Maybe ()) -> (InstrumentSigExp out) -> InstrumentAssociation out instr instrument = instrumentAssociation (\() -> []) id -- simplified variant of 'instrument' for comparable @instrument@ types instrumentEq :: Eq instrument => InstrumentId -> instrument -> (InstrumentSigExp out) -> InstrumentAssociation out instrument instrumentEq name instrumentId = instrument name (\x -> toMaybe (instrumentId==x) ()) instrument1 :: InstrumentId -> (instr -> Maybe Attribute) -> (SigExp -> InstrumentSigExp out) -> InstrumentAssociation out instr instrument1 = instrumentAssociation (\p0 -> [p0]) (\graph -> graph (attributeControl 0)) instrument2 :: InstrumentId -> (instr -> Maybe (Attribute, Attribute)) -> (SigExp -> SigExp -> InstrumentSigExp out) -> InstrumentAssociation out instr instrument2 = instrumentAssociation (\(p0,p1) -> [p0,p1]) (\graph -> graph (attributeControl 0) (attributeControl 1)) instrument3 :: InstrumentId -> (instr -> Maybe (Attribute, Attribute, Attribute)) -> (SigExp -> SigExp -> SigExp -> InstrumentSigExp out) -> InstrumentAssociation out instr instrument3 = instrumentAssociation (\(p0,p1,p2) -> [p0,p1,p2]) (\graph -> graph (attributeControl 0) (attributeControl 1) (attributeControl 2)) instrument4 :: InstrumentId -> (instr -> Maybe (Attribute, Attribute, Attribute, Attribute)) -> (SigExp -> SigExp -> SigExp -> SigExp -> InstrumentSigExp out) -> InstrumentAssociation out instr instrument4 = instrumentAssociation (\(p0,p1,p2,p3) -> [p0,p1,p2,p3]) (\graph -> graph (attributeControl 0) (attributeControl 1) (attributeControl 2) (attributeControl 3)) type DrumTable out drum = [(drum, DrumSigExp out)] type DrumTableWithAttributes out drum = [DrumAssociation out drum] type DrumSigExp out = SigExp -> SigExp -> out data DrumAssociation out drum = DrumAssociation DrumId (drum -> Maybe AttributeList) out lookupDrum :: DrumTableWithAttributes out drum -> ToSound drum lookupDrum table drumId = case mapMaybe (\(DrumAssociation name toAttributes _) -> fmap (\ps -> (ps,name)) (toAttributes drumId)) table of [] -> error "SuperCollider.InstrumentMap.lookup: drum not found" [x] -> x _ -> error "SuperCollider.InstrumentMap.lookup: multiple drums found" drumTableToInstrBlocks :: DrumTableWithAttributes out instr -> [Orchestra.InstrBlock out] drumTableToInstrBlocks = map (\(DrumAssociation i _ out) -> Orchestra.InstrBlock i 0 out []) addDrumControls :: DrumSigExp out -> out addDrumControls graph = graph noteDur noteVel drumAssociation :: (parameterTuple -> AttributeList) -> (graph -> DrumSigExp out) -> DrumId -> (drum -> Maybe parameterTuple) -> graph -> DrumAssociation out drum drumAssociation makeAttributeList makeDrumSigExp name select graph = DrumAssociation name (fmap makeAttributeList . select) (addDrumControls $ makeDrumSigExp graph) drum :: DrumId -> (drum -> Maybe ()) -> (DrumSigExp out) -> DrumAssociation out drum drum = drumAssociation (\() -> []) id -- simplified variant of 'drum' for comparable @drum@ types drumEq :: Eq drum => DrumId -> drum -> (DrumSigExp out) -> DrumAssociation out drum drumEq name drumId = drum name (\x -> toMaybe (drumId==x) ()) drum1 :: DrumId -> (drum -> Maybe Attribute) -> (SigExp -> DrumSigExp out) -> DrumAssociation out drum drum1 = drumAssociation (\p0 -> [p0]) (\graph -> graph (attributeControl 0)) drum2 :: DrumId -> (drum -> Maybe (Attribute, Attribute)) -> (SigExp -> SigExp -> DrumSigExp out) -> DrumAssociation out drum drum2 = drumAssociation (\(p0,p1) -> [p0,p1]) (\graph -> graph (attributeControl 0) (attributeControl 1)) drum3 :: DrumId -> (drum -> Maybe (Attribute, Attribute, Attribute)) -> (SigExp -> SigExp -> SigExp -> DrumSigExp out) -> DrumAssociation out drum drum3 = drumAssociation (\(p0,p1,p2) -> [p0,p1,p2]) (\graph -> graph (attributeControl 0) (attributeControl 1) (attributeControl 2)) drum4 :: DrumId -> (drum -> Maybe (Attribute, Attribute, Attribute, Attribute)) -> (SigExp -> SigExp -> SigExp -> SigExp -> DrumSigExp out) -> DrumAssociation out drum drum4 = drumAssociation (\(p0,p1,p2,p3) -> [p0,p1,p2,p3]) (\graph -> graph (attributeControl 0) (attributeControl 1) (attributeControl 2) (attributeControl 3))