csound-expression 3.2.3 → 3.3.0
raw patch · 9 files changed
+194/−25 lines, 9 filesdep ~csound-expression-typedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: csound-expression-typed
API changes (from Hackage documentation)
+ Csound.Air: addSpec :: Sig -> Sig -> Sig
+ Csound.Air: delaySnd :: Sigs a => D -> a -> a
+ Csound.Air: fromSpec :: Spec -> Sig
+ Csound.Air: mapSpec :: (Spec -> Spec) -> Sig -> Sig
+ Csound.Air: scaleSpec :: Sig -> Sig -> Sig
+ Csound.Air: segmentSnd :: Sigs a => D -> D -> a -> a
+ Csound.Air: toSpec :: Sig -> Spec
+ Csound.Control.Evt: eventList :: [(D, D, a)] -> Evt [(D, D, a)]
+ Csound.Control.Evt: impulse :: D -> Sig
+ Csound.Control.Evt: impulseE :: D -> Evt Unit
+ Csound.Control.Evt: loadbang :: Evt Unit
+ Csound.Control.Instr: schedHarps :: (Arg a, Sigs b) => D -> (a -> SE b) -> Evt [a] -> b
+ Csound.Control.Instr: schedHarpsBy :: (Arg a, Sigs b, Arg c) => D -> (a -> SE b) -> (c -> Evt [a]) -> c -> b
+ Csound.Control.Instr: schedUntils :: (Arg a, Sigs b) => (a -> SE b) -> Evt [a] -> Evt c -> b
+ Csound.Control.Instr: schedUntils_ :: Arg a => (a -> SE ()) -> Evt [a] -> Evt c -> SE ()
+ Csound.Control.Instr: scheds :: (Arg a, Sigs b) => (a -> SE b) -> Evt [(D, a)] -> b
+ Csound.Control.Instr: schedsBy :: (Arg a, Sigs b, Arg c) => (a -> SE b) -> (c -> Evt [(D, a)]) -> c -> b
+ Csound.Control.Instr: scheds_ :: Arg a => (a -> SE ()) -> Evt [(D, a)] -> SE ()
+ Csound.Control.Instr: trigs :: (Arg a, Sigs b) => (a -> SE b) -> Evt [(D, D, a)] -> b
+ Csound.Control.Instr: trigsBy :: (Arg a, Sigs b, Arg c) => (a -> SE b) -> (c -> Evt [(D, D, a)]) -> c -> b
+ Csound.Control.Instr: trigs_ :: Arg a => (a -> SE ()) -> Evt [(D, D, a)] -> SE ()
+ Csound.Control.Instr: withDurs :: D -> Evt [a] -> Evt [(D, a)]
+ Csound.IO: writeSnd :: RenderCsd a => String -> a -> IO ()
+ Csound.IO: writeSndBy :: RenderCsd a => Options -> String -> a -> IO ()
+ Csound.Options: setDur :: Sigs a => D -> a -> a
- Csound.Air: takeSnd :: Sigs a => Double -> a -> a
+ Csound.Air: takeSnd :: Sigs a => D -> a -> a
Files
- csound-expression.cabal +2/−2
- examples/DubBass.hs +1/−1
- examples/Gm.hs +1/−1
- examples/Tibetan.hs +2/−2
- src/Csound/Air.hs +71/−6
- src/Csound/Control/Evt.hs +20/−1
- src/Csound/Control/Instr.hs +83/−11
- src/Csound/IO.hs +13/−1
- src/Csound/Options.hs +1/−0
csound-expression.cabal view
@@ -1,5 +1,5 @@ Name: csound-expression-Version: 3.2.3+Version: 3.3.0 Cabal-Version: >= 1.6 License: BSD3 License-file: LICENSE@@ -107,7 +107,7 @@ Ghc-Options: -Wall Build-Depends: base >= 4, base < 5, process, data-default, Boolean >= 0.1.0,- csound-expression-typed >= 0.0.4, csound-expression-opcodes+ csound-expression-typed >= 0.0.5, csound-expression-opcodes Hs-Source-Dirs: src/ Exposed-Modules: Csound.Base
examples/DubBass.hs view
@@ -23,7 +23,7 @@ instr (coeff, cps) = return $ wobbly (sig spb) (sig coeff) (sig $ cpspch cps) -main = totem $ mix $ str (dspb * 2) $ sco instr $ melMap temp $ +main = dac $ mix $ str (dspb * 2) $ sco instr $ melMap temp $ [ (2, 6.04) , (1/3, 7.04) , (2, 6.04)
examples/Gm.hs view
@@ -2,7 +2,7 @@ -- | Accords in just intonation Gm with 14/8 beat. module Main where -import Csound+import Csound hiding (N) import Color(marimbaSynth)
examples/Tibetan.hs view
@@ -17,7 +17,7 @@ import System.Random -import Csound +import Csound hiding (N) import Color(blurp, blue) -- | A pure tibetan instrument with randomized parameters.@@ -204,7 +204,7 @@ main = do notes <- run acts- totem $ mix $ har + dac $ mix $ har [ introBlurp , del (introDur * 0.70) $ har [ globalEffect $ har
src/Csound/Air.hs view
@@ -46,8 +46,14 @@ readWav1, loopWav1, -- ** Utility- takeSnd, repeatSnd, lengthSnd, toMono, segments,+ lengthSnd, segments, + -- * Signal manipulation+ takeSnd, delaySnd, segmentSnd, repeatSnd, toMono,++ -- * Spectral functions+ toSpec, fromSpec, mapSpec, scaleSpec, addSpec,+ -- * Patterns mean, vibrate, randomPitch, chorus, resons, resonsBy, modes, dryWet, @@ -74,8 +80,8 @@ import Csound.Typed.Opcode hiding (display) import Csound.Typed.Gui import Csound.Control.Gui(funnyRadio)-import Csound.Control.Evt(metroE)-import Csound.Control.Instr(withDur)+import Csound.Control.Evt(metroE, eventList)+import Csound.Control.Instr(withDur, sched) import Csound.Tab(sine) @@ -332,66 +338,125 @@ mlp :: Sig -> Sig -> Sig -> Sig mlp cf q asig = moogladder asig cf q + ----------------------------------------------------------------------------- sound files playback+-- Signal manipulation -takeSnd :: Sigs a => Double -> a -> a-takeSnd dt asig = mix $ sco (const $ return $ asig) (CsdEventList dt [(0, dt, unit)])+-- | Takes only given amount (in seconds) from the signal (the rest is silence).+takeSnd :: Sigs a => D -> a -> a+takeSnd dt asig = trigs (const $ return asig) $ eventList [(0, dt, unit)] +-- | Delays signals by the given amount (in seconds).+delaySnd :: Sigs a => D -> a -> a+delaySnd dt asig = trigs (const $ return asig) $ eventList [(dt, -1, unit)]++-- | Delays a signal by the first argument and takes only second argument amount+-- of signal (everything is measured in seconds).+segmentSnd ::Sigs a => D -> D -> a -> a+segmentSnd del dur asig = trigs (const $ return asig) $ eventList [(del, dur, unit)]++-- | Repeats the signal with the given period. repeatSnd :: Sigs a => D -> a -> a repeatSnd dt asig = sched (const $ return asig) $ segments dt +--------------------------------------------------------------------------+-- sound files playback+ isMp3 :: String -> Bool isMp3 name = ".mp3" `isSuffixOf` name +-- | Converts stereosignal to mono with function mean. toMono :: (Sig, Sig) -> Sig toMono (a, b) = 0.5 * a + 0.5 * b +-- | Length in seconds of the sound file. lengthSnd :: String -> D lengthSnd fileName | isMp3 fileName = mp3len $ text fileName | otherwise = filelen $ text fileName +-- | Produces repeating segments with the given time in seconds. segments :: D -> Evt (D, Unit) segments dt = withDur dt $ metroE (sig $ recip dt) -- Stereo +-- | Reads stereo signal from the sound-file (wav or mp3 or aiff). readSnd :: String -> (Sig, Sig) readSnd fileName | isMp3 fileName = mp3in (text fileName) | otherwise = diskin2 (text fileName) 1 +-- | Reads stereo signal from the sound-file (wav or mp3 or aiff)+-- and loops it with the given period (in seconds). loopSndBy :: D -> String -> (Sig, Sig) loopSndBy dt fileName = repeatSnd dt $ readSnd fileName +-- | Reads stereo signal from the sound-file (wav or mp3 or aiff)+-- and loops it with the file length. loopSnd :: String -> (Sig, Sig) loopSnd fileName = loopSndBy (lengthSnd fileName) fileName +-- | Reads the wav file with the given speed (if speed is 1 it's a norma playback).+-- We can use negative speed to read file in reverse. readWav :: Sig -> String -> (Sig, Sig) readWav speed fileName = diskin2 (text fileName) speed +-- | Reads th wav file and loops over it. loopWav :: Sig -> String -> (Sig, Sig) loopWav speed fileName = flip withDs [0, 1] $ ar2 $ diskin2 (text fileName) speed -- Mono +-- | The mono variant of the function @readSnd@. readSnd1 :: String -> Sig readSnd1 fileName | isMp3 fileName = toMono $ readSnd fileName | otherwise = diskin2 (text fileName) 1 +-- | The mono variant of the function @loopSndBy@. loopSndBy1 :: D -> String -> Sig loopSndBy1 dt fileName = repeatSnd dt $ readSnd1 fileName +-- | The mono variant of the function @loopSnd@. loopSnd1 :: String -> Sig loopSnd1 fileName = loopSndBy1 (lengthSnd fileName) fileName +-- | The mono variant of the function @readWav@. readWav1 :: Sig -> String -> Sig readWav1 speed fileName = diskin2 (text fileName) speed +-- | The mono variant of the function @loopWav@. loopWav1 :: Sig -> String -> Sig loopWav1 speed fileName = flip withDs [0, 1] $ diskin2 (text fileName) speed++--------------------------------------------------------------------------+-- spectral functions++-- | Converts signal to spectrum.+toSpec :: Sig -> Spec+toSpec asig = pvsanal asig 1024 256 1024 1++-- | Converts spectrum to signal.+fromSpec :: Spec -> Sig+fromSpec = pvsynth++-- | Applies a transformation to the spectrum of the signal.+mapSpec :: (Spec -> Spec) -> Sig -> Sig+mapSpec f = fromSpec . f . toSpec++-- | Scales all frequencies. Usefull for transposition. +-- For example, we can transpose a signal by the given amount of semitones: +--+-- > scaleSpec (semitone 1) asig+scaleSpec :: Sig -> Sig -> Sig+scaleSpec k = mapSpec $ \x -> pvscale x k++-- | Adds given amount of Hz to all frequencies.+--+-- > addSpec hz asig+addSpec :: Sig -> Sig -> Sig+addSpec hz = mapSpec $ \x -> pvshift x hz 0 -------------------------------------------------------------------------- -- patterns
src/Csound/Control/Evt.hs view
@@ -9,9 +9,10 @@ Snap, snapshot, snaps, sync, syncBpm, -- * Opcodes- metroE, changedE, triggerE, + metroE, impulseE, changedE, triggerE, loadbang, impulse, -- * Higher-level event functions+ eventList, cycleE, iterateE, repeatE, appendE, mappendE, partitionE, splitToggle, oneOf, freqOf, freqAccum, randDs, randInts, randSkip, randSkipBy, @@ -30,6 +31,24 @@ -- | Behaves like 'Csound.Opcode.Basic.metro', but returns an event stream. metroE :: Sig -> Evt Unit metroE = sigToEvt . metro++-- | Fires a single event right now.+--+-- > loadbang = pulseE 0+loadbang :: Evt Unit+loadbang = impulseE 0++-- | Fires a single true value in the given time ahead.+impulse :: D -> Sig +impulse dt = mpulse 1 0 `withD` dt++-- | Fires a single event in the given time ahead.+impulseE :: D -> Evt Unit+impulseE = sigToEvt . impulse++-- | Makes an event stream from list of events.+eventList :: [(D, D, a)] -> Evt [(D, D, a)]+eventList es = fmap (const es) loadbang -- | Behaves like 'Csound.Opcode.Basic.changed', but returns an event stream. changedE :: [Sig] -> Evt Unit
src/Csound/Control/Instr.hs view
@@ -82,12 +82,20 @@ -- ** Reading midi note parameters cpsmidi, ampmidi, - -- * Evt + -- * Evt ++ -- ** Singlular trig, sched, schedHarp, schedUntil, schedToggle, trig_, sched_, schedUntil_, trigBy, schedBy, schedHarpBy, withDur, + -- ** Plural+ trigs, scheds, schedHarps, schedUntils,+ trigs_, scheds_, schedUntils_, + trigsBy, schedsBy, schedHarpsBy,+ withDurs,+ -- * Overload -- | Converters to make it easier a construction of the instruments. Outs(..), onArg, MidiInstr(..), AmpInstr(..), CpsInstr(..)@@ -105,13 +113,7 @@ ampCps :: Msg -> (D, D) ampCps msg = (ampmidi msg 1, cpsmidi msg) --- | Sets the same duration for all events. It's useful with the functions @sched@, @schedBy@, @sched_@. ------ > withDur dur events === fmap (\x -> (dur, x)) events-withDur :: D -> Evt a -> Evt (D, a)-withDur dt = fmap $ \x -> (dt, x) - -- | Mixes the scores and plays them in the loop. mixLoop :: (CsdSco f, Sigs a) => f (Mix a) -> a mixLoop a = sched instr $ withDur dur $ repeatE unit $ metroE $ sig $ 1 / dur@@ -133,8 +135,8 @@ -- | Invokes an instrument with first event stream and -- holds the note until the second event stream is active.-schedUntil :: (Arg a, Sigs b) => (a -> SE b) -> Evt a -> Evt c -> b-schedUntil instr onEvt offEvt = sched instr' $ withDur (-1) onEvt+schedUntils :: (Arg a, Sigs b) => (a -> SE b) -> Evt [a] -> Evt c -> b+schedUntils instr onEvt offEvt = scheds instr' $ withDurs (-1) onEvt where instr' x = do res <- instr x@@ -150,11 +152,81 @@ -- | Invokes an instrument with first event stream and -- holds the note until the second event stream is active.-schedUntil_ :: (Arg a) => (a -> SE ()) -> Evt a -> Evt c -> SE ()-schedUntil_ instr onEvt offEvt = sched_ instr' $ withDur (-1) onEvt+schedUntils_ :: (Arg a) => (a -> SE ()) -> Evt [a] -> Evt c -> SE ()+schedUntils_ instr onEvt offEvt = scheds_ instr' $ withDurs (-1) onEvt where instr' x = do res <- instr x runEvt offEvt $ const $ turnoff return res++-- | Sets the same duration for all events. It's useful with the functions @scheds@, @schedsBy@, @scheds_@. +withDurs :: D -> Evt [a] -> Evt [(D, a)]+withDurs dt = fmap $ fmap $ \x -> (dt, x) ++-------------------------------------------------------------------------+-------------------------------------------------------------------------+-- singular++-- | Sets the same duration for all events. It's useful with the functions @sched@, @schedBy@, @sched_@. +withDur :: D -> Evt a -> Evt (D, a)+withDur dt = fmap $ \x -> (dt, x) ++-------------------------------------------------------------------------+-- sinlgular case for event triggers++fromPlural :: (Evt [a] -> b) -> (Evt a -> b)+fromPlural f = f . fmap return++fromPluralBy :: ((c -> Evt [a]) -> c -> b) -> ((c -> Evt a) -> c -> b)+fromPluralBy f instr c = f (fmap return . instr) c++-- | Triggers an instrument with an event stream. The event stream+-- contains triples:+--+-- > (delay_after_event_is_fired, duration_of_the_event, argument_for_the_instrument)+trig :: (Arg a, Sigs b) => (a -> SE b) -> Evt (D, D, a) -> b+trig f = fromPlural $ trigs f++-- | It's like the function @trig@, but delay is set to zero.+sched :: (Arg a, Sigs b) => (a -> SE b) -> Evt (D, a) -> b+sched f = fromPlural $ scheds f++-- | An instrument is triggered with event stream and delay time is set to zero +-- (event fires immediately) and duration is set to inifinite time. The note is +-- held while the instrument is producing something. If the instrument is silent+-- for some seconds (specified in the first argument) then it's turned off.+schedHarp :: (Arg a, Sigs b) => D -> (a -> SE b) -> Evt a -> b+schedHarp dt f = fromPlural $ schedHarps dt f++-- | Invokes an instrument with first event stream and +-- holds the note until the second event stream is active.+schedUntil :: (Arg a, Sigs b) => (a -> SE b) -> Evt a -> Evt c -> b+schedUntil f eOn eOff = schedUntils f (fmap return eOn) eOff++-- | Triggers a procedure on the event stream.+trig_ :: Arg a => (a -> SE ()) -> Evt (D, D, a) -> SE ()+trig_ f = fromPlural $ trigs_ f++-- | Triggers a procedure on the event stream. A delay time is set to zero.+sched_ :: Arg a => (a -> SE ()) -> Evt (D, a) -> SE ()+sched_ f = fromPlural $ scheds_ f++-- | Invokes an instrument with first event stream and +-- holds the note until the second event stream is active.+schedUntil_ :: Arg a => (a -> SE ()) -> Evt a -> Evt c -> SE ()+schedUntil_ f eOn eOff = schedUntils_ f (fmap return eOn) eOff++-- | A closure to trigger an instrument inside the body of another instrument.+trigBy :: (Arg a, Sigs b, Arg c) => (a -> SE b) -> (c -> Evt (D, D, a)) -> c -> b+trigBy f = fromPluralBy $ trigsBy f++-- | A closure to trigger an instrument inside the body of another instrument.+schedBy :: (Arg a, Sigs b, Arg c) => (a -> SE b) -> (c -> Evt (D, a)) -> c -> b+schedBy f = fromPluralBy $ schedsBy f++-- | A closure to trigger an instrument inside the body of another instrument.+schedHarpBy :: (Arg a, Sigs b, Arg c) => D -> (a -> SE b) -> (c -> Evt a) -> c -> b+schedHarpBy dt f = fromPluralBy $ schedHarpsBy dt f+
src/Csound/IO.hs view
@@ -23,8 +23,9 @@ module Csound.IO ( -- * Rendering RenderCsd(..),- renderCsd, + renderCsd, writeCsd, writeCsdBy, + writeSnd, writeSndBy, -- * Playing the sound playCsd, playCsdBy, @@ -126,6 +127,17 @@ -- | Render Csound file with options and save it to the give file. writeCsdBy :: RenderCsd a => Options -> String -> a -> IO () writeCsdBy opt file a = writeFile file =<< renderCsdBy opt a++-- | Render Csound file and save result sound to the wav-file.+writeSnd :: RenderCsd a => String -> a -> IO ()+writeSnd = writeSndBy def++-- | Render Csound file with options and save result sound to the wav-file.+writeSndBy :: RenderCsd a => Options -> String -> a -> IO ()+writeSndBy opt file a = do+ writeCsdBy opt fileCsd a+ runWithUserInterrupt $ "csound -o " ++ file ++ " " ++ fileCsd+ where fileCsd = "tmp.csd" -- | Renders Csound file, saves it to the given file, renders with csound command and plays it with the given program. --
src/Csound/Options.hs view
@@ -2,6 +2,7 @@ Options(..), -- * Shortcuts+ setDur, setRates, setBufs, setGain, setJack, setOutput, setInput, setDac, setAdc, setDacBy, setAdcBy, setThru,