packages feed

temporal-csound 0.2.1 → 0.3.0

raw patch · 5 files changed

+545/−37 lines, 5 filesdep +csound-catalogdep +temporal-music-notation-westerndep ~csound-expression

Dependencies added: csound-catalog, temporal-music-notation-western

Dependency ranges changed: csound-expression

Files

LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2013, Anton Kholomiov+Copyright (c) 2014, Anton Kholomiov  All rights reserved. 
src/Csound.hs view
@@ -1,5 +1,6 @@ {-# Language FlexibleInstances #-}--- | Defines instance of 'Csound.Base.CsdSco' for 'Temporal.Music.Score.Score'. +-- | Defines instance of 'Csound.Base.CsdSco' for 'Temporal.Music.Score.Score' and+--  reexports all functions from packages csound-expression and temporal-music-notation-western. -- -- We can trigger Csound orchestra with 'Temporal.Music.Score.Score'. --@@ -26,55 +27,177 @@ -- There are two handy infix operators for delay and stretch: @(+|)@ and @(*|)@. So we can write the previous score: -- -- > res = 0.5 *| mel [ temp a, 2 *| temp b, 1 +| har [temp a, temp b] ]+--+-- There are shortcuts for notes in western notation (a is 440 Hz).+--+-- > a, b, c, d, e, f, g+--+-- Notes reside in the same octave. To get the notes in higher or lower octaves+-- we can apply the functions:+--+-- * 'Temporal.Music.Score.high', 'Temporal.Music.Score.low' -- take note an octaver higher or lower+--+-- * 'Temporal.Music.Score.higher' n, 'Temporal.Music.Score.lower' n -- take note for @n@ octaves higher or lower+--+-- There are shortcuts for stretching the notes and rests:+--+-- > bn, wn, qn, en, sn -- brevis, whole, quarter, eight, sixteenth notes+--+-- and for rests+--+-- > bnr, wnr, qnr, enr, snr+--+-- These functions transform the melodies with given factors.+-- We can construct melodies:+--+-- > melody = mel [qn $ mel [c, e, g], bn $ har [c, e, g, high c], wnr]+--+-- Then we can apply a csound instrument to the melody to get the signal.+--+-- > res = notes someInstr melody+--+-- Now let's mix it to the signal and send the output to speakers:+--+-- > dac $ mix res +--+-- WARNING: The function 'dac' spawns a csound process in the background which+-- can run forever. If your haskell build tool doesn't kills the child processes with+-- haskell-runing process (As far as I know Sublime Editor doesn't, but vim does) +-- it's better to run the program from ghci and to stop it press @Ctrl+C@:+--+-- > % ghci MyMusic+-- > MyMusic> main +-- >+-- >    ... The programm runs ... press Ctrl+C to stop it+-- >+-- +-- @runhaskell@ doesn't stop the child process. So it's better to use the+-- @dac@ function with terminal.+-- +-- If signal is to loud or to quiet we can scale it:+--+-- > dac $ mul factor $ mix res +-- +-- We can make it brighter with reverb ('Csound.Air.smallRoom', 'Csound.Air.smallHall', 'Csound.Air.largeHall', 'Csound.Air.reverTime')+--+-- > dac $ mul 0.2 $ smallHall $ mix res + module Csound (-    {-+         -- * Converters-    CsdNote, csdNote, CsdDrum, csdDrum,       +    CsdNote(..), csdNote, CsdDrum, csdDrum, N, Dr,      -- * Scores-    -    -- | Tools to make compositions out of timbres.-    sco, notes, drums,-    -}+    --+    -- | Funxtions that apply instruments to scores. +    --+    -- Notes on signatures:+    --+    -- * The class 'Csound.Base.Outs' includes the tuples of signals +    --   that have side effects or have no side effects.+    --+    -- * @SigOuts@ -- means an underlying tuple of signals.+    --   For instance, it can be @Sig@  or @SE Sig@, the @SigOuts@+    --   converts it to the @Sig@. The @SigOuts@ removes the +    --   prefix @SE@ if it is present.+    --+    -- * To get the final signal out of the type @Score (Mix (SigOuts b))@+    --   we should apply the function 'Csound.Base.mix' to it:+    --+    -- > mix :: (CsdSco f, Sigs a) => f (Mix a) -> a+    -- +    --  Or we can continue to build the track of signals with +    --  functions loke 'Temporal.Music.Score.mel', 'Temporal.Music.Score.har', 'Temporal.Music.Score.str'.+    notes, drums,    ++    -- * Midis   +    --+    -- | Plays instruments with midi devices.+    --+    -- > import Csound +    -- > import Csound.Patch(vibraphone2)+    -- >+    -- > -- | Plays with virtual midi device (if you have a midi device+    -- > -- you can substitute @vdac@ for @dac@).+    -- > main = vdac $ mul 0.1 $ largeHall $ onMidi vibraphone2+    -- +    onMidi, onMidin, onPgmidi, +    onMidiWith, onMidinWith, onPgmidiWith,         -    module Temporal.Music,+    module Temporal.Music.Western.P12,     module Csound.Base ) where -import Temporal.Music hiding (delay, event, line, chord) import Temporal.Media(Track) import Csound.Base--import qualified Temporal.Music as T+import Temporal.Music.Western.P12 hiding (delay, event, line, chord, tone)  instance CsdSco (Track Double) where     toCsdEventList x = CsdEventList (dur x) (fmap toEvt $ render x)         where toEvt a = (eventStart a, eventDur a, eventContent a)     singleCsdEvent (start, dt, a) = del start $ str dt $ temp a -{---- | Plays some notes with Csound instrument. -sco :: Arg a => (a -> Out) -> Score a -> SigOut-sco instr s = score instr (fmap unpackEvent $ alignByZero $ render s)-    where unpackEvent e = (eventStart e, eventDur e, eventContent e)+type N  = CsdNote Unit+type Dr = CsdDrum Unit --- | Playes notes.-notes :: Arg a => (CsdNote a -> Out) -> Score (Note a) -> SigOut-notes instr as = sco instr (fmap csdNote as)+-- | Contains amplitude, frequency and auxiliary parameters.+--+-- > (amplitude, frequencyInHz, timbralParameters)+type CsdNote a = (D, D, a) --- | Plays drum-notes.-drums :: Arg a => (CsdDrum a -> Out) -> Score (Drum a) -> SigOut-drums instr as = sco instr (fmap csdDrum as)-  --- | Csound note: (amplitude, cyclesPerSecond, otherParams) -type CsdNote a = (D, D, a)    +-- | Contains amplitude and auxiliary parameters.+--+-- > (amplitude, timbralParameters)+type CsdDrum a = (D, a) -csdNote :: Note a -> CsdNote a-csdNote a = (double $ amp $ noteVolume a, double $ hz  $ notePitch a, noteParam a)+-- | Converts the @Note@ to low level @CsdNote@.+csdNote :: Default a => Note a -> CsdNote a+csdNote a =  	+	( double $ volumeAsDouble $ noteVolume a+    , double $ absPitch $ notePitch a+    , maybe def id $ noteParam a) --- | Csound drum-note: (amplitude, otherParams)-type CsdDrum a = (D, a)+-- | Converts the @Note@ to low level @CsdNote@.+csdDrum :: Default a => Drum a -> CsdDrum a+csdDrum a =  	+	( double $ volumeAsDouble $ drumVolume a+    , maybe def id $ drumParam a) -csdDrum :: Drum a -> CsdDrum a-csdDrum a = (double $ amp $ drumVolume a, drumParam a)--}+-- | Plays the notes with csound instrument.+notes :: (Arg a, Default a, Outs b) => (CsdNote a -> b) -> Score (Note a) -> Score (Mix (SigOuts b))+notes g f = sco (toOuts . g) (fmap csdNote f)++-- | Plays the drum notes with csound instrument.+drums :: (Arg a, Default a, Outs b) => (CsdDrum a -> b) -> Score (Drum a) -> Score (Mix (SigOuts b))+drums g f = sco (toOuts . g) (fmap csdDrum f)++toMidiInstr :: (Default a, Outs b) => (CsdNote a -> b) -> (Msg -> SE (SigOuts b))+toMidiInstr f = \msg -> toOuts $ f (ampmidi msg 1, cpsmidi msg, def) ++toMidiInstrWith :: (Outs b) => a -> (CsdNote a -> b) -> (Msg -> SE (SigOuts b))+toMidiInstrWith defVal f = \msg -> toOuts $ f (ampmidi msg 1, cpsmidi msg, defVal) ++-- | Triggers an instrument on all midi-channels.+onMidi :: (Default a, Outs b) => (CsdNote a -> b) -> SigOuts b+onMidi f = midi $ toMidiInstr f++-- | Triggers an instrument on the given midi-channel.+onMidin :: (Default a, Outs b) => Channel -> (CsdNote a -> b) -> SigOuts b+onMidin chn f = midin chn $ toMidiInstr f++-- | Triggers an instrument on channel and programm bank.+onPgmidi :: (Default a, Outs b) => Maybe Int -> Channel -> (CsdNote a -> b) -> SigOuts b+onPgmidi pgm chn f = pgmidi pgm chn $ toMidiInstr f++-- | Just like @onMidi@ but takes a value for default auxiliary parameters.+onMidiWith :: (Outs b) => a -> (CsdNote a -> b) -> SigOuts b+onMidiWith defVal f = midi $ toMidiInstrWith defVal f++-- | Just like @onMidin@ but takes a value for default auxiliary parameters.+onMidinWith :: (Outs b) => a -> Channel -> (CsdNote a -> b) -> SigOuts b+onMidinWith defVal chn f = midin chn $ toMidiInstrWith defVal f++-- | Just like @onPgmidi@ but takes a value for default auxiliary parameters.+onPgmidiWith :: (Outs b) => a -> Maybe Int -> Channel -> (CsdNote a -> b) -> SigOuts b+onPgmidiWith defVal pgm chn f = pgmidi pgm chn $ toMidiInstrWith defVal f+
+ src/Csound/Converter.hs view
@@ -0,0 +1,33 @@+-- | Converters for the instruments.+module Csound.Converter(+    -- * Pitched instruments+    fromF, fromFs, fromAF, fromAsFs, fromAFs, fromAsF,++    -- * Drums+    fromDrum+) where++import Csound++fromF :: SigSpace a => (D -> a) -> CsdNote Unit -> a+fromF f (amp, cps, _) = mul (sig amp) $ f cps++fromFs :: SigSpace a => (Sig -> a) -> CsdNote Unit -> a+fromFs f (amp, cps, _) = mul (sig amp) $ f (sig cps)++fromAF :: (D -> D -> a) -> CsdNote Unit -> a+fromAF f (amp, cps, _) =  f amp cps++fromAsFs :: (Sig -> Sig -> a) -> CsdNote Unit -> a+fromAsFs f (amp, cps, _) = f (sig amp) (sig cps)++fromAFs :: (D -> Sig -> a) -> CsdNote Unit -> a+fromAFs f (amp, cps, _) = f amp (sig cps)++fromAsF :: (Sig -> D -> a) -> CsdNote Unit -> a+fromAsF f (amp, cps, _) = f (sig amp) cps++-- Drums++fromDrum :: SigSpace a => a -> Dr -> a+fromDrum a (amp, _) = mul (sig amp) a
+ src/Csound/Patch.hs view
@@ -0,0 +1,301 @@+-- | Ready to use instruments.+--+-- An instrument takes in a note (@N@ which is shortcut for @CsdNote Unit@ +-- or @Dr@ which is shortcut for @CsdDrum Unit@) and procuces a signal.+--  We can use instruments with functions 'Csound.notes' and 'Csound.drums'.+--+-- > import Csound +-- > import Csound.Patch(stringPad)+-- >+-- > -- | Plays C-major chord.+-- > main = dac $ mul 0.2 $ smallHall $ mix $ notes stringPad $	+-- > 	 str 0.5 $ mel [c, e, g, str 4 $ har [c, e, g, high c], rest 4]+--+-- Let's explain the functions:+-- +-- > -- dac -- sends signal to speakers+-- > -- +-- > -- mul -- scales the signal+-- > -- +-- > -- smallHall -- adds a reverb+-- > --+-- > -- mix -- mixes several tracks to a single signal+-- > --+-- > -- notes -- applies an instrument to the notes+-- > --+-- > -- stringPad -- predefined instrument+-- > -- +-- > -- str -- stretch the notes in time domain+-- > --+-- > -- mel, har -- sequential and parallel composition of the notes+-- > --+-- > -- c, e, g -- notes in western notation (a, b, c, d, ...), a is 440 Hz +-- > --+-- > -- high -- an octave higher+-- > --+-- > -- rest -- pause for a given amount of time+module Csound.Patch(+    -- * Pads+    stringPad, phasingSynth, pulseWidthPad,+    melodica, tibetan, ++    -- * Mystic+    sparkles, xanaduHarp,++    -- * Lead+    delaySaw, pulseWidth, toneWheel,++    -- * Tech+    okComp, OkCompParam(..), fmMod,++    -- * Plucked+    delayedStringLong, delayedStringShort, +    plucked, xanadu1, xanadu2,+    guitar, harpsichord, harpsichordHarp, plainString, plainStringHarp,++    -- * Strike+    noisyMarimba, dahina, banyan, xylophone,+    spinelSphere, aluminumBar, +    vibraphone1, vibraphone2, wineGlass, xing,++    -- ** Bells +    amBell, fmTubularBell, tubularBell, albertClockBellBelfast,++    -- * Drums+    dumb, dumbBass, pluckSnare, knockSweep, metalBoink,+    snare, openHihat, closedHihat, bassDrum, crash, handClap,+    bambooDr, guiroDr, tambourineDr, cabasaDr, crunchDr,+    sleighbellsDr, sekereDr, sandpaperDr    ++) where++import Csound(N, Dr, CsdNote, CsdDrum)+import Csound.Base++import qualified Csound.Catalog.Wave as C+import qualified Csound.Catalog.Effect as C+import qualified Csound.Catalog.Reson as C+import qualified Csound.Catalog.Drum as C++import Csound.Converter++fade :: SigSpace a => D -> D -> (b -> a) -> (b -> a)+fade ris dec f = mul (fades ris dec) . f++--------------------------------------------------------------------+-- Padds++stringPad :: N -> Sig+stringPad = fade 0.5 1.5 $ fromAsFs C.stringPad++phasingSynth :: N -> Sig+phasingSynth = fade 0.3 1.5 $ fromAsFs C.phasingSynth++melodica :: N -> SE Sig+melodica = fade 0.5 2.5 $ fromFs $ C.melody 5++-- | Parameter is time of fade out in seconds.+tibetan :: D -> N -> Sig+tibetan dec = fade 1 dec $ fromF $ C.tibetan 9 0.02++pulseWidthPad :: N -> Sig+pulseWidthPad = fade 1 1.5 $ fromAsFs C.pulseWidth++--------------------------------------------------------------------+-- Mystic++sparkles :: N -> SE Sig+sparkles = fade 0.01 2.5 $ fromFs $ C.blue 3 8 0.5 15++xanaduHarp :: N -> SE Sig+xanaduHarp = fade 0.01 5 $ fromF C.xanadu1++--------------------------------------------------------------------+-- Lead++pulseWidth :: N -> Sig+pulseWidth = fade 0.1 0.1 $ fromAsFs C.pulseWidth++delaySaw :: N -> Sig+delaySaw = fade 0.1 0.2 $ fromFs $ C.delaySaw++toneWheel :: N -> Sig+toneWheel = fade 0.01 0.1 $ fromF C.toneWheel++--------------------------------------------------------------------+-- Tech++okComp :: CsdDrum OkCompParam -> SE Sig+okComp = fade 0.01 0.1 $ \(amp, OkCompParam rate) -> mul (sig amp) $ C.okComputer (sig rate)++newtype OkCompParam = OkCompParam { unOkCompParam :: D }++instance Tuple OkCompParam where+	tupleMethods = makeTupleMethods OkCompParam unOkCompParam++instance Arg OkCompParam++instance Default OkCompParam where+	def = OkCompParam 10++fmMod :: N -> Sig+fmMod = fade 0.01 0.1 $ fromFs $ C.fmMod 5++--------------------------------------------------------------------+-- Plucked++pick :: SigSpace b => D -> (a -> b) -> (a -> b)+pick dec = fade 0.01 dec++delayedStringLong :: N -> Sig+delayedStringLong = pick 2.5 $ fromF C.delayedString++delayedStringShort :: N -> Sig+delayedStringShort = pick 0.1 $ fromF C.delayedString++plucked :: N -> Sig+plucked = pick 0.3 $ fromFs C.rhodes++xanadu1 :: N -> SE Sig+xanadu1 = pick 1.5 $ fromF C.xanadu1++xanadu2 :: N -> SE Sig+xanadu2 = pick 0.8 $ fromF C.xanadu2++guitar :: N -> Sig+guitar = fade 0.05 2 $ fromF C.guitar++harpsichord :: N -> Sig+harpsichord = pick 0.2 $ fromF C.harpsichord++harpsichordHarp :: N -> Sig+harpsichordHarp = pick 5 $ fromF C.harpsichord++plainString :: N -> Sig+plainString = pick 0.5 $ fromF C.plainString++plainStringHarp :: N -> Sig+plainStringHarp = pick 5 $ fromF C.plainString++--------------------------------------------------------------------+-- Striked++strk :: SigSpace b => (a -> b) -> (a -> b)+strk = pick 2.5++noisyMarimba :: N -> SE Sig+noisyMarimba = strk $ fromFs C.blackMarimba++dahina :: N -> Sig+dahina = strk $ fromFs C.dahina++banyan :: N -> Sig+banyan = strk $ fromFs C.banyan++xylophone :: N -> Sig+xylophone = strk $ fromFs C.xylophone++spinelSphere :: N -> Sig+spinelSphere = strk $ fromFs C.spinelSphere++aluminumBar :: N -> Sig+aluminumBar = strk $ fromFs C.uniformAluminumBar++vibraphone1 :: N -> Sig+vibraphone1 = strk $ fromFs C.vibraphone1++vibraphone2 :: N -> Sig+vibraphone2 = strk $ fromFs C.vibraphone2++wineGlass :: N -> Sig+wineGlass = strk $ fromFs C.wineGlass++xing :: N -> Sig +xing = strk $ fromFs $ C.xing 3++-- Bells++bl :: SigSpace b => (a -> b) -> (a -> b)+bl = pick 4++amBell :: N -> Sig+amBell = bl $ fromAFs $ C.amBell++fmTubularBell :: N -> Sig+fmTubularBell = bl $ fromFs $ C.fmTubularBell++tubularBell :: N -> Sig+tubularBell = bl $ fromFs C.tubularBell++albertClockBellBelfast :: N -> Sig+albertClockBellBelfast = bl $ fromFs C.albertClockBellBelfast++--------------------------------------------------------------------+-- drums++dumb :: Dr -> SE Sig+dumb = fromDrum C.dumb++dumbBass :: Dr -> SE Sig+dumbBass = fromDrum C.dumbBass++pluckSnare :: Dr -> Sig+pluckSnare = fromDrum C.pluckSnare++knockSweep :: Dr -> SE Sig+knockSweep = fromDrum C.sortaKnockSweep++metalBoink :: Dr -> Sig+metalBoink = fromDrum C.metalBoink++snare :: Dr -> SE Sig+snare = fromDrum C.snare++openHihat :: Dr -> SE Sig+openHihat = fromDrum C.openHihat++closedHihat :: Dr -> SE Sig+closedHihat = fromDrum C.closedHihat++bassDrum :: D -> Dr -> Sig+bassDrum cps = fromDrum $ C.bassDrum cps++-- | Recommended values for frequency parameter @cpspch(13.03) - cpspch(13.10)@ +crash :: D -> Dr -> SE Sig+crash cps = fromDrum $ C.crash cps++handClap :: D -> Dr -> SE Sig+handClap cps = fromDrum $ C.handClap cps++-- models++fromModel :: (Sig -> D -> Sig) -> Dr -> Sig+fromModel f (amp, _) = f (sig amp) 0.01++fromModelD :: (D -> D -> Sig) -> Dr -> Sig+fromModelD f (amp, _) = f amp 0.01++bambooDr :: Dr -> Sig+bambooDr = fromModel bamboo ++guiroDr :: Dr -> Sig+guiroDr = fromModel guiro ++tambourineDr :: Dr -> Sig+tambourineDr = fromModel tambourine++cabasaDr :: Dr -> Sig+cabasaDr = fromModelD cabasa++crunchDr :: Dr -> Sig+crunchDr = fromModelD crunch++sleighbellsDr :: Dr -> Sig+sleighbellsDr = fromModel sleighbells++sekereDr :: Dr -> Sig+sekereDr = fromModelD sekere++sandpaperDr :: Dr -> Sig+sandpaperDr = fromModelD sandpaper+
temporal-csound.cabal view
@@ -2,9 +2,8 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                temporal-csound-version:             0.2.1-synopsis:            brings together temporal-music-notation and csound-expression packages--- description:         +version:             0.3.0+synopsis:            library to make electronic music, brings together temporal-music-notation and csound-expression packages license:             BSD3 license-file:        LICENSE author:              Anton Kholomiov@@ -14,6 +13,53 @@ build-type:          Simple cabal-version:       >=1.6 +description:         +    This package joins the forces of the packages temporal-music-notation +    and csound-expression.+    The former package gives you handy primitives to arrange the events+    in sequences (like parallel or sequential composition, the tempo change,+    standard names for notes and durations) and the later is used for+    creation of musical timbres or software synthesizers. +    .+    You can find the short intro in the module "Csound".+    .+    * The tutorial for csound-epression packageb (timbres):+        <https://github.com/anton-k/csound-expression/blob/master/tutorial/QuickStart.markdown> +    .+    * The tutorial for temporal-music-notation package (composition)+         and temporal-music-notation-western package (standard names for notes): see module "Csound"    +    .+    This library defines standard note representation that let's you +    invoke csound instruments with notes defined in the package temporal-music-notation.+    .+    Also this library provides you with some cool instruments to try the things out (see "Csound.Patch").+    .+    WARNING: the library works best within ghci. The real-time sound rendering function dac spawns+    a child process in the background which may continue to execute after you stop the main process that runs the programm.+    It's not so in vim but it happens in the Sublime Editor and when you invoke runhaskell. So the best+    is to write you program in the separate file and then load it in the ghci and invoke the function main (which+    runs the sound rendering with the function dac). +    .+    Library strives to be very simple. For example, to trigger the instrument with virtual midi-device is+    as simple as (in ghci with loaded modules "Csound" and "Csound.Patch")+    .+    > Csound Csound.Patch> vdac $ mul 0.2 $ largeHall $ onMidi stringPad+    .+    If you have a connected hardware midi-device you can just type:+    .+    > Csound Csound.Patch> dac $ mul 0.2 $ largeHall $ onMidi stringPad+    .+    And you are ready to go. To play a C-major chord just do:+    .+    > Csound Csound.Patch> dac $ mul 0.2 $ magicCave $ mix $ notes vibraphone2 $ mel [c, e, g, high c, rest 15]+    .+    Here we send the output to speakers (dac or vdac), scale the signal to make it quiter (mul), +    place the signal in some room with reverberation (largeHall or magicCave), listen to midi+    events (onMidi or onMidin for a midi on the given channel) or get the signal from scores (mix),+    trigger the csound instrument (stringPad or vibraphone2) on events (notes) and construct+    the events in sequence (mel). Events include notes (c, e, g - C major) and rests (rest).++ Extra-Source-Files :   Homepage:        https://github.com/anton-k/temporal-csound@@ -28,5 +74,10 @@   Hs-Source-Dirs:      src/   exposed-modules:          Csound+    Csound.Patch+    Csound.Converter   -- other-modules:       -  build-depends:       base >= 4, base < 5, temporal-music-notation>=0.4, csound-expression>=3.1.0 , temporal-media >= 0.4+  build-depends:       +    base >= 4, base < 5, temporal-music-notation>=0.4, +    csound-expression>=3.2.1, csound-catalog>=0.1.1,+    temporal-media >= 0.4, temporal-music-notation-western>=0.4.0