synthesizer-llvm-0.5: src/Synthesizer/LLVM/Server/CausalPacked/Speech.hs
{-# LANGUAGE NoImplicitPrelude #-}
module Synthesizer.LLVM.Server.CausalPacked.Speech where
import Synthesizer.LLVM.Server.CausalPacked.Instrument
(Control, Frequency, frequencyControl, )
import Synthesizer.LLVM.Server.CommonPacked (Vector, VectorValue, )
import Synthesizer.LLVM.Server.Common (SampleRate, Real, frequency, )
import qualified Synthesizer.MIDI.CausalIO.Process as MIO
import qualified Synthesizer.CausalIO.Gate as Gate
import qualified Synthesizer.CausalIO.Process as PIO
import Synthesizer.LLVM.CausalParameterized.Process (($<), )
import Synthesizer.LLVM.CausalParameterized.FunctionalPlug (($&), (&|&), )
import qualified Synthesizer.LLVM.Frame.Stereo as Stereo
import qualified Synthesizer.LLVM.Frame.SerialVector as Serial
import qualified Synthesizer.LLVM.CausalParameterized.FunctionalPlug as FP
import qualified Synthesizer.LLVM.CausalParameterized.ControlledPacked as CtrlPS
import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP
import qualified Synthesizer.LLVM.Parameterized.Signal as SigP
import qualified Synthesizer.Zip as Zip
import qualified Sound.MIDI.Message.Channel.Voice as VoiceMsg
import qualified Synthesizer.PiecewiseConstant.Signal as PC
import qualified Synthesizer.Plain.Filter.Recursive.Universal as UniFilter
import Synthesizer.Plain.Filter.Recursive (Pole(Pole))
import qualified Data.StorableVector as SV
import qualified LLVM.Core as LLVM
import Control.Arrow (Arrow, arr, (^<<), )
import Control.Category ((.), )
import Control.Applicative (liftA, liftA3, )
import NumericPrelude.Numeric
import NumericPrelude.Base hiding (id, (.), )
{-
stimmhaft
a, e, i, o, u, ä, ö, ü
l, m, n, ng
Diphtong
ai, oi, au, ui, ei
stimmlos/Zischlaute
f, h, w, s, sch, th, ch (weich), ch (kochen), r
explosiv
b, p, g, k, d, t
-}
{-
Formanten:
a - 700 Hz
i - 400 Hz, 2200 Hz
o - 600 Hz, 3000 Hz
f - white noise
sch - highpass cutoff 1500 Hz
-}
phoneme ::
IO (SampleRate Real -> VoiceMsg.Pitch ->
PIO.T (Zip.T MIO.GateChunk (SV.Vector (Stereo.T Vector)))
(SV.Vector (Stereo.T Vector)))
phoneme =
liftA
(\osc sr p ->
case formants p of
Nothing -> arr $ const SV.empty
Just fs ->
osc (sr, fs)
.
Gate.shorten)
(CausalP.processIO
(CausalP.stereoFromMono
(let lowpass q f =
UniFilter.bandpass
^<<
CtrlPS.process
$<
SigP.constant
(UniFilter.parameter . Pole q ^<< frequency f)
in lowpass 100 fst + lowpass 20 snd)))
formants :: VoiceMsg.Pitch -> Maybe (Real, Real)
formants p =
case VoiceMsg.fromPitch p - 36 of
00 -> Just ( 320, 800) -- u
02 -> Just ( 500, 1000) -- o
04 -> Just (1000, 1400) -- a
05 -> Just (1500, 500) -- oe
07 -> Just (1650, 320) -- ue
09 -> Just (1800, 700) -- ae
11 -> Just (2300, 500) -- e
12 -> Just (3200, 320) -- i
_ -> Nothing
type Input a = FP.Input (SampleRate Real) a
plugUniFilterParameter ::
Input a (Control Real) ->
Input a (Control Frequency) ->
FP.T (SampleRate Real) pl a (UniFilter.Parameter (LLVM.Value Real))
plugUniFilterParameter reson freq =
FP.plug $
liftA3
(\resonChunk freqChunk sr ->
PC.zipWith
(\ r f -> UniFilter.parameter $ Pole r f)
resonChunk $ frequencyControl sr freqChunk)
reson freq FP.askParameter
type FormantControl =
Zip.T (Control Real)
(Zip.T (Control Real) (Control Frequency))
singleFormant ::
(Input inp (Control Real),
(Input inp (Control Real), Input inp (Control Frequency))) ->
Input inp (SV.Vector (Stereo.T Vector)) ->
FP.T (SampleRate Real) pl inp (Stereo.T VectorValue)
singleFormant (amp, (reson, freq)) x =
CausalP.envelopeStereo $&
(CausalP.mapSimple Serial.upsample $& FP.plug amp)
&|&
(CausalP.stereoFromMonoControlled
(UniFilter.bandpass ^<< CtrlPS.process) $&
plugUniFilterParameter reson freq
&|&
FP.plug x)
filterFormant ::
IO (SampleRate Real ->
PIO.T
(Zip.T FormantControl (SV.Vector (Stereo.T Vector)))
(SV.Vector (Stereo.T Vector)))
filterFormant =
liftA
(\filt sr -> filt sr (sr, ()))
(FP.withArgs $ \(fmt, x) -> singleFormant fmt x)
filterFormants ::
IO (SampleRate Real ->
PIO.T (Zip.T
(Zip.T FormantControl
(Zip.T FormantControl
(Zip.T FormantControl
(Zip.T FormantControl FormantControl))))
(SV.Vector (Stereo.T Vector)))
(SV.Vector (Stereo.T Vector)))
filterFormants =
liftA
(\filt sr -> filt sr (sr, ()))
(FP.withArgs $ \((fmt0, (fmt1, (fmt2, (fmt3, fmt4)))), x) ->
foldl1 (+) $ map (flip singleFormant x) [fmt0, fmt1, fmt2, fmt3, fmt4])