packages feed

dobutokO2 0.21.0.0 → 0.22.0.0

raw patch · 8 files changed

+545/−490 lines, 8 files

Files

CHANGELOG.md view
@@ -165,8 +165,8 @@  ## 0.17.1.0 -- 2020-03-25 -* Seventeenth version revised A. Fixed issues with being not compiled and duplicate export in 'DobutokO.Sound.IntermediateF'. Added two new functions 'soxE' and-'soxE1'. +* Seventeenth version revised A. Fixed issues with being not compiled and duplicate export in 'DobutokO.Sound.IntermediateF'. Added two new functions+'soxE' and 'soxE1'.   ## 0.18.0.0 -- 2020-03-26 @@ -191,8 +191,15 @@  ## 0.21.0.0 -- 2020-03-30 -* Thirteenth version. Starting from the version 0.21.0.0 the package extends its library functions with the possibility to create not only+* Twenty-first version. Starting from the version 0.21.0.0 the package extends its library functions with the possibility to create not only single notes or intervals of sounds playing simultaneously but also sets of three, four, five, six, seven or more sounds played simultanously with their obertones. For more information, please, refer to the documentation for the DobutokO.Sound.Functional module. Added the needed functionality for this. Rearrange modules DobutokO.Sound and DobutokO.Sound.Functional to provide more flexibility and shorten the code. Added new generalized functions to the DobutokO.Sound.Functional module. Some documentation improvements.++## 0.22.0.0 -- 2020-04-02++* Twenty-second version. Added 1G generalized functions to the DobutokO.Sound.Functional module. They allow additional volume adjustment in dB given by+an additional vector of Double values for the overtones. Changed the names of the functions and documentation from 'ober' ('Ober') to English 'over'+('Over'). Fixed issue with 'partialTest_k' function for being not generated overtones files for the indices that can be without a remainder divided by+50. Some code and documentation improvements.
DobutokO/Sound.hs view
@@ -7,39 +7,38 @@ -- -- A program and a library to create experimental music -- from a mono audio and a Ukrainian text.--{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE BangPatterns, LambdaCase #-} {-# OPTIONS_GHC -threaded #-}  module DobutokO.Sound (   -- * Library and executable functions   -- ** For the fixed timbre-  oberSoXSynthN+  overSoXSynthN   -- *** For the fixed timbre with different signs for harmonics coefficients-  , oberTones2-  , oberSoXSynth2-  , oberSoXSynthN2-  , oberSoXSynthN3+  , overTones2+  , overSoXSynth2+  , overSoXSynthN2+  , overSoXSynthN3   -- *** Use additional parameters-  , oberSoXSynthDN-  , oberSoXSynth2DN+  , overSoXSynthDN+  , overSoXSynth2DN   -- *** Use a file for information-  , oberSoXSynthNGen-  , oberSoXSynthNGen2-  , oberSoXSynthNGen3+  , overSoXSynthNGen+  , overSoXSynthNGen2+  , overSoXSynthNGen3   -- ** For the unique for the String structure timbre-  , uniqOberTonesV-  , uniqOberSoXSynth-  , uniqOberSoXSynthN+  , uniqOvertonesV+  , uniqOverSoXSynth+  , uniqOverSoXSynthN   -- *** For the unique for the String structure timbre with different signs for harmonics coefficients-  , uniqOberTonesV2-  , uniqOberSoXSynth2-  , uniqOberSoXSynthN3-  , uniqOberSoXSynthN4+  , uniqOvertonesV2+  , uniqOverSoXSynth2+  , uniqOverSoXSynthN3+  , uniqOverSoXSynthN4   -- *** Use a file for information-  , uniqOberSoXSynthNGen-  , uniqOberSoXSynthNGen3-  , uniqOberSoXSynthNGen4+  , uniqOverSoXSynthNGen+  , uniqOverSoXSynthNGen3+  , uniqOverSoXSynthNGen4   -- ** Work with octaves   , octaveUp   , octaveDown@@ -60,13 +59,13 @@   , octavesTA   -- * Extended generation using enky functionality   -- ** With somewhat fixed timbre-  , oberSoXSynthNGenE-  , oberSoXSynthNGen2E-  , oberSoXSynthNGen3E+  , overSoXSynthNGenE+  , overSoXSynthNGen2E+  , overSoXSynthNGen3E   -- ** With usage of additional information in the Ukrainian text-  , uniqOberSoXSynthNGenE-  , uniqOberSoXSynthNGen3E-  , uniqOberSoXSynthNGen4E+  , uniqOverSoXSynthNGenE+  , uniqOverSoXSynthNGen3E+  , uniqOverSoXSynthNGen4E   -- * Auxiliary functions   , signsFromString ) where@@ -77,7 +76,7 @@ import Control.Exception (onException) import System.Environment (getArgs) import Data.List (isPrefixOf,sort,sortBy,nubBy)-import Data.Maybe (isJust,isNothing,fromJust)+import Data.Maybe (isJust,isNothing,fromJust,maybe) import Data.Char (isDigit) import qualified Data.Vector as V import System.Process@@ -133,7 +132,7 @@  -- | Returns an analogous note in the lower octave (its frequency in Hz). octaveDown :: Double -> Double-octaveDown x = x / fromIntegral 2+octaveDown x = x / 2 {-# INLINE octaveDown #-}  -----------------------------------------------------------------------------------------------------------------------------@@ -161,12 +160,12 @@   | compare (closestNote x) 24.4996 == GT =       case compare (fromJust . whichOctave $ x) n of         EQ -> Just (closestNote x)-        LT -> let z  = log (V.unsafeIndex notes (n * 12) / closestNote x) / log 2.0+        LT -> let z  = logBase 2.0 (V.unsafeIndex notes (n * 12) / closestNote x)                   z1 = truncate z in                    if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001                      then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) octaveUp $ closestNote x)                      else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) octaveUp $ closestNote x)-        _  -> let z  = log (closestNote x / V.unsafeIndex notes (n * 12)) / log 2.0+        _  -> let z  = logBase 2.0 (closestNote x / V.unsafeIndex notes (n * 12))                   z1 = truncate z in                    if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001                      then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) octaveDown $ closestNote x)@@ -177,28 +176,27 @@ -- The function also takes into account the lower pure quint for the obtained note behaviour. If it is not practical to determine the octave, the resulting -- frequency is omitted from the resulting 'V.Vector'. liftInOctaveV :: Int -> V.Vector Double -> V.Vector Double-liftInOctaveV n = V.mapMaybe (\z -> liftInOctave n z)+liftInOctaveV n = V.mapMaybe (liftInOctave n)  --------------------------------------------------------------------------------------------------------------------------------  -- | For the given frequency of the note it generates a 'V.Vector' of the tuples, each one of which contains the harmonics' frequency and amplitude. For every given -- 'String' structure of the uniqueness (see the documentation for @mmsyn7s@ package and its 'MMSyn7.Syllable' module) it produces the unique timbre.-uniqOberTonesV :: Double -> String -> ObertonesO-uniqOberTonesV note xs =+uniqOvertonesV :: Double -> String -> OvertonesO+uniqOvertonesV note xs =   let ys = uniquenessPeriods xs       z  = sum ys       v  = V.fromList . fmap (\y -> fromIntegral y / fromIntegral z) $ ys       z2 = V.length v-      v2 = V.generate z2 $ (\i -> V.unsafeIndex v i / fromIntegral (i + 1)) in+      v2 = V.generate z2 (\i -> V.unsafeIndex v i / fromIntegral (i + 1)) in         V.takeWhile (\(!u,!z) -> compare u (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.unsafeSlice 1 (z2 - 1) .           V.zip (V.generate z2 (\i -> note * fromIntegral (i + 1))) $ v2  -- | Additional function to produce signs from the given 'String' of the Ukrainian text. Ukrainian vowels and voiced consonants gives \"+\" sign (+1), voiceless -- and sonorous consonants gives \"-\" sign (-1). Voiceless2 gives "0". Other symbols are not taken into account. signsFromString :: Int -> String -> V.Vector Int-signsFromString n1 ts =-  V.take n1 . V.fromList . concatMap (fmap (\x ->-    case x of+signsFromString n1 =+  V.take n1 . V.fromList . concatMap (fmap (\case       Vowel _ -> 1       Voiced _ -> 1       VoicedP _ -> 1@@ -206,12 +204,12 @@       VoicelessP _ -> (-1)       Sonorous _ -> (-1)       SonorousP _ -> (-1)-      _ -> 0) . concat . fmap representProlonged) . syllablesUkrP . take (3 * n1) . cycle $ ts+      _ -> 0) . concatMap representProlonged) . syllablesUkrP . take (3 * n1) . cycle   -- | For the given frequency of the note and a Ukrainian text it generates a 'V.Vector' of the tuples, each one of which contains -- the harmonics' frequency and amplitude. The 'String' is used to produce the signs for harmonics coefficients.-oberTones2 :: Double -> String -> ObertonesO-oberTones2 note ts =+overTones2 :: Double -> String -> OvertonesO+overTones2 note ts =   V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.filter (\(_, t4) -> t4 /= 0.0) .     V.zip (V.generate 1024 (\i -> note * fromIntegral (i + 2))) $ (V.generate 1024 (\i -> fromIntegral (V.unsafeIndex (signsFromString 1024 ts)       (i + 1)) / fromIntegral ((i + 1) * (i + 1))))@@ -219,97 +217,95 @@ -- | For the given frequency of the note it generates a 'V.Vector' of the tuples, each one of which contains the harmonics' frequency and amplitude. For every given -- first 'String' argument structure of the uniqueness (see the documentation for @mmsyn7s@ package and its 'MMSyn7.Syllable' module) it produces the unique timbre. -- The second 'String' is used to produce the signs for harmonics coefficients.-uniqOberTonesV2 :: Double -> String -> String -> ObertonesO-uniqOberTonesV2 note xs ts = +uniqOvertonesV2 :: Double -> String -> String -> OvertonesO+uniqOvertonesV2 note xs ts =    let ys = uniquenessPeriods xs       z  = sum ys       v  = V.fromList . fmap (\y -> fromIntegral y / fromIntegral z) $ ys       z2 = V.length v-      v2 = V.generate z2 $ (\i -> (V.unsafeIndex (V.map fromIntegral . signsFromString z2 $ ts) i) * V.unsafeIndex v i / fromIntegral (i + 1)) in+      v2 = V.generate z2 (\i -> (V.unsafeIndex (V.map fromIntegral . signsFromString z2 $ ts) i) * V.unsafeIndex v i / fromIntegral (i + 1)) in         V.takeWhile (\(!u,!z) -> compare u (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.filter (\(_, t4) -> t4 /= 0.0) .           V.unsafeSlice 1 (z2 - 1) . V.zip (V.generate z2 (\i -> note * fromIntegral (i + 1))) $ v2 --- | Similar to 'oberSoXSynth' except that takes not necessarily pure lower quint note as the second one, but the one specified by the 'String' parameter+-- | Similar to 'overSoXSynth' except that takes not necessarily pure lower quint note as the second one, but the one specified by the 'String' parameter -- as an argument to 'dNote'. If you begin the 'String' with space characters, or \"сь\", or \"ць\", or dash, or apostrophe, or soft sign, than there will--- be no interval and the sound will be solely one with its obertones.-oberSoXSynthDN :: Double -> String -> IO ()-oberSoXSynthDN x zs- | V.null . convertToProperUkrainian $ zs = oberSoXSynth x+-- be no interval and the sound will be solely one with its Overtones.+overSoXSynthDN :: Double -> String -> IO ()+overSoXSynthDN x zs+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x  | otherwise = do   let note0 = closestNote x       note1 = dNote (V.unsafeIndex (intervalsFromString zs) 0) note0-      v0    = oberTones note0-      v1    = if isNothing note1 then V.empty-              else oberTones . fromJust $ note1-      oberSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+      v0    = overTones note0+      v1    = maybe V.empty overTones note1+      overSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))         ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN /           fromIntegral l) $ show 0] "") vec-      oberSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+      overSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))         ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN /           fromIntegral l) $ show 0] "") vec   _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", "0.5","sine", showFFloat (Just 4) note0 $ show 0, "vol","0.5"] ""-  if isNothing note1 then do oberSoXSynthHelp v0+  if isNothing note1 then overSoXSynthHelp v0   else do      _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB.wav", "synth", "0.5","sine", showFFloat (Just 4) (fromJust note1) $ show 0,   "vol","0.5"]   ""-    oberSoXSynthHelp v0-    oberSoXSynthHelp2 v1+    overSoXSynthHelp v0+    overSoXSynthHelp2 v1   mixTest --- | Similar to 'oberSoXSynthDN' except that the resulting duration is specified by the second 'Double' parameter in seconds. For 'oberSoXSynthDN'+-- | Similar to 'overSoXSynthDN' except that the resulting duration is specified by the second 'Double' parameter in seconds. For 'overSoXSynthDN' -- it is equal to 0.5.-oberSoXSynth2DN :: Double -> Double -> String -> IO ()-oberSoXSynth2DN x y zs- | V.null . convertToProperUkrainian $ zs = oberSoXSynth x+overSoXSynth2DN :: Double -> Double -> String -> IO ()+overSoXSynth2DN x y zs+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x  | otherwise = do     let note0 = closestNote x         note1 = dNote (V.unsafeIndex (intervalsFromString zs) 0) note0-        v0    = oberTones note0-        v1    = if isNothing note1 then V.empty-                else oberTones . fromJust $ note1-        oberSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+        v0    = overTones note0+        v1    = maybe V.empty overTones note1+        overSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))           ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", showFFloat (Just 4) y $ show 0,"sine", showFFloat (Just 4) noteN $ show 0,             "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] "") vec-        oberSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+        overSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))           ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", showFFloat (Just 4) y $ show 0,"sine", showFFloat (Just 4) noteN $ show 0,             "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] "") vec     _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", showFFloat (Just 4) y $ show 0,"sine",        showFFloat (Just 4) note0 $ show 0, "vol","0.5"] ""-    if isNothing note1 then do oberSoXSynthHelp v0+    if isNothing note1 then overSoXSynthHelp v0     else do        _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB.wav", "synth", showFFloat (Just 4) y $ show 0,"sine",          showFFloat (Just 4) (fromJust note1) $ show 0, "vol","0.5"] ""-      oberSoXSynthHelp v0-      oberSoXSynthHelp2 v1+      overSoXSynthHelp v0+      overSoXSynthHelp2 v1     mixTest  -- | For the given frequency it generates a musical sound with a timbre. The main component of the sound includes the lower pure quint, -- which can be in the same octave or in the one with the number lower by one. Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.--- The 'String' argument is used to define signs of the harmonics coefficients for obertones.-oberSoXSynth2 :: Double -> String -> IO ()-oberSoXSynth2 x tts = do+-- The 'String' argument is used to define signs of the harmonics coefficients for Overtones.+overSoXSynth2 :: Double -> String -> IO ()+overSoXSynth2 x tts = do   let note0 = closestNote x       note1 = pureQuintNote note0-      v0    = oberTones2 note0 tts-      v1    = oberTones2 note1 tts-      oberSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+      v0    = overTones2 note0 tts+      v1    = overTones2 note1 tts+      overSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))         ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN /           fromIntegral l) $ show 0] "") vec-      oberSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+      overSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))         ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN /            fromIntegral l) $ show 0] "") vec   _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test01.wav", "synth", "0.5","sine", showFFloat (Just 4) note0 $ show 0, "synth", "0.5","sine", "mix", showFFloat (Just 4) note1 $ show 0, "vol","0.5"] ""-  oberSoXSynthHelp v0-  oberSoXSynthHelp2 v1+  overSoXSynthHelp v0+  overSoXSynthHelp2 v1   mixTest   -- | Function to create a melody for the given arguments. 'String' is used to provide a rhythm. The main component of the sound includes the lower pure quint, which -- can be in the same octave or in the one with the number lower by one. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude--- for obertones. If it is set to 1.0 the obertones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results+-- for Overtones. If it is set to 1.0 the overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results -- in their becoming more silent ones. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.-oberSoXSynthN :: Int -> Double -> Double -> String -> V.Vector Double -> IO ()-oberSoXSynthN n ampL time3 zs vec0+overSoXSynthN :: Int -> Double -> Double -> String -> V.Vector Double -> IO ()+overSoXSynthN n ampL time3 zs vec0  | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =      let (t, ws) = splitAt 1 . syllableStr n $ zs         m     = length ws@@ -317,32 +313,32 @@         v2    = V.map (\yy -> time3 * fromIntegral (yy * m) / fromIntegral (head t)) . V.fromList $ ws in V.imapM_ (\j x -> do            let note0 = closestNote x                     -- zs is obtained from the command line arguments               note1 = pureQuintNote note0-              v0    = oberTones note0-              v1    = oberTones note1-              oberSoXSynthHelpN vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+              v0    = overTones note0+              v1    = overTones note1+              overSoXSynthHelpN vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine",                   showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l * ampL) $ show 0] "") vec-              oberSoXSynthHelpN2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+              overSoXSynthHelpN2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,                    "sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l * ampL) $ show 0] "") vec                 soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++ prependZeroes zeroN "1" ++  ".wav",                 "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine", showFFloat (Just 4) note01 $ show 0, "synth", showFFloat (Just 4)                   (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine", "mix", showFFloat (Just 4) note02 $ show 0, "vol","0.5"] ""           soxSynthHelpMain note0 note1-          oberSoXSynthHelpN v0-          oberSoXSynthHelpN2 v1+          overSoXSynthHelpN v0+          overSoXSynthHelpN2 v1           mixTest) vec0  | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in-    if abs ampL1 < 0.01 then oberSoXSynthN n 0.01 time3 zs vec0-    else oberSoXSynthN n ampL1 time3 zs vec0+    if abs ampL1 < 0.01 then overSoXSynthN n 0.01 time3 zs vec0+    else overSoXSynthN n ampL1 time3 zs vec0  -- | Function to create a melody for the given arguments. 'String' is used to provide a rhythm. The main component of the sound includes the lower pure quint, which -- can be in the same octave or in the one with the number lower by one. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude--- for obertones. If it is set to 1.0 the obertones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results+-- for Overtones. If it is set to 1.0 the overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results -- in their becoming more silent ones. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.-oberSoXSynthN2 :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()-oberSoXSynthN2 n ampL time3 zs tts vec0+overSoXSynthN2 :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()+overSoXSynthN2 n ampL time3 zs tts vec0  | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =      let (t, ws) = splitAt 1 . syllableStr n $ zs         m     = length ws@@ -350,36 +346,36 @@         v2    = V.map (\yy -> time3 * fromIntegral (yy * m) / fromIntegral (head t)) . V.fromList $ ws in V.imapM_ (\j x -> do            let note0 = closestNote x                     -- zs is obtained from the command line arguments               note1 = pureQuintNote note0-              v0    = oberTones2 note0 tts-              v1    = oberTones2 note1 tts-              oberSoXSynthHelpN vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+              v0    = overTones2 note0 tts+              v1    = overTones2 note1 tts+              overSoXSynthHelpN vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine",                   showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l * ampL) $ show 0] "") vec-              oberSoXSynthHelpN2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+              overSoXSynthHelpN2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,                    "sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l * ampL) $ show 0] "") vec                 soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++ prependZeroes zeroN "1" ++  ".wav",                 "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine", showFFloat (Just 4) note01 $ show 0, "synth", showFFloat (Just 4)                   (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine", "mix", showFFloat (Just 4) note02 $ show 0, "vol","0.5"] ""           soxSynthHelpMain note0 note1-          oberSoXSynthHelpN v0-          oberSoXSynthHelpN2 v1+          overSoXSynthHelpN v0+          overSoXSynthHelpN2 v1           mixTest) vec0  | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in-    if abs ampL1 < 0.01 then oberSoXSynthN2 n 0.01 time3 zs tts vec0-    else oberSoXSynthN2 n ampL1 time3 zs tts vec0    +    if abs ampL1 < 0.01 then overSoXSynthN2 n 0.01 time3 zs tts vec0+    else overSoXSynthN2 n ampL1 time3 zs tts vec0      -- | Function to create a melody for the given arguments. 'String' is used to provide a rhythm. The main component of the sound includes the lower pure quint, which -- can be in the same octave or in the one with the number lower by one. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude--- for obertones. If it is set to 1.0 the obertones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results+-- for Overtones. If it is set to 1.0 the overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results -- in their becoming more silent ones. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten. -- The third 'String' argument is used to define the intervals for the notes if any. -- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of--- the main note. If it is rather great, it can signal that the volume for the second note obertones are greater than for the main note obetones.+-- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones. -- The last one is experimental feature.-oberSoXSynthN3 :: Int -> Double -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()-oberSoXSynthN3 n ampL time3 dAmpl zs tts vs vec0+overSoXSynthN3 :: Int -> Double -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()+overSoXSynthN3 n ampL time3 dAmpl zs tts vs vec0  | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =      let (t, ws) = splitAt 1 . syllableStr n $ zs         m     = length ws@@ -389,13 +385,13 @@         v2    = V.map (\yy -> time3 * fromIntegral (yy * m) / fromIntegral (head t)) . V.fromList $ ws in V.imapM_ (\j x -> do            let note0 = closestNote x                     -- zs is obtained from the command line arguments               note1 = dNote (V.unsafeIndex v3 (j `rem` l)) note0-              v0    = oberTones2 note0 tts+              v0    = overTones2 note0 tts               v1    = if isNothing note1 then V.empty-                      else oberTones2 (fromJust note1) tts-              oberSoXSynthHelpN vec = let l1 = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+                      else overTones2 (fromJust note1) tts+              overSoXSynthHelpN vec = let l1 = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine",                   showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l1 * ampL) $ show 0] "") vec-              oberSoXSynthHelpN2 vec = let l1 = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+              overSoXSynthHelpN2 vec = let l1 = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,                    "sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (if dAmpl * amplN / fromIntegral l1 * ampL > 1.0 then 1.0 else dAmpl                       * amplN / fromIntegral l1 * ampL) $ show 0] "") vec  @@ -403,71 +399,71 @@                 "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine", showFFloat (Just 4) note01 $ show 0, "vol","0.5"] ""               soxSynthHelpMain1 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB" ++                  prependZeroes zeroN "1" ++  ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine", showFFloat (Just 4) note02 $-                   show 0, "vol", showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / fromIntegral 2) $ show 0] ""+                   show 0, "vol", showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / 2) $ show 0] ""           if isNothing note1 then do { soxSynthHelpMain0 note0-                                     ; oberSoXSynthHelpN v0 }+                                     ; overSoXSynthHelpN v0 }           else do { soxSynthHelpMain0 note0                   ; soxSynthHelpMain1 (fromJust note1)-                  ; oberSoXSynthHelpN v0-                  ; oberSoXSynthHelpN2 v1}+                  ; overSoXSynthHelpN v0+                  ; overSoXSynthHelpN2 v1}           paths0 <- listDirectory "."           let paths = sort . filter (isPrefixOf "test") $ paths0           _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result0" ++ prependZeroes zeroN (show j) ++ ".wav","vol","0.3"]) ""           mapM_ removeFile paths) vec0  | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in-    if abs ampL1 < 0.01 then oberSoXSynthN3 n 0.01 time3 dAmpl zs tts vs vec0-    else oberSoXSynthN3 n ampL1 time3 dAmpl zs tts vs vec0+    if abs ampL1 < 0.01 then overSoXSynthN3 n 0.01 time3 dAmpl zs tts vs vec0+    else overSoXSynthN3 n ampL1 time3 dAmpl zs tts vs vec0 --- | Similar to 'oberSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts+-- | Similar to 'overSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts -- the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]). The first 'Double' argument from--- the range [0.01..1.0] is used as a maximum amplitude for obertones. If it is set to 1.0 the obertones amplitudes are just maximum ones,+-- the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the overTones amplitudes are just maximum ones, -- otherwise they are multiplied by the parameter and this results in their becoming more silent ones. -- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" and \"end.wav\" files in the current directory, because they can be overwritten. -- -- For better usage the 'FilePath' should be a filepath for the .wav file.-oberSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> IO ()-oberSoXSynthNGen file m ampL time3 zs = oberSoXSynthNGenE file m 12 ampL time3 zs+overSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> IO ()+overSoXSynthNGen file m = overSoXSynthNGenE file m 12   --- | Similar to 'oberSoXSynthNGen', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'oberSoXSynthNGen'. To obtain+-- | Similar to 'overSoXSynthNGen', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'overSoXSynthNGen'. To obtain -- its modifications, please, use 2, 3, 4, 6, or 9.-oberSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> IO ()-oberSoXSynthNGenE file m ku ampL time3 zs = do+overSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> IO ()+overSoXSynthNGenE file m ku ampL time3 zs = do   duration0 <- durationA file   let n = truncate (duration0 / 0.001)   vecA <- freqsFromFile file n   let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA-  oberSoXSynthN n ampL time3 zs vecB+  overSoXSynthN n ampL time3 zs vecB   endFromResult        --- | Similar to 'oberSoXSynthN2', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts+-- | Similar to 'overSoXSynthN2', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts -- the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]). The first 'Double' argument from--- the range [0.01..1.0] is used as a maximum amplitude for obertones. If it is set to 1.0 the obertones amplitudes are just maximum ones,+-- the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the overTones amplitudes are just maximum ones, -- otherwise they are multiplied by the parameter and this results in their becoming more silent ones. -- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" and \"end.wav\" files in the current directory, because they can be overwritten. --  -- For better usage the 'FilePath' should be a filepath for the .wav file. -- The second 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.-oberSoXSynthNGen2 :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()-oberSoXSynthNGen2 file m ampL time3 zs tts = oberSoXSynthNGen2E file m 12 ampL time3 zs tts+overSoXSynthNGen2 :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()+overSoXSynthNGen2 file m = overSoXSynthNGen2E file m 12   --- | Similar to 'oberSoXSynthNGen2', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'oberSoXSynthNGen2'. To obtain+-- | Similar to 'overSoXSynthNGen2', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'overSoXSynthNGen2'. To obtain -- its modifications, please, use 2, 3, 4, 6, or 9.-oberSoXSynthNGen2E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()-oberSoXSynthNGen2E file m ku ampL time3 zs tts = do+overSoXSynthNGen2E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()+overSoXSynthNGen2E file m ku ampL time3 zs tts = do   duration0 <- durationA file   let n = truncate (duration0 / 0.001)   vecA <- freqsFromFile file n   let vecB = liftInEnkuV m ku. V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA-  oberSoXSynthN2 n ampL time3 zs tts vecB+  overSoXSynthN2 n ampL time3 zs tts vecB   endFromResult       --- | Similar to 'oberSoXSynthN2', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts+-- | Similar to 'overSoXSynthN2', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts -- the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]). The first 'Double' argument from--- the range [0.01..1.0] is used as a maximum amplitude for obertones. If it is set to 1.0 the obertones amplitudes are just maximum ones,+-- the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the overTones amplitudes are just maximum ones, -- otherwise they are multiplied by the parameter and this results in their becoming more silent ones. -- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" and \"end.wav\" files in the current directory, because they can be overwritten.@@ -476,21 +472,21 @@ -- The second 'String' argument is used to define signs of the harmonics coefficients in the generated sounds. -- The third 'String' argument is used to define the intervals for the notes if any. -- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of--- the main note. If it is rather great, it can signal that the volume for the second note obertones are greater than for the main note obetones.+-- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones. -- The last one is experimental feature.-oberSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()-oberSoXSynthNGen3 file m ampL time3 dAmpl zs tts vs = oberSoXSynthNGen3E file m 12 ampL time3 dAmpl zs tts vs+overSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()+overSoXSynthNGen3 file m = overSoXSynthNGen3E file m 12   --- | Similar to 'oberSoXSynthNGen3', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'oberSoXSynthNGen3'. To obtain+-- | Similar to 'overSoXSynthNGen3', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'overSoXSynthNGen3'. To obtain -- its modifications, please, use 2, 3, 4, 6, or 9.-oberSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()-oberSoXSynthNGen3E file m ku ampL time3 dAmpl zs tts vs = do+overSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()+overSoXSynthNGen3E file m ku ampL time3 dAmpl zs tts vs = do   duration0 <- durationA file   let n = truncate (duration0 / 0.001)   vecA <- freqsFromFile file n   let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA-  oberSoXSynthN3 n ampL time3 dAmpl zs tts vs vecB+  overSoXSynthN3 n ampL time3 dAmpl zs tts vs vecB   endFromResult      -- | For the given frequency and a Ukrainian text it generates a musical sound with the timbre obtained from the Ukrainian text (see the@@ -499,21 +495,21 @@ -- and quickly synthesize differently sounding intervals. The main component of the sound includes the lower pure quint, which can be in -- the same octave or in the one with the number lower by one. Please, check before executing  -- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.-uniqOberSoXSynth :: Double -> String -> IO ()-uniqOberSoXSynth x wws = do+uniqOverSoXSynth :: Double -> String -> IO ()+uniqOverSoXSynth x wws = do   let note0 = closestNote x       note1 = pureQuintNote note0-      v0    = uniqOberTonesV note0 wws-      v1    = uniqOberTonesV note1 wws-      uniqOberSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+      v0    = uniqOvertonesV note0 wws+      v1    = uniqOvertonesV note1 wws+      uniqOverSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))         ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN /           fromIntegral l) $ show 0] "") vec-      uniqOberSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+      uniqOverSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))         ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN /           fromIntegral l) $ show 0] "") vec   _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test-.wav", "synth", "0.5","sine", showFFloat (Just 4) note0 $ show 0, "synth", "0.5","sine", "mix", showFFloat (Just 4) note1 $ show 0, "vol","0.5"] ""-  uniqOberSoXSynthHelp v0-  uniqOberSoXSynthHelp2 v1+  uniqOverSoXSynthHelp v0+  uniqOverSoXSynthHelp2 v1   mixTest  -- | For the given frequency and a Ukrainian text it generates a musical sound with the timbre obtained from the Ukrainian text (see the@@ -522,35 +518,35 @@ -- and quickly synthesize differently sounding intervals. The main component of the sound includes the lower pure quint, which can be in -- the same octave or in the one with the number lower by one. Please, check before executing  -- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.--- The second 'String' argument is used to define signs for the harmonics coefficients for obertones.-uniqOberSoXSynth2 :: Double -> String -> String -> IO ()-uniqOberSoXSynth2 x wws tts = do+-- The second 'String' argument is used to define signs for the harmonics coefficients for Overtones.+uniqOverSoXSynth2 :: Double -> String -> String -> IO ()+uniqOverSoXSynth2 x wws tts = do   let note0 = closestNote x       note1 = pureQuintNote note0-      v0    = uniqOberTonesV2 note0 wws tts-      v1    = uniqOberTonesV2 note1 wws tts-      uniqOberSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+      v0    = uniqOvertonesV2 note0 wws tts+      v1    = uniqOvertonesV2 note1 wws tts+      uniqOverSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))         ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN /           fromIntegral l) $ show 0] "") vec-      uniqOberSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+      uniqOverSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))         ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN /           fromIntegral l) $ show 0] "") vec   _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test-.wav", "synth", "0.5","sine", showFFloat (Just 4) note0 $ show 0, "synth",      "0.5","sine", "mix", showFFloat (Just 4) note1 $ show 0, "vol","0.5"] ""-  uniqOberSoXSynthHelp v0-  uniqOberSoXSynthHelp2 v1+  uniqOverSoXSynthHelp v0+  uniqOverSoXSynthHelp2 v1   mixTest  -- | Function to create a melody for the given arguments. The first 'String' is used to provide a rhythm. The second one -- to provide a timbre. -- The timbre for another given text usually differs, but can be the same. This gives an opportunity to practically and quickly--- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for obertones.--- If it is set to 1.0 the obertones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in+-- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones.+-- If it is set to 1.0 the overTones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in -- their becoming more silent ones. The main component of the sound is in the given octave with a number given -- by 'Int' parameter. Besides, another main component of the sound includes the lower pure quint, which can be in the same octave or in the one with -- the number lower by one. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.-uniqOberSoXSynthN :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()-uniqOberSoXSynthN n ampL time3 zs wws vec0+uniqOverSoXSynthN :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN n ampL time3 zs wws vec0  | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =     let (t, ws) = splitAt 1 . syllableStr n $ zs         m     = length ws@@ -558,36 +554,36 @@         v2    = V.map (\yy -> time3 * fromIntegral (yy * m) / fromIntegral (head t)) . V.fromList $ ws in V.imapM_ (\j x -> do              let note0 = closestNote x                         -- zs ? vec0 -- are they related to the one object? No, they are obtained from different sources.               note1 = pureQuintNote note0-              v0    = uniqOberTonesV note0 wws-              v1    = uniqOberTonesV note1 wws-              uniqOberSoXSynthHelpN vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+              v0    = uniqOvertonesV note0 wws+              v1    = uniqOvertonesV note1 wws+              uniqOverSoXSynthHelpN vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,                    "sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l * ampL) $ show 0] "") vec-              uniqOberSoXSynthHelpN2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+              uniqOverSoXSynthHelpN2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,                    "sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l * ampL) $ show 0] "") vec                soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++                  prependZeroes zeroN "1" ++  ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine", showFFloat (Just 4) note01 $                   show 0, "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine", "mix", showFFloat (Just 4) note02 $ show 0, "vol","0.5"]  ""           soxSynthHelpMain note0 note1-          uniqOberSoXSynthHelpN v0-          uniqOberSoXSynthHelpN2 v1+          uniqOverSoXSynthHelpN v0+          uniqOverSoXSynthHelpN2 v1           mixTest) vec0  | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in-    if abs ampL1 < 0.01 then uniqOberSoXSynthN n 0.01 time3 zs wws vec0-    else uniqOberSoXSynthN n ampL1 time3 zs wws vec0+    if abs ampL1 < 0.01 then uniqOverSoXSynthN n 0.01 time3 zs wws vec0+    else uniqOverSoXSynthN n ampL1 time3 zs wws vec0  -- | Function to create a melody for the given arguments. The first 'String' is used to provide a rhythm. The second one -- to provide a timbre. -- The timbre for another given text usually differs, but can be the same. This gives an opportunity to practically and quickly--- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for obertones.--- If it is set to 1.0 the obertones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in+-- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones.+-- If it is set to 1.0 the overTones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in -- their becoming more silent ones. The main component of the sound is in the given octave with a number given -- by 'Int' parameter. Besides, another main component of the sound includes the lower pure quint, which can be in the same octave or in the one with -- the number lower by one. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten. -- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.-uniqOberSoXSynthN3 :: Int -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()-uniqOberSoXSynthN3 n ampL time3 zs wws tts vec0+uniqOverSoXSynthN3 :: Int -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN3 n ampL time3 zs wws tts vec0  | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =     let (t, ws) = splitAt 1 . syllableStr n $ zs         m     = length ws@@ -595,29 +591,29 @@         v2    = V.map (\yy -> time3 * fromIntegral (yy * m) / fromIntegral (head t)) . V.fromList $ ws in V.imapM_ (\j x -> do              let note0 = closestNote x                         -- zs ? vec0 -- are they related to the one object? No, they are obtained from different sources.               note1 = pureQuintNote note0-              v0    = uniqOberTonesV2 note0 wws tts-              v1    = uniqOberTonesV2 note1 wws tts-              uniqOberSoXSynthHelpN vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+              v0    = uniqOvertonesV2 note0 wws tts+              v1    = uniqOvertonesV2 note1 wws tts+              uniqOverSoXSynthHelpN vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,                    "sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l * ampL) $ show 0] "") vec-              uniqOberSoXSynthHelpN2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+              uniqOverSoXSynthHelpN2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,                    "sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l * ampL) $ show 0] "") vec                soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++                 prependZeroes zeroN "1" ++  ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine", showFFloat (Just 4) note01 $                   show 0,"synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine", "mix", showFFloat (Just 4) note02 $ show 0, "vol","0.5"] ""           soxSynthHelpMain note0 note1-          uniqOberSoXSynthHelpN v0-          uniqOberSoXSynthHelpN2 v1+          uniqOverSoXSynthHelpN v0+          uniqOverSoXSynthHelpN2 v1           mixTest) vec0  | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in-    if abs ampL1 < 0.01 then uniqOberSoXSynthN3 n 0.01 time3 zs wws tts vec0-    else uniqOberSoXSynthN3 n ampL1 time3 zs wws tts vec0    +    if abs ampL1 < 0.01 then uniqOverSoXSynthN3 n 0.01 time3 zs wws tts vec0+    else uniqOverSoXSynthN3 n ampL1 time3 zs wws tts vec0      -- | Function to create a melody for the given arguments. The first 'String' is used to provide a rhythm. The second one -- to provide a timbre. -- The timbre for another given text usually differs, but can be the same. This gives an opportunity to practically and quickly--- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for obertones.--- If it is set to 1.0 the obertones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in+-- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones.+-- If it is set to 1.0 the overTones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in -- their becoming more silent ones. The main component of the sound is in the given octave with a number given -- by 'Int' parameter. Besides, another main component of the sound includes the lower pure quint, which can be in the same octave or in the one with -- the number lower by one. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing@@ -625,10 +621,10 @@ -- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds. -- The fourth 'String' argument is used to define the intervals for the notes if any. -- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of--- the main note. If it is rather great, it can signal that the volume for the second note obertones are greater than for the main note obetones.+-- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones. -- The last one is experimental feature.-uniqOberSoXSynthN4 :: Int -> Double -> Double -> Double -> String -> String -> String -> String -> V.Vector Double -> IO ()-uniqOberSoXSynthN4 n ampL time3 dAmpl zs wws tts vs vec0+uniqOverSoXSynthN4 :: Int -> Double -> Double -> Double -> String -> String -> String -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN4 n ampL time3 dAmpl zs wws tts vs vec0  | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =     let (t, ws) = splitAt 1 . syllableStr n $ zs         m     = length ws@@ -638,13 +634,13 @@         v2    = V.map (\yy -> time3 * fromIntegral (yy * m) / fromIntegral (head t)) . V.fromList $ ws in V.imapM_ (\j x -> do              let note0 = closestNote x                         -- zs ? vec0 -- are they related to the one object? No, they are obtained from different sources.               note1 = dNote (V.unsafeIndex v3 (j `rem` l)) note0-              v0    = uniqOberTonesV2 note0 wws tts+              v0    = uniqOvertonesV2 note0 wws tts               v1    = if isNothing note1 then V.empty-                      else uniqOberTonesV2 (fromJust note1) wws tts-              uniqOberSoXSynthHelpN vec = let l1 = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+                      else uniqOvertonesV2 (fromJust note1) wws tts+              uniqOverSoXSynthHelpN vec = let l1 = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,                   "sine",showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l1 * ampL) $ show 0] "") vec-              uniqOberSoXSynthHelpN2 vec = let l1 = V.length vec in V.imapM_ (\i (noteN, amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+              uniqOverSoXSynthHelpN2 vec = let l1 = V.length vec in V.imapM_ (\i (noteN, amplN) -> readProcessWithExitCode (fromJust (showE "sox"))                 ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,                    "sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (if dAmpl * amplN / fromIntegral l * ampL > 1.0 then 1.0 else dAmpl *                       amplN / fromIntegral l * ampL) $ show 0] "") vec @@ -653,69 +649,69 @@                    show 0, "vol","0.5"] ""               soxSynthHelpMain1 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB" ++                  prependZeroes zeroN "1" ++  ".wav", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) $ show 0,"sine", showFFloat (Just 4) note02 $-                   show 0, "vol", showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / fromIntegral 2) $ show 0] ""+                   show 0, "vol", showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / 2) $ show 0] ""           if isNothing note1 then do { soxSynthHelpMain0 note0-                                     ; uniqOberSoXSynthHelpN v0 }+                                     ; uniqOverSoXSynthHelpN v0 }           else do { soxSynthHelpMain0 note0                   ; soxSynthHelpMain1 (fromJust note1)-                  ; uniqOberSoXSynthHelpN v0-                  ; uniqOberSoXSynthHelpN2 v1}+                  ; uniqOverSoXSynthHelpN v0+                  ; uniqOverSoXSynthHelpN2 v1}           mixTest) vec0  | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in-    if abs ampL1 < 0.01 then uniqOberSoXSynthN4 n 0.01 time3 dAmpl zs wws tts vs vec0-    else uniqOberSoXSynthN4 n ampL1 time3 dAmpl zs wws tts vs vec0    +    if abs ampL1 < 0.01 then uniqOverSoXSynthN4 n 0.01 time3 dAmpl zs wws tts vs vec0+    else uniqOverSoXSynthN4 n ampL1 time3 dAmpl zs wws tts vs vec0     --- | Similar to 'uniqOberSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. +-- | Similar to 'uniqOverSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one.  -- Besides, the function lifts the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]).--- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for obertones. If it is set to 1.0 the--- obertones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones.+-- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the+-- overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones. -- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" and \"end.wav\" files in the current directory, because they can be overwritten. -- -- For better usage the 'FilePath' should be a filepath for the .wav file.-uniqOberSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()-uniqOberSoXSynthNGen file m ampL time3 zs wws = uniqOberSoXSynthNGenE file m 12 ampL time3 zs wws+uniqOverSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()+uniqOverSoXSynthNGen file m = uniqOverSoXSynthNGenE file m 12 --- | Similar to 'uniqOberSoXSynthNGen', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOberSoXSynthNGen'. To obtain+-- | Similar to 'uniqOverSoXSynthNGen', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOverSoXSynthNGen'. To obtain -- its modifications, please, use 2, 3, 4, 6, or 9.-uniqOberSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()-uniqOberSoXSynthNGenE file m ku ampL time3 zs wws = do+uniqOverSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()+uniqOverSoXSynthNGenE file m ku ampL time3 zs wws = do   duration0 <- durationA file   let n = truncate (duration0 / 0.001)   vecA <- freqsFromFile file n   let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA-  uniqOberSoXSynthN n ampL time3 zs wws vecB+  uniqOverSoXSynthN n ampL time3 zs wws vecB   endFromResult --- | Similar to 'uniqOberSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. +-- | Similar to 'uniqOverSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one.  -- Besides, the function lifts the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]).--- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for obertones. If it is set to 1.0 the--- obertones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones.+-- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the+-- overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones. -- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" and \"end.wav\" files in the current directory, because they can be overwritten. -- -- For better usage the 'FilePath' should be a filepath for the .wav file. -- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.-uniqOberSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> String -> String -> String -> IO ()-uniqOberSoXSynthNGen3 file m ampL time3 zs wws tts = uniqOberSoXSynthNGen3E file m 12 ampL time3 zs wws tts+uniqOverSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen3 file m = uniqOverSoXSynthNGen3E file m 12 --- | Similar to 'uniqOberSoXSynthNGen3', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOberSoXSynthNGen3'. To obtain+-- | Similar to 'uniqOverSoXSynthNGen3', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOverSoXSynthNGen3'. To obtain -- its modifications, please, use 2, 3, 4, 6, or 9.-uniqOberSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> String -> IO ()-uniqOberSoXSynthNGen3E file m ku ampL time3 zs wws tts = do+uniqOverSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen3E file m ku ampL time3 zs wws tts = do   duration0 <- durationA file   let n = truncate (duration0 / 0.001)   vecA <- freqsFromFile file n   let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA-  uniqOberSoXSynthN3 n ampL time3 zs wws tts vecB+  uniqOverSoXSynthN3 n ampL time3 zs wws tts vecB   endFromResult --- | Similar to 'uniqOberSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. +-- | Similar to 'uniqOverSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one.  -- Besides, the function lifts the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]).--- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for obertones. If it is set to 1.0 the--- obertones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones.+-- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the+-- overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones. -- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" and \"end.wav\" files in the current directory, because they can be overwritten. --@@ -723,19 +719,19 @@ -- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds. -- The fourth 'String' argument is used to define the intervals for the notes if any. -- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of--- the main note. If it is rather great, it can signal that the volume for the second note obertones are greater than for the main note obetones.+-- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones. -- The last one is an experimental feature.-uniqOberSoXSynthNGen4 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()-uniqOberSoXSynthNGen4 file m ampL time3 dAmpl zs wws tts vs = uniqOberSoXSynthNGen4E file m 12 ampL time3 dAmpl zs wws tts vs+uniqOverSoXSynthNGen4 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen4 file m = uniqOverSoXSynthNGen4E file m 12 --- | Similar to 'uniqOberSoXSynthNGen4', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOberSoXSynthNGen4'. To obtain+-- | Similar to 'uniqOverSoXSynthNGen4', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOverSoXSynthNGen4'. To obtain -- its modifications, please, use 2, 3, 4, 6, or 9.-uniqOberSoXSynthNGen4E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()-uniqOberSoXSynthNGen4E file m ku ampL time3 dAmpl zs wws tts vs = do+uniqOverSoXSynthNGen4E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen4E file m ku ampL time3 dAmpl zs wws tts vs = do   duration0 <- durationA file   let n = truncate (duration0 / 0.001)   vecA <- freqsFromFile file n   let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA-  uniqOberSoXSynthN4 n ampL time3 dAmpl zs wws tts vs vecB+  uniqOverSoXSynthN4 n ampL time3 dAmpl zs wws tts vs vecB   endFromResult
DobutokO/Sound/Executable.hs view
@@ -8,6 +8,7 @@ -- A program and a library to create experimental music -- from a mono audio and a Ukrainian text. +{-# LANGUAGE LambdaCase #-} {-# OPTIONS_GHC -threaded #-}  module DobutokO.Sound.Executable (@@ -18,6 +19,7 @@   , dobutokO2H9 ) where +import Control.Monad (void) import System.Exit (ExitCode (ExitSuccess)) import qualified Data.List as L (groupBy,sort) import CaseBi (getBFst')@@ -25,7 +27,7 @@ import Control.Exception (onException) import System.Environment (getArgs) import Data.List (isPrefixOf)-import Data.Maybe (fromJust,isNothing)+import Data.Maybe (fromJust,isNothing,fromMaybe) import Data.Char (isDigit,isSpace) import System.Process import EndOfExe (showE)@@ -58,7 +60,7 @@   let octave1 = read octave::Int       ampL = read ampLS::Double       time3 = read time2::Double-  oberSoXSynthNGen file octave1 ampL time3 args+  overSoXSynthNGen file octave1 ampL time3 args {-# INLINE dobutokO2H1 #-}  dobutokO2H2 :: Bool -> String -> FilePath -> IO ()@@ -67,7 +69,7 @@   let octave1 = read octave::Int       ampL = read ampLS::Double       time3 = read time2::Double-  uniqOberSoXSynthNGen file octave1 ampL time3 args wws+  uniqOverSoXSynthNGen file octave1 ampL time3 args wws {-# INLINE dobutokO2H2 #-}  dobutokO2H3 :: Bool -> String -> FilePath -> IO ()@@ -76,7 +78,7 @@   let octave1 = read octave::Int       ampL = read ampLS::Double       time3 = read time2::Double-  oberSoXSynthNGen2 file octave1 ampL time3 args tts+  overSoXSynthNGen2 file octave1 ampL time3 args tts {-# INLINE dobutokO2H3 #-}  dobutokO2H4 :: Bool -> String -> FilePath -> IO ()@@ -85,7 +87,7 @@   let octave1 = read octave::Int       ampL = read ampLS::Double       time3 = read time2::Double-  uniqOberSoXSynthNGen3 file octave1 ampL time3 args wws tts+  uniqOverSoXSynthNGen3 file octave1 ampL time3 args wws tts {-# INLINE dobutokO2H4 #-}  dobutokO2H5 :: Bool -> String -> FilePath -> IO ()@@ -95,7 +97,7 @@       ampL = read ampLS::Double       time3 = read time2::Double       dAmpl = read dAmpl0::Double-  oberSoXSynthNGen3 file octave1 ampL time3 dAmpl args tts vs+  overSoXSynthNGen3 file octave1 ampL time3 dAmpl args tts vs {-# INLINE dobutokO2H5 #-}  dobutokO2H :: Bool -> String -> FilePath -> IO ()@@ -105,7 +107,7 @@       ampL = read ampLS::Double       time3 = read time2::Double       dAmpl = read dAmpl0::Double-  uniqOberSoXSynthNGen4 file octave1 ampL time3 dAmpl args wws tts vs+  uniqOverSoXSynthNGen4 file octave1 ampL time3 dAmpl args wws tts vs {-# INLINE dobutokO2H #-}  dobutokO2H61 :: Bool -> String -> FilePath -> IO ()@@ -115,11 +117,21 @@       ampL = read ampLS::Double       time3 = read time2::Double       dAmpl = read dAmpl0::Double-  uniqOberSoXSynthNGen4E file nTh enkA ampL time3 dAmpl args wws tts vs+  uniqOverSoXSynthNGen4E file nTh enkA ampL time3 dAmpl args wws tts vs {-# INLINE dobutokO2H61 #-}  dobutokO2H8 :: Bool -> String -> FilePath -> IO ()-dobutokO2H8 _ _ _ = do+dobutokO2H8 _ _ _ = void dobutokO2H8G+{-# INLINE dobutokO2H8 #-}++dobutokO2H80 :: Bool -> String -> FilePath -> IO ()+dobutokO2H80 _ _ _ = dobutokO2H8G >>= \case+    (ExitSuccess, path8v) -> mapM_ removeFile path8v+    _           -> return ()+{-# INLINE dobutokO2H80 #-}++dobutokO2H8G :: Bool -> String -> FilePath -> IO (ExitCode, V.Vector FilePath)+dobutokO2H8G _ _ _ = do   path8s0 <- listDirectory "."   let path8v = V.fromList . L.sort . filter (isPrefixOf "result") $ path8s0       path8v1 = V.generate (V.length path8v `quot` 800) (\i0 -> V.unsafeSlice (i0 * 800) 800 path8v ) `V.snoc` V.unsafeSlice (800 *@@ -135,9 +147,10 @@       if exi1         then do           removeFile "end.wav"-          error $ "The end file \"end.wav\" was not created. "+          error "The end file \"end.wav\" was not created. "         else error "The end file \"end.wav\" was not created. "-{-# INLINE dobutokO2H8 #-}+  return (code1, path8v)+{-# INLINE dobutokO2H8G #-}  dobutokO2H11 :: Bool -> String -> FilePath -> IO () dobutokO2H11 exist2 args file = do@@ -145,7 +158,7 @@   let [enkA,nTh] = map (\z -> read z::Int) . words $ complexNky       ampL = read ampLS::Double       time3 = read time2::Double-  oberSoXSynthNGenE file nTh enkA ampL time3 args+  overSoXSynthNGenE file nTh enkA ampL time3 args {-# INLINE dobutokO2H11 #-}  dobutokO2H21 :: Bool -> String -> FilePath -> IO ()@@ -154,7 +167,7 @@   let [enkA,nTh] = map (\z -> read z::Int) . words $ complexNky       ampL = read ampLS::Double       time3 = read time2::Double-  uniqOberSoXSynthNGenE file nTh enkA ampL time3 args wws+  uniqOverSoXSynthNGenE file nTh enkA ampL time3 args wws {-# INLINE dobutokO2H21 #-}  dobutokO2H31 :: Bool -> String -> FilePath -> IO ()@@ -163,7 +176,7 @@   let [enkA,nTh] = map (\z -> read z::Int) . words $ complexNky       ampL = read ampLS::Double       time3 = read time2::Double-  oberSoXSynthNGen2E file nTh enkA ampL time3 args tts+  overSoXSynthNGen2E file nTh enkA ampL time3 args tts {-# INLINE dobutokO2H31 #-}  dobutokO2H41 :: Bool -> String -> FilePath -> IO ()@@ -172,7 +185,7 @@   let [enkA,nTh] = map (\z -> read z::Int) . words $ complexNky       ampL = read ampLS::Double       time3 = read time2::Double-  uniqOberSoXSynthNGen3E file nTh enkA ampL time3 args wws tts+  uniqOverSoXSynthNGen3E file nTh enkA ampL time3 args wws tts {-# INLINE dobutokO2H41 #-}  dobutokO2H51 :: Bool -> String -> FilePath -> IO ()@@ -182,7 +195,7 @@       ampL = read ampLS::Double       time3 = read time2::Double       dAmpl = read dAmpl0::Double-  oberSoXSynthNGen3E file nTh enkA ampL time3 dAmpl args tts vs+  overSoXSynthNGen3E file nTh enkA ampL time3 dAmpl args tts vs {-# INLINE dobutokO2H51 #-}  dO2H8 :: Int -> V.Vector String -> IO ()@@ -199,29 +212,6 @@         else error $ "The intermediate file " ++ "\"end0" ++ show i ++ ".wav\" was not created. " {-# INLINE dO2H8 #-} -dobutokO2H80 :: Bool -> String -> FilePath -> IO ()-dobutokO2H80 _ _ _ = do-  path8s0 <- listDirectory "."-  let path8v = V.fromList . L.sort . filter (isPrefixOf "result") $ path8s0-      path8v1 = V.generate (V.length path8v `quot` 800) (\i0 -> V.unsafeSlice (i0 * 800) 800 path8v ) `V.snoc` V.unsafeSlice (800 *-         (V.length path8v `quot` 800)) (V.length path8v `rem` 800) path8v -  V.imapM_ dO2H8 path8v1-  epath0s <- listDirectory "."-  let epaths = L.sort . filter (isPrefixOf "end0") $ epath0s-  (code1,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (epaths ++ ["end.wav"]) ""-  case code1 of-    ExitSuccess -> do-      mapM_ removeFile epaths-      mapM_ removeFile $ V.toList path8v-    _           -> do-      exi1 <- doesFileExist "end.wav"-      if exi1-        then do-          removeFile "end.wav"-          error $ "The end file \"end.wav\" was not created. "-        else error "The end file \"end.wav\" was not created. "-{-# INLINE dobutokO2H80 #-}- -- | Actually works as 'pAnR_' function. dobutokO2H9 :: Bool -> String -> FilePath -> IO () dobutokO2H9 _ _ _ = pAnR_@@ -235,8 +225,8 @@   list1 <- recAndProcess file (99::Int)   let yss = divideToStr l0 list1       v01 = V.fromList yss-      mxE = if isNothing (maxLinV v01) then (l0 - 1) else fromJust (maxLinV v01)-      mnE = if isNothing (minLinV v01) then 0 else fromJust (minLinV v01)+      mxE = fromMaybe (l0 - 1) (maxLinV v01)+      mnE = fromMaybe 0 (minLinV v01)       zss = map (filterToBnds mnE mxE) yss       v1 = doubleLtoV zss   V.mapM_ (\idx -> playE (V.unsafeIndex dir0V idx) argss) v1@@ -250,8 +240,8 @@   list1 <- recAndProcess file (999::Int)   let yss = divideToStr l0 list1       v01 = V.fromList yss-      mxE = if isNothing (maxLinV v01) then (l0 - 1) else fromJust (maxLinV v01)-      mnE = if isNothing (minLinV v01) then 0 else fromJust (minLinV v01)+      mxE = fromMaybe (l0 - 1) (maxLinV v01)+      mnE = fromMaybe 0 (minLinV v01)       zss = map (filterToBnds mnE mxE) yss       v1 = doubleLtoV zss   V.mapM_ (\idx -> soxE1 (V.unsafeIndex dir0V idx) argss) v1@@ -261,13 +251,13 @@ divideToStr n = map (parseStoLInts n). lines  isDataStr :: String -> Bool-isDataStr = null . filter (== '@')+isDataStr = notElem '@'  isTextPair :: String -> String -> Bool isTextPair xs ys = isDataStr xs && isDataStr ys  -- | Used to obtain one multiline specially formatted textual input and do the full processment for the sound. --- The function generates obertones using additional 'String' and allows maximum control over the parameters.+-- The function generates overtones using additional 'String' and allows maximum control over the parameters. -- Besides, all the needed information it obtains from the singular formatted input, which can be ended -- with a keyboard keys combination that means an end of input (e. g. for Unices, that is probably Ctrl + D). -- \'@\' are separators for the input parts for their respective parts. For more information about the@@ -292,7 +282,7 @@           octave1 = read (d3H octave0)::Int           ampL = read (d4H ampLS0)::Double           time3 = read (d5H time20)::Double-      uniqOberSoXSynthNGen file octave1 ampL time3 args wws) (do+      uniqOverSoXSynthNGen file octave1 ampL time3 args wws) (do         putStrLn "--------------------------------------------------------------------------------------------------------------------"         putStrLn ""         putStrLn "The operation was not successful because of the not valid textual input. Please, specify a valid textual input. "@@ -302,7 +292,7 @@           octave1 = read (d3H octave0)::Int           ampL = read (d4H ampLS0)::Double           time3 = read (d5H time20)::Double-      uniqOberSoXSynthNGen3 file octave1 ampL time3 args wws (d7H tts0)) (do+      uniqOverSoXSynthNGen3 file octave1 ampL time3 args wws (d7H tts0)) (do         putStrLn "--------------------------------------------------------------------------------------------------------------------"         putStrLn ""         putStrLn "The operation was not successful because of the not valid textual input. Please, specify a valid textual input. "@@ -313,7 +303,7 @@           ampL = read (d4H ampLS0)::Double           time3 = read (d5H time20)::Double           dAmpl = read (d8H dAmpl0)::Double-      uniqOberSoXSynthNGen4 file octave1 ampL time3 dAmpl args wws (d7H tts0) (d9H vs0)) (do+      uniqOverSoXSynthNGen4 file octave1 ampL time3 dAmpl args wws (d7H tts0) (d9H vs0)) (do         putStrLn "--------------------------------------------------------------------------------------------------------------------"         putStrLn ""         putStrLn "The operation was not successful because of the not valid textual input. Please, specify a valid textual input. "@@ -348,9 +338,9 @@ -- | Function records and processes the sound data needed to generate the \"end.wav\" file in the 'dobutokO2' function. Please, check before executing -- whether there is no \"x.wav\" file in the current directory, because it can be overwritten. recAndProcess :: FilePath -> Int -> IO String-recAndProcess file x =+recAndProcess file =   getBFst' (processD, V.fromList [(0,processD0 file),(1,processD1),(2,processD2 file),(3,processD3),(4,processD4),(5,processD5),(7,processD7),-    (8,processD8),(9,processD9),(11,processD_1),(99,processD99),(999,processD999)]) x+    (8,processD8),(9,processD9),(11,processD_1),(99,processD99),(999,processD999)])  processD_1 :: IO String processD_1 = onException (do@@ -400,7 +390,7 @@   tempeRa 0   putStrLn "Please, specify, how many seconds long sound data you would like to record."   time <- getLine-  let time0 = read (filter (\t -> isDigit t || t == '.') $ time)::Double+  let time0 = read (filter (\t -> isDigit t || t == '.') time)::Double   putStrLn "Please, wait for 0.5 second and produce the needed sound now."   recA "x.wav" time0   putStrLn ""@@ -430,7 +420,7 @@                  else tail addit     controlNoiseReduction $ '0':noiseP      norm "_x.wav" -    if isPrefixOf "nx." file +    if "nx." `isPrefixOf` file        then putStr ""        else renameFile "8_x.wav" file      removeFile "x.wav" @@ -449,8 +439,7 @@ processD3 = onException (do   putStr "Please, specify the octave number, to which you would like all the main components (not taking into account their respective lower pure quints) "   putStrLn "should belong. The number should be better in the range [1..8]"-  octave0 <- getLine-  return $ d3H octave0 ) (do+  d3H <$> getLine) (do     putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."     putStrLn "_______________________________________________________________________"     processD3)@@ -462,11 +451,10 @@  processD4 :: IO String processD4 = onException (do-  putStr "Please, specify the amplitude for the generated obertones as an Int number in the range [0..99]. "+  putStr "Please, specify the amplitude for the generated overtones as an Int number in the range [0..99]. "   putStrLn "The default one is 99"   putStrLn "To use the default value, you can simply press Enter."-  amplOb0 <- getLine-  return $ d4H amplOb0) (do+  d4H <$> getLine) (do              putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."              putStrLn "_______________________________________________________________________"              processD4)@@ -487,8 +475,7 @@   putStr "Please, specify the basic duration for the generated sounds as a Double number in the range [0.1..4.0]. "   putStrLn "The default one is 0.5"   putStrLn "To use the default value, you can simply press Enter."-  time0 <- getLine-  return $ d5H time0) (do+  d5H <$> getLine) (do              putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."              putStrLn "_______________________________________________________________________"              processD5)@@ -497,19 +484,18 @@ d5H :: String -> String d5H xs   | null xs = "0.5"-  | otherwise = let time1 = (read (filter (\z -> isDigit z || z == '.') $ xs)::Double) in+  | otherwise = let time1 = (read (filter (\z -> isDigit z || z == '.') xs)::Double) in       if compare time1 0.1 /= LT && compare time1 4.0 /= GT then showFFloat (Just 4) time1 $ show 0       else let mantissa = time1 - (fromIntegral . truncate $ time1)                ceilP    = (truncate time1::Int) `rem` 4 in-             if ceilP == 0 then "0." ++ (showFFloat (Just 4) mantissa $ show 0)-             else show ceilP ++ "." ++ (showFFloat (Just 4) mantissa $ show 0)+             if ceilP == 0 then "0." ++ showFFloat (Just 4) mantissa (show 0)+             else show ceilP ++ "." ++ showFFloat (Just 4) mantissa (show 0) {-# INLINE d5H #-}  processD7 :: IO String processD7 = onException (do   putStrLn "Please, input the Ukrainian text that will be used to define signs for the harmonics coefficients to produce a special timbre for the notes: "-  tts <- getLine-  return $ d7H tts) (do+  d7H <$> getLine) (do     putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."     putStrLn "_______________________________________________________________________"     processD7)@@ -526,8 +512,7 @@   putStr "Please, specify in how many times the amplitude for the second lower note (if any) is greater than the amplitude for the main note. "   putStrLn "The number is in the range [0.1..2.0]. The default one is 1.0"   putStrLn "To use the default value, you can simply press Enter."-  dAmpl0 <- getLine-  return $ d8H dAmpl0) (do+  d8H <$> getLine) (do              putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."              putStrLn "_______________________________________________________________________"              processD8)@@ -536,12 +521,12 @@ d8H :: String -> String d8H xs   | null xs = "1.0"-  | otherwise = let dAmpl1 = (read (filter (\z -> isDigit z || z == '.') $ xs)::Double) in+  | otherwise = let dAmpl1 = (read (filter (\z -> isDigit z || z == '.') xs)::Double) in     if compare dAmpl1 0.1 /= LT && compare dAmpl1 2.0 /= GT then showFFloat (Just 4) dAmpl1 $ show 0     else let mantissa = dAmpl1 - (fromIntegral . truncate $ dAmpl1)              ceilP    = (truncate dAmpl1::Int) `rem` 2 in-           if ceilP == 0 then "0." ++ (showFFloat (Just 4) mantissa $ show 0)-           else show ceilP ++ "." ++ (showFFloat (Just 4) mantissa $ show 0)+           if ceilP == 0 then "0." ++ showFFloat (Just 4) mantissa (show 0)+           else show ceilP ++ "." ++ showFFloat (Just 4) mantissa (show 0) {-# INLINE d8H #-}  processD9 :: IO String@@ -549,8 +534,7 @@   putStrLn "Please, input the Ukrainian text that will be used to define intervals to be used to produce the lower note for the given main one. "   putStrLn "The default one is \"й\". "   putStrLn "To use the default value, you can simply press Enter."-  vs <- getLine-  return $ d9H vs) (do+  d9H <$> getLine) (do     putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."     putStrLn "_______________________________________________________________________"     processD9)@@ -565,8 +549,7 @@ processD :: IO String processD = onException (do   putStrLn "Please, input the Ukrainian text that will be used to create a special timbre for the notes: "-  wws <- getLine-  return wws) (do+  getLine) (do     putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."     putStrLn "_______________________________________________________________________"     processD)@@ -578,8 +561,7 @@   putStr "with SoX effects applied to. The lists must be separated with newline (just press \"Enter\"), empty lists are ignored. If index is "   putStrLn "element of several input lists then if its number of occurrences in all the lists is odd, then it is played, otherwise it is not. "   putStrLn "To end the input, just press the combination that means end of input (e. g. for Unices, it's probably Ctrl + D). "-  wws <- getContents-  return wws) (do+  getContents) (do     putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."     putStrLn "_______________________________________________________________________"     processD)@@ -591,8 +573,7 @@   putStr "with SoX effects applied to. The lists must be separated with newline (just press \"Enter\"), empty lists are ignored. If index is "   putStrLn "element of several input lists then if its number of occurrences in all the lists is odd, then it is played, otherwise it is not. "   putStrLn "To end the input, just press the combination that means end of input (e. g. for Unices, it's probably Ctrl + D). "-  wws <- getContents-  return wws) (do+  getContents) (do     putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."     putStrLn "_______________________________________________________________________"     processD)
DobutokO/Sound/Functional.hs view
@@ -14,14 +14,14 @@ module DobutokO.Sound.Functional (   -- * Type synonyms with different semantics   SoundsO-  , ObertonesO+  , OvertonesO   , NotePairs   -- * Work with notes (general)   , notes   , neighbourNotes   , closestNote   , pureQuintNote -  , oberTones +  , overTones    -- * Work with enky (extension to octaves functionality)   , nkyT   , whichEnka @@ -36,28 +36,36 @@   -- * Working with files   , freqsFromFile   , endFromResult-  -- * Work with obertones-  , oberSoXSynth +  -- * Work with overtones+  , overSoXSynth    -- * Use additional function as a parameter-  , oberSoXSynth2FDN-  , oberSoXSynth2FDN_B+  , overSoXSynth2FDN+  , overSoXSynth2FDN_B   -- ** Just simple function application-  , oberSoXSynth2FDN_S+  , overSoXSynth2FDN_S   -- *** With additional filtering-  , oberSoXSynth2FDN_Sf-  , oberSoXSynth2FDN_Sf3+  , overSoXSynth2FDN_Sf+  , overSoXSynth2FDN_Sf3   -- * Use additional function and Ukrainian texts and generates melody-  , oberSoXSynthGen2FDN-  , oberSoXSynthGen2FDN_B-  , oberSoXSynthGen2FDN_S-  , oberSoXSynthGen2FDN_Sf-  , oberSoXSynthGen2FDN_Sf3+  , overSoXSynthGen2FDN+  , overSoXSynthGen2FDN_B+  , overSoXSynthGen2FDN_S+  , overSoXSynthGen2FDN_Sf+  , overSoXSynthGen2FDN_Sf3   , dNote+  -- * 1G generalized functions with dB volume overtones adjustments+  , overSoXSynth2FDN1G+  , overSoXSynth2FDN_B1G+  , overSoXSynth2FDN_S1G+  , partialTest_k1G   -- * Generalized functions with several functional parameters   , soundGenF3-  , oberSoXSynthGen2FDN_SG-  , oberSoXSynthGen2FDN_Sf3G+  , overSoXSynthGen2FDN_SG+  , overSoXSynthGen2FDN_Sf3G+  -- ** 1G generalized function with db volume overtones adjustments and several functional parameters+  , soundGenF31G   -- ** Auxiliary functions+  , adjust_dbVol   , partialTest_k   , prependZeroes    , nOfZeroesLog @@ -76,7 +84,7 @@ import System.Exit (ExitCode( ExitSuccess )) import Numeric import Data.List (isPrefixOf,sort,sortBy,nubBy)-import Data.Maybe (isNothing,fromJust,isJust)+import Data.Maybe (isNothing,fromJust,fromMaybe,maybe) import qualified Data.Vector as V import System.Process import EndOfExe@@ -88,14 +96,14 @@ -- | Is used to represent a sequence of intervals, each note being a 'Double' value (its frequency in Hz). type SoundsO = V.Vector (Double, Double) --- | Is used to represent a set of obertones for the single sound, the first 'Double' value is a frequency and the second one -- an amplitude.-type ObertonesO = V.Vector (Double, Double)+-- | Is used to represent a set of overtones for the single sound, the first 'Double' value is a frequency and the second one -- an amplitude.+type OvertonesO = V.Vector (Double, Double)  -- | Is used to represent a set of pairs of notes for each element of which the 'Double' values (notes frequencies in Hz) are somewhat -- musically connected one with another.. type NotePairs = V.Vector (Double, Double) --- | Similar to 'oberSoXSynth2DN' but instead of 'oberTones' function, it uses volatile function @f::Double -> Vector (Double, Double)@ with+-- | Similar to 'overSoXSynth2DN' but instead of 'overTones' function, it uses volatile function @f::Double -> Vector (Double, Double)@ with -- somewhat sophisticated mechanism to normalize the resulting 'V.Vector' elements @(Double, Double)@. 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 -- 'convertToProperUkrainian' to the 'String' parameter must not be 'V.empty'. 'Int' argument is an index of the element to be taken from @@ -104,62 +112,68 @@ -- 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 'oberSoXSynth2FDN'.-oberSoXSynth2FDN :: (Double -> ObertonesO) -> (Double, Double) -> Int -> String -> IO ()-oberSoXSynth2FDN f (x, y) j zs- | V.null . convertToProperUkrainian $ zs = oberSoXSynth x+-- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN'.+overSoXSynth2FDN :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()+overSoXSynth2FDN f (x, y) j zs = overSoXSynth2FDN1G f (x, y) j zs (V.replicate (V.length . f . closestNote $ if x /= 0.0 then abs x else V.unsafeIndex notes 0) 0.0)++-- | Is used internally in the 'readProcessWithExitCode' to adjust volume for the sound with additional dB value given by 'Double' argument.+adjust_dbVol :: [String] -> Double -> [String]+adjust_dbVol xss y+ | y == 0.0 = xss+ | otherwise = xss ++ ["vol",showFFloat (Just 4) y (show 0) ++ "dB","0.01"]++-- | 'V.Vector' of 'Double' is a vector of dB volume adjustments for the corresponding harmonices (overtones).+overSoXSynth2FDN1G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> IO ()+overSoXSynth2FDN1G f (x, y) j zs vdB+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x  | otherwise = do     let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)         l0     = length zs         note1 = dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) note0         g0    = V.fromList . nubBy (\(!x1,_) (!x2,_) -> x1 == x2) . V.toList . V.map (\(noteX, !amplX) ->-           if noteX <= 0.0 then (fromIntegral 2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,+           if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,              abs (amplX - (fromIntegral . truncate $ amplX)))) . f         g k   = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .                    V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 k) $ 0), z0)) . g0 $ k          v0    = g note0-        v1    = if isNothing note1 then V.empty-                else g . fromJust $ note1+        v1    = maybe V.empty g note1         ts = showFFloat (Just 4) (abs y) $ show 0 -        oberSoXSynthHelp vec =+        overSoXSynthHelp vec =           let l  = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))             ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat (Just 4) noteN $ show 0,               "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] "") vec-        oberSoXSynthHelp2 vec =+        overSoXSynthHelp2 vec vdB =           let l  = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))-            ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat (Just 4) noteN $ show 0,-              "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] "") vec+            (adjust_dbVol ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat (Just 4) noteN $ show 0,+              "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] (V.unsafeIndex vdB i)) "") vec     _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", showFFloat (Just 4) (abs y) $ show 0,"sine",        showFFloat (Just 4) note0 $ show 0] ""-    if isNothing note1 then do-      oberSoXSynthHelp v0+    if isNothing note1 then overSoXSynthHelp v0     else do        _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB.wav", "synth", showFFloat (Just 4) (abs y) $ show 0,"sine",          showFFloat (Just 4) (fromJust note1) $ show 0] ""-      oberSoXSynthHelp v0-      oberSoXSynthHelp2 v1+      overSoXSynthHelp v0+      overSoXSynthHelp2 v1 vdB     mixTest  -- | 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 'Double' parameter is a -- basic sound duration, it defines tempo of the melody in general.-oberSoXSynthGen2FDN :: FilePath -> Int -> Int -> (Double -> ObertonesO) -> Double -> String -> String -> IO ()-oberSoXSynthGen2FDN file m ku f y zs wws = oberSoXSynthGen2FDN_SG file m ku f y zs wws oberSoXSynth2FDN+overSoXSynthGen2FDN :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()+overSoXSynthGen2FDN file m ku f y zs wws = overSoXSynthGen2FDN_SG file m ku f y zs wws overSoXSynth2FDN  -- | Gets 'V.Vector' of 'Int' frequencies from the given 'FilePath' using SoX. The frequencies are \"rough\" according to the SoX documentation and -- the duration is too small so they can be definitely other than expected ones. Is used as a source of variable numbers (somewhat close each to another -- in their order but not neccessarily). . freqsFromFile :: FilePath -> Int -> IO (V.Vector Int)-freqsFromFile file n = do-  vecA <- V.generateM n (\k -> do {+freqsFromFile file n = V.generateM n (\k -> do {     (_, _, herr) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", showFFloat (Just 4) (fromIntegral k * 0.001) $ show 0,       "0.001", "stat"] ""     ; let line0s = lines herr           noteN0 = takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s     ; if null noteN0 then return (11440::Int)       else let noteN1  = read (takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s)::Int in return noteN1 })-  return vecA  -- | Combines (mixes) all \"test\*" files in the given directory. The files should be similar in parameters and must be sound files for SoX to work -- on them properly. Afterwards, the function deletes these combined files.@@ -187,11 +201,13 @@         putStrLn "Use them manually as needed."      -- | Creates part of the needed \"test\*\.wav" files in the current directory. -partialTest_k :: ObertonesO -> Int -> String -> IO ()+partialTest_k :: OvertonesO -> Int -> String -> IO () partialTest_k vec k ts =   let l     = V.length vec       zeroN = numVZeroesPre vec in V.imapM_ (\i (noteN, !amplN) -> if i /= 0 && i `rem` 50 == 0     then do+      _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test" ++ show k ++ show (i + 2) ++ ".wav", "synth", ts,"sine",+        showFFloat (Just 4) (abs noteN) $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] ""       path1s <- listDirectory "."       let path2s = sort . filter (isPrefixOf $ "test" ++ show k) $ path1s       (code,_,herr0) <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ path2s ++ ["test-" ++ show k ++ prependZeroes zeroN@@ -200,18 +216,38 @@         ExitSuccess -> mapM_ removeFile path2s         _           -> do           exi <- doesFileExist $ "test-" ++ show k ++ prependZeroes zeroN (show (i `quot` 50)) ++ ".wav"-          if exi then putStrLn ("DobutokO.Sound.Functional.partialTest_k: " ++ herr0) >> (removeFile $ "test-" ++ show k ++ prependZeroes zeroN (show (i `quot` 50)) ++ ".wav")+          if exi then putStrLn ("DobutokO.Sound.Functional.partialTest_k: " ++ herr0) >> removeFile ("test-" ++ show k ++ prependZeroes zeroN (show (i `quot` 50)) ++ ".wav")           else putStrLn $ "DobutokO.Sound.Functional.partialTest_k: " ++ herr0     else readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test" ++ show k ++ show (i + 2) ++ ".wav", "synth", ts,"sine",       showFFloat (Just 4) (abs noteN) $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] "" >> putStr "") vec --- | Generates a 'V.Vector' of 'ObertonesO' that represents the melody. The order of elements of the vector is the order of the melody.-doubleVecFromVecOfDouble :: (Double -> ObertonesO) -> Double -> V.Vector (Maybe Double) -> V.Vector ObertonesO-doubleVecFromVecOfDouble f t0 vec =-  V.map (\note1 -> if isNothing note1 then V.empty else V.filter (\(_,!z) -> compare (abs z) t0 == GT) . f . fromJust $ note1) vec-   +-- | Generalized version of the 'partialTest_k' with the additional volume adjustment in dB given by 'V.Vector' of 'Double'.+partialTest_k1G :: OvertonesO -> Int -> String -> V.Vector Double -> IO ()+partialTest_k1G vec k ts vdB =+  let l     = V.length vec+      zeroN = numVZeroesPre vec in V.imapM_ (\i (noteN, !amplN) -> if i /= 0 && i `rem` 50 == 0+    then do+      _ <- readProcessWithExitCode (fromJust (showE "sox")) (adjust_dbVol ["-r22050", "-n", "test" ++ show k ++ show (i + 2) ++ ".wav", "synth", ts,"sine",+        showFFloat (Just 4) (abs noteN) $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] (V.unsafeIndex vdB i)) ""+      path1s <- listDirectory "."+      let path2s = sort . filter (isPrefixOf $ "test" ++ show k) $ path1s+      (code,_,herr0) <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ path2s ++ ["test-" ++ show k ++ prependZeroes zeroN+        (show (i `quot` 50)) ++ ".wav"]) ""+      case code of+        ExitSuccess -> mapM_ removeFile path2s+        _           -> do+          exi <- doesFileExist $ "test-" ++ show k ++ prependZeroes zeroN (show (i `quot` 50)) ++ ".wav"+          if exi then putStrLn ("DobutokO.Sound.Functional.partialTest_k1G: " ++ herr0) >> removeFile ("test-" ++ show k ++ prependZeroes zeroN (show (i `quot` 50)) ++ ".wav")+          else putStrLn $ "DobutokO.Sound.Functional.partialTest_k1G: " ++ herr0+    else readProcessWithExitCode (fromJust (showE "sox")) (adjust_dbVol ["-r22050", "-n", "test" ++ show k ++ show (i + 2) ++ ".wav", "synth", ts,"sine",+      showFFloat (Just 4) (abs noteN) $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] (V.unsafeIndex vdB i)) "" >> putStr "") vec --- | Similar to 'oberSoXSynth2DN' but instead of 'oberTones' function, it uses volatile function @f::Double -> Vector (Double, Double)@ with+-- | Generates a 'V.Vector' of 'OvertonesO' that represents the sound. +doubleVecFromVecOfDouble :: (Double -> OvertonesO) -> Double -> V.Vector (Maybe Double) -> V.Vector OvertonesO+doubleVecFromVecOfDouble f t0 =+  V.map (\note1 -> if isNothing note1 then V.empty else V.filter (\(_,!z) -> compare (abs z) t0 == GT) . f . fromJust $ note1)+   +-- | Similar to 'overSoXSynth2DN' but instead of 'overTones' function, it uses volatile function @f::Double -> Vector (Double, Double)@ with -- somewhat sophisticated mechanism to normalize the resulting 'V.Vector' elements @(Double, Double)@. 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 -- 'convertToProperUkrainian' to the 'String' parameter must not be 'V.empty'. The function also tries to perform filtering to avoid possible beating.@@ -222,53 +258,56 @@ -- 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 'oberSoXSynth2FDN_B'.-oberSoXSynth2FDN_B :: (Double -> ObertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()-oberSoXSynth2FDN_B f (x, y, limB) j zs- | V.null . convertToProperUkrainian $ zs = oberSoXSynth x+-- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_B'.+overSoXSynth2FDN_B :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()+overSoXSynth2FDN_B f (x, y, limB) j zs = overSoXSynth2FDN_B1G f (x, y, limB) j zs (V.replicate (V.length . f . closestNote $ if x /= 0.0 then abs x else V.unsafeIndex notes 0) 0.0)++-- | 'V.Vector' of 'Double' is a vector of dB volume adjustments for the corresponding harmonices (overtones).+overSoXSynth2FDN_B1G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> V.Vector Double -> IO ()+overSoXSynth2FDN_B1G f (x, y, limB) j zs vdB+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x  | otherwise = do-    let limA0 = abs ((limB / fromIntegral 10) - (fromIntegral . truncate $ (limB / fromIntegral 10))) * fromIntegral 10+    let limA0 = abs ((limB / 10) - (fromIntegral . truncate $ (limB / 10))) * 10         limA  = if compare limA0 0.1 == LT then 0.1 else limA0         l0    = length zs         note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)         note1 = dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) note0         g0    = V.fromList . nubBy (\(!x1,_) (!x2,_) -> compare (abs (x1 - x2)) limA == LT) . V.toList . V.map (\(noteX, !amplX) ->-           if noteX <= 0.0 then (fromIntegral 2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,+           if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,              abs (amplX - (fromIntegral . truncate $ amplX)))) . f-        g k   = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .-                   V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 k) $ 0), z0)) . g0 $ k -        v0    = g note0+        v0    = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .+                   V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 note0) $ 0), z0)) . g0 $ note0          v1    = if isNothing note1 then V.empty-                else g . fromJust $ note1+                else V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .+                   V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 . fromJust $ note1) $ 0), z0)) . g0 . fromJust $ note1         ts = showFFloat (Just 4) (abs y) $ show 0 -        oberSoXSynthHelp vec =+        overSoXSynthHelp vec =           let l  = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))             ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat (Just 4) noteN $ show 0,               "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] "") vec-        oberSoXSynthHelp2 vec =+        overSoXSynthHelp2 vec vdB =           let l  = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))-            ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat (Just 4) noteN $ show 0,-              "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] "") vec+            (adjust_dbVol ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat (Just 4) noteN $ show 0,+              "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] (V.unsafeIndex vdB i))"") vec     _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", showFFloat (Just 4) (abs y) $ show 0,"sine",        showFFloat (Just 4) note0 $ show 0] ""-    if isNothing note1 then do-      oberSoXSynthHelp v0+    if isNothing note1 then overSoXSynthHelp v0     else do        _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB.wav", "synth", showFFloat (Just 4) (abs y) $ show 0,"sine",          showFFloat (Just 4) (fromJust note1) $ show 0] ""-      oberSoXSynthHelp v0-      oberSoXSynthHelp2 v1-    mixTest+      overSoXSynthHelp v0+      overSoXSynthHelp2 v1 vdB+    mixTest      -- | 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 'Double' 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]@.-oberSoXSynthGen2FDN_B :: FilePath -> Int -> Int -> (Double -> ObertonesO) -> Double -> Double -> String -> String -> IO ()-oberSoXSynthGen2FDN_B file m ku f y limB zs wws = oberSoXSynthGen2FDN_Sf3G file m ku f y limB zs wws oberSoXSynth2FDN_B+overSoXSynthGen2FDN_B :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Double -> 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 --- | Similar to 'oberSoXSynth2FDN' but it does not make any normalizing transformations with the 'V.Vector' argument. To be used properly, it is needed+-- | Similar to 'overSoXSynth2FDN' but it does not make any normalizing transformations with the 'V.Vector' argument. To be used properly, it is needed -- that every second element in the tuple in the 'V.Vector' 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.@@ -276,22 +315,20 @@ -- 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 'oberSoXSynth2FDN_S'.-oberSoXSynth2FDN_S :: (Double -> ObertonesO) -> (Double, Double) -> Int -> String -> IO ()-oberSoXSynth2FDN_S f (x, y) j zs- | V.null . convertToProperUkrainian $ zs = oberSoXSynth x+-- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_S'.+overSoXSynth2FDN_S :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()+overSoXSynth2FDN_S f (x, y) j zs+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x  | otherwise = do     let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)         l0    = length zs         note1 = dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) note0         v0    = f note0-        v1    = if isNothing note1 then V.empty-                else f . fromJust $ note1+        v1    = maybe V.empty f note1         ts = showFFloat (Just 4) (abs y) $ show 0     _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", showFFloat (Just 4) (abs y) $ show 0,"sine",        showFFloat (Just 4) note0 $ show 0] ""-    if isNothing note1 then do-      partialTest_k v0 0 ts+    if isNothing note1 then partialTest_k v0 0 ts     else do        _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB.wav", "synth", showFFloat (Just 4) (abs y) $ show 0,"sine",          showFFloat (Just 4) (fromJust note1) $ show 0] ""@@ -299,9 +336,30 @@       partialTest_k v1 1 ts     mixTest --- | Similar to 'oberSoXSynthGen2FDN', but instead of 'oberSoXSynth2FDN' uses 'oberSoXSynth2FDN_S' function. -oberSoXSynthGen2FDN_SG :: FilePath -> Int -> Int -> (Double -> ObertonesO) -> Double -> String -> String -> ((Double -> ObertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()-oberSoXSynthGen2FDN_SG file m ku f y zs wws h = do+-- | Generalized version of the 'overSoXSynth2FDN_S' with the additional volume adjustment in dB for overtones given by 'V.Vector' of 'Double'.+overSoXSynth2FDN_S1G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> IO ()+overSoXSynth2FDN_S1G f (x, y) j zs vdB+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x+ | otherwise = do+    let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+        l0    = length zs+        note1 = dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) note0+        v0    = f note0+        v1    = maybe V.empty f note1+        ts = showFFloat (Just 4) (abs y) $ show 0+    _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", showFFloat (Just 4) (abs y) $ show 0,"sine",+       showFFloat (Just 4) note0 $ show 0] ""+    if isNothing note1 then partialTest_k1G v0 0 ts vdB+    else do +      _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB.wav", "synth", showFFloat (Just 4) (abs y) $ show 0,"sine",+         showFFloat (Just 4) (fromJust note1) $ show 0] ""+      partialTest_k1G v0 0 ts vdB+      partialTest_k1G v1 1 ts vdB+    mixTest    ++-- | Similar to 'overSoXSynthGen2FDN', but instead of 'overSoXSynth2FDN' uses 'overSoXSynth2FDN_S' function. +overSoXSynthGen2FDN_SG :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()+overSoXSynthGen2FDN_SG file m ku f y zs wws h = do   duration0 <- durationA file   let n = truncate (duration0 / 0.001)   vecA <- freqsFromFile file n@@ -314,24 +372,24 @@         renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB   endFromResult --- | Similar to 'oberSoXSynthGen2FDN', but instead of 'oberSoXSynth2FDN' uses 'oberSoXSynth2FDN_S' function. -oberSoXSynthGen2FDN_S :: FilePath -> Int -> Int -> (Double -> ObertonesO) -> Double -> String -> String -> IO ()-oberSoXSynthGen2FDN_S file m ku f y zs wws = oberSoXSynthGen2FDN_SG file m ku f y zs wws oberSoXSynth2FDN_S+-- | Similar to 'overSoXSynthGen2FDN', but instead of 'overSoXSynth2FDN' uses 'overSoXSynth2FDN_S' function. +overSoXSynthGen2FDN_S :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()+overSoXSynthGen2FDN_S file m ku f y zs wws = overSoXSynthGen2FDN_SG file m ku f y zs wws overSoXSynth2FDN_S --- | Similar to 'oberSoXSynth2FDN_S' but additionally the program filters out from the resulting 'V.Vector' after \"f\" application values that are smaller+-- | Similar to 'overSoXSynth2FDN_S' but additionally the program filters out from the resulting 'V.Vector' after \"f\" application values that are smaller -- by absolute value than 0.001. 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 'oberSoXSynth2FDN_Sf'.-oberSoXSynth2FDN_Sf :: (Double -> ObertonesO) -> (Double, Double) -> Int -> String -> IO ()-oberSoXSynth2FDN_Sf f (x, y) j zs = oberSoXSynth2FDN_Sf3 f (x, y, 0.001) j zs+-- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_Sf'.+overSoXSynth2FDN_Sf :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()+overSoXSynth2FDN_Sf f (x, y) = overSoXSynth2FDN_Sf3 f (x, y, 0.001) --- | Similar to 'oberSoXSynthGen2FDN_S', but instead of 'oberSoXSynth2FDN_S' uses 'oberSoXSynth2FDN_Sf' function. -oberSoXSynthGen2FDN_Sf :: FilePath -> Int -> Int -> (Double -> ObertonesO) -> Double -> String -> String -> IO ()-oberSoXSynthGen2FDN_Sf file m ku f y zs wws = do+-- | Similar to 'overSoXSynthGen2FDN_S', but instead of 'overSoXSynth2FDN_S' uses 'overSoXSynth2FDN_Sf' function. +overSoXSynthGen2FDN_Sf :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()+overSoXSynthGen2FDN_Sf file m ku f y zs wws = do   duration0 <- durationA file   let n = truncate (duration0 / 0.001)   vecA <- freqsFromFile file n@@ -340,27 +398,26 @@       m0    = length ws       zeroN = numVZeroesPre vecB       v2    = V.map (\yy -> y * fromIntegral (yy * m0) / fromIntegral (head t)) . V.fromList $ ws in V.imapM_ (\j x -> do-        oberSoXSynth2FDN_Sf f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws+        overSoXSynth2FDN_Sf f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws         renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB   endFromResult    --- | Similar to 'oberSoXSynth2FDN_S' but additionally the program filters out from the resulting 'V.Vector' after \"f\" application values that are smaller+-- | Similar to 'overSoXSynth2FDN_S' but additionally the program filters out from the resulting 'V.Vector' after \"f\" application values that are smaller -- than the third 'Double' parameter by an absolute value in the triple of @Double@'s. 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 'oberSoXSynth2FDN_Sf3'.-oberSoXSynth2FDN_Sf3 :: (Double -> ObertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()-oberSoXSynth2FDN_Sf3 f (x, y, t0) j zs- | V.null . convertToProperUkrainian $ zs = oberSoXSynth x+-- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_Sf3'.+overSoXSynth2FDN_Sf3 :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()+overSoXSynth2FDN_Sf3 f (x, y, t0) j zs+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x  | otherwise = do     let l0    = length zs-    soundGenF3 (V.fromList [\x -> closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0),\x -> if isNothing $ dNote-     (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) (closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)) then V.unsafeIndex notes 0-       else fromJust $ dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) (closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0))])-         (V.replicate 2 x) (V.fromList [1,V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))]) f (x, y, t0) j zs+    soundGenF3 (V.fromList [\x -> closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0),\x -> fromMaybe (V.unsafeIndex notes 0)+     (dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) (closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)))])+       (V.replicate 2 x) (V.fromList [1,V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))]) f (x, y, t0) j zs     mixTest  helpF1 :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> V.Vector (Maybe Double)@@ -372,34 +429,49 @@  helpF0 :: Int -> String helpF0 =-  getBFst' ("ZZ0",V.fromList . zip [0..] $ (map (:[]) "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++ concatMap (\z -> map (z:) . map (:[]) $ "ABCDEFGHIJKLMNOPQRSTUVWXYZ")+  getBFst' ("ZZ0",V.fromList . zip [0..] $ (map (:[]) "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++ concatMap (\z -> map ((z:) . (:[])) "ABCDEFGHIJKLMNOPQRSTUVWXYZ")      "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))  --- | Can generates multiple notes with their respective obertones that are played simultaneously (e. g. it can be just one note with obertones,--- an interval with obertones, an accord with obertones etc.). This allows to get a rather complex or even comlicated behaviour to obtain expressive+-- | 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.-soundGenF3 :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> (Double -> ObertonesO) -> (Double, Double, Double) -> Int ->+soundGenF3 :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> (Double -> OvertonesO) -> (Double, Double, Double) -> Int ->   String -> IO () soundGenF3 vf vd vi f (x, y, t0) j zs = do   let vD = helpF1 vf vd vi   -- Vector of notes played simultaneously (e. g. just one, interval, accord etc.)-      vDz = V.mapMaybe id $ vD -- The previous one without Nothings and Justs+      vDz = V.mapMaybe id vD -- The previous one without Nothings and Justs       ilDz = V.length vDz - 1-      vNotes = doubleVecFromVecOfDouble f t0 (V.map (Just) vDz) -- Vector of vectors of pairs (freq,ampl) -- notes and their absence (V.empty) with obertones+      vNotes = doubleVecFromVecOfDouble f t0 (V.map Just vDz) -- Vector of vectors of pairs (freq,ampl) -- notes and their absence (V.empty) with overtones       l0 = length zs       ts = showFFloat (Just 4) (abs y) $ show 0 -- duration of the sound to be generated   V.imapM_ (\i note1 -> do     _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test" ++ helpF0 i ++ ".wav", "synth", showFFloat (Just 4) (abs y) $ show 0,         "sine", showFFloat (Just 4) (V.unsafeIndex vDz i) $ show 0] ""     partialTest_k (V.unsafeIndex vNotes i) i ts) vDz++-- | Generalized variant of the 'soundGenF3' with volume adjustment in dB given by the second @Vector Double@ for the overtones.+soundGenF31G :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> (Double -> OvertonesO) -> (Double, Double, Double) -> Int ->+  String -> V.Vector Double -> IO ()+soundGenF31G vf vd vi f (x, y, t0) j zs vdB = do+  let vD = helpF1 vf vd vi   -- Vector of notes played simultaneously (e. g. just one, interval, accord etc.)+      vDz = V.mapMaybe id vD -- The previous one without Nothings and Justs+      ilDz = V.length vDz - 1+      vNotes = doubleVecFromVecOfDouble f t0 (V.map Just vDz) -- Vector of vectors of pairs (freq,ampl) -- notes and their absence (V.empty) with overtones+      l0 = length zs+      ts = showFFloat (Just 4) (abs y) $ show 0 -- duration of the sound to be generated+  V.imapM_ (\i note1 -> do+    _ <- readProcessWithExitCode (fromJust (showE "sox")) (adjust_dbVol ["-r22050", "-n", "test" ++ helpF0 i ++ ".wav", "synth", showFFloat (Just 4)+      (abs y) $ show 0, "sine", showFFloat (Just 4) (V.unsafeIndex vDz i) $ show 0] (V.unsafeIndex vdB i)) ""+    partialTest_k1G (V.unsafeIndex vNotes i) i ts vdB) vDz           --- | Similar to 'oberSoXSynthGen2FDN_S', but instead of 'oberSoXSynth2FDN_S' uses 'oberSoXSynth2FDN_Sf3' function. -oberSoXSynthGen2FDN_Sf3 :: FilePath -> Int -> Int -> (Double -> ObertonesO) -> Double -> Double -> String -> String -> IO ()-oberSoXSynthGen2FDN_Sf3 file m ku f y t0 zs wws = oberSoXSynthGen2FDN_Sf3G file m ku f y t0 zs wws oberSoXSynth2FDN_Sf3+-- | Similar to 'overSoXSynthGen2FDN_S', but instead of 'overSoXSynth2FDN_S' uses 'overSoXSynth2FDN_Sf3' function. +overSoXSynthGen2FDN_Sf3 :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Double -> String -> String -> IO ()+overSoXSynthGen2FDN_Sf3 file m ku f y t0 zs wws = overSoXSynthGen2FDN_Sf3G file m ku f y t0 zs wws overSoXSynth2FDN_Sf3 --- | Similar to 'oberSoXSynthGen2FDN_S', but instead of 'oberSoXSynth2FDN_S' uses 'oberSoXSynth2FDN_Sf3' function. -oberSoXSynthGen2FDN_Sf3G :: FilePath -> Int -> Int -> (Double -> ObertonesO) -> Double -> Double -> String -> String ->- ((Double -> ObertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()) -> IO ()-oberSoXSynthGen2FDN_Sf3G file m ku f y t0 zs wws h = do+-- | Similar to 'overSoXSynthGen2FDN_S', but instead of 'overSoXSynth2FDN_S' uses 'overSoXSynth2FDN_Sf3' function. +overSoXSynthGen2FDN_Sf3G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Double -> String -> String ->+ ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()) -> IO ()+overSoXSynthGen2FDN_Sf3G file m ku f y t0 zs wws h = do   duration0 <- durationA file   let n = truncate (duration0 / 0.001)   vecA <- freqsFromFile file n@@ -422,7 +494,7 @@ -- | 'V.Vector' of musical notes in Hz. notes :: V.Vector Double -- notes V.! 57 = 440.0   -- A4 in Hz-notes = V.generate 108 (\t ->  fromIntegral 440 * 2 ** (fromIntegral (t - 57) / fromIntegral 12))+notes = V.generate 108 (\t ->  440 * 2 ** (fromIntegral (t - 57) / 12))  -- | Function returns either the nearest two musical notes if frequency is higher than one for C0 and lower than one for B8 -- or the nearest note duplicated in a tuple.@@ -457,16 +529,12 @@ nOfZeroesLog :: Int -> Maybe Int nOfZeroesLog x   | compare x 0 /= GT = Nothing-  | otherwise = Just (truncate (log (fromIntegral x) / log 10) + 1)+  | otherwise = Just (truncate (logBase 10 (fromIntegral x)) + 1) {-# INLINE nOfZeroesLog #-}    -- | Is a minimal number of decimal places that are just enough to represent a length of the 'V.Vector' given. For an 'V.empty' returns 0. numVZeroesPre :: V.Vector a -> Int-numVZeroesPre v =-  let xx = nOfZeroesLog . V.length $ v in-    if isJust xx-      then fromJust xx-      else 0::Int+numVZeroesPre v = fromMaybe (0 :: Int) (nOfZeroesLog . V.length $ v) {-# INLINE numVZeroesPre #-}        -- | Function is used to generate a rhythm of the resulting file \'end.wav\' from the Ukrainian text and a number of sounds either in the syllables or in the words without vowels.@@ -481,7 +549,7 @@ -- | Similarly to 'liftInOctaveV' returns a 'V.Vector' 'Double' (actually frequencies) for the n-th elements set of notes (see 'nkyT') instead of octaves. -- A second 'Int' parameter defines that @n@.  liftInEnkuV :: Int -> Int -> V.Vector Double -> V.Vector Double-liftInEnkuV n ku = V.mapMaybe (\z -> liftInEnku n ku z)+liftInEnkuV n ku = V.mapMaybe (liftInEnku n ku)  -- | Similarly to 'liftInOctave' returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). -- A second 'Int' parameter defines that @n@.@@ -491,12 +559,12 @@   | getBFst' (False, V.fromList . zip [2,3,4,6,9,12] $ repeat True) ku && compare (closestNote x) 24.4996 == GT =       case compare (fromJust . whichEnka ku $ x) n of         EQ -> Just (closestNote x)-        LT -> let z  = log (V.unsafeIndex notes (n * ku) / closestNote x) / log 2.0+        LT -> let z  = logBase 2.0 (V.unsafeIndex notes (n * ku) / closestNote x)                   z1 = truncate z in                    if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001                      then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) (enkuUp ku) $ closestNote x)                      else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) (enkuUp ku) $ closestNote x)-        _  -> let z  = log (closestNote x / V.unsafeIndex notes (n * ku)) / log 2.0+        _  -> let z  = logBase 2.0 (closestNote x / V.unsafeIndex notes (n * ku))                   z1 = truncate z in                    if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001                      then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) (enkuDown ku) $ closestNote x)@@ -519,20 +587,20 @@ -- | Returns an analogous note in the higher n-th elements set (its frequency in Hz) (see 'nkyT'). An 'Int' parameter defines this @n@. enkuUp  :: Int -> Double -> Double enkuUp n x-  | getBFst' (False, V.fromList . zip [2..11] $ repeat True) n = 2 ** (fromIntegral n / fromIntegral 12) * x+  | getBFst' (False, V.fromList . zip [2..11] $ repeat True) n = 2 ** (fromIntegral n / 12) * x   | otherwise = 2 * x {-# INLINE enkuUp #-}    -- | Returns an analogous note in the lower n-th elements set (its frequency in Hz) (see 'nkyT'). An 'Int' parameter defines this @n@. enkuDown  :: Int -> Double -> Double enkuDown n x-  | getBFst' (False, V.fromList . zip [2..11] $ repeat True) n = 2 ** (fromIntegral (-n) / fromIntegral 12) * x-  | otherwise = x / fromIntegral 2+  | getBFst' (False, V.fromList . zip [2..11] $ repeat True) n = 2 ** (fromIntegral (-n) / 12) * x+  | otherwise = x / 2 {-# INLINE enkuDown #-} --- | Function is used to get numbers of intervals from a Ukrainian 'String'. It is used internally in the 'uniqOberSoXSynthN4' function.+-- | Function is used to get numbers of intervals from a Ukrainian 'String'. It is used internally in the 'uniqOverSoXSynthN4' function. intervalsFromString :: String -> V.Vector Int-intervalsFromString vs = vStrToVInt . convertToProperUkrainian $ vs+intervalsFromString = vStrToVInt . convertToProperUkrainian  vStrToVInt :: V.Vector String -> V.Vector Int vStrToVInt = V.map strToInt@@ -561,30 +629,30 @@ -- | For the given frequency it generates a musical sound with a timbre. The main component of the sound includes the lower pure quint, -- which can be in the same octave or in the one with the number lower by one. Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" and \"end.wav\" files in the current directory, because they can be overwritten.-oberSoXSynth :: Double -> IO ()-oberSoXSynth x = do+overSoXSynth :: Double -> IO ()+overSoXSynth x = do   let note0 = if x /= 0.0 then closestNote (abs x) else V.unsafeIndex notes 0       note1 = pureQuintNote note0-      v0    = oberTones note0-      v1    = oberTones note1-      oberSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+      v0    = overTones note0+      v1    = overTones note1+      overSoXSynthHelp vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))         ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN /           fromIntegral l) $ show 0] "") vec-      oberSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+      overSoXSynthHelp2 vec = let l = V.length vec in V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))         ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN $ show 0, "vol", showFFloat (Just 4) (amplN /           fromIntegral l) $ show 0] "") vec   _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test01.wav", "synth", "0.5","sine", showFFloat (Just 4) note0 $ show 0, "synth", "0.5","sine", "mix", showFFloat (Just 4) note1 $ show 0, "vol","0.5"] ""-  oberSoXSynthHelp v0-  oberSoXSynthHelp2 v1+  overSoXSynthHelp v0+  overSoXSynthHelp2 v1   mixTest   -- | Returns a pure quint lower than the given note. pureQuintNote :: Double -> Double-pureQuintNote x = x / 2 ** (fromIntegral 7 / fromIntegral 12)+pureQuintNote x = x / 2 ** (7 / 12) {-# INLINE pureQuintNote #-}  -- | For the given frequency of the note it generates a 'V.Vector' of the tuples, each one of which contains the harmonics' frequency and amplitude.-oberTones :: Double -> ObertonesO-oberTones note =+overTones :: Double -> OvertonesO+overTones note =   V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.zip (V.generate 1024 (\i ->-    note * fromIntegral (i + 2))) $ (V.generate 1024 (\i -> fromIntegral 1 / fromIntegral ((i + 1) * (i + 1))))+    note * fromIntegral (i + 2))) $ (V.generate 1024 (\i -> 1 / fromIntegral ((i + 1) * (i + 1))))
DobutokO/Sound/IntermediateF.hs view
@@ -60,6 +60,7 @@   , playE ) where +import Control.Monad (void) import Control.Concurrent (myThreadId,forkIO,threadDelay,killThread) import qualified Data.List as L (sort) import Control.Exception (onException)@@ -81,8 +82,7 @@ getFileRSizes = do   dirN <- listDirectory "."   let dirN1 = V.fromList . L.sort . filter (isPrefixOf "result") . filter (isSuffixOf ".wav") $ dirN-  sizes <- V.mapM getFileSize dirN1-  return sizes+  V.mapM getFileSize dirN1  -- | Similar to 'getFileRSizes', but sizes are 'Int', not 'Integer'. For most cases it is more memory efficient. getFileRSizesS :: IO (V.Vector Int)@@ -125,7 +125,7 @@         myThread <- myThreadId         playA xs         killThread myThread-      threadDelay (read (show $ truncate (duration * fromIntegral 1000000))::Int)+      threadDelay (read (show $ truncate (duration * 1000000))::Int)       putStr "How do you mark the file that has just been played now -- if of high quality, print \"1\", if of low quality, print \"0\", "       putStrLn "if it is just accepted, press \'Enter\'. "         mark0 <- getLine@@ -134,7 +134,7 @@       case mark of         "1" -> return $ show i ++ "*" ++ xs         "0" -> return $ show i ++ "**" ++ xs-        _   -> return []) vec >>= V.filterM (\t -> return . not . null $ t) +        _   -> return []) vec >>= V.filterM (return . not . null)   -- | Function 'playAndMark' applied to all the \"result\*.wav\" files in the current directory. playAMrk :: IO (V.Vector String)@@ -154,7 +154,7 @@  -- | Gets an index of the 'V.Vector' element corresponding to the 'String' generated by 'playAndMark' function. indexesFromMrk :: String -> Int-indexesFromMrk xs = read (takeWhile (\t1 -> t1 /= '*') xs)::Int+indexesFromMrk xs = read (takeWhile (/= '*') xs)::Int  -- | Used to obtain parameters for processment. internalConv :: ([String],[String]) -> (V.Vector Int, V.Vector String)@@ -200,14 +200,14 @@ playSeqAR index0 = do   (minBnd,maxBnd) <- ixInterv index0   dirV2 <- listVDirectory-  mapM_ (\i -> playA $ V.unsafeIndex dirV2 i) [minBnd..maxBnd]+  mapM_ (playA . V.unsafeIndex dirV2) [minBnd..maxBnd]  -- | Plays a sequence of consequential sounds in the melody in the interval of them obtained by 'ixInterv' function for each element index -- from 'V.Vector' of indexes. playSeqARV :: V.Vector Int -> IO () playSeqARV vec = do   dirV2 <- listVDirectory-  V.mapM_ (\i -> playA $ V.unsafeIndex dirV2 i) vec+  V.mapM_ (playA . V.unsafeIndex dirV2) vec  -- | Plays a sequence of sounds considered of higher quality. playSeqARV2 :: V.Vector String -> IO ()@@ -221,8 +221,7 @@ playCollectDec vec = do   dirV3 <- listVDirectory   let indexesHQs = fst . last . infoFromV $ vec-  vecBools <- V.mapM (playCollect1Dec dirV3) indexesHQs-  return vecBools+  V.mapM (playCollect1Dec dirV3) indexesHQs  -- | Actually replaces the file represented by 'FilePath' argument with no (then there is no replacement at all), or with just one, -- or with a sequence of sounds being considered of higher quality to form a new melody. If the lengths of the second and the third@@ -237,7 +236,7 @@          renameFile "resultI.wav" file0       | otherwise -> putStrLn "Nothing has changed. "     _ -> do-         let yss = V.toList . V.ifilter (\i _ -> V.unsafeIndex vecBools i == True) $ stringHQs+         let yss = V.toList . V.ifilter (\i _ -> V.unsafeIndex vecBools i) $ stringHQs          case length yss of           0 -> putStrLn "That's all!"           1 -> copyFile (head yss) file0@@ -308,7 +307,7 @@ reverbE file arggs = do   (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) ([file,file ++ "reverb.wav","reverb"] ++ arggs) ""   case code of-    ExitSuccess -> do renameFile (file ++ "reverb.wav") file+    ExitSuccess -> renameFile (file ++ "reverb.wav") file     _ -> do        removeFile $ file ++ "reverb.wav"        putStrLn $ "DobutokO.Sound.IntermediateF.reverbE: file \"" ++ file ++ "\" has not been successful. The file has not been changed at all. "@@ -320,7 +319,7 @@ reverb1E file arggs = do   (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) ([file,file ++ "reverb1.wav","reverb"] ++ arggs ++ ["channels","1"]) ""   case code of-    ExitSuccess -> do renameFile (file ++ "reverb1.wav") file+    ExitSuccess -> renameFile (file ++ "reverb1.wav") file     _ -> do        removeFile $ file ++ "reverb1.wav"        putStrLn $ "DobutokO.Sound.IntermediateF.reverb1E: file \"" ++ file ++ "\" has not been successful. The file has not been changed at all. "@@ -333,7 +332,7 @@ reverbWE file arggs = do   (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) ([file,file ++ "reverbW.wav","reverb","-w"] ++ arggs) ""   case code of-    ExitSuccess -> do renameFile (file ++ "reverbW.wav") file+    ExitSuccess -> renameFile (file ++ "reverbW.wav") file     _ -> do        removeFile $ file ++ "reverbW.wav"        putStrLn $ "DobutokO.Sound.IntermediateF.reverbWE: file \"" ++ file ++ "\" has not been successful. The file has not been changed at all. "@@ -345,7 +344,7 @@ reverbW1E file arggs = do   (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) ([file,file ++ "reverbW1.wav","reverb","-w"] ++ arggs ++ ["channels","1"]) ""   case code of-    ExitSuccess -> do renameFile (file ++ "reverbW1.wav") file+    ExitSuccess -> renameFile (file ++ "reverbW1.wav") file     _ -> do        removeFile $ file ++ "reverbW1.wav"        putStrLn $ "DobutokO.Sound.IntermediateF.reverbW1E: file \"" ++ file ++ "\" has not been successful. The file has not been changed at all. "@@ -361,7 +360,7 @@ soxE file arggs = do   (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) ([file,file ++ "effects.wav"] ++ arggs) ""   case code of-    ExitSuccess -> do renameFile (file ++ "effects.wav") file+    ExitSuccess -> renameFile (file ++ "effects.wav") file     _ -> do        removeFile $ file ++ "effects.wav"        putStrLn $ "DobutokO.Sound.IntermediateF.soxE: file \"" ++ file ++ "\" has not been successful. The file has not been changed at all. "@@ -373,7 +372,7 @@ soxE1 file arggs = do   (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) ([file,file ++ "effects.wav"] ++ arggs ++ ["channels","1"]) ""   case code of-    ExitSuccess -> do renameFile (file ++ "effects.wav") file+    ExitSuccess -> renameFile (file ++ "effects.wav") file     _ -> do        removeFile $ file ++ "effects.wav"        putStrLn $ "DobutokO.Sound.IntermediateF.soxE1: file \"" ++ file ++ "\" has not been successful. The file has not been changed at all. "@@ -400,7 +399,7 @@         then return ()         else catchEnd (NotRecorded file)                  | isJust (showE "rec") = do-  (code, _, _) <- readProcessWithExitCode (fromJust (showE "rec")) ([file] ++ arggs) ""+  (code, _, _) <- readProcessWithExitCode (fromJust (showE "rec")) (file:arggs) ""   if code /= ExitSuccess     then do       e0 <- doesFileExist file@@ -461,10 +460,10 @@ playE :: FilePath -> [String] -> IO () playE file arggs | take 5 os == "mingw" =    if isJust (showE "sox") -    then readProcessWithExitCode (fromJust (showE "sox")) ([file, "-t", "waveaudio", "-d"] ++ arggs) "" >> return ()+    then void (readProcessWithExitCode (fromJust (showE "sox")) ([file, "-t", "waveaudio", "-d"] ++ arggs) "")     else catchEnd ExecutableNotProperlyInstalled                  | otherwise = if isJust (showE "play") -  then readProcessWithExitCode (fromJust (showE "play")) ([file] ++ arggs) "" >> return ()+  then void (readProcessWithExitCode (fromJust (showE "play")) ([file] ++ arggs) "")   else catchEnd ExecutableNotProperlyInstalled  -------------------------------------------------------------------------------------------  @@ -493,7 +492,7 @@  -- | Applied to list of @[a]@ where a is an instance for 'Ord' class gives a sorted in the ascending order 'V.Vector' of @a@, each of them being unique. doubleLtoV :: Ord a => [[a]] -> V.Vector a-doubleLtoV xss = V.fromList . shortenL . L.sort . concat $ xss+doubleLtoV = V.fromList . shortenL . L.sort . concat    where shortenL z1@(z:_)           | length (takeWhile (== z) z1) `rem` 2 == 1 = z:shortenL (dropWhile (== z) z1)           | otherwise = shortenL (dropWhile (== z) z1)@@ -501,5 +500,5 @@  -- | Filters 'Int' elements in a list so that they are limited with the first two 'Int' arguments of the function as a lower and a higher bounds. filterToBnds :: Int -> Int -> [Int] -> [Int]-filterToBnds lbnd hbnd xs = filter (\x -> compare x lbnd /= LT && compare x hbnd /= GT) xs+filterToBnds lbnd hbnd = filter (\x -> compare x lbnd /= LT && compare x hbnd /= GT) 
DobutokO/Sound/ParseList.hs view
@@ -15,7 +15,7 @@ import Data.Char (isSpace) import qualified Data.Vector as V import Text.Read (lex,readMaybe)-import Data.Maybe (isNothing,fromJust)+import Data.Maybe (isNothing,fromJust,fromMaybe)  parseTup :: String -> [String] parseTup xs = map (dropWhile isSpace . fst) (takeWhile (/= ("","")) . iterate (head . lex . snd) $ head (lex xs))@@ -128,6 +128,5 @@ -- If it is not possible or list is empty, returns []. Preceding whitespaces are ignored. An 'Int' argument is used as a delimiter to avoid infinite lists. parseStoLInts :: Int -> String -> [Int] parseStoLInts n xs-  | canBePreParseV . parseTupV . dropWhile isSpace $ xs =-     if isNothing . parseV n $ (parseTupV . dropWhile isSpace $ xs) then [] else fromJust . parseV n $ (parseTupV . dropWhile isSpace $ xs)+  | canBePreParseV . parseTupV . dropWhile isSpace $ xs = fromMaybe [] (parseV n (parseTupV . dropWhile isSpace $ xs))   | otherwise = []
README.markdown view
@@ -27,13 +27,13 @@ If the first command line argument equals to one of the numbers below, then the program behaves as follows: -  "1", or "3", or "5" ->  then the executable uses the oberTones functions,-    so for the given parameters the obertones are the same for every call.+  "1", or "3", or "5" ->  then the executable uses the overTones functions,+    so for the given parameters the overtones are the same for every call. -  "2", or "4", or "6" -> then the program uses uniqOberTones functions.+  "2", or "4", or "6" -> then the program uses uniqOverTones functions.    "3", or "4", or "5", or "6" -> the program uses additional String to define-    signs for the harmonics coefficients for obertones.+    signs for the harmonics coefficients for overtones.    "11", or "21", or "31", or "41", or "51", or "61" -> the program works as for      the respective inputs with only the first character in the option@@ -77,23 +77,23 @@   "0" -> the program just converts multiline Ukrainian text from stdin      into a String and prints it to stdout. No other arguments are used. -  "1" -> basic functionality without the possibility to define individual obertones.+  "1" -> basic functionality without the possibility to define individual overtones.    "11" -> the same as "1", but works with enky. See general information above.   -  "2" -> basic functionality with the possibility to define individual obertones.-     In such a case, another text gives the other obertones.+  "2" -> basic functionality with the possibility to define individual overtones.+     In such a case, another text gives the other overtones.    "21" -> the same as "2", but works with enky. See general information above.    "3" -> adittionally to basic functionality gives an opportunity -     to specify the signs for the harmonics coefficients for obertones+     to specify the signs for the harmonics coefficients for overtones        by additional String.    "31" -> the same as "3", but works with enky. See general information above.    "4" -> similarly to "2" gives an opportunity to specify the signs-     for the harmonics coefficients for obertones by additional String.+     for the harmonics coefficients for overtones by additional String.    "41" -> the same as "4", but works with enky. See general information above. @@ -105,12 +105,12 @@    "51" -> the same as "5", but works with enky. See general information above. -  "6" -> the same as "5", but you can define also obertones by an additional String.+  "6" -> the same as "5", but you can define also overtones by an additional String.    "61" -> the same as "6", but works with enky. See general information above.    "7" -> the program behaves like for the "5" option, but generates-     obertones using additional String and allows maximum control over+     overtones using additional String and allows maximum control over        the parameters. Besides, all the needed information it obtains from          the singular formatted input, which can be ended with a keyboard keys            combination that means an end of input (e. g. for Unices, that is@@ -143,7 +143,7 @@   "9", "99", or "999" -> see the information above.                _  -> the program behaves like for the "5" option, but generates-     obertones using additional String and allows maximum control over+     overtones using additional String and allows maximum control over         the parameters.  After the program executing (it takes some time) with the first command line@@ -158,10 +158,15 @@ is not a '0' or '1') by simply pressing 'Enter' while being prompted and the informational message contains the line about the default value. -Starting from the version 0.21.0.0 the package extends its library functions with+Since the 0.21.0.0 version the package extends its library functions with the possibility to create not only single notes or intervals of sounds playing simultaneously but also sets of three, four, five, six, seven or more sounds-played simultanously with their obertones. For more information, please, refer+played simultaneously with their overtones. For more information, please, refer+to the documentation for the DobutokO.Sound.Functional module.++Since the 0.22.0.0 version the library functions are extended also with the+possibility to adjust volume for the overtones using generalized functions '1G'+with adjustment being represented in dB. For more information, please, refer to the documentation for the DobutokO.Sound.Functional module.  ** Note:
dobutokO2.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                dobutokO2-version:             0.21.0.0+version:             0.22.0.0 synopsis:            A program and a library to create experimental music from a mono audio and a Ukrainian text description:         It can also create a timbre for the notes. Uses SoX inside. homepage:            https://hackage.haskell.org/package/dobutokO2