-- | Functions to generate a click track from a metric structure.
module Sound.SC3.Auditor.CT where

import Data.List {- base -}

import qualified Music.Theory.Duration.CT as T {- hmt -}
import qualified Music.Theory.Time.Seq as T {- hmt -}

import Sound.SC3 {- hsc3 -}

import qualified Sound.SC3.Auditor as A {- hsc3-auditor -}

type CT_SF = (FilePath,A.Index,A.Amplitude)
type CT_Node_SF = T.CT_Node -> [CT_SF]

ct_note :: CT_SF -> A.Note
ct_note (_,i,j) = A.Note i j

ct_realise :: CT_Node_SF -> T.Dseq Double T.CT_Node -> T.Tseq Double [CT_SF]
ct_realise ix_fn = T.tseq_map ix_fn . T.dseq_to_tseq 0 T.CT_End

ct_normalise_sf :: [CT_SF] -> [(A.Index,FilePath)]
ct_normalise_sf = nub . sort . map (\(fn,ix,_) -> (ix,fn))

ct_sf_seq :: [(A.Index,FilePath)] -> [FilePath]
ct_sf_seq sq =
    let (ix,fn) = unzip sq
    in if ix `isPrefixOf` [0..]
       then fn
       else error "ct_sf_seq"

ct_auditor :: CT_Node_SF -> T.Dseq Double T.CT_Node -> ([FilePath],A.PP)
ct_auditor ix_fn sq =
    let sf = ct_realise ix_fn sq
        pp = T.tseq_map (map ct_note) sf
        fn_set = ct_sf_seq (ct_normalise_sf (concatMap snd sf))
    in (fn_set,pp)

ct_ldr :: [FilePath] -> A.Sample_Loader
ct_ldr = A.au_loader [0]

ct_sc :: CT_Node_SF -> T.CT -> NRT
ct_sc ix_fn ct =
    let (rq,n) = T.ct_count ct
        pre = T.ct_leadin (rq,fromRational (T.ct_tempo0_err ct),n)
        (fn_set,pp) = ct_auditor ix_fn (pre ++ T.ct_dseq ct)
    in A.pp_nrt 1 (Just (ct_ldr fn_set)) pp

ct_render :: FilePath -> FilePath -> CT_Node_SF -> T.CT -> IO ()
ct_render osc_fn wav_fn ix_fn =
    nrt_render_plain (osc_fn,wav_fn,1,48000,PcmInt16) .
    ct_sc ix_fn