{- | General-MIDI definitions. Taken from Haskore. -} module Sound.MIDI.General where import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg import Sound.MIDI.Message.Channel (Channel, toChannel, ) import Data.Ix(Ix) import qualified Data.List as List import Sound.MIDI.Utility (mapSnd, enumRandomR, boundedEnumRandom, chooseEnum, ) import Test.QuickCheck (Arbitrary(..), ) import System.Random (Random(random,randomR), ) {- * Instrument definitions -} instrumentNameToProgram :: String -> Maybe VoiceMsg.Program instrumentNameToProgram = fmap VoiceMsg.toProgram . flip List.elemIndex instrumentNames instrumentNames :: [String] instrumentNames = map fst instrumentPrograms instrumentPrograms :: [(String, VoiceMsg.Program)] instrumentPrograms = map (mapSnd VoiceMsg.toProgram) [ ("Acoustic Grand Piano",0), ("Bright Acoustic Piano",1), ("Electric Grand Piano",2), ("Honky Tonk Piano",3), ("Rhodes Piano",4), ("Chorused Piano",5), ("Harpsichord",6), ("Clavinet",7), ("Celesta",8), ("Glockenspiel",9), ("Music Box",10), ("Vibraphone",11), ("Marimba",12), ("Xylophone",13), ("Tubular Bells",14), ("Dulcimer",15), ("Hammond Organ",16), ("Percussive Organ",17), ("Rock Organ",18), ("Church Organ",19), ("Reed Organ",20), ("Accordion",21), ("Harmonica",22), ("Tango Accordion",23), ("Acoustic Guitar (nylon)",24), ("Acoustic Guitar (steel)",25), ("Electric Guitar (jazz)",26), ("Electric Guitar (clean)",27), ("Electric Guitar (muted)",28), ("Overdriven Guitar",29), ("Distortion Guitar",30), ("Guitar Harmonics",31), ("Acoustic Bass",32), ("Electric Bass (fingered)",33), ("Electric Bass (picked)",34), ("Fretless Bass",35), ("Slap Bass 1",36), ("Slap Bass 2",37), ("Synth Bass 1",38), ("Synth Bass 2",39), ("Violin",40), ("Viola",41), ("Cello",42), ("Contrabass",43), ("Tremolo Strings",44), ("Pizzicato Strings",45), ("Orchestral Harp",46), ("Timpani",47), ("String Ensemble 1",48), ("String Ensemble 2",49), ("Synth Strings 1",50), ("Synth Strings 2",51), ("Choir Aahs",52), ("Voice Oohs",53), ("Synth Voice",54), ("Orchestra Hit",55), ("Trumpet",56), ("Trombone",57), ("Tuba",58), ("Muted Trumpet",59), ("French Horn",60), ("Brass Section",61), ("Synth Brass 1",62), ("Synth Brass 2",63), ("Soprano Sax",64), ("Alto Sax",65), ("Tenor Sax",66), ("Baritone Sax",67), ("Oboe",68), ("Bassoon",69), ("English Horn",70), ("Clarinet",71), ("Piccolo",72), ("Flute",73), ("Recorder",74), ("Pan Flute",75), ("Blown Bottle",76), ("Shakuhachi",77), ("Whistle",78), ("Ocarina",79), ("Lead 1 (square)",80), ("Lead 2 (sawtooth)",81), ("Lead 3 (calliope)",82), ("Lead 4 (chiff)",83), ("Lead 5 (charang)",84), ("Lead 6 (voice)",85), ("Lead 7 (fifths)",86), ("Lead 8 (bass+lead)",87), ("Pad 1 (new age)",88), ("Pad 2 (warm)",89), ("Pad 3 (polysynth)",90), ("Pad 4 (choir)",91), ("Pad 5 (bowed)",92), ("Pad 6 (metallic)",93), ("Pad 7 (halo)",94), ("Pad 8 (sweep)",95), ("FX1 (train)",96), ("FX2 (soundtrack)",97), ("FX3 (crystal)",98), ("FX4 (atmosphere)",99), ("FX5 (brightness)",100), ("FX6 (goblins)",101), ("FX7 (echoes)",102), ("FX8 (sci-fi)",103), ("Sitar",104), ("Banjo",105), ("Shamisen",106), ("Koto",107), ("Kalimba",108), ("Bagpipe",109), ("Fiddle",110), ("Shanai",111), ("Tinkle Bell",112), ("Agogo",113), ("Steel Drums",114), ("Woodblock",115), ("Taiko Drum",116), ("Melodic Drum",117), ("Synth Drum",118), ("Reverse Cymbal",119), ("Guitar Fret Noise",120), ("Breath Noise",121), ("Seashore",122), ("Bird Tweet",123), ("Telephone Ring",124), ("Helicopter",125), ("Applause",126), ("Gunshot",127) ] instrumentFromProgram :: VoiceMsg.Program -> Instrument instrumentFromProgram = toEnum . VoiceMsg.fromProgram instrumentToProgram :: Instrument -> VoiceMsg.Program instrumentToProgram = VoiceMsg.toProgram . fromEnum instrumentChannels :: [Channel] instrumentChannels = map toChannel $ [0..8] ++ [10..15] instruments :: [Instrument] instruments = enumFromTo minBound maxBound data Instrument = AcousticGrandPiano | BrightAcousticPiano | ElectricGrandPiano | HonkyTonk | ElectricPiano1 | ElectricPiano2 | Harpsichord | Clavinet | Celesta | Glockenspiel | MusicBox | Vibraphone | Marimba | Xylophone | TubularBells | Dulcimer | DrawbarOrgan | PercussiveOrgan | RockOrgan | ChurchOrgan | ReedOrgan | Accordion | Harmonica | TangoAccordian | AcousticGuitarNylon | AcousticGuitarSteel | ElectricGuitarJazz | ElectricGuitarClean | ElectricGuitarMuted | OverdrivenGuitar | DistortionGuitar | GuitarHarmonics | AcousticBass | ElectricBassFinger | ElectricBassPick | 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 | EnglishHorn | Bassoon | Clarinet | Piccolo | Flute | Recorder | PanFlute | BlownBottle | Skakuhachi | Whistle | Ocarina | Lead1Square | Lead2Sawtooth | Lead3Calliope | Lead4Chiff | Lead5Charang | Lead6Voice | Lead7Fifths | Lead8BassLead | Pad1NewAge | Pad2Warm | Pad3Polysynth | Pad4Choir | Pad5Bowed | Pad6Metallic | Pad7Halo | Pad8Sweep | FX1Rain | FX2Soundtrack | FX3Crystal | FX4Atmosphere | FX5Brightness | FX6Goblins | FX7Echoes | FX8SciFi | Sitar | Banjo | Shamisen | Koto | Kalimba | Bagpipe | Fiddle | Shanai | TinkleBell | Agogo | SteelDrums | Woodblock | TaikoDrum | MelodicTom | SynthDrum | ReverseCymbal | GuitarFretNoise | BreathNoise | Seashore | BirdTweet | TelephoneRing | Helicopter | Applause | Gunshot deriving (Show, Eq, Ord, Ix, Enum, Bounded) instance Random Instrument where random = boundedEnumRandom randomR = enumRandomR instance Arbitrary Instrument where arbitrary = chooseEnum coarbitrary = error "GeneralMIDI.Instrument.coarbitrary not implemented" {- * Drum definitions -} drumChannel :: Channel drumChannel = toChannel 9 drumProgram :: VoiceMsg.Program drumProgram = VoiceMsg.toProgram 0 drumMinKey :: VoiceMsg.Pitch drumMinKey = VoiceMsg.toPitch 35 drumKeyTable :: [(Drum, VoiceMsg.Pitch)] drumKeyTable = zip drums [drumMinKey ..] drumFromKey :: VoiceMsg.Pitch -> Drum drumFromKey = toEnum . VoiceMsg.subtractPitch drumMinKey drumToKey :: Drum -> VoiceMsg.Pitch drumToKey = flip VoiceMsg.increasePitch drumMinKey . fromEnum drums :: [Drum] drums = enumFromTo minBound maxBound data Drum = AcousticBassDrum -- Midi Key 35 | BassDrum1 -- Midi Key 36 | 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 -- Midi Key 82 deriving (Show, Eq, Ord, Ix, Enum, Bounded) -- http://oxygen.cside6.com/gallery/ins_gm.html instance Random Drum where random = boundedEnumRandom randomR = enumRandomR instance Arbitrary Drum where arbitrary = chooseEnum coarbitrary = error "GeneralMIDI.Drum.coarbitrary not implemented"