packages feed

temporal-music-notation-demo-0.1.2: gen/genGM.hs

-- | Generates module 'GeneralMidi'

import Data.Char
import Data.List.Split

import Language.Haskell.Exts.Syntax
import Language.Haskell.Exts.Pretty
import Language.Haskell.Exts.Build'

import qualified Text.PrettyPrint as P

toFunName :: String -> String
toFunName x = map toLower pref ++ suff
    where pref = takeWhile isUpper x
          suff = dropWhile isUpper x  

-- module


moduleGM name instrs drums = P.vcat $ P.punctuate wspace [
        P.text "-- | General MIDI names",
        moduleHead name instrs drums,
        imports,
        division "Instruments",
        pp $ instrSig instrs,
        P.vcat $ map pp $ instrFuns instrs,
        division "Percussion",
        pp $ drumSig drums,
        P.vcat $ map pp $ drumFuns drums]
    where pp = P.text . prettyPrint
          wspace     = P.text "\n\n"
          division x = (P.text $ replicate 20 '-') 
                        P.$$ (P.text $ "--" ++ x)


moduleHead name instrs drums = P.vcat [
    P.text $ "module " ++ name ++ "(",
    P.nest 4 $ exports instrs drums P.<> P.rparen,
    P.text "where"]

exports instrs drums =
   P.vcat [
        P.text (toSec1 "Instruments"),
        
        P.vcat $ map ( P.<> P.comma) $
            map (uncurry expFunNames) $ 
            expInstrFunNames (map toSec2 familyNames) instrs, 
        P.text "\n\n",
        expFunNames (toSec1 "Percussion")  drums]

toSec1 = ("-- * " ++ )
toSec2 = ("-- ** " ++)

expInstrFunNames fams names = zip fams $ splitEvery 8 names 

expFunNames :: String -> [String] -> P.Doc
expFunNames sec names = (P.text sec P.$$ ) $ P.vcat $ 
    P.punctuate P.comma $ map P.text names

imports :: P.Doc
imports = P.vcat [
    P.text "import Temporal.Music.Notation(Score, Seg)",
    P.text "import Temporal.Music.Notation.Note(Note, Drum)",
    P.text "import Temporal.Music.Notation.Demo"]

-- instruments

zSrcLoc = SrcLoc "" 0 0 

instrSig :: [String] -> Decl
instrSig xs = typeSig zSrcLoc xs $ 
    [var "Seg" "nVol", var "Seg" "nPch"] 
    =>> var "Score" <$> var "Note" `apps` [var "nVol", var "nPch", var "a"] 
    ->> var "Score" <$> var "MidiEvent"

instrFuns = toFuns 0 "instr"

-- drums

drumSig :: [String] -> Decl
drumSig xs = typeSig zSrcLoc xs $ 
    [var "Seg" "nVol"] 
    =>> var "Score" <$> var "Drum" `apps` [var "nVol", var "a"] 
    ->> var "Score" <$> var "MidiEvent"

drumFuns = toFuns 35 "drumInstr"

-- funs

toFuns :: Integer -> String -> [String] -> [Decl]
toFuns i0 constr = map (uncurry $ toFun constr) . zip [i0 .. ]

toFun :: String -> Integer -> String -> Decl
toFun constr id name = fun zSrcLoc name [] <=> (var constr <$> int id)

out :: Pretty a => a -> IO ()
out = putStrLn . prettyPrint


main = do
    let i = map (toFunName . show) $ [(minBound :: InstrumentName) .. maxBound]
        d = map (toFunName . show) $ [(minBound :: PercussionName) .. maxBound] 

    writeFile "GeneralMidi.hs" $ show $ 
        moduleGM "Temporal.Music.Notation.Demo.GeneralMidi" i d 

    
familyNames :: [String]
familyNames = map (splitAtUpper . show) 
        [(minBound :: InstrumentFamily) .. maxBound] 
        where splitAtUpper = unwords . split (keepDelimsL $ whenElt isUpper)  


data InstrumentFamily =  
    Piano          | ChromaticPercussion     | Organ            | Guitar
  | Bass           | Strings                 | Ensemble         | Brass 
  | Reed           | Pipe                    | SynthLead        | SynthPad    
  | SynthEffects   | Ethnic                  | Percussive       | SoundEffects
  deriving (Show, Enum, Bounded)


data InstrumentName = 
     AcousticGrandPiano     | BrightAcousticPiano    | ElectricGrandPiano
  |  HonkyTonkPiano         | RhodesPiano            | ChorusedPiano
  |  Harpsichord            | Clavinet               | Celesta 
  |  Glockenspiel           | MusicBox               | Vibraphone  
  |  Marimba                | Xylophone              | TubularBells
  |  Dulcimer               | HammondOrgan           | PercussiveOrgan 
  |  RockOrgan              | ChurchOrgan            | ReedOrgan
  |  Accordion              | Harmonica              | TangoAccordion
  |  AcousticGuitarNylon    | AcousticGuitarSteel    | ElectricGuitarJazz
  |  ElectricGuitarClean    | ElectricGuitarMuted    | OverdrivenGuitar
  |  DistortionGuitar       | GuitarHarmonics        | AcousticBass
  |  ElectricBassFingered   | ElectricBassPicked     | FretlessBass
  |  SlapBass1              | SlapBass2              | SynthBass1   
  |  SynthBass2             | Violin                 | Viola  
  |  Cello                  | Contrabass             | TremoloStrings
  |  PizzicatoStrings       | OrchestralHarp         | Timpani
  |  StringEnsemble1        | StringEnsemble2        | SynthStrings1
  |  SynthStrings2          | ChoirAahs              | VoiceOohs
  |  SynthVoice             | OrchestraHit           | Trumpet
  |  Trombone               | Tuba                   | MutedTrumpet
  |  FrenchHorn             | BrassSection           | SynthBrass1
  |  SynthBrass2            | SopranoSax             | AltoSax 
  |  TenorSax               | BaritoneSax            | Oboe  
  |  Bassoon                | EnglishHorn            | Clarinet
  |  Piccolo                | Flute                  | Recorder
  |  PanFlute               | BlownBottle            | Shakuhachi
  |  Whistle                | Ocarina                | Lead1Square
  |  Lead2Sawtooth          | Lead3Calliope          | Lead4Chiff
  |  Lead5Charang           | Lead6Voice             | Lead7Fifths
  |  Lead8BassLead          | Pad1NewAge             | Pad2Warm
  |  Pad3Polysynth          | Pad4Choir              | Pad5Bowed
  |  Pad6Metallic           | Pad7Halo               | Pad8Sweep
  |  FX1Train               | FX2Soundtrack          | FX3Crystal
  |  FX4Atmosphere          | FX5Brightness          | FX6Goblins
  |  FX7Echoes              | FX8SciFi               | Sitar
  |  Banjo                  | Shamisen               | Koto
  |  Kalimba                | Bagpipe                | Fiddle 
  |  Shanai                 | TinkleBell             | Agogo  
  |  SteelDrums             | Woodblock              | TaikoDrum
  |  MelodicDrum            | SynthDrum              | ReverseCymbal
  |  GuitarFretNoise        | BreathNoise            | Seashore
  |  BirdTweet              | TelephoneRing          | Helicopter
  |  Applause               | Gunshot     
    deriving (Show, Enum, Bounded)

data PercussionName = 
    AcousticBassDrum       | BassDrum1	            | SideStick	 
  | AcousticSnare	       | HandClap	            | ElectricSnare	 
  | LowFloorTom	           | ClosedHiHat	        | HighFloorTom	 
  | PedalHiHat	           | LowTom	                | OpenHiHat	 
  | LowMidTom	           | HiMidTom	            | CrashCymbal1	 
  | HighTom	               | RideCymbal1	        | ChineseCymbal	 
  | RideBell	           | Tambourine	            | SplashCymbal	 
  | Cowbell	               | CrashCymbal2	        | Vibraslap	 
  | RideCymbal2	           | HiBongo	            | LowBongo	 
  | MuteHiConga	           | OpenHiConga	        | LowConga	 
  | HighTimbale	           | LowTimbale	            | HighAgogo	 
  | LowAgogo	           | Cabasa	                | Maracas	 
  | ShortWhistle	       | LongWhistle	        | ShortGuiro	 
  | LongGuiro	           | Claves	                | HiWoodBlock	 
  | LowWoodBlock	       | MuteCuica	            | OpenCuica	 
  | MuteTriangle	       | OpenTriangle
    deriving (Show, Enum, Bounded)