mmsyn7ukr (empty) → 0.1.0.0
raw patch · 8 files changed
+623/−0 lines, 8 filesdep +basedep +directorydep +mmsyn2setup-changed
Dependencies added: base, directory, mmsyn2, mmsyn3, mmsyn6ukr, process, vector
Files
- ChangeLog.md +5/−0
- LICENSE +20/−0
- Main.hs +179/−0
- README +63/−0
- Setup.hs +2/−0
- SoXBasics.hs +255/−0
- UkrainianLControl.hs +66/−0
- mmsyn7ukr.cabal +33/−0
+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for mmsyn7ukr++## 0.1.0.0 -- 2019-12-19++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2019 OleksandrZhabenko++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Main.hs view
@@ -0,0 +1,179 @@+-- |+-- Module : Main+-- Copyright : (c) OleksandrZhabenko 2019+-- License : MIT+--+-- Maintainer : olexandr543@yahoo.com+--+-- A program and a library that can be used as a simple basic interface to some SoX functionality +-- or for producing the approximately Ukrainian speech with your own recorded voice.+--++module Main where++import System.Directory+import Control.Exception (bracketOnError, onException)+import EndOfExe (showE)+import Data.Maybe (fromJust)+import Data.Char+import Data.List (isSuffixOf)+import qualified Data.Vector as V+import System.Process+import System.IO+import SoXBasics+import Melodics.Ukrainian (appendS16LEFile, convertToProperUkrainian)+import Paths_mmsyn6ukr+import UkrainianLControl+import CaseBi (getBFst')++-- | Function responds for general program execution. It starts with Caution to be responsible for usage and to +-- use it personally. Then the program guides you through the creating and using your Ukrainian \"voice\". +-- Please, use it carefully. After the execution the program if terminated naturally without interruption +-- removes (cleans) all the created sound files in the current directory for security reasons. If it terminates +-- by interruption or in general it is a good practice to remove the current directory sound files manually.+-- +main :: IO ()+main = do+ putStrLn " ***** CAUTION! *****"+ putStrLn ""+ putStrLn "With great power comes great responsibility"+ putStrLn ""+ putStrLn "The program mmsyn7ukr produces the approximately Ukrainian speech with your own recorded voice."+ putStr " It approximates your voice with a sequence of recorded separate sounds with your control over "+ putStr "the duration of the sounds. They are then precessed by the SoX binaries in the system"+ putStrLn " to produce the needed sounds and then you can spell some Ukrainian text with your recorded \"voice\"."+ putStr "Be aware that if somebody can get access to the sounds of your voice or to the recorded speech except you "+ putStrLn "then this possibility creates security issues and concerns. So, please, do NOT give access to the records to anybody else except you."+ putStrLn ""+ putStrLn "The program is for personal usage of every user ONLY!"+ putStrLn ""+ putStr "As an advice, run the program in the empty writable, readable and seekable diractory only for the current user -- better in the RAM, "+ putStr "wait until the program ends and then reboot the computer. If the program ends earlier, you must then remove (better wipe) the directory "+ putStr "contents. No other users should have access to the computer "+ putStr "after you have begun to run the program and have not deleted (or better wiped) the contents of the directory."+ putStr " Please, be aware, that there are possibilities to read sensitive information from the drives after you have "+ putStr "deleted the files in a usual way. You can use wiping for better security. Besides, if somebody can get access "+ putStr "to the memory of the computer or to the directory contents where you run the program or (may be) to the temporary "+ putStr "files created by SoX or to the drive where you run the program (not in the RAM, or may be in it) "+ putStr "then your \"voice\" can be stolen and / or used inappropriately. Use all possible precautions and measures to avoid the "+ putStrLn "situation."+ putStr "Be aware also that the given by the program technology (or documentation for it in any form) of the voice processing can be improved so there is NO guarantees "+ putStr "that the given technology or its successors cannot be used in violating your voice identity to produce from some voice records available "+ putStr "the \"voice\" for the inappropriate or illegal usage. So, better is to proove your identity not only with the solely voice itself but "+ putStrLn "with some additional independent sources and measures. "+ putStr "The author of the program accordingly to the LICENSE (MIT) does not response for any possible issues, but by this notification tries to "+ putStrLn "intent you to be aware of some possible issues."+ putStrLn ""+ onException (do + let eS = fromJust (showE "sox")+ eSi = fromJust (showE "soxi")+ eSp = fromJust (showE "play")+ eSr = fromJust (showE "rec")+ return ()) (error "SoX is not properly installed in your system. Please, install it properly and the run the program again! ")+ paths <- mapM getDataFileName ["A.wav", "B.wav", "C.wav", "D.wav", "E.wav", "F.wav", "G.wav", "H.wav", + "I.wav", "J.wav", "K.wav", "L.wav", "M.wav", "N.wav", "O.wav", "P.wav", "Q.wav", "R.wav", + "S.wav", "T.wav", "U.wav", "V.wav", "W.wav", "X.wav", "Y.wav", "Z.wav", "a.wav", "b.wav", "c.wav", + "d.wav", "e.wav", "f.wav"]+ copiedFs <- mapM getDataFileName ["-.wav", "0.wav", "1.wav"]+ mapM_ produceSound paths+ currD <- getCurrentDirectory+ mapM_ (flip copyFile currD) copiedFs+ putStrLn ""+ putStrLn "Your voice sound files are now created in the current directory! Use in a secure way! Remember thu initial CAUTION! "+ putStrLn ""+ createAndPlayFs+ cleanTemp+ cleanCreatedSoundFs+ return ()+ +-- | Function that being given a path to the installed by the @mmsyn6ukr@ package file produces the corresponding analogous sound with your created +-- voicing.+produceSound :: FilePath -> IO ()+produceSound file = let file1 = drop (length file - 5) file in do+ let soundUkr = getBFst' ("е", V.fromList . zip ["A.wav", "B.wav", "C.wav", "D.wav", "E.wav", "F.wav", "G.wav", "H.wav", + "I.wav", "J.wav", "K.wav", "L.wav", "M.wav", "N.wav", "O.wav", "P.wav", "Q.wav", "R.wav", + "S.wav", "T.wav", "U.wav", "V.wav", "W.wav", "X.wav", "Y.wav", "Z.wav", "a.wav", "b.wav", "c.wav", + "d.wav", "e.wav", "f.wav"] $ ["а", "б", "в", "г", "д", "дж", "дз", "е", "ж", "з", "и", "й", "к", "л", "м", "н", "о", "п", "р", + "с", "сь", "т", "у", "ф", "х", "ц", "ць", "ч", "ш", "ь", "і", "ґ"]) $ file1+ putStrLn $ "Listen to the \"" ++ soundUkr ++ "\" sound and note first of all its duration. "+ playA file+ longerK0 <- tempS soundUkr+ (_, Just hout, _, _) <- createProcess (proc (fromJust . showE $ "soxi") ["-D", file]) { std_out = CreatePipe }+ x3 <- hGetContents hout+ let longerK = (read x3::Double)*longerK0+ putStrLn $ "Please, now spell the sound representation of the " ++ soundUkr ++ " sound! "+ recA "x.wav" (7*longerK)+ putStrLn "The file is recorded and now will be automatically processed. You will be notificated with the text message in the terminal about the creation of the needed file. Please, wait a little. "+ norm "x.wav"+ noiseProfB "8x.wav"+ noiseReduceB "8x.wav"+ lim0 <- durationA "_8x.wav"+ alterVadB "_8x.wav" lim0+ lim1 <- durationA "7_8x.wav"+ alterVadE "7_8x.wav" lim1+ sincA "67_8x.wav"+ resampleA "4.67_8x.wav" (22050::Int)+ quarterSinFade "34.67_8x.wav"+ volS2 "434.67_8x.wav" file+ renameFile "8.434.67_8x.wav" file1+ cleanTemp++-- | Function to get the @Double@ value, which shows in how many times you expect that your sound representation will be longer than the one provided by the @mmsyn6ukr@ package. +tempS :: String -> IO Double+tempS soundUkr = onException (do + putStrLn $ "In how many times do you think your sound representing " ++ soundUkr ++ " will sound longer than the recently played one? Specify as a Double value without \"e\" notation. "+ longivityY <- getLine+ let longS = take 5 longivityY in let long = read longS::Double in return long) (do + putStrLn "Please, specify the value of the Double type!"+ tempS soundUkr)++-- | Function that removes all the sounds with ".raw", ".wav", ".ogg", ".flac" extensions in the current directory. It is used for +-- the security reasons.+cleanCreatedSoundFs :: IO ()+cleanCreatedSoundFs = do+ dirCs <- listDirectory "."+ let remFs = concatMap (\ys -> filter (\zs -> ys `isSuffixOf` zs) dirCs) [".raw", ".wav", ".ogg", ".flac"] in mapM_ removeFile remFs++-- | Function that repeatedly proposes and creates if accepted the sound records with the new \"voice\". Besides it can play the newly created file once.+createAndPlayFs :: IO ()+createAndPlayFs = do + putStrLn "Next file can be now voiced by your \"voice\". If you would like to run a new round and create a new speech, enter \"y\" as text input now!"+ putStrLn "Otherwise, the program will end and remove all your sound files in the current directory created with your voice during the program execution time."+ choice <- getLine+ if take 1 choice == "y"+ then do+ main6Ukr+ createAndPlayFs+ else return ()+ +-- | Function that proposes and creates if accepted the sound record with the new \"voice\". Besides it can play the newly created file once. It is used in the+-- 'createAndPlayFs' function internally and recursively.+main6Ukr :: IO ()+main6Ukr = bracketOnError (do+ putStrLn "Please, specify the arguments to control the output speech file! "+ putStrLn "See https://hackage.haskell.org/package/mmsyn6ukr-0.6.0.0/docs/UkrainianLControl.html#v:genControl for more information."+ putStrLn "You can specify e. g. \"o9-1\" or \"o5-1\" or other options."+ arg <- getLine+ let args = take 1 . words $ arg in do + putStrLn "Please, specify the name of the resulting sound file! Please, do NOT use '}' character and space or control characters!"+ nameOfSoundFile <- getLine+ let nameSF = filter (\x -> not (isSpace x) && not (isControl x) && x /= '}') nameOfSoundFile in+ return (args, nameSF)) (\(args, nameSF) -> do+ putStr $ "Notice, there was (may be) CmdLineArgument exception. To avoid it, please, specify the command line argument (if needed) in the form \"ABC\""+ putStrLn $ " where A is either a letter \'f\', \'o\', \'w\' or a digit and B and C are both digits! The exception (may be) arose from the command line arguments " + ++ show args ++ " for the file: " ++ show nameSF ++ ". Please, check also whether the SoX was installed with the support for needed codec.") (\(args, nameSF) -> do + xs <- getContents+ let ys = take (nSymbols (let zs = take 1 args in if null zs then [] else fst . genControl . head $ zs)) xs in + withBinaryFile (nameSF ++ ".raw") AppendMode (appendS16LEFile (convertToProperUkrainian ys))+ putStrLn "The .raw file was created by the program. It will be processed further. "+ let ts = fromJust (showE "sox") in do+ _ <- readProcessWithExitCode ts ["r22050","-c1","-L","-esigned-integer","-b16", nameSF ++ ".raw", + fst . snd . genControl . concat $ args, nameSF ++ (snd . snd . genControl . concat $ args)] ""+ removeFile $ nameSF ++ ".raw"+ putStrLn "Would you like to play the resulting file now?"+ pls <- getLine+ if take 1 pls == "y" || take 1 pls == "Y" + then playA $ nameSF ++ (snd . snd . genControl . concat $ args)+ else return ())+ +
+ README view
@@ -0,0 +1,63 @@+A program and a library that can be used as a simple +basic interface to some SoX functionality or for producing +the approximately Ukrainian speech with your own recorded +voice.++The program starts with Caution to be responsible for usage +and to use it personally. Then the program guides you +through the creating and using your Ukrainian \"voice\". +Please, use it carefully. After the execution the program if +terminated naturally without interruption removes (cleans) +all the created sound files in the current directory for +security reasons. If it terminates by interruption or in +general it is a good practice to remove the current +directory sound files manually.++ ***** CAUTION! *****++With great power comes great responsibility++The program mmsyn7ukr produces the approximately Ukrainian +speech with your own recorded voice. It approximates your +voice with a sequence of recorded separate sounds with +your control over the duration of the sounds. They are then +precessed by the SoX binaries in the system to produce the +needed sounds and then you can spell some Ukrainian text +with your recorded "voice". Be aware that if somebody can get +access to the sounds of your voice or to the recorded speech +except you then this possibility creates security issues and +concerns. So, please, do NOT give access to the records to +anybody else except you.++The program is for personal usage of every user ONLY!++As an advice, run the program in the empty writable, readable +and seekable diractory only for the current user -- better +in the RAM, wait until the program ends and then reboot the +computer. If the program ends earlier, you must then remove +(better wipe) the directory contents. No other users should +have access to the computer after you have begun to run the +program and have not deleted (or better wiped) the contents +of the directory. Please, be aware, that there are possibilities +to read sensitive information from the drives after you have +deleted the files in a usual way. You can use wiping for better +security. Besides, if somebody can get access to the memory of +the computer or to the directory contents where you run the +program or (may be) to the temporary files created by SoX or +to the drive where you run the program (not in the RAM, or may +be in it) then your voice can be stolen and / or used +inappropriately. Use all possible precautions and measures to +avoid the situation. ++Be aware also that the given by the program technology (or +documentation for it in any form) of the voice processing can +be improved so there is NO guarantees that the given technology +or its successors cannot be used in violating your voice identity +to produce from some voice records available the voice for the +inappropriate usage. So, better is to proove your identity not +only with the solely voice itself but with some additional +independent sources and measures. ++The author of the program accordingly to the LICENSE (MIT) does not +response for any possible issues, but by this notification tries to +intent you to be aware of some possible issues.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ SoXBasics.hs view
@@ -0,0 +1,255 @@+-- |+-- Module : SoXBasics+-- Copyright : (c) OleksandrZhabenko 2019+-- License : MIT+--+-- Maintainer : olexandr543@yahoo.com+--+-- A program and a library that can be used as a simple basic interface to some SoX functionality +-- or for producing the approximately Ukrainian speech with your own recorded voice.+--++module SoXBasics where++import System.Directory+import Data.Maybe (isJust, fromJust)+import Numeric+import Data.Char+import System.Process+import System.IO+import EndOfExe++-- | Function 'maxAbs' allows to choose a maximum by absolute value if the values are written as @String@. Bool @True@ corresponds to maximum value, @False@ - to minimum value+maxAbs :: (String, String) -> (String, Bool)+maxAbs (xs, ys) | null xs || null ys = ([], False)+ | head xs == '-' && head ys == '-' = if compare xs ys /= LT then (xs, False) else (ys, False)+ | head xs /= '-' && head ys /= '-' = if compare xs ys == GT then (xs, True) else (ys, True)+ | head xs == '-' && head ys /= '-' = if compare (tail xs) ys /= LT then (xs, False) else (ys, True)+ | otherwise = if compare xs (tail ys) == GT then (xs, True) else (ys, False)++-- | Function 'getMaxA' returns a maximum amplitude of the sound in the file in the given lower and upper bounds represented as a tuple of @Int@ values.+getMaxA :: FilePath -> (Int, Int) -> IO String+getMaxA file (lowerbound, upperbound) = if isJust (showE "sox") + then do+ (_, _, herr) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", show lowerbound ++ "s", "=" ++ show upperbound ++ "s", "stat"] ""+ let zs = lines herr in return (let u = (words $ zs !! 3) !! 2 in if head u == '-' then take 9 u else take 8 u)+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'getMinA' returns a minimum amplitude of the sound in the file in the given lower and upper bounds represented as a tuple of @Int@ values. +getMinA :: FilePath -> (Int, Int) -> IO String+getMinA file (lowerbound, upperbound) = if isJust (showE "sox") + then do+ (_, _, herr1) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", show lowerbound ++ "s", "=" ++ show upperbound ++ "s", "stat"] ""+ let zs = lines herr1 in return (let u = (words $ zs !! 4) !! 2 in if head u == '-' then take 9 u else take 8 u)+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'selMaxAbs' returns a maximum by absolute value amplitude of the sound and allows by its second value in the tuple determine whether it is a maximum or minimum. +-- Bool @True@ corresponds to maximum value, @False@ - to minimum value.+selMaxAbs :: FilePath -> (Int, Int) -> IO (String, Bool)+selMaxAbs file (lowerbnd, upperbnd) = do + tX <- getMaxA file (lowerbnd, upperbnd)+ tN <- getMinA file (lowerbnd, upperbnd)+ return (maxAbs (tX, tN))++-- | Function 'selMA' returns a maximum or a minimum of the sound amplitude of the file depending on the @Bool@ value given. +-- Bool @True@ corresponds to maximum value, @False@ - to minimum value.+selMA :: FilePath -> (Int, Int) -> Bool -> IO String+selMA file (lowerbnd, upperbnd) x = if x then getMaxA file (lowerbnd, upperbnd) else getMinA file (lowerbnd, upperbnd)+{-# INLINE selMA #-}++-- | Function 'extremeS' returns an approximate sample number of the extremum, which will be used further for fade effect.+extremeS :: FilePath -> (Int, Int) -> Int -> IO (String, Bool) -> IO Int+extremeS file (lowerbnd, upperbnd) eps x = if compare (upperbnd - lowerbnd) (eps + 33) == LT + then return $ (upperbnd + lowerbnd) `quot` 2+ else do + (ys, z) <- x+ let t = (lowerbnd + upperbnd) `quot` 2 + rs <- selMA file (lowerbnd, t) z+ if (ys == rs) + then extremeS file (lowerbnd, t) eps x+ else extremeS file (t, upperbnd) eps x+{-# INLINE extremeS #-} ++-- | Function 'alterVadB' removes an approximate silence measured by the absolute value of the sound amplitude from the beginning of the file. +-- The function must be used with the @FilePath@ parameter containing no directories in its name (that mean the file of the @FilePath@ parameter must be +-- in the same directory that also the function is called from).+alterVadB :: FilePath -> Double -> IO ()+alterVadB file lim = if isJust (showE "sox") && isJust (showE "soxi")+ then do+ (_, _, herr) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", "0", showFFloat Nothing lim $ show 0, "stat"] ""+ -- (_, Just hout, _, _) <- createProcess (proc (fromJust (showE "soxi")) ["-d",file]){ std_out = CreatePipe }+ --y0 <- hGetContents hout+ let zs = lines herr in let z = concatMap (dropWhile (not . isDigit)) . take 1 . drop 3 $ zs in if z < "0.04" + then readProcessWithExitCode (fromJust (showE "sox")) [file, "7" ++ file, "trim", showFFloat Nothing lim $ show 0, "-0.000"] "" >> return ()+ else alterVadB file (lim / 2.0)+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'norm' applies a SoX normalization effect on the audio file. +-- The function must be used with the @FilePath@ parameter containing no directories in its name (that mean the file of the @FilePath@ parameter must be +-- in the same directory that also the function is called from).+norm :: FilePath -> IO ()+norm file = if isJust (showE "sox") + then readProcessWithExitCode (fromJust (showE "sox")) [file, "8" ++ file, "norm"] "" >> return ()+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'normL' applies a SoX gain effect on the audio file with the maximum absolute dB value given by the @Int@ argument. +-- The function must be used with the @FilePath@ parameter containing no directories in its name (that mean the file of the @FilePath@ parameter must be +-- in the same directory that also the function is called from).+normL :: FilePath -> Int -> IO ()+normL file level = if isJust (showE "sox") + then readProcessWithExitCode (fromJust (showE "sox")) [file, "9" ++ file, "gain", "-n", show level] "" >> return ()+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'soxStat' prints a SoX statistics for the audio file.+soxStat :: FilePath -> IO ()+soxStat file = if isJust (showE "sox") + then do + (_, _, herr) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "stat"] ""+ putStrLn herr+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."+ +-- | Function 'alterVadE' removes an approximate silence measured by the absolute value of the sound amplitude from the end of the file. +-- The function must be used with the @FilePath@ parameter containing no directories in its name (that mean the file of the @FilePath@ parameter must be +-- in the same directory that also the function is called from).+alterVadE :: FilePath -> Double -> IO ()+alterVadE file lim = if isJust (showE "sox") + then do+ _ <- readProcessWithExitCode (fromJust (showE "sox")) [file, "6" ++ file, "reverse"] ""+ alterVadB ("6" ++ file) lim+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ["76" ++ file, "6" ++ file, "reverse"] ""+ removeFile $ "76" ++ file+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'upperBnd' returns a maximum number of samples for use in other functions.+upperBnd :: FilePath -> IO Int+upperBnd file = if isJust (showE "soxi") + then do + (_, Just hout, _, _) <- createProcess (proc (fromJust (showE "soxi")) ["-s",file]){ std_out = CreatePipe }+ x0 <- hGetContents hout+ let z = read x0::Int in return z+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Variant of the function 'extremeS' with all the additional information included.+extremeS1 :: FilePath -> IO Int+extremeS1 file = do+ upp <- upperBnd file+ extremeS file (0::Int, upp) (if upp `quot` 32 > 2 then upp `quot` 32 else 2::Int) (selMaxAbs file (0::Int, upp))++-- | Function 'quarterSinFade' applies a fade effect by SoX to the audio file with \"q\" type. +-- The function must be used with the @FilePath@ parameter containing no directories in its name (that mean the file of the @FilePath@ parameter must be +-- in the same directory that also the function is called from).+quarterSinFade :: FilePath -> IO ()+quarterSinFade file = if isJust (showE "sox") + then do+ pos <- extremeS1 file+ upp <- upperBnd file+ _ <- readProcessWithExitCode (fromJust (showE "sox")) [file, "4" ++ file, "fade", "q", show pos ++ "s", "=" ++ show upp ++ "s", show (upp - pos) ++ "s"] ""+ return ()+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'silenceBoth' adds a silence to both ends of the audio. +-- The function must be used with the @FilePath@ parameter containing no directories in its name (that mean the file of the @FilePath@ parameter must be +-- in the same directory that also the function is called from).+silenceBoth :: FilePath -> Int -> Int -> IO ()+silenceBoth file beginning end = if isJust (showE "sox") + then do+ _ <- readProcessWithExitCode (fromJust (showE "sox")) [file, "3" ++ file, "delay", show beginning ++ "s", "reverse"] ""+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ["3" ++ file, "2" ++ file, "delay", show end ++ "s", "reverse"] ""+ removeFile $ "3" ++ file+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'cleanTemp' removes all the intermediate temporary files in the directory where it is called from.+cleanTemp :: IO ()+cleanTemp = do+ filenames <- getDirectoryContents =<< getCurrentDirectory+ let rems = filter (\x -> head x `elem` (['2'..'9'] ++ "_" ++ "x")) filenames in mapM_ removeFile rems++-- | Function 'recA' records audio file with the given name and duration in seconds+recA :: FilePath -> Double -> IO ()+recA file x = if isJust (showE "rec") + then readProcessWithExitCode (fromJust (showE "rec")) ["-b16", "-c1", "-e", "signed-integer", "-L", file, "trim", "0.5", showFFloat Nothing x $ show 0] "" >> return ()+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'resampleA' changes the sample rate for the recorded audio for further processing. +-- The function must be used with the @FilePath@ parameter containing no directories in its name (that mean the file of the @FilePath@ parameter must be +-- in the same directory that also the function is called from).+resampleA :: FilePath -> Int -> IO ()+resampleA file frequency = if isJust (showE "sox") + then readProcessWithExitCode (fromJust (showE "sox")) [file, "3" ++ file, "rate", "-s", "-I", show frequency] "" >> return ()+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'durationA' returns a duration of the audio file in seconds+durationA :: FilePath -> IO Double+durationA file = if isJust (showE "soxi") + then do+ (_, Just hout, _, _) <- createProcess (proc (fromJust (showE "soxi")) ["-D",file]){ std_out = CreatePipe }+ x0 <- hGetContents hout+ let z = read x0::Double in return z+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'playA' plays the given file with SoX+playA :: FilePath -> IO ()+playA file = if isJust (showE "play") + then readProcessWithExitCode (fromJust (showE "play")) [file] "" >> return ()+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'noiseProfB' creates with SoX a file containing a noise profile for the first 0.05 s of the audio file given+noiseProfB :: FilePath -> IO ()+noiseProfB file = if isJust (showE "sox") + then readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", "0", "0.05", "noiseprof",file ++ ".b.prof"] "" >> return ()+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'noiseProfE' creates with SoX a file containing a noise profile for the last 0.05 s of the audio file given. +noiseProfE :: FilePath -> IO ()+noiseProfE file = if isJust (showE "sox") + then readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", "-0.05", "0.05", "noiseprof",file ++ ".e.prof"] "" >> return ()+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'noiseReduceB' reduces with SoX a noise in the file given with the corresponding noise profile created with 'noiseProfB' function. +-- The function must be used with the @FilePath@ parameter containing no directories in its name (that mean the file of the @FilePath@ parameter must be +-- in the same directory that also the function is called from).+noiseReduceB :: FilePath -> IO ()+noiseReduceB file = if isJust (showE "sox")+ then readProcessWithExitCode (fromJust (showE "sox")) [file, "_" ++ file, "noisered", file ++ ".b.prof"] "" >> return ()+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'noiseReduceE' reduces with SoX a noise in the file given with the corresponding noise profile created with 'noiseProfE' function. +-- The function must be used with the @FilePath@ parameter containing no directories in its name (that mean the file of the @FilePath@ parameter must be +-- in the same directory that also the function is called from).+noiseReduceE :: FilePath -> IO ()+noiseReduceE file = if isJust (showE "sox") + then readProcessWithExitCode (fromJust (showE "sox")) [file, "_." ++ file, "noisered", file ++ ".e.prof"] "" >> return ()+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'volS' changes the given audio with the linear ratio for the amplitude so that the resulting amlitude is equal to the given @Double@ parameter.+-- The function must be used with the @FilePath@ parameter containing no directories in its name (that mean the file of the @FilePath@ parameter must be +-- in the same directory that also the function is called from).+volS :: FilePath -> Double -> IO ()+volS file amplitude = if isJust (showE "sox") + then do+ norm file+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ["8" ++ file, "8." ++ file, "vol", showFFloat Nothing amplitude $ show 0, "amplitude", "0.01"] ""+ removeFile $ "8" ++ file+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'volS2' changes the given audio (the first @FilePath@ parameter) with the linear ratio for the amplitude so that +-- the resulting amlitude is equal to the maximum by absolute value amplitude for the file given by the second @FilePath@ parameter. +-- The function must be used with the first @FilePath@ parameter containing no directories in its name (that mean the file of the first +-- @FilePath@ parameter must be in the same directory that also the function is called from).+volS2 :: FilePath -> FilePath -> IO ()+volS2 fileA fileB = if isJust (showE "sox") + then do+ norm fileA+ upp <- upperBnd fileB+ amplMax <- selMA fileB (0, upp) True+ amplMin <- selMA fileB (0, upp) False+ let ampl = read (fst . maxAbs $ (amplMax, amplMin))::Double+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ["8" ++ fileA, "8." ++ fileA, "vol", showFFloat Nothing ampl $ show 0, "amplitude", "0.01"] ""+ removeFile $ "8" ++ fileA+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."++-- | Function 'sincA' uses a sinc effect with -a 50 -I 0.1k-11k band-pass filter for the audio file given.+sincA :: FilePath -> IO ()+sincA file = if isJust (showE "sox") + then readProcessWithExitCode (fromJust (showE "sox")) [file, "4." ++ file, "sinc", "-a", "50", "-I", "0.1k-11k"] "" >> return ()+ else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
+ UkrainianLControl.hs view
@@ -0,0 +1,66 @@+-- |+-- Module : UkrainianLControl+-- Copyright : (c) OleksandrZhabenko 2019+-- License : MIT+--+-- Maintainer : olexandr543@yahoo.com+--+-- A program and a library that can be used as a musical instrument synthesizer or for Ukrainian speech synthesis +-- especially for poets, translators and writers. +--++module UkrainianLControl (+ -- * Control the program+ genControl,+ -- * Security and Limits+ nSymbols+) where++import Data.Char (isDigit)+import qualified Data.Vector as V (generate)+import CaseBi (getBFst')++-- | Function that converts the first digit in the command line argument (starting the argument or being the second one after the letter character) given, +-- which is a digit in the range @[0..9]@ (providing an ascending approximately exponential scale with a basis of 10 starting from 2 and ending at 1000000001), +-- to the upper bound of number of symbols that the 'main' function of the @mmsyn6ukr@ executable reads from the 'System.IO.stdin' for sounding.+-- The default resulting value (no input) is 31416. If there is another first command line argument then the program +-- terminates with the informational message. Using the command line argument is done for the security reasons: +-- because of performative writing to the resulting file(s) there is a need to limit the used memory. For most cases it is+-- enough to use the default value. If you have enough resources and a large Ukrainian text amount then specify the higher values +-- (5 or a greater one). +nSymbols :: String -> Int+nSymbols xs | null xs = 31416::Int+ | otherwise = getBFst' (31416::Int, V.generate 10 (\n -> (n, (10^n + 1)::Int))) (let temp = read xs::Int in if temp <= 9 && temp >= 0+ then temp + else error "Please, specify a digit as a command line argument for the program!")++-- | Function that prepares arguments for the controlling functions for the executable @mmsyn6ukr@. It takes a first command line argument and makes +-- an analysis to produce a set of String. The first resulting String is an argument to 'nSymbols' function, the first in the inner tuple is an argument+-- to the compression level for the comressed formats and the last one is the resulting file extension. The default value (no command line arguments) is+-- @("", ("", ".wav"))@. Please, specify the command line argument (if needed) in the form \"ABC\""+-- where A is either a letter \'f\', \'o\', \'w\' or a digit and B and C are both digits (or something equivalent, see below). +-- +-- Their meaning:+-- +-- A:+-- +-- \'f\' -> native FLAC format with compression from 0 (least) to 8 (best compression ratio) specified by the third characters; \'9\' is equivalent to \'8\'. This format is optional so, +-- please, check whether it is supported by your SoX binaries. If no, install the SoX with support for the format. For more information, please, refer to the @sox@ documentation.+-- +-- \'o\' -> Ogg Vorbis format with compression from -1 (best) to 10 (least) specified by the characters after the first two characters. The default value is "-1". This format is optional +-- so, please, check whether it is supported by your SoX binaries. If no, install the SoX with support for the format. For more information, please, refer to the @sox@ documentation.+-- +-- \'w\' -> WAV format with two options for bitrate - 11025 if the third character is less than '5' and greater than '0' and otherwise 22050 (the default one also for no command line arguments). +-- +-- If A is a digit, then it is used accordingly to 'nSymbols' function and SoX (if properly installed) quickly converts the .raw file to the default .wav with 22050 Hz bitrate.+-- +-- To obtain the best compression ratio, please specify something like \"o9-1\" or \"o5-1\" (or similar). For the best lossless compression - \"f98\" or \"f58\" (or similar). +-- +-- For more information, please, see the @sox@ manuals (e. g. for @soxformat@).+genControl :: String -> (String, (String, String))+genControl (x:xs) | x == 'f' = ([head xs], ("-C" ++ (if (compare (tail xs) "9" /= GT) && (compare (tail xs) "0" /= LT) then take 1 . tail $ xs else "8"), ".flac"))+ | x == 'o' = ([head xs], ("-C" ++ (if ((compare (tail xs) "9" /= GT) && (compare (tail xs) "0" /= LT)) then take 1 . tail $ xs else if (tail xs == "10") then "10" else "-1"), ".ogg"))+ | x == 'w' = ([head xs], ("-r" ++ (if ((compare (tail xs) "4" /= GT) && (compare (tail xs) "0" /= LT)) then "11025" else "22050"), ".wav"))+ | isDigit x = ([x], ("", ".wav"))+ | otherwise = ("", ("", ".wav"))+genControl [] = ("", ("", ".wav"))
+ mmsyn7ukr.cabal view
@@ -0,0 +1,33 @@+-- Initial mmsyn7ukr.cabal generated by cabal init. For further+-- documentation, see http://haskell.org/cabal/users-guide/++name: mmsyn7ukr+version: 0.1.0.0+synopsis: A simple basic interface to some SoX functionality or the approximately Ukrainian speech synthesizer with your own recorded voice.+description: A program and a library that can be used as a simple basic interface to some SoX functionality or for producing the approximately Ukrainian speech with your own recorded voice.+homepage: https://hackage.haskell.org/package/mmsyn7ukr+license: MIT+license-file: LICENSE+author: OleksandrZhabenko+maintainer: olexandr543@yahoo.com+copyright: (c) Oleksandr Zhabenko 2019+category: Language+build-type: Simple+extra-source-files: ChangeLog.md, README+cabal-version: >=1.10++library+ exposed-modules: UkrainianLControl, SoXBasics, Main+ -- other-modules:+ -- other-extensions:+ build-depends: base >=4.7 && <4.13, process >=1.4 && <1.8, vector >=0.11 && <0.14, mmsyn2 >=0.1.6.1 && <1, directory >=1.2.5 && <1.4, mmsyn6ukr >=0.6 && <1, mmsyn3 >=0.1.3 && <1+ -- hs-source-dirs:+ default-language: Haskell2010++executable mmsyn7ukr+ main-is: Main.hs+ -- other-modules:+ -- other-extensions:+ build-depends: base >=4.7 && <4.13, process >=1.4 && <1.8, vector >=0.11 && <0.14, mmsyn2 >=0.1.6.1 && <1, directory >=1.2.5 && <1.4, mmsyn6ukr >=0.6 && <1, mmsyn3 >=0.1.3 && <1+ -- hs-source-dirs:+ default-language: Haskell2010