hsc3-auditor-0.14: Sound/SC3/Auditor.hs
-- | Auditor functions common to all sample libraries.
module Sound.SC3.Auditor where
import Data.List {- base -}
import Sound.OSC {- hosc -}
import Sound.SC3 {- hsc3 -}
-- | Amplitude
type Amplitude = Double
-- | Index
type Index = Int
-- | Number of channels
type NC = Int
type Note = (Index,Amplitude)
-- | Chord
type Chord = [Note]
-- | Duration
type Duration = Double
-- | Start time
type Start_Time = Double
-- | 'Start_Time' and 'Chord'.
type P = (Start_Time,Chord)
-- | Set of 'P'.
type PP = [P]
-- | Function to generate the set of 'OSC' commands required to load
-- the set of 'Index'ed files.
type Sample_Loader = [Index] -> [Message]
to_p :: (a -> Index,a -> Amplitude) -> (Start_Time,[a]) -> P
to_p (i,a) (t,x) =
let f e = (i e,a e)
in (t,map f x)
note_index :: Note -> Index
note_index = fst
note_amplitude :: Note -> Amplitude
note_amplitude = snd
chord_indices :: Chord -> [Index]
chord_indices = map fst
p_start_time :: P -> Start_Time
p_start_time = fst
p_chord :: P -> Chord
p_chord = snd
pp_start_times :: PP -> [Start_Time]
pp_start_times = map p_start_time
pp_chords :: PP -> [Chord]
pp_chords = map p_chord
-- | Start time of last 'P' at 'PP'.
pp_duration :: PP -> Duration
pp_duration = p_start_time . last
-- | The set of 'Index' referenced to by 'PP'.
pp_indices :: PP -> [Index]
pp_indices = nub . sort . concatMap (chord_indices . p_chord)
chd_osc :: Chord -> [Message]
chd_osc =
let f n = s_new "s" (-1) AddToTail 1 [("b",fromIntegral (note_index n))
,("a",note_amplitude n)]
in map f
p_osc :: P -> Bundle
p_osc (t,c) = bundle t (chd_osc c)
-- | Generate set of 'OSC' given 'NC', 'Sample_Loader' and 'PP'.
pp_nrt :: NC -> Sample_Loader -> PP -> NRT
pp_nrt nc ld pp =
let b = bundle
ix = pp_indices pp
group_zero = g_new [(1, AddToTail, 0)]
sc_init = let h = b 0 [group_zero,instr_osc nc]
in h : map (b 0 . return) (ld ix)
sc_end = [b (pp_duration pp + 12) [g_freeAll [1]]]
in NRT (sc_init ++ map p_osc pp ++ sc_end)
-- | Variant of 'pp_osc' that writes @NRT@ score to named file using
-- 'writeNRT'.
pp_nrt_write :: FilePath -> NC -> Sample_Loader -> PP -> IO ()
pp_nrt_write nm nc ld = writeNRT nm . pp_nrt nc ld
-- * Instrument
instr_osc :: NC -> Message
instr_osc nc = d_recv (synthdef "s" (smplr nc))
smplr :: NC -> UGen
smplr nc =
let b = control KR "b" 0 -- buffer
a = control KR "a" 1 -- amplitude
o = control KR "o" 0 -- output channel
b_d = bufDur KR b
b_r = bufRateScale KR b
c = envCoord [(0,1),(1,1)] b_d 1 EnvLin
e = envGen KR 1 a 0 1 RemoveSynth c
in out o (playBuf nc AR b b_r 1 0 NoLoop DoNothing * e)
-- * Audition
-- | Load sample playback instrument to @scsynth@ at 'Transport'.
au_load_instr :: Transport m => NC -> m ()
au_load_instr nc = do
_ <- async (instr_osc nc)
return ()
au_chd :: Transport m => (Chord,Duration) -> m ()
au_chd (c,d) = do
--putStrLn ("au_chd: " ++ show d)
mapM_ send (chd_osc c)
pauseThread d
pp_st_to_dur :: PP -> [(Chord,Duration)]
pp_st_to_dur pp =
let (t,x) = (pp_start_times pp,pp_chords pp)
in zip x (zipWith (-) (drop 1 t) t ++ [0])
-- | Audition 'PP' at @scsynth@ instance at 'Transport'.
pp_audition :: (Transport m) => PP -> m ()
pp_audition pp = mapM_ au_chd (pp_st_to_dur pp)