diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -188,3 +188,11 @@
 
 * Twentieth version. Improved behaviour of the functions in the DobutokO.Sound.Functional module. Added new functions to produce melodies. Some minor
 documentation improvements.
+
+## 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
+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.
diff --git a/DobutokO/Sound.hs b/DobutokO/Sound.hs
--- a/DobutokO/Sound.hs
+++ b/DobutokO/Sound.hs
@@ -14,9 +14,7 @@
 module DobutokO.Sound (
   -- * Library and executable functions
   -- ** For the fixed timbre
-  oberTones
-  , oberSoXSynth
-  , oberSoXSynthN
+  oberSoXSynthN
   -- *** For the fixed timbre with different signs for harmonics coefficients
   , oberTones2
   , oberSoXSynth2
@@ -43,19 +41,11 @@
   , uniqOberSoXSynthNGen3
   , uniqOberSoXSynthNGen4
   -- ** Work with octaves
-  , octavesT
   , octaveUp
   , octaveDown
   , whichOctave
   , liftInOctave
   , liftInOctaveV
-  -- * Work with enky (extension to octaves functionality)
-  , nkyT
-  , enkuUp
-  , enkuDown
-  , whichEnka
-  , liftInEnku
-  , liftInEnkuV
   -- ** Even more extended
   , dviykyTA
   , triykyTA
@@ -78,16 +68,7 @@
   , uniqOberSoXSynthNGen3E
   , uniqOberSoXSynthNGen4E
   -- * Auxiliary functions
-  , notes
-  , neighbourNotes
-  , closestNote
-  , pureQuintNote
-  , syllableStr
   , signsFromString
-  , prependZeroes
-  , intervalsFromString
-  , dNote
-  , numVZeroesPre
 ) where
 
 import CaseBi (getBFst')
@@ -107,57 +88,39 @@
 import SoXBasics
 import Processing_mmsyn7ukr
 import Melodics.Ukrainian (convertToProperUkrainian)
-
--- | '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))
-
--- | Returns a 'V.Vector' of tuples with the lowest and highest frequencies for the notes in the octaves.
-octavesT :: V.Vector (Double, Double)
-octavesT = V.generate 9 (\i -> (V.unsafeIndex notes (i * 12), V.unsafeIndex notes (i * 12 + 11)))
-
--- | Returns a 'V.Vector' of tuples with the lowest and highest frequencies for the notes in the sets consisting of @n@ consequential notes
--- (including semi-tones). An 'Int' parameter defines this @n@. It can be 2, 3, 4, 6, 9, or 12 (the last one is for default octaves, see 'octavesT').
--- So for different valid @n@ you obtain doubles, triples and so on. The function being applied returns a 'V.Vector' of such sets with
--- their respective lowest and highest frequencies.
-nkyT :: Int -> V.Vector (Double, Double)
-nkyT n
-  | getBFst' (False,V.fromList . zip [2,3,4,6,9,12] $ repeat True) n = V.generate (108 `quot` n) (\i -> (V.unsafeIndex notes (i * n),
-       V.unsafeIndex notes (i * n + (n - 1))))
-  | otherwise = octavesT
+import DobutokO.Sound.Functional
 
-dviykyTA :: V.Vector (Double, Double)
+dviykyTA :: NotePairs
 dviykyTA = V.generate 107 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 1)))
 
-triykyTA :: V.Vector (Double, Double)
+triykyTA :: NotePairs
 triykyTA = V.generate 106 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 2)))
 
-chetvirkyTA :: V.Vector (Double, Double)
+chetvirkyTA :: NotePairs
 chetvirkyTA = V.generate 105 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 3)))
 
-p'yatirkyTA :: V.Vector (Double, Double)
+p'yatirkyTA :: NotePairs
 p'yatirkyTA = V.generate 104 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 4)))
 
-shistkyTA :: V.Vector (Double, Double)
+shistkyTA :: NotePairs
 shistkyTA = V.generate 103 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 5)))
 
-simkyTA :: V.Vector (Double, Double)
+simkyTA :: NotePairs
 simkyTA = V.generate 102 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 6)))
 
-visimkyTA :: V.Vector (Double, Double)
+visimkyTA :: NotePairs
 visimkyTA = V.generate 101 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 7)))
 
-dev'yatkyTA :: V.Vector (Double, Double)
+dev'yatkyTA :: NotePairs
 dev'yatkyTA = V.generate 100 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 8)))
 
-desyatkyTA :: V.Vector (Double, Double)
+desyatkyTA :: NotePairs
 desyatkyTA = V.generate 99 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 9)))
 
-odynadtsyatkyTA  :: V.Vector (Double, Double)
+odynadtsyatkyTA  :: NotePairs
 odynadtsyatkyTA = V.generate 98 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 10)))
 
-octavesTA :: V.Vector (Double, Double)
+octavesTA :: NotePairs
 octavesTA = V.generate 97 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 11)))
 
 --------------------------------------------------------------------------------------------------------------------------
@@ -167,25 +130,12 @@
 octaveUp x = 2 * x
 {-# INLINE octaveUp #-}
 
--- | 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
-  | otherwise = octaveUp x
-{-# INLINE enkuUp #-}  
 
 -- | Returns an analogous note in the lower octave (its frequency in Hz).
 octaveDown :: Double -> Double
 octaveDown x = x / fromIntegral 2
 {-# INLINE octaveDown #-}
 
--- | 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 = octaveDown x
-{-# INLINE enkuDown #-}
-
 -----------------------------------------------------------------------------------------------------------------------------
 
 -- | Function can be used to determine to which octave (in the American notation for the notes, this is a number in the note written form,
@@ -201,19 +151,6 @@
            _ -> z - 1) t
        _    -> Just 8) . V.findIndex (\(t1, t2) -> compare (closestNote x) t1 == LT) $ octavesT
   | otherwise = Nothing
-
--- | Similarly to 'whichOctave' returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT').
--- An 'Int' parameter defines that @n@.
-whichEnka :: Int -> Double -> Maybe Int
-whichEnka n x
-  | getBFst' (False,V.fromList . zip [2,3,4,6,9,12] $ repeat True) n && compare (closestNote x) 24.4996 == GT = (\t ->
-     case isJust t of 
-       True -> fmap (\z ->
-         case z of
-           0 -> z
-           _ -> z - 1) t
-       _    -> Just ((108 `quot` n) - 1)) . V.findIndex (\(t1, t2) -> compare (closestNote x) t1 == LT) $ nkyT n
-  | otherwise = Nothing    
   
 -- | Function lifts the given frequency to the given number of the octave (in American notation, from 0 to 8). This number is an 'Int' parameter.
 -- The function also takes into account the lower pure quint for the closest note.
@@ -236,85 +173,17 @@
                      else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) octaveDown $ closestNote x)
   | otherwise = Nothing
 
--- | 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@.
-liftInEnku :: Int -> Int -> Double -> Maybe Double
-liftInEnku n ku x
-  | compare n 0 == LT || compare n ((108 `quot` ku) - 1) == GT = Nothing
-  | 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
-                  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
-                  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)
-                     else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) (enkuDown ku) $ closestNote x)
-  | otherwise = Nothing  
-
 -- | Function lifts the 'V.Vector' of 'Double' representing frequencies to the given octave with the 'Int' number. Better to use numbers in the range [1..8].
 -- 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)
 
--- | 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)
-
 --------------------------------------------------------------------------------------------------------------------------------
 
--- | 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.
-neighbourNotes :: Double -> V.Vector Double -> (Double, Double)
-neighbourNotes x v
-  | compare x (V.unsafeIndex v 0) /= GT = (V.unsafeIndex v 0, V.unsafeIndex v 0)
-  | compare x (V.unsafeIndex v (V.length v - 1)) /= LT = (V.unsafeIndex v (V.length v - 1), V.unsafeIndex v (V.length v - 1))
-  | compare (V.length v) 2 == GT = if compare x (V.unsafeIndex  v (V.length v `quot` 2)) /= GT
-      then neighbourNotes x (V.unsafeSlice 0 (V.length v `quot` 2 + 1) v)
-      else neighbourNotes x (V.unsafeSlice (V.length v `quot` 2) (V.length v - (V.length v `quot` 2)) v)
-  | otherwise = (V.unsafeIndex v 0, V.unsafeIndex v (V.length v - 1))
-
--- | Returns the closest note to the given frequency in Hz.  
-closestNote :: Double -> Double
-closestNote x
- | compare x 0.0 == GT =
-    let (x0, x2) = neighbourNotes x notes
-        r0       = x / x0
-        r2       = x2 / x in 
-     if compare r2 r0 == GT
-       then x0
-       else x2
- | otherwise = 0.0
-
--- | Returns a pure quint lower than the given note.
-pureQuintNote :: Double -> Double
-pureQuintNote x = x / 2 ** (fromIntegral 7 / fromIntegral 12)
-{-# INLINE pureQuintNote #-}
-
--- | 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.
-syllableStr :: Int -> String -> [Int]
-syllableStr n xs =
-  let ps = take n . cycle . concat . sylLengthsP2 . syllablesUkrP $ xs
-      y  = sum ps in
-       case y of
-         0 -> [0]
-         _ -> y:ps
-
--- | 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 -> V.Vector (Double, Double)
-oberTones 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))))
-
 -- | 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 -> V.Vector (Double, Double)
+uniqOberTonesV :: Double -> String -> ObertonesO
 uniqOberTonesV note xs =
   let ys = uniquenessPeriods xs
       z  = sum ys
@@ -341,7 +210,7 @@
 
 -- | 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 -> V.Vector (Double, Double)
+oberTones2 :: Double -> String -> ObertonesO
 oberTones2 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)
@@ -350,7 +219,7 @@
 -- | 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 -> V.Vector (Double, Double)
+uniqOberTonesV2 :: Double -> String -> String -> ObertonesO
 uniqOberTonesV2 note xs ts = 
   let ys = uniquenessPeriods xs
       z  = sum ys
@@ -360,29 +229,6 @@
         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
 
--- | 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
-  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"))
-        ["-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"))
-        ["-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
-  paths0 <- listDirectory "."
-  let paths = sort . filter (isPrefixOf "test") $ paths0
-  _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
-  mapM_ removeFile paths
-
 -- | Similar to 'oberSoXSynth' 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.
@@ -407,10 +253,7 @@
     _ <- 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
-  paths0 <- listDirectory "."
-  let paths = sort . filter (isPrefixOf "test") $ paths0
-  _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
-  mapM_ removeFile paths
+  mixTest
 
 -- | Similar to 'oberSoXSynthDN' except that the resulting duration is specified by the second 'Double' parameter in seconds. For 'oberSoXSynthDN'
 -- it is equal to 0.5.
@@ -437,10 +280,7 @@
          showFFloat (Just 4) (fromJust note1) $ show 0, "vol","0.5"] ""
       oberSoXSynthHelp v0
       oberSoXSynthHelp2 v1
-    paths0 <- listDirectory "."
-    let paths = sort . filter (isPrefixOf "test") $ paths0
-    _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
-    mapM_ removeFile paths
+    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
@@ -461,10 +301,7 @@
   _ <- 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
-  paths0 <- listDirectory "."
-  let paths = sort . filter (isPrefixOf "test") $ paths0
-  _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
-  mapM_ removeFile paths  
+  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
@@ -494,10 +331,7 @@
           soxSynthHelpMain note0 note1
           oberSoXSynthHelpN v0
           oberSoXSynthHelpN2 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
+          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
@@ -530,11 +364,7 @@
           soxSynthHelpMain note0 note1
           oberSoXSynthHelpN v0
           oberSoXSynthHelpN2 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
+          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    
@@ -597,28 +427,8 @@
 --
 -- 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 = do
-  duration0 <- durationA file
-  let n = truncate (duration0 / 0.001)
-  vecA <- 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
-        noteN1  = takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s
-  ; if null noteN1 then return (11440::Int)
-      else let noteN2  = read (takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s)::Int in return noteN2 })
-  let vecB = liftInOctaveV m . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
-  oberSoXSynthN n ampL time3 zs vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."
-
+oberSoXSynthNGen file m ampL time3 zs = oberSoXSynthNGenE file m 12 ampL time3 zs
+  
 -- | 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
 -- its modifications, please, use 2, 3, 4, 6, or 9.
@@ -626,24 +436,10 @@
 oberSoXSynthNGenE file m ku ampL time3 zs = do
   duration0 <- durationA file
   let n = truncate (duration0 / 0.001)
-  vecA <- 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
-        noteN1  = takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s
-  ; if null noteN1 then return (11440::Int)
-      else let noteN2  = read (takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s)::Int in return noteN2 })
+  vecA <- freqsFromFile file n
   let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
   oberSoXSynthN n ampL time3 zs vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."        
+  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
 -- 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
@@ -655,28 +451,8 @@
 -- 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 = do
-  duration0 <- durationA file
-  let n = truncate (duration0 / 0.001)
-  vecA <- 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
-        noteN1  = takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s
-  ; if null noteN1 then return (11440::Int)
-      else let noteN2  = read (takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s)::Int in return noteN2 })
-  let vecB = liftInOctaveV m . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
-  oberSoXSynthN2 n ampL time3 zs tts vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."
-
+oberSoXSynthNGen2 file m ampL time3 zs tts = oberSoXSynthNGen2E file m 12 ampL time3 zs tts
+  
 -- | 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
 -- its modifications, please, use 2, 3, 4, 6, or 9.
@@ -684,24 +460,10 @@
 oberSoXSynthNGen2E file m ku ampL time3 zs tts = do
   duration0 <- durationA file
   let n = truncate (duration0 / 0.001)
-  vecA <- 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
-        noteN1  = takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s
-  ; if null noteN1 then return (11440::Int)
-      else let noteN2  = read (takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s)::Int in return noteN2 })
+  vecA <- freqsFromFile file n
   let vecB = liftInEnkuV m ku. V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
   oberSoXSynthN2 n ampL time3 zs tts vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."        
+  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
 -- 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
@@ -717,28 +479,8 @@
 -- 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 last one is experimental feature.
 oberSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()
-oberSoXSynthNGen3 file m ampL time3 dAmpl zs tts vs = do
-  duration0 <- durationA file
-  let n = truncate (duration0 / 0.001)
-  vecA <- 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
-        noteN1  = takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s
-  ; if null noteN1 then return (11440::Int)
-      else let noteN2  = read (takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s)::Int in return noteN2 })
-  let vecB = liftInOctaveV m . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
-  oberSoXSynthN3 n ampL time3 dAmpl zs tts vs vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."
-
+oberSoXSynthNGen3 file m ampL time3 dAmpl zs tts vs = oberSoXSynthNGen3E file m 12 ampL time3 dAmpl zs tts vs
+  
 -- | 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
 -- its modifications, please, use 2, 3, 4, 6, or 9.
@@ -746,47 +488,11 @@
 oberSoXSynthNGen3E file m ku ampL time3 dAmpl zs tts vs = do
   duration0 <- durationA file
   let n = truncate (duration0 / 0.001)
-  vecA <- 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
-        noteN1  = takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s
-  ; if null noteN1 then return (11440::Int)
-      else let noteN2  = read (takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s)::Int in return noteN2 })
+  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
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."        
-  
--- | Additional function to prepend zeroes to the given 'String'. The number of them are just that one to fulfill the length to the given 'Int' parameter.
-prependZeroes :: Int -> String -> String 
-prependZeroes n xs 
-  | if compare n 0 /= GT || null xs then True else compare n (length xs) /= GT = xs
-  | otherwise = replicate (n - length xs) '0' ++ xs
-{-# INLINE prependZeroes #-}  
-
-nOfZeroesLog :: Int -> Maybe Int
-nOfZeroesLog x
-  | compare x 0 /= GT = Nothing
-  | otherwise = Just (truncate (log (fromIntegral x) / log 10) + 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
-{-# INLINE numVZeroesPre #-}      
-  
+  endFromResult
+    
 -- | For the given frequency and a Ukrainian text it generates a musical sound with the timbre obtained from the Ukrainian text (see the
 -- documentation for @mmsyn7s@ package). The timbre for another given text usually differs, but can be the same. The last one is only
 -- if the uniqueness structure and length are the same for both 'String'. Otherwise, they differs. This gives an opportunity to practically
@@ -808,10 +514,7 @@
   _ <- 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
-  paths0 <- listDirectory "."
-  let paths = sort . filter (isPrefixOf "test") $ paths0
-  _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
-  mapM_ removeFile paths
+  mixTest
 
 -- | For the given frequency and a Ukrainian text it generates a musical sound with the timbre obtained from the Ukrainian text (see the
 -- documentation for @mmsyn7s@ package). The timbre for another given text usually differs, but can be the same. The last one is only
@@ -836,10 +539,7 @@
      "0.5","sine", "mix", showFFloat (Just 4) note1 $ show 0, "vol","0.5"] ""
   uniqOberSoXSynthHelp v0
   uniqOberSoXSynthHelp2 v1
-  paths0 <- listDirectory "."
-  let paths = sort . filter (isPrefixOf "test") $ paths0
-  _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
-  mapM_ removeFile paths  
+  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
@@ -868,15 +568,11 @@
                    "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"]
-                    ""
+                  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
-          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
+          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
@@ -913,10 +609,7 @@
           soxSynthHelpMain note0 note1
           uniqOberSoXSynthHelpN v0
           uniqOberSoXSynthHelpN2 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
+          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    
@@ -967,35 +660,11 @@
                   ; soxSynthHelpMain1 (fromJust note1)
                   ; uniqOberSoXSynthHelpN v0
                   ; uniqOberSoXSynthHelpN2 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
+          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    
 
--- | Function is used to get numbers of intervals from a Ukrainian 'String'. It is used internally in the 'uniqOberSoXSynthN4' function.
-intervalsFromString :: String -> V.Vector Int
-intervalsFromString vs = vStrToVInt . convertToProperUkrainian $ vs
-
-vStrToVInt :: V.Vector String -> V.Vector Int
-vStrToVInt = V.map strToInt
-
-strToInt :: String -> Int
-strToInt =
-  getBFst' (0, V.fromList [("а", 12), ("б", 4), ("в", 7), ("г", 3), ("д", 4), ("дж", 5), ("дз", 5), ("е", 12), ("ж", 3), ("з", 8), ("и", 12), 
-    ("й", 7), ("к", 10), ("л", 7), ("м", 7), ("н", 7), ("о", 12), ("п", 10), ("р", 7), ("с", 10), ("т", 2), ("у", 12), ("ф", 2), ("х", 2),
-      ("ц", 11), ("ч", 11), ("ш", 1), ("і", 12), ("ґ", 9)])
-{-# INLINE strToInt #-}      
-
--- | Function to get from the number of semi-tones and a note a 'Maybe' note for the second lower note in the interval if any. If there is
--- no need to obtain such a note, then the result is 'Nothing'.
-dNote :: Int -> Double -> Maybe Double
-dNote n note
-  | n == 0 || compare note (V.unsafeIndex notes 0) == LT || compare note (V.unsafeIndex notes 107) == GT = Nothing
-  | otherwise = Just (note / 2 ** (fromIntegral n / 12))
-
 -- | Similar to 'uniqOberSoXSynthN', 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
@@ -1005,28 +674,7 @@
 --
 -- 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 = do
-  duration0 <- durationA file
-  let n = truncate (duration0 / 0.001)
-  vecA <- 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 })
-  let vecB = liftInOctaveV m . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
-  uniqOberSoXSynthN n ampL time3 zs wws vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."
+uniqOberSoXSynthNGen file m ampL time3 zs wws = uniqOberSoXSynthNGenE file m 12 ampL time3 zs wws
 
 -- | 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
@@ -1035,25 +683,10 @@
 uniqOberSoXSynthNGenE file m ku ampL time3 zs wws = do
   duration0 <- durationA file
   let n = truncate (duration0 / 0.001)
-  vecA <- 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 })
+  vecA <- freqsFromFile file n
   let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
   uniqOberSoXSynthN n ampL time3 zs wws vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."
+  endFromResult
 
 -- | Similar to 'uniqOberSoXSynthN', 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]).
@@ -1065,28 +698,7 @@
 -- 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 = do
-  duration0 <- durationA file
-  let n = truncate (duration0 / 0.001)
-  vecA <- 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 })
-  let vecB = liftInOctaveV m . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
-  uniqOberSoXSynthN3 n ampL time3 zs wws tts vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."
+uniqOberSoXSynthNGen3 file m ampL time3 zs wws tts = uniqOberSoXSynthNGen3E file m 12 ampL time3 zs wws tts
 
 -- | 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
@@ -1095,25 +707,10 @@
 uniqOberSoXSynthNGen3E file m ku ampL time3 zs wws tts = do
   duration0 <- durationA file
   let n = truncate (duration0 / 0.001)
-  vecA <- 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 })
+  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
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."        
+  endFromResult
 
 -- | Similar to 'uniqOberSoXSynthN', 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]).
@@ -1129,28 +726,7 @@
 -- 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 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 = do
-  duration0 <- durationA file
-  let n = truncate (duration0 / 0.001)
-  vecA <- 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 })
-  let vecB = liftInOctaveV m . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
-  uniqOberSoXSynthN4 n ampL time3 dAmpl zs wws tts vs vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."
+uniqOberSoXSynthNGen4 file m ampL time3 dAmpl zs wws tts vs = uniqOberSoXSynthNGen4E file m 12 ampL time3 dAmpl zs wws tts vs
 
 -- | 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
@@ -1159,22 +735,7 @@
 uniqOberSoXSynthNGen4E file m ku ampL time3 dAmpl zs wws tts vs = do
   duration0 <- durationA file
   let n = truncate (duration0 / 0.001)
-  vecA <- 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 })
+  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
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."
+  endFromResult
diff --git a/DobutokO/Sound/Functional.hs b/DobutokO/Sound/Functional.hs
--- a/DobutokO/Sound/Functional.hs
+++ b/DobutokO/Sound/Functional.hs
@@ -12,8 +12,34 @@
 {-# OPTIONS_GHC -threaded #-}
 
 module DobutokO.Sound.Functional (
+  -- * Type synonyms with different semantics
+  SoundsO
+  , ObertonesO
+  , NotePairs
+  -- * Work with notes (general)
+  , notes
+  , neighbourNotes
+  , closestNote
+  , pureQuintNote 
+  , oberTones 
+  -- * Work with enky (extension to octaves functionality)
+  , nkyT
+  , whichEnka 
+  , enkuUp 
+  , enkuDown 
+  , liftInEnkuV
+  , liftInEnku
+  -- ** Work with octaves
+  , octavesT
+  -- * Combining intermediate files
+  , mixTest
+  -- * Working with files
+  , freqsFromFile
+  , endFromResult
+  -- * Work with obertones
+  , oberSoXSynth 
   -- * Use additional function as a parameter
-  oberSoXSynth2FDN
+  , oberSoXSynth2FDN
   , oberSoXSynth2FDN_B
   -- ** Just simple function application
   , oberSoXSynth2FDN_S
@@ -26,21 +52,49 @@
   , oberSoXSynthGen2FDN_S
   , oberSoXSynthGen2FDN_Sf
   , oberSoXSynthGen2FDN_Sf3
+  , dNote
+  -- * Generalized functions with several functional parameters
+  , soundGenF3
+  , oberSoXSynthGen2FDN_SG
+  , oberSoXSynthGen2FDN_Sf3G
+  -- ** Auxiliary functions
+  , partialTest_k
+  , prependZeroes 
+  , nOfZeroesLog 
+  , numVZeroesPre
+  , syllableStr 
+  , intervalsFromString 
+  , vStrToVInt 
+  , strToInt
+  , doubleVecFromVecOfDouble
+  , helpF1
+  , helpF0
 ) where
 
+import CaseBi (getBFst')
 import Data.Char (isDigit)
 import System.Exit (ExitCode( ExitSuccess ))
 import Numeric
 import Data.List (isPrefixOf,sort,sortBy,nubBy)
-import Data.Maybe (isNothing,fromJust)
+import Data.Maybe (isNothing,fromJust,isJust)
 import qualified Data.Vector as V
 import System.Process
 import EndOfExe
 import System.Directory
-import Melodics.Ukrainian
+import Melodics.Ukrainian (convertToProperUkrainian)
 import SoXBasics (durationA)
-import DobutokO.Sound hiding (oberSoXSynth2FDN)
+import MMSyn7.Syllable 
 
+-- | 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 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
 -- 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
@@ -51,7 +105,7 @@
 -- 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 -> V.Vector (Double, Double)) -> (Double, Double) -> Int -> String -> IO ()
+oberSoXSynth2FDN :: (Double -> ObertonesO) -> (Double, Double) -> Int -> String -> IO ()
 oberSoXSynth2FDN f (x, y) j zs
  | V.null . convertToProperUkrainian $ zs = oberSoXSynth x
  | otherwise = do
@@ -84,19 +138,20 @@
          showFFloat (Just 4) (fromJust note1) $ show 0] ""
       oberSoXSynthHelp v0
       oberSoXSynthHelp2 v1
-    paths0 <- listDirectory "."
-    let paths = sort . filter (isPrefixOf "test") $ paths0
-    _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
-    mapM_ removeFile paths
+    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 -> V.Vector (Double, Double)) -> Double -> String -> String -> IO ()
-oberSoXSynthGen2FDN file m ku f y zs wws = do
-  duration0 <- durationA file
-  let n = truncate (duration0 / 0.001)
+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
+
+-- | 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 {
     (_, _, herr) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", showFFloat (Just 4) (fromIntegral k * 0.001) $ show 0,
       "0.001", "stat"] ""
@@ -104,13 +159,22 @@
           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 })
-  let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
-      (t, ws) = splitAt 1 . syllableStr n $ zs
-      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 f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws
-        renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB
+  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.
+mixTest :: IO ()
+mixTest = do
+  paths0 <- listDirectory "."
+  let paths = sort . filter (isPrefixOf "test") $ paths0
+  _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
+  mapM_ removeFile paths
+
+-- | Gets an \"end.wav\" file from the intermediate \"result\*.wav\" files in the current directory. If it is not successful, produces the notification
+-- message and exits without error. If you would like to create the file if there are too many intermediate ones, please, run
+-- \"dobutokO2 8\" or \"dobutokO2 80\" in the current directory.
+endFromResult :: IO ()
+endFromResult = do
   path2s <- listDirectory "."
   let paths3 = sort . filter (isPrefixOf "result") $ path2s
   (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
@@ -120,8 +184,33 @@
       exi <- doesFileExist "end.wav"
       if exi then removeFile "end.wav"
       else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."
+        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 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
+      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_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
+   
+
 -- | Similar to 'oberSoXSynth2DN' but instead of 'oberTones' 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
@@ -134,7 +223,7 @@
 -- 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 -> V.Vector (Double, Double)) -> (Double, Double, Double) -> Int -> String -> IO ()
+oberSoXSynth2FDN_B :: (Double -> ObertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()
 oberSoXSynth2FDN_B f (x, y, limB) j zs
  | V.null . convertToProperUkrainian $ zs = oberSoXSynth x
  | otherwise = do
@@ -169,44 +258,15 @@
          showFFloat (Just 4) (fromJust note1) $ show 0] ""
       oberSoXSynthHelp v0
       oberSoXSynthHelp2 v1
-    paths0 <- listDirectory "."
-    let paths = sort . filter (isPrefixOf "test") $ paths0
-    _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
-    mapM_ removeFile paths
+    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 -> V.Vector (Double, Double)) -> Double -> Double -> String -> String -> IO ()
-oberSoXSynthGen2FDN_B file m ku f y limB zs wws = do
-  duration0 <- durationA file
-  let n = truncate (duration0 / 0.001)
-  vecA <- 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 })
-  let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
-      (t, ws) = splitAt 1 . syllableStr n $ zs
-      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_B f (x, (V.unsafeIndex v2 (j `rem` (V.length v2))), limB) j wws
-        renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."
+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
 
 -- | Similar to 'oberSoXSynth2FDN' 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
@@ -217,7 +277,7 @@
 -- 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 -> V.Vector (Double, Double)) -> (Double, Double) -> Int -> String -> IO ()
+oberSoXSynth2FDN_S :: (Double -> ObertonesO) -> (Double, Double) -> Int -> String -> IO ()
 oberSoXSynth2FDN_S f (x, y) j zs
  | V.null . convertToProperUkrainian $ zs = oberSoXSynth x
  | otherwise = do
@@ -228,84 +288,36 @@
         v1    = if isNothing note1 then V.empty
                 else f . fromJust $ note1
         ts = showFFloat (Just 4) (abs y) $ show 0
-        oberSoXSynthHelp vec =
-          let l     = V.length vec
-              zeroN = numVZeroesPre vec in V.imapM_ (\i (noteN, !amplN) -> if i /= 0 && i `rem` 250 == 0
-            then do
-              path1s <- listDirectory "."
-              let path2s = sort . filter (isPrefixOf "test0") $ path1s
-              (code,_,herr0) <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ path2s ++ ["test-0" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"]) ""
-              case code of
-                ExitSuccess -> mapM_ removeFile path2s
-                _           -> do
-                   exi <- doesFileExist $ "test-0" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"
-                   if exi then putStrLn ("Line 161: " ++ herr0) >> removeFile ("test-0" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav")
-                   else putStrLn $ "Line 162: " ++ herr0 
-            else do
-            _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine",
-              showFFloat (Just 4) (abs noteN) $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] ""
-            return ()) vec
-        oberSoXSynthHelp2 vec =
-          let l     = V.length vec
-              zeroN = numVZeroesPre vec in V.imapM_ (\i (noteN, !amplN) -> if i /= 0 && i `rem` 250 == 0
-            then do
-              path3s <- listDirectory "."
-              let path4s = sort . filter (isPrefixOf "test1") $ path3s
-              (code2,_,herr2) <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ path4s ++ ["test-1" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"]) ""
-              case code2 of
-                ExitSuccess -> mapM_ removeFile path4s
-                _           -> do
-                   exi <- doesFileExist $ "test-1" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"
-                   if exi then putStrLn ("Line 177: " ++ herr2) >> removeFile ("test-1" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav")
-                   else putStrLn $ "Line 178: " ++ herr2
-            else do
-            _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine",
-              showFFloat (Just 4) (abs noteN) $ show 0, "vol", showFFloat (Just 4) (amplN / fromIntegral l) $ show 0] ""
-            return ()) 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
+      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] ""
-      oberSoXSynthHelp v0
-      oberSoXSynthHelp2 v1
-    paths0 <- listDirectory "."
-    let paths = sort . filter (isPrefixOf "test") $ paths0
-    _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
-    mapM_ removeFile paths
+      partialTest_k v0 0 ts
+      partialTest_k v1 1 ts
+    mixTest
 
 -- | Similar to 'oberSoXSynthGen2FDN', but instead of 'oberSoXSynth2FDN' uses 'oberSoXSynth2FDN_S' function. 
-oberSoXSynthGen2FDN_S :: FilePath -> Int -> Int -> (Double -> V.Vector (Double, Double)) -> Double -> String -> String -> IO ()
-oberSoXSynthGen2FDN_S file m ku f y zs wws = do
+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
   duration0 <- durationA file
   let n = truncate (duration0 / 0.001)
-  vecA <- 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 })
+  vecA <- freqsFromFile file n
   let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
       (t, ws) = splitAt 1 . syllableStr n $ zs
       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_S f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws
+        h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws
         renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."
+  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 'oberSoXSynth2FDN_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.
@@ -314,73 +326,15 @@
 -- 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 -> V.Vector (Double, Double)) -> (Double, Double) -> Int -> String -> IO ()
-oberSoXSynth2FDN_Sf f (x, y) j zs
- | V.null . convertToProperUkrainian $ zs = oberSoXSynth 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    = V.filter (\(_,!z) -> compare (abs z) 0.001 == GT) . f $ note0
-        v1    = if isNothing note1 then V.empty
-                else V.filter (\(_,!z) -> compare z 0.001 == GT) . f . fromJust $ note1
-        ts = showFFloat (Just 4) (abs y) $ show 0 
-        oberSoXSynthHelp vec =
-          let l     = V.length vec
-              zeroN = numVZeroesPre vec in V.imapM_ (\i (noteN, !amplN) -> if i /= 0 && i `rem` 250 == 0
-            then do
-              path1s <- listDirectory "."
-              let path2s = sort . filter (isPrefixOf "test0") $ path1s
-              (code,_,herr0) <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ path2s ++ ["test-0" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"]) ""
-              case code of
-                ExitSuccess -> mapM_ removeFile path2s
-                _           -> do
-                   exi <- doesFileExist $ "test-0" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"
-                   if exi then putStrLn ("Line 224: " ++ herr0) >> (removeFile $ "test-0" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav")
-                   else putStrLn $ "Line 225: " ++ herr0
-            else readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test0" ++ 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
-        oberSoXSynthHelp2 vec =
-          let l     = V.length vec
-              zeroN = numVZeroesPre vec in V.imapM_ (\i (noteN, !amplN) -> if i /= 0 && i `rem` 250 == 0
-            then do
-              path3s <- listDirectory "."
-              let path4s = sort . filter (isPrefixOf "test1") $ path3s
-              (code,_,herr1) <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ path4s ++ ["test-1" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"]) ""
-              case code of
-                ExitSuccess -> mapM_ removeFile path4s
-                _           -> do
-                   exi <- doesFileExist $ "test-1" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"
-                   if exi then putStrLn ("Line 239: " ++ herr1) >> (removeFile $ "test-1" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav")
-                   else putStr $ "Line 240: " ++ herr1
-            else readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test1" ++ 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
-    _ <- 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
-    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
-    paths0 <- listDirectory "."
-    let paths = sort . filter (isPrefixOf "test") $ paths0
-    _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
-    mapM_ removeFile paths
+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
 
 -- | Similar to 'oberSoXSynthGen2FDN_S', but instead of 'oberSoXSynth2FDN_S' uses 'oberSoXSynth2FDN_Sf' function. 
-oberSoXSynthGen2FDN_Sf :: FilePath -> Int -> Int -> (Double -> V.Vector (Double, Double)) -> Double -> String -> String -> IO ()
+oberSoXSynthGen2FDN_Sf :: FilePath -> Int -> Int -> (Double -> ObertonesO) -> Double -> String -> String -> IO ()
 oberSoXSynthGen2FDN_Sf file m ku f y zs wws = do
   duration0 <- durationA file
   let n = truncate (duration0 / 0.001)
-  vecA <- 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 })
+  vecA <- freqsFromFile file n
   let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
       (t, ws) = splitAt 1 . syllableStr n $ zs
       m0    = length ws
@@ -388,16 +342,7 @@
       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
         renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."    
+  endFromResult   
 
 -- | Similar to 'oberSoXSynth2FDN_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
@@ -407,87 +352,239 @@
 -- 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 -> V.Vector (Double, Double)) -> (Double, Double, Double) -> Int -> String -> IO ()
+oberSoXSynth2FDN_Sf3 :: (Double -> ObertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()
 oberSoXSynth2FDN_Sf3 f (x, y, t0) j zs
  | V.null . convertToProperUkrainian $ zs = oberSoXSynth 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    = V.filter (\(_,!z) -> compare (abs z) t0 == GT) . f $ note0
-        v1    = if isNothing note1 then V.empty
-                else V.filter (\(_,!z) -> compare (abs z) t0 == GT) . f . fromJust $ note1
-        ts = showFFloat (Just 4) (abs y) $ show 0 
-        oberSoXSynthHelp vec =
-          let l     = V.length vec
-              zeroN = numVZeroesPre vec in V.imapM_ (\i (noteN, !amplN) -> if i /= 0 && i `rem` 250 == 0
-            then do
-              path1s <- listDirectory "."
-              let path2s = sort . filter (isPrefixOf "test0") $ path1s
-              (code,_,herr0) <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ path2s ++ ["test-0" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"]) ""
-              case code of
-                ExitSuccess -> mapM_ removeFile path2s
-                _           -> do
-                   exi <- doesFileExist $ "test-0" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"
-                   if exi then putStrLn ("Line 285: " ++ herr0) >> (removeFile $ "test-0" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav")
-                   else putStrLn $ "Line 286: " ++ herr0
-            else readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test0" ++ 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
-        oberSoXSynthHelp2 vec =
-          let l     = V.length vec
-              zeroN = numVZeroesPre vec in V.imapM_ (\i (noteN, !amplN) -> if i /= 0 && i `rem` 250 == 0
-            then do
-              path3s <- listDirectory "."
-              let path4s = sort . filter (isPrefixOf "test1") $ path3s
-              (code,_,herr1) <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ path4s ++ ["test-1" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"]) ""
-              case code of
-                ExitSuccess -> mapM_ removeFile path4s
-                _           -> do
-                   exi <- doesFileExist $ "test-1" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav"
-                   if exi then putStrLn ("Line 300: " ++ herr1) >> (removeFile $ "test-1" ++ prependZeroes zeroN (show (i `quot` 250)) ++ ".wav")
-                   else putStrLn $ "Line 301: " ++ herr1
-            else readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test1" ++ 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
-    _ <- 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
-    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
-    paths0 <- listDirectory "."
-    let paths = sort . filter (isPrefixOf "test") $ paths0
-    _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""
-    mapM_ removeFile paths
+    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
+    mixTest
 
+helpF1 :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> V.Vector (Maybe Double)
+helpF1 vf vd =
+  V.map (\(f1,x,i2) ->
+    case i2 of
+      0 -> Nothing
+      _ -> Just $ f1 x) . V.zip3 vf vd
+
+helpF0 :: Int -> String
+helpF0 =
+  getBFst' ("ZZ0",V.fromList . zip [0..] $ (map (:[]) "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++ concatMap (\z -> map (z:) . map (:[]) $ "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
+-- and rich sound.
+soundGenF3 :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> (Double -> ObertonesO) -> (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
+      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
+      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
+      
 -- | Similar to 'oberSoXSynthGen2FDN_S', but instead of 'oberSoXSynth2FDN_S' uses 'oberSoXSynth2FDN_Sf3' function. 
-oberSoXSynthGen2FDN_Sf3 :: FilePath -> Int -> Int -> (Double -> V.Vector (Double, Double)) -> Double -> Double -> String -> String -> IO ()
-oberSoXSynthGen2FDN_Sf3 file m ku f y t0 zs wws = do
+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 '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
   duration0 <- durationA file
   let n = truncate (duration0 / 0.001)
-  vecA <- 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 })
+  vecA <- freqsFromFile file n
   let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA
       (t, ws) = splitAt 1 . syllableStr n $ zs
       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_Sf3 f (x, (V.unsafeIndex v2 (j `rem` (V.length v2))), t0) j wws
+        h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2))), t0) j wws
         renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB
-  path2s <- listDirectory "."
-  let paths3 = sort . filter (isPrefixOf "result") $ path2s
-  (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""
-  case code of
-    ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "
-    _           -> do
-      exi <- doesFileExist "end.wav"
-      if exi then removeFile "end.wav"
-      else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>
-        putStrLn "Use them manually as needed."    
+  endFromResult
+
+-- | Function to get from the number of semi-tones and a note a 'Maybe' note for the second lower note in the interval if any. If there is
+-- no need to obtain such a note, then the result is 'Nothing'.
+dNote :: Int -> Double -> Maybe Double
+dNote n note
+  | n == 0 || compare note (V.unsafeIndex notes 0) == LT || compare note (V.unsafeIndex notes 107) == GT = Nothing
+  | otherwise = Just (note / 2 ** (fromIntegral n / 12))
+
+-- | '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))
+
+-- | 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.
+neighbourNotes :: Double -> V.Vector Double -> (Double, Double)
+neighbourNotes x v
+  | compare x (V.unsafeIndex v 0) /= GT = (V.unsafeIndex v 0, V.unsafeIndex v 0)
+  | compare x (V.unsafeIndex v (V.length v - 1)) /= LT = (V.unsafeIndex v (V.length v - 1), V.unsafeIndex v (V.length v - 1))
+  | compare (V.length v) 2 == GT = if compare x (V.unsafeIndex  v (V.length v `quot` 2)) /= GT
+      then neighbourNotes x (V.unsafeSlice 0 (V.length v `quot` 2 + 1) v)
+      else neighbourNotes x (V.unsafeSlice (V.length v `quot` 2) (V.length v - (V.length v `quot` 2)) v)
+  | otherwise = (V.unsafeIndex v 0, V.unsafeIndex v (V.length v - 1))
+
+-- | Returns the closest note to the given frequency in Hz.  
+closestNote :: Double -> Double
+closestNote x
+ | compare x 0.0 == GT =
+    let (x0, x2) = neighbourNotes x notes
+        r0       = x / x0
+        r2       = x2 / x in 
+     if compare r2 r0 == GT
+       then x0
+       else x2
+ | otherwise = 0.0
+
+-- | Additional function to prepend zeroes to the given 'String'. The number of them are just that one to fulfill the length to the given 'Int' parameter.
+prependZeroes :: Int -> String -> String 
+prependZeroes n xs 
+  | if compare n 0 /= GT || null xs then True else compare n (length xs) /= GT = xs
+  | otherwise = replicate (n - length xs) '0' ++ xs
+{-# INLINE prependZeroes #-}  
+
+nOfZeroesLog :: Int -> Maybe Int
+nOfZeroesLog x
+  | compare x 0 /= GT = Nothing
+  | otherwise = Just (truncate (log (fromIntegral x) / log 10) + 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
+{-# 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.
+syllableStr :: Int -> String -> [Int]
+syllableStr n xs =
+  let ps = take n . cycle . concat . sylLengthsP2 . syllablesUkrP $ xs
+      y  = sum ps in
+       case y of
+         0 -> [0]
+         _ -> y:ps   
+
+-- | 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)
+
+-- | 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@.
+liftInEnku :: Int -> Int -> Double -> Maybe Double
+liftInEnku n ku x
+  | compare n 0 == LT || compare n ((108 `quot` ku) - 1) == GT = Nothing
+  | 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
+                  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
+                  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)
+                     else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) (enkuDown ku) $ closestNote x)
+  | otherwise = Nothing
+
+-- | Similarly to 'whichOctave' returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT').
+-- An 'Int' parameter defines that @n@.
+whichEnka :: Int -> Double -> Maybe Int
+whichEnka n x
+  | getBFst' (False,V.fromList . zip [2,3,4,6,9,12] $ repeat True) n && compare (closestNote x) 24.4996 == GT = (\t ->
+     case isJust t of 
+       True -> fmap (\z ->
+         case z of
+           0 -> z
+           _ -> z - 1) t
+       _    -> Just ((108 `quot` n) - 1)) . V.findIndex (\(t1, t2) -> compare (closestNote x) t1 == LT) $ nkyT n
+  | otherwise = Nothing
+
+-- | 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
+  | 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
+{-# INLINE enkuDown #-}
+
+-- | Function is used to get numbers of intervals from a Ukrainian 'String'. It is used internally in the 'uniqOberSoXSynthN4' function.
+intervalsFromString :: String -> V.Vector Int
+intervalsFromString vs = vStrToVInt . convertToProperUkrainian $ vs
+
+vStrToVInt :: V.Vector String -> V.Vector Int
+vStrToVInt = V.map strToInt
+
+strToInt :: String -> Int
+strToInt =
+  getBFst' (0, V.fromList [("а", 12), ("б", 4), ("в", 7), ("г", 3), ("д", 4), ("дж", 5), ("дз", 5), ("е", 12), ("ж", 3), ("з", 8), ("и", 12), 
+    ("й", 7), ("к", 10), ("л", 7), ("м", 7), ("н", 7), ("о", 12), ("п", 10), ("р", 7), ("с", 10), ("т", 2), ("у", 12), ("ф", 2), ("х", 2),
+      ("ц", 11), ("ч", 11), ("ш", 1), ("і", 12), ("ґ", 9)])
+{-# INLINE strToInt #-}       
+
+-- | Returns a 'V.Vector' of tuples with the lowest and highest frequencies for the notes in the sets consisting of @n@ consequential notes
+-- (including semi-tones). An 'Int' parameter defines this @n@. It can be 2, 3, 4, 6, 9, or 12 (the last one is for default octaves, see 'octavesT').
+-- So for different valid @n@ you obtain doubles, triples and so on. The function being applied returns a 'V.Vector' of such sets with
+-- their respective lowest and highest frequencies.
+nkyT :: Int -> NotePairs
+nkyT n
+  | getBFst' (False,V.fromList . zip [2,3,4,6,9,12] $ repeat True) n = V.generate (108 `quot` n) (\i -> (V.unsafeIndex notes (i * n),
+       V.unsafeIndex notes (i * n + (n - 1))))
+  | otherwise = octavesT
+
+-- | Returns a 'V.Vector' of tuples with the lowest and highest frequencies for the notes in the octaves.
+octavesT :: NotePairs
+octavesT = V.generate 9 (\i -> (V.unsafeIndex notes (i * 12), V.unsafeIndex notes (i * 12 + 11)))
+
+-- | 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
+  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"))
+        ["-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"))
+        ["-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
+  mixTest 
+
+-- | Returns a pure quint lower than the given note.
+pureQuintNote :: Double -> Double
+pureQuintNote x = x / 2 ** (fromIntegral 7 / fromIntegral 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 =
+  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))))
diff --git a/README.markdown b/README.markdown
--- a/README.markdown
+++ b/README.markdown
@@ -158,6 +158,12 @@
 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
+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.
+
 ** Note:
 
 * Better to execute in the RAM. Need rather a lot of space on the disk for
diff --git a/dobutokO2.cabal b/dobutokO2.cabal
--- a/dobutokO2.cabal
+++ b/dobutokO2.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                dobutokO2
-version:             0.20.0.0
+version:             0.21.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
