{-# OPTIONS -fno-implicit-prelude #-} module Music.SwanLake where import Synthesizer as Syn import Synthesizer.Plain.Control(exponential2) import Instruments import Sox.File import qualified Algebra.Transcendental as Trans import qualified Algebra.Field as Field import qualified Algebra.Ring as Ring import qualified Haskore.Music as Music import Haskore.Music.Standard as StdMusic import Haskore.Melody.Standard as StdMelody import Haskore.Performance.Player as Player import qualified Haskore.Interface.Signal.Write as MusicSignal import Haskore.Interface.Signal.Write(Time,Volume) import System.Exit(ExitCode) import PreludeBase import NumericPrelude ------------ The song description ------------- -- Comfortable creation of chords of notes of the same length chordDur :: t -> [t -> [NoteAttribute] -> StdMelody.T] -> StdMelody.T chordDur dr chd = chord (zipWith (\n v -> n dr [Velocity (toPRational v)]) chd [1,0.3,0.3,0.3]) chords :: StdMelody.T chords = transpose 12 (line [chordDur wn [a (-3), e 0, a 0, c 1], chordDur wn [d (-2), f 0, a 0, d 1], chordDur wn [a (-2), e 0, a 0, c 1], chordDur wn [gs(-2), e 0, a 0, c 1], chordDur wn [g (-2), e 0, a 0, c 1], chordDur hn [d (-2), f 0, a 0, d 1], chordDur hn [f (-3), f 0, a 0, c 1], chordDur wn [a (-3), e 0, a 0, c 1] ]) makeMelody :: [[a] -> StdMelody.T] -> StdMelody.T makeMelody mel = transpose 24 (line (map ($ []) mel)) melody :: StdMelody.T melody = makeMelody [e 1 wn, a 0 qn, b 0 qn, c 1 qn, d 1 qn, e 1 dhn, c 1 qn, e 1 dhn, c 1 qn, e 1 dhn, a 0 qn, c 1 qn, a 0 qn, f 0 qn, c 1 qn, a 0 wn] ----------- Configuration of the player ----------- defltSampleRate :: Ring.C a => a defltSampleRate = 44100 -- Volume type arises from Haskore songToSignalMono :: Volume -> StdMelody.T -> [Volume] songToSignalMono dif song = MusicSignal.fromRhyMusic defltSampleRate (MusicSignal.detuneInstrs dif [("string", MusicSignal.amplify (0.5::Volume) simpleSaw)]) Player.fancyMap (MusicSignal.contextMetro 120 qn) (StdMusic.fromStdMelody "string" song) songSignal :: Volume -> [Volume] songSignal dif = songToSignalMono dif chords polarisator :: Trans.C a => a -> a -> [Pole a] polarisator sampleRate freq = map (flip Pole (freq/sampleRate)) (exponential2 (0.5*sampleRate) 100) filterSignal :: Time -> [Pole Volume] filterSignal dif = -- we must remove gaps because a pole frequency 0 let most filters crash -- hope that the signal doesn't become too short ... filter (/= Pole 0 0) (MusicSignal.fromRhyMusic defltSampleRate (MusicSignal.detuneInstrs dif [("filter", polarisator)]) Player.fancyMap (MusicSignal.contextMetro 120 qn) (StdMusic.fromStdMelody "filter" melody)) filteredSignal :: Volume -> [Volume] filteredSignal dif = Syn.amplify (0.1::Volume) (moogFilter 10 (map (moogFilterParam 10) (filterSignal 1)) (songSignal (1/dif))) {- filteredSignal dif = map (\(_,_,x) -> 0.1*x) (uniFilter (map uniFilterParam filterSignal) songSignal) -} stereoSignal :: [(Volume, Volume)] stereoSignal = zip (filteredSignal 1.002) (filteredSignal 0.998) main :: IO ExitCode main = Sox.File.writeStereo "SwanLake" defltSampleRate stereoSignal