-- | -- Module : Composition.Sound.Functional -- Copyright : (c) OleksandrZhabenko 2020-2021 -- License : MIT -- Stability : Experimental -- Maintainer : olexandr543@yahoo.com -- -- Helps to create experimental music from a file (or its part) and a Ukrainian text. -- It can also generate a timbre for the notes. Uses SoX inside. {-# LANGUAGE BangPatterns #-} {-# OPTIONS_GHC -threaded #-} module Composition.Sound.Functional ( -- * Use additional function as a parameter overSoXSynth2FDN , overSoXSynth2FDN_B -- ** Just simple function application -- *** With additional filtering -- * Use additional function and Ukrainian texts and generates melody , overSoXSynthGen2FDN , overSoXSynthGen2FDN_B -- * 1G generalized functions with dB volume overtones adjustments , overSoXSynth2FDN1G , overSoXSynth2FDN_B1G , overSoXSynth2FDN_S1G , overSoXSynth2FDN_Sf1G , overSoXSynth2FDN_Sf31G -- * 2G generalized functions with additional sound quality specifying , overSoXSynth2FDN2G , overSoXSynth2FDN_B2G , overSoXSynth2FDN_S2G , overSoXSynth2FDN_Sf2G , overSoXSynth2FDN_Sf32G -- ** 2G generalized functions for melody producing , overSoXSynthGen2FDN_SG2G , overSoXSynthGen2FDN_Sf3G2G -- * Generalized functions with several functional parameters , overSoXSynthGen2FDN_SG , overSoXSynthGen2FDN_Sf3G -- ** 1G generalized function with db volume overtones adjustments and several functional parameters , soundGenF31G -- * New functions for the version 0.36.0.0 , overSoXSynthGen2FDN4G , overSoXSynthGen2FDN_SG4G , overSoXSynthGen2FDN_SG4GS -- * New generalized 5G functions that works with Intervals , overSoXSynth2FDN5G , overSoXSynth2FDN_B5G , overSoXSynth2FDN_S5G , overSoXSynth2FDN_Sf35G -- * New generalized 6G functions that works with Strengths , overSoXSynth2FDN6G , overSoXSynth2FDN6GS , overSoXSynth2FDN_B6G , overSoXSynth2FDN_B6GS , overSoXSynth2FDN_S6G , overSoXSynth2FDN_S6GS , overSoXSynth2FDN_Sf36G , overSoXSynth2FDN_Sf36GS , overSoXSynthGen2FDN_SG6G , overSoXSynthGen2FDN_SG6GS , overSoXSynthGen2FDN_SG6GSu -- * Auxiliar functions , help11 , help12 , help13 ) where import Numeric import Data.List (nubBy) import Data.Maybe (isNothing,fromJust,fromMaybe,maybe) import GHC.Arr import qualified Data.Foldable as F import System.Process import EndOfExe import System.Directory import Melodics.ByteString.Ukrainian.Arr (convertToProperUkrainianS) import Composition.Sound.IntermediateF import Composition.Sound.Functional.Basics import Composition.Sound.Functional.Params import Composition.Sound.DIS5G6G (intervalsFromStringG,str2Durations,str2Vol1,str2Volume) -- | Similar to 'overSoXSynth2DN' but instead of 'overTones' function, it uses volatile function @f::Float -> [(Float, Float)]@ with -- somewhat sophisticated mechanism to normalize the resulting list elements @(Float, Float)@. The last one is an experimental feature, so -- it is your responsibility to provide a function so that it does not lead to clipping. In such a case, the result of application of the -- 'convertToProperUkrainianS' to the 'String' parameter must not be []. 'Int' argument is an index of the element to be taken from -- the 'intervalsFromString' applied to the 'String' argument. To obtain compatible with versions prior to 0.20.0.0 behaviour, use for the 'Int' 0. -- -- Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function. -- But for a lot of functions this works well. -- -- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN'. overSoXSynth2FDN :: (Float -> OvertonesO) -> (Float, Float) -> Int -> String -> IO () overSoXSynth2FDN f (x, y) j zs = overSoXSynth2FDN1G f (x, y) j zs ((\rs -> listArray (0, l - 1) rs) . replicate l $ 0.0) where !l = length . f . closestNote $ if x /= 0.0 then abs x else unsafeAt notes 0 {-# INLINE overSoXSynth2FDN #-} -- | 'Array' 'Int' of 'Float' is a vector of dB volume adjustments for the corresponding harmonices (overtones). overSoXSynth2FDN1G :: (Float -> OvertonesO) -> (Float, Float) -> Int -> String -> Array Int Float -> IO () overSoXSynth2FDN1G f (x, y) j zs vdB = overSoXSynth2FDN2G f (x, y) j zs vdB [] {-# INLINE overSoXSynth2FDN1G #-} -- | Similar to 'overSoXSynth2FDN1G', but additionally allows to specify by the second 'String' argument a quality changes to the generated files -- (please, see 'soxBasicParams'). Since version 0.36.0.0 the function supports generation of the pauses. overSoXSynth2FDN2G :: (Float -> OvertonesO) -> (Float, Float) -> Int -> String -> Array Int Float -> String -> IO () overSoXSynth2FDN2G f (x, y) j zs vdB ys | null . convertToProperUkrainianS $ zs = overSoXSynthG f x | otherwise = do let note0 = closestNote (if x /= 0.0 then abs x else unsafeAt notes 0) l0 = length zs note1 = dNote (unsafeAt (intervalsFromString zs) (abs (j `rem` l0))) note0 help11 f (x, y) j vdB ys l0 note1 note0 -- | Similar to 'overSoXSynth2FDN2G', but additionally allows to specify by the 'Intervals' argument to specify your own intervals. For more information, -- please, refer to 'intervalsFromStringG'. overSoXSynth2FDN5G :: (Float -> OvertonesO) -> (Float, Float) -> Int -> Intervals -> Array Int Float -> String -> IO () overSoXSynth2FDN5G f (x, y) j v5 vdB ys | F.null v5 = overSoXSynthG f x | otherwise = do let note0 = closestNote (if x /= 0.0 then abs x else unsafeAt notes 0) l0 = numElements v5 note1 = dNote (unsafeAt v5 (abs (j `rem` l0))) note0 help11 f (x, y) j vdB ys l0 note1 note0 help11 :: (Float -> OvertonesO) -> (Float, Float) -> Int -> Array Int Float -> String -> Int -> Maybe Float -> Float -> IO () help11 f (x, y) j vdB ys l0 note1 note0 = do let g0 = nubBy (\(!x1,_) (!x2,_) -> x1 == x2) . map (\(noteX, !amplX) -> if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX, abs (amplX - (fromIntegral . truncate $ amplX)))) . f g k = takeWhile (\(!w,!z) -> w <= unsafeAt notes 107 && abs z > 0.001) . map (\(i, (_,!z0)) -> (fromIntegral (i + 1) * (fst . head . g0 $ k), z0)) . zip [0..] . g0 $ k v0 = g note0 v1 = maybe [] g note1 ts = showFFloat (Just 4) (abs y) "" overSoXSynthHelp = mapM_ (\(i, (noteN, !amplN)) -> readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat Nothing noteN "", "vol", if y > 0.0 then showFFloat Nothing amplN "" else "0"]) "") . zip [0..] overSoXSynthHelp2 vec vdB = mapM_ (\(i, (noteN, !amplN)) -> readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) (adjust_dbVol ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat Nothing noteN "","vol", if y > 0.0 then showFFloat Nothing amplN "" else "0"] (unsafeAt vdB i))) "") . zip [0..] $ vec _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts, "sine", showFFloat Nothing note0 "","vol", if y > 0.0 then "1.0" else "0"]) "" if isNothing note1 then overSoXSynthHelp v0 else do _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts, "sine", showFFloat Nothing (fromJust note1) "","vol", if y > 0.0 then "1.0" else "0"]) "" overSoXSynthHelp v0 overSoXSynthHelp2 v1 vdB if null ys then mixTest else mixTest2G ys {-# INLINE help11 #-} -- | Generalized variant of the 'overSoXSynth2FDN5G' with afterwards 'apply6Gf' usage. overSoXSynth2FDN6G :: (Float -> OvertonesO) -> (Float, Float) -> Int -> Intervals -> Array Int Float -> String -> Float -> IO () overSoXSynth2FDN6G f (x, y) j v5 vdB ys vol | F.null v5 = overSoXSynthG f x | otherwise = do let note0 = closestNote (if x /= 0.0 then abs x else unsafeAt notes 0) l0 = numElements v5 note1 = dNote (unsafeAt v5 (abs (j `rem` l0))) note0 help11 f (x, y) j vdB ys l0 note1 note0 if y > 0.0 then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr "" -- | A variant of the 'overSoXSynth2FDN6G' where volume adjustment is obtained from a Ukrainian text. overSoXSynth2FDN6GS :: (Float -> OvertonesO) -> (Float, Float) -> Int -> Intervals -> String -> Array Int Float -> String -> String -> IO () overSoXSynth2FDN6GS f (x, y) j v5 xs vdB ys xxs | null . convertToProperUkrainianS $ xxs = putStrLn "Composition.Sound.Functional.overSoXSynth2FDN6GS: You provided no information to obtain volume adjustment! " | otherwise = overSoXSynth2FDN6G f (x, y) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs) {-# INLINE overSoXSynth2FDN6GS #-} -- | Uses additional 'Int' parameters. The first one is a number of enka (see 'nkyT'). The second one defines, to which n-th elements set -- (see 'nkyT') belongs the obtained higher notes in the intervals. To obtain reasonable results, please, use for the first one 2, 3, 4, 6, 9, or 12. -- The first 'String' parameter is used to produce durations of the notes. The second one is used to define intervals. A 'Float' parameter is a -- basic sound duration, it defines tempo of the melody in general. overSoXSynthGen2FDN :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Float -> String -> String -> IO () overSoXSynthGen2FDN file m ku f y zs wws = overSoXSynthGen2FDN_SG file m ku f y zs wws overSoXSynth2FDN {-# INLINE overSoXSynthGen2FDN #-} -- | Generalized variant of the 'overSoXSynthGen2FDN' with your own specified 'Durations' for the sounds and pauses. -- Instead of using a Ukrainian text to specify a durations for the sounds (and a rhythm -- respectively) you provide your own rhythm as 'Durations'. Positive values correspond to durations of the sounds generated -- and negative values -- to durations of the pauses respectively. overSoXSynthGen2FDN4G :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Durations -> String -> IO () overSoXSynthGen2FDN4G file m ku f v2 wws = overSoXSynthGen2FDN_SG4G file m ku f v2 wws overSoXSynth2FDN {-# INLINE overSoXSynthGen2FDN4G #-} -- | Similar to 'overSoXSynth2DN' but instead of 'overTones' function, it uses volatile function @f::Float -> [(Float, Float)]@ with -- somewhat sophisticated mechanism to normalize the resulting list elements @(Float, Float)@. The last one is experimental feature, so -- it is your responsibility to provide a function so that it does not lead to clipping. In such a case, the result of application of the -- 'convertToProperUkrainianS' to the 'String' parameter must not be []. The function also tries to perform filtering to avoid possible beating. -- The third 'Float' parameter in the tuple is used as a limit for frequencies difference in Hz to be filtered out from the resulting sound. It is -- considered to be from the range @[0.1..10.0]@. An 'Int' parameter is used to define the needed interval. To obtain compatible with versions prior -- to 0.20.0.0 behaviour, use for the 'Int' 0. -- -- Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function. -- But for a lot of functions this works well. -- -- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_B'. overSoXSynth2FDN_B :: (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> String -> IO () overSoXSynth2FDN_B f (x, y, limB) j zs = overSoXSynth2FDN_B1G f (x, y, limB) j zs ((\rs -> listArray (0,l - 1) rs) . replicate l $ 0.0) where !l = length . f . closestNote $ if x /= 0.0 then abs x else unsafeAt notes 0 {-# INLINE overSoXSynth2FDN_B #-} -- | 'Array' 'Int' of 'Float' is a vector of dB volume adjustments for the corresponding harmonices (overtones). overSoXSynth2FDN_B1G :: (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> String -> Array Int Float -> IO () overSoXSynth2FDN_B1G f (x, y, limB) j zs vdB = overSoXSynth2FDN_B2G f (x, y, limB) j zs vdB [] {-# INLINE overSoXSynth2FDN_B1G #-} -- | Generalized version of the 'overSoXSynth2FDN_B1G' with a possibility to specify sound quality parameters using additional second 'String' -- argument. For more information, please, refer to 'soxBasicParams'. overSoXSynth2FDN_B2G :: (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> String -> Array Int Float -> String -> IO () overSoXSynth2FDN_B2G f (x, y, limB) j zs vdB ys | null . convertToProperUkrainianS $ zs = overSoXSynthG f x | otherwise = do let l0 = length zs note0 = closestNote (if x /= 0.0 then abs x else unsafeAt notes 0) note1 = dNote (unsafeAt (intervalsFromString zs) (abs (j `rem` l0))) note0 help12 f (x, y, limB) j vdB ys l0 note1 note0 -- | Generalized version of the 'overSoXSynth2FDN_B2G' with a possibility to specify your own 'Intervals'. For more information, please, -- refer to 'intervalsFromStringG'. overSoXSynth2FDN_B5G :: (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> Intervals -> Array Int Float -> String -> IO () overSoXSynth2FDN_B5G f (x, y, limB) j v5 vdB ys | F.null v5 = overSoXSynthG f x | otherwise = do let l0 = numElements v5 note0 = closestNote (if x /= 0.0 then abs x else unsafeAt notes 0) note1 = dNote (unsafeAt v5 (abs (j `rem` l0))) note0 help12 f (x, y, limB) j vdB ys l0 note1 note0 help12 :: (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> Array Int Float -> String -> Int -> Maybe Float -> Float -> IO () help12 f (x, y, limB) j vdB ys l0 note1 note0 = do let limA0 = abs ((limB / 10) - (fromIntegral . truncate $ (limB / 10))) * 10 limA = if limA0 < 0.1 then 0.1 else limA0 g0 = nubBy (\(!x1,_) (!x2,_) -> abs (x1 - x2) < limA) . map (\(noteX, !amplX) -> if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX, abs (amplX - (fromIntegral . truncate $ amplX)))) . f v0 = takeWhile (\(!w,!z) -> w <= unsafeAt notes 107 && abs z > 0.001) . map (\(i, (_,!z0)) -> (fromIntegral (i + 1) * (fst . head . g0 $ note0), z0)) . zip [0..] . g0 $ note0 v1 = if isNothing note1 then [] else takeWhile (\(!w,!z) -> w <= unsafeAt notes 107 && abs z > 0.001) . map (\(i, (_,!z0)) -> (fromIntegral (i + 1) * (fst . head . g0 . fromJust $ note1), z0)) . zip [0..] . g0 . fromJust $ note1 ts = showFFloat (Just 4) (abs y) "" overSoXSynthHelp = mapM_ (\(i, (noteN, !amplN)) -> readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat Nothing noteN "", "vol", if y > 0.0 then showFFloat Nothing amplN "" else "0"]) "") . zip [0..] overSoXSynthHelp2 vec vdB = mapM_ (\(i, (noteN, !amplN)) -> readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ((if F.null vdB then id else (\wwws -> adjust_dbVol wwws (unsafeAt vdB i))) ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat Nothing noteN "", "vol", if y > 0.0 then showFFloat Nothing amplN "" else "0"])) "") . zip [0..] $ vec _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine", showFFloat Nothing note0 "","vol", if y > 0.0 then "1.0" else "0"]) "" if isNothing note1 then overSoXSynthHelp v0 else do _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine", showFFloat Nothing (fromJust note1) "","vol", if y > 0.0 then "1.0" else "0"]) "" overSoXSynthHelp v0 overSoXSynthHelp2 v1 vdB if null ys then mixTest else mixTest2G ys {-# INLINE help12 #-} -- | Generalized variant of the 'overSoXSynth2FDN_B5G' with afterwards 'apply6G' usage. overSoXSynth2FDN_B6G :: (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> Intervals -> Array Int Float -> String -> Float -> IO () overSoXSynth2FDN_B6G f (x, y, limB) j v5 vdB ys vol | F.null v5 = overSoXSynthG f x | otherwise = do let l0 = numElements v5 note0 = closestNote (if x /= 0.0 then abs x else unsafeAt notes 0) note1 = dNote (unsafeAt v5 (abs (j `rem` l0))) note0 help12 f (x, y, limB) j vdB ys l0 note1 note0 if y > 0.0 then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr "" -- The line which differs for this function and the 'overSoXSynth2FDN_B5G'. -- | A variant of the 'overSoXSynth2FDN_B6G' where volume adjustment is obtained from a Ukrainian text. overSoXSynth2FDN_B6GS :: (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> Intervals -> String -> Array Int Float -> String -> String -> IO () overSoXSynth2FDN_B6GS f (x, y, limB) j v5 xs vdB ys xxs | null . convertToProperUkrainianS $ xxs = putStrLn "Composition.Sound.Functional.overSoXSynth2FDN_B6GS: You provided no information to obtain volume adjustment! " | otherwise = overSoXSynth2FDN_B6G f (x, y, limB) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs) {-# INLINE overSoXSynth2FDN_B6GS #-} -- | Uses additional 'Int' parameters. The first one is a number of enka (see 'nkyT'). The second one defines, to which n-th elements set -- (see 'nkyT') belongs the obtained higher notes in the intervals. To obtain reasonable results, please, use for the first one 2, 3, 4, 6, 9, or 12. -- The first 'String' parameter is used to produce durations of the notes. The second one is used to define intervals. The first 'Float' parameter is a -- basic sound duration, it defines tempo of the melody in general. The second one is a limit for frequencies difference in Hz to be filtered out from the -- resulting sound. It is considered to be from the range @[0.1..10.0]@. overSoXSynthGen2FDN_B :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Float -> Float -> String -> String -> IO () overSoXSynthGen2FDN_B file m ku f y limB zs wws = overSoXSynthGen2FDN_Sf3G file m ku f y limB zs wws overSoXSynth2FDN_B {-# INLINE overSoXSynthGen2FDN_B #-} -- | Similar to 'overSoXSynth2FDN' with the additional volume adjustment in dB for overtones given by 'Array' 'Int' of 'Float', but it does not make any normalizing transformations. To be used properly, it is needed -- that every second element in the tuple in the list argument must be in the range [-1.0..1.0] and every first element must be in between -- 16.351597831287414 and 7902.132820097988 (Hz). An 'Int' parameter is used to define an interval. To obtain compatible with versions prior to -- 0.20.0.0 behaviour, use for the 'Int' 0. -- -- Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function. -- But for a lot of functions this works well. -- -- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_S'. overSoXSynth2FDN_S1G :: (Float -> OvertonesO) -> (Float, Float) -> Int -> String -> Array Int Float -> IO () overSoXSynth2FDN_S1G f (x, y) j zs vdB = overSoXSynth2FDN_S2G f (x, y) j zs vdB [] {-# INLINE overSoXSynth2FDN_S1G #-} -- | Generalized version of the 'overSoXSynth2FDN_S1G' with a possibility to specify sound quality parameters using the second 'String' argument. -- For more information, please, refer to 'soxBasicParams'. overSoXSynth2FDN_S2G :: (Float -> OvertonesO) -> (Float, Float) -> Int -> String -> Array Int Float -> String -> IO () overSoXSynth2FDN_S2G f (x, y) j zs vdB ys | null . convertToProperUkrainianS $ zs = overSoXSynthG f x | otherwise = do let note0 = closestNote (if x /= 0.0 then abs x else unsafeAt notes 0) l0 = length zs note1 = dNote (unsafeAt (intervalsFromString zs) (abs (j `rem` l0))) note0 help13 f (x, y) j vdB ys l0 note1 note0 help13 :: (Float -> OvertonesO) -> (Float, Float) -> Int -> Array Int Float -> String -> Int -> Maybe Float -> Float -> IO () help13 f (x, y) j vdB ys l0 note1 note0 = do let v0 = f note0 v1 = maybe [] f note1 ts = showFFloat (Just 4) (abs y) "" _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine", showFFloat Nothing note0 "","vol", if y > 0.0 then "1.0" else "0"]) "" if isNothing note1 then partialTest_k2G v0 0 ts vdB ys else do _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine", showFFloat Nothing (fromJust note1) "","vol", if y > 0.0 then "1.0" else "0"]) "" partialTest_k2G v0 0 ts vdB ys partialTest_k2G v1 1 ts vdB ys if null ys then mixTest else mixTest2G ys -- | Generalized version of the 'overSoXSynth2FDN_S2G' where you specify your own 'Intervals'. For more information, please, refer -- to 'intervalsFromStringG'. overSoXSynth2FDN_S5G :: (Float -> OvertonesO) -> (Float, Float) -> Int -> Intervals -> Array Int Float -> String -> IO () overSoXSynth2FDN_S5G f (x, y) j v5 vdB ys | F.null v5 = overSoXSynthG f x | otherwise = do let note0 = closestNote (if x /= 0.0 then abs x else unsafeAt notes 0) l0 = numElements v5 note1 = dNote (unsafeAt v5 (abs (j `rem` l0))) note0 help13 f (x, y) j vdB ys l0 note1 note0 -- | Generalized variant of the 'overSoXSynth2FDN_S5G' with afterwards 'apply6G' usage. Arguments for the latter is the three last function arguments. overSoXSynth2FDN_S6G :: (Float -> OvertonesO) -> (Float, Float) -> Int -> Intervals -> Array Int Float -> String -> Float -> IO () overSoXSynth2FDN_S6G f (x, y) j v5 vdB ys vol | F.null v5 = overSoXSynthG f x | otherwise = do let note0 = closestNote (if x /= 0.0 then abs x else unsafeAt notes 0) l0 = numElements v5 note1 = dNote (unsafeAt v5 (abs (j `rem` l0))) note0 help13 f (x, y) j vdB ys l0 note1 note0 if y > 0.0 then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr "" -- | A variant of the 'overSoXSynth2FDN_S6G' where volume adjustment is obtained from a Ukrainian text. overSoXSynth2FDN_S6GS :: (Float -> OvertonesO) -> (Float, Float) -> Int -> Intervals -> String -> Array Int Float -> String -> String -> IO () overSoXSynth2FDN_S6GS f (x, y) j v5 xs vdB ys xxs | null . convertToProperUkrainianS $ xxs = putStrLn "Composition.Sound.Functional.overSoXSynth2FDN_S6GS: You provided no information to obtain volume adjustment! " | otherwise = overSoXSynth2FDN_S6G f (x, y) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs) {-# INLINE overSoXSynth2FDN_S6GS #-} -- | Similar to 'overSoXSynthGen2FDN', but instead of 'overSoXSynth2FDN' uses 'overSoXSynth2FDN_S' function. Note that the first 'Int' arguments are used by 'liftInEnku' in that order so it -- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@. overSoXSynthGen2FDN_SG :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Float -> String -> String -> ((Float -> OvertonesO) -> (Float, Float) -> Int -> String -> IO ()) -> IO () overSoXSynthGen2FDN_SG file m ku f y zs wws h = do n <- duration1000 file overSoXSynthGen2FDN_SG4G file m ku f (str2DurationsDef n zs y) wws h {-# INLINE overSoXSynthGen2FDN_SG #-} -- | Generalized version of the 'overSoXSynthGen2FDN_SG' where instead of using a Ukrainian text to specify a durations for the sounds (and a rhythm -- respectively) you provide your own rhythm as 'Durations'. Positive values correspond to durations of the sounds generated -- and negative values -- to durations of the pauses respectively. Please, use a function @h :: ((Float -> OvertonesO) -> (Float, Float) -> -- Int -> String -> IO ())@ such that it can create for the given values accorgingly sounds and pauses. Otherwise, please, check whether at -- least it can deal with such arguments without errors. Note that 'Int' arguments are used by 'liftInEnku' in that order so it -- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@. overSoXSynthGen2FDN_SG4G :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Durations -> String -> ((Float -> OvertonesO) -> (Float, Float) -> Int -> String -> IO ()) -> IO () overSoXSynthGen2FDN_SG4G file m ku f v2 wws h = do n <- duration1000 file vecA <- freqsFromFile file n let vecB = liftInEnkuV m ku . map fromIntegral . filter (/= (11440::Int)) $ vecA zeroN = numVZeroesPre vecB !l = numElements v2 in mapM_ (\(j, x) -> do h f (x, (unsafeAt v2 (j `rem` l))) j wws renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") . zip [0..] $ vecB endFromResult -- | A variant of the 'overSoXSynthGen2FDN_SG4G' where instead of providing your own durations as 'Durations' you use a Ukrainian text and -- a function treats each symbol in it as a duration parameter with its sign. Positive values correspond to durations of the sounds generated -- and negative values -- to durations of the pauses respectively. Please, use a function @h :: ((Float -> OvertonesO) -> (Float, Float) -> -- Int -> String -> IO ())@ such that it can create for the given values accorgingly sounds and pauses. Otherwise, please, check whether at -- least it can deal with such arguments without errors. overSoXSynthGen2FDN_SG4GS :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Float -> String -> String -> ((Float -> OvertonesO) -> (Float, Float) -> Int -> String -> IO ()) -> IO () overSoXSynthGen2FDN_SG4GS file m ku f y zs = overSoXSynthGen2FDN_SG4G file m ku f (str2Durations zs y) {-# INLINE overSoXSynthGen2FDN_SG4GS #-} -- | 6G generalized variant of the 'overSoXSynthGen2FDN_SG4G' with volume adjustments given by 'Strengths'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it -- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@. overSoXSynthGen2FDN_SG6G :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Durations -> String -> ((Float -> OvertonesO) -> (Float, Float) -> Int -> String -> IO ()) -> Strengths -> Float -> IO () overSoXSynthGen2FDN_SG6G file m ku f v2 wws h v6 limV | F.null v6 = putStrLn "Composition.Sound.Functional.overSoXSynthGen2FDN_SG6G: You did not provide a volume adjustments array! " | otherwise = do n <- duration1000 file vecA <- freqsFromFile file n let vecB = liftInEnkuV m ku . map fromIntegral . filter (/= (11440::Int)) $ vecA zeroN = numVZeroesPre vecB !l2 = numElements v2 !l6 = numElements v6 in mapM_ (\(j, x) -> do h f (x, (unsafeAt v2 (j `rem` l2))) j wws renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav" apply6GSilentFile ("result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") limV (unsafeAt v6 (j `rem` l6))) . zip [0..] $ vecB endFromResult -- | A variant of the 'overSoXSynthGen2FDN_SG6G' where 'Strengths' are obtained from a Ukrainian text and 'str2Volume'. overSoXSynthGen2FDN_SG6GS :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Float -> String -> String -> ((Float -> OvertonesO) -> (Float, Float) -> Int -> String -> IO ()) -> String -> Float -> IO () overSoXSynthGen2FDN_SG6GS file m ku f y zs wws h zzs = overSoXSynthGen2FDN_SG6G file m ku f (str2Durations zs y) wws h (str2Volume zzs) {-# INLINE overSoXSynthGen2FDN_SG6GS #-} -- | A variant of the 'overSoXSynthGen2FDN_SG6GS' where 'Strengths' are obtained from the same Ukrainian text as also 'Durations' so the last -- 'String' argument is omitted (it is equal to the first one). Helps to create a speech-like composition. overSoXSynthGen2FDN_SG6GSu :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Float -> String -> String -> ((Float -> OvertonesO) -> (Float, Float) -> Int -> String -> IO ()) -> Float -> IO () overSoXSynthGen2FDN_SG6GSu file m ku f y zs wws h = overSoXSynthGen2FDN_SG6G file m ku f (str2Durations zs y) wws h (str2Volume zs) {-# INLINE overSoXSynthGen2FDN_SG6GSu #-} -- | Generalized variant of the 'overSoXSynthGen2FDN_SG' with a possibility to specify with the third 'String' argument sound quality parameters. -- Besides, the second from the end argument (a function) needs to be one more argument -- just also 'String'. -- For more information, please, refer to 'soxBasicParams'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it -- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@. overSoXSynthGen2FDN_SG2G :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Float -> String -> String -> ((Float -> OvertonesO) -> (Float, Float) -> Int -> String -> String -> IO ()) -> String -> IO () overSoXSynthGen2FDN_SG2G file m ku f y zs wws h ys = do n <- duration1000 file vecA <- freqsFromFile file n let vecB = liftInEnkuV m ku . map fromIntegral . filter (/= (11440::Int)) $ vecA zeroN = numVZeroesPre vecB v2 = str2DurationsDef n zs y !l2 = n in mapM_ (\(j, x) -> do h f (x, (unsafeAt v2 (j `rem` l2))) j wws ys renameFile ("result." ++ if drop 3 ys == "f" then "flac" else "wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ if drop 3 ys == "f" then ".flac" else ".wav") . zip [0..] $ vecB endFromResult2G ys -- | Generalized variant of the 'overSoXSynth2FDN_Sf' with a possibility to adjust volume using 'adjust_dbVol'. 'Array' 'Int' of 'Float' is -- used to specify adjustments in dB. For more information, please, refer to 'adjust_dbVol'. overSoXSynth2FDN_Sf1G :: (Float -> OvertonesO) -> (Float, Float) -> Int -> String -> Array Int Float -> IO () overSoXSynth2FDN_Sf1G f (x, y) = overSoXSynth2FDN_Sf31G f (x, y, 0.001) {-# INLINE overSoXSynth2FDN_Sf1G #-} -- | Generalized variant of the 'overSoXSynth2FDN_Sf1G' with a possibility to specify sound quality using the second 'String' argument. -- For more information, please, refer to 'soxBasicParams'. overSoXSynth2FDN_Sf2G :: (Float -> OvertonesO) -> (Float, Float) -> Int -> String -> Array Int Float -> String -> IO () overSoXSynth2FDN_Sf2G f (x, y) = overSoXSynth2FDN_Sf32G f (x, y, 0.001) {-# INLINE overSoXSynth2FDN_Sf2G #-} -- | Generalized variant of the 'overSoXSynth2FDN_Sf3' function with a possibility to adjust volume using 'adjust_dBVol'. 'Array' 'Int' of 'Float' -- specifies the needed adjustments in dB. overSoXSynth2FDN_Sf31G :: (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> String -> Array Int Float -> IO () overSoXSynth2FDN_Sf31G f (x, y, t0) j zs vdB = overSoXSynth2FDN_Sf32G f (x, y, t0) j zs vdB [] {-# INLINE overSoXSynth2FDN_Sf31G #-} -- | Generalized variant of the 'overSoXSynth2FDN_Sf31G' with a possibility to specify sound quality using the second 'String' parameter. -- For more information, please, refer to 'soxBasicParams'. overSoXSynth2FDN_Sf35G :: (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> Intervals -> Array Int Float -> String -> IO () overSoXSynth2FDN_Sf35G f (x, y, t0) j v5 vdB ys | F.null v5 = overSoXSynthG f x | otherwise = do let !l0 = numElements v5 soundGenF32G ([\x -> closestNote (if x /= 0.0 then abs x else unsafeAt notes 0),\x -> fromMaybe (unsafeAt notes 0) (dNote (unsafeAt v5 (abs (j `rem` l0))) (closestNote (if x /= 0.0 then abs x else unsafeAt notes 0)))]) (replicate 2 x) ([1,unsafeAt v5 (abs (j `rem` l0))]) f (x, y, t0) j vdB ys if null ys then mixTest else mixTest2G ys -- | Generalized variant of the 'overSoXSynth2FDN_Sf35G' with afterwards 'apply6G' usage. overSoXSynth2FDN_Sf36G :: (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> Intervals -> Array Int Float -> String -> Float -> IO () overSoXSynth2FDN_Sf36G f (x, y, t0) j v5 vdB ys vol | F.null v5 = overSoXSynthG f x | otherwise = overSoXSynth2FDN_Sf35G f (x, y, t0) j v5 vdB ys >> if y > 0.0 then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr "" -- | A variant of the 'overSoXSynth2FDN_Sf36G' where volume adjustment is obtained from a Ukrainian text. overSoXSynth2FDN_Sf36GS :: (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> Intervals -> String -> Array Int Float -> String -> String -> IO () overSoXSynth2FDN_Sf36GS f (x, y, t0) j v5 xs vdB ys xxs | null . convertToProperUkrainianS $ xxs = putStrLn "Composition.Sound.Functional.overSoXSynth2FDN_Sf36GS: You provided no information to obtain volume adjustment! " | otherwise = overSoXSynth2FDN_Sf36G f (x, y, t0) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs) {-# INLINE overSoXSynth2FDN_Sf36GS #-} -- | Can generate multiple notes with their respective overtones that are played simultaneously (e. g. it can be just one note with overtones, -- an interval with overtones, an accord with overtones etc.). This allows to get a rather complex or even complicated behaviour to obtain expressive -- and rich sound. It uses volume adjustment in dB given by the second @[Float]@ for the overtones. soundGenF31G :: [(Float -> Float)] -> [Float] -> [Int] -> (Float -> OvertonesO) -> (Float, Float, Float) -> Int -> Array Int Float -> IO () soundGenF31G vf vd vi f (x, y, t0) j vdB = soundGenF32G vf vd vi f (x, y, t0) j vdB [] {-# INLINE soundGenF31G #-} -- | Similar to 'overSoXSynthGen2FDN_S', but instead of 'overSoXSynth2FDN_S' uses 'overSoXSynth2FDN_Sf3' function. Note that 'Int' arguments are used by 'liftInEnku' in that order so it -- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@. overSoXSynthGen2FDN_Sf3G :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Float -> Float -> String -> String -> ((Float -> OvertonesO) -> (Float, Float, Float) -> Int -> String -> IO ()) -> IO () overSoXSynthGen2FDN_Sf3G file m ku f y t0 zs wws h = do n <- duration1000 file vecA <- freqsFromFile file n let vecB = liftInEnkuV m ku . map fromIntegral . filter (/= (11440::Int)) $ vecA zeroN = numVZeroesPre vecB v2 = str2DurationsDef n zs y !l2 = numElements v2 in mapM_ (\(j, x) -> do h f (x, (unsafeAt v2 (j `rem` l2)), t0) j wws renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") . zip [0..] $ vecB endFromResult -- | Generalized variant of the 'ovorSoXSynthGen2FDN_Sf3G' with a possibility to specify sound quality with the third 'String' argument. -- Besides, the second from the end argument (a function) needs to be one more argument -- just also 'String'. -- For more information, please, refer to 'soxBasicParams'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it -- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@. overSoXSynthGen2FDN_Sf3G2G :: FilePath -> Int -> Int -> (Float -> OvertonesO) -> Float -> Float -> String -> String -> ((Float -> OvertonesO) -> (Float, Float, Float) -> Int -> String -> String -> IO ()) -> String -> IO () overSoXSynthGen2FDN_Sf3G2G file m ku f y t0 zs wws h ys = do n <- duration1000 file vecA <- freqsFromFile file n let vecB = liftInEnkuV m ku . map fromIntegral . filter (/= (11440::Int)) $ vecA zeroN = numVZeroesPre vecB v2 = str2DurationsDef n zs y !l2 = numElements v2 in mapM_ (\(j, x) -> do h f (x, (unsafeAt v2 (j `rem` l2)), t0) j wws ys renameFile ("result." ++ if drop 3 ys == "f" then "flac" else "wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ if drop 3 ys == "f" then ".flac" else ".wav") . zip [0..] $ vecB endFromResult2G ys