module SoXBasics (
maxAbs
, getMaxA
, getMinA
, selMaxAbs
, selMA
, extremeS
, extremeS1
, soxStat
, upperBnd
, durationA
, sampleAn
, alterVadB
, alterVadE
, alterVadHelp
, opFile
, norm
, normL
, gainL
, quarterSinFade
, silenceBoth
, recA
, resampleA
, noiseProfB
, noiseProfE
, noiseReduceB
, noiseReduceE
, sincA
, volS
, volS2
, playA
) where
import System.Directory
import Data.Maybe (isJust, fromJust)
import Numeric
import Data.Char
import System.Process
import System.IO
import EndOfExe
import System.Exit
import Control.Concurrent (threadDelay)
import Control.Exception (onException)
import System.Info (os)
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)
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."
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."
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))
selMA :: FilePath -> (Int, Int) -> Bool -> IO String
selMA file (lowerbnd, upperbnd) x = if x then getMaxA file (lowerbnd, upperbnd) else getMinA file (lowerbnd, upperbnd)
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
alterVadB :: FilePath -> Double -> Int -> Double -> IO ()
alterVadB file lim noiseMax exit | compare lim exit /= GT = putStrLn $ "File " ++ file ++ " is ready for further processing."
| otherwise =
if isJust (showE "sox")
then do
lim1 <- durationA file
alterVadHelp file lim1 lim noiseMax exit
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
alterVadHelp :: FilePath -> Double -> Double -> Int -> Double -> IO ()
alterVadHelp file lim1 lim noiseMax exit | compare lim1 lim == LT = alterVadB file lim1 noiseMax exit
| compare lim1 lim == EQ =
let noiseM = (case noiseMax of
0 -> "0.01"
1 -> "0.02"
2 -> "0.04"
3 -> "0.08"
_ -> "0.04") in do
(_, _, herr) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", "0", showFFloat Nothing (lim1 / 2.0) $ show 0, "stat"] ""
let zs = lines herr in let z = concatMap (dropWhile (not . isDigit)) . take 1 . drop 3 $ zs in if z < noiseM
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "7" ++ file, "trim", showFFloat Nothing (lim1 / 2.0) $ show 0, "-0.000000"] ""
if code == ExitSuccess
then do
threadDelay 100000
opFile file exit noiseMax
else do
e0 <- doesFileExist $ "7" ++ file
if e0
then do
removeFile $ "7" ++ file
error "The function did not create the needed file, but may be it trimmed the initial one (not enough)!"
else error "The function did not create the needed file, but may be it trimmed the initial one (not enough)!"
else alterVadB file (lim1 / 4.0) noiseMax exit
| otherwise =
let noiseM = (case noiseMax of
0 -> "0.01"
1 -> "0.02"
2 -> "0.04"
3 -> "0.08"
_ -> "0.04") in do
(_, _, herr) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", "0", showFFloat Nothing (lim / 2.0) $ show 0, "stat"] ""
let zs = lines herr in let z = concatMap (dropWhile (not . isDigit)) . take 1 . drop 3 $ zs in if z < noiseM
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "7" ++ file, "trim", showFFloat Nothing (lim / 2.0) $ show 0, "-0.000000"] ""
if code == ExitSuccess
then do
threadDelay 100000
opFile file exit noiseMax
else do
e0 <- doesFileExist $ "7" ++ file
if e0
then do
removeFile $ "7" ++ file
error "The function did not create the needed file, but may be it trimmed the initial one (not enough)!"
else error "The function did not create the needed file, but may be it trimmed the initial one (not enough)!"
else alterVadB file (lim / 4.0) noiseMax exit
opFile :: FilePath -> Double -> Int -> IO ()
opFile file exit noiseMax = do
removeFile file
exist0 <- doesFileExist file
if not exist0
then do
renameFile ("7" ++ file) file
lim2 <- durationA file
alterVadB file lim2 noiseMax exit
else opFile file exit noiseMax
norm :: FilePath -> IO ()
norm file = if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "8" ++ file, "norm"] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "8" ++ file
if e1
then do
removeFile $ "8" ++ file
error "File was not created with \"norm\" effect!"
else error "File was not created with \"norm\" effect!"
else do
e2 <- doesFileExist $ "8" ++ file
if e2
then return ()
else error "The initial file was not changed!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
normL :: FilePath -> Int -> IO ()
normL file level = if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "9" ++ file, "gain", "-n", show level] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "9" ++ file
if e1
then do
removeFile $ "9" ++ file
error "File was not created with \"gain -n\" effect!"
else error "File was not created with \"gain -n\" effect!"
else do
e2 <- doesFileExist $ "9" ++ file
if e2
then return ()
else error "The initial file was not changed!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
gainL :: FilePath -> Double -> IO ()
gainL file level = if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "9" ++ file, "gain", "-b", showFFloat (Just 6) level $ show 0] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "9" ++ file
if e1
then do
removeFile $ "9" ++ file
error "File was not created with \"gain -b\" effect!"
else error "File was not created with \"gain -b\" effect!"
else do
e2 <- doesFileExist $ "9" ++ file
if e2
then return ()
else error "The initial file was not changed!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
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."
alterVadE :: FilePath -> Double -> Int -> Double -> IO ()
alterVadE file lim noiseMax exit | compare lim exit /= GT = putStrLn $ "File " ++ file ++ " is ready for further processing"
| otherwise =
if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "6" ++ file, "reverse"] ""
if code /= ExitSuccess
then do
e0 <- doesFileExist $ "6" ++ file
if e0
then do
removeFile $ "6" ++ file
error "The function did not create the needed file!"
else do
error "The function did not create the needed file!"
else do
alterVadB ("6" ++ file) lim noiseMax exit
(code1, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) ["6" ++ file, "76" ++ file, "reverse"] ""
if code1 /= ExitSuccess
then do
e1 <- doesFileExist $ "76" ++ file
if e1
then do
removeFile $ "76" ++ file
removeFile $ "6" ++ file
error "The function did not create the needed file!"
else do
removeFile $ "6" ++ file
error "The function did not create the needed file!"
else do
e2 <- doesFileExist $ "76" ++ file
if e2
then do
removeFile $ "6" ++ file
removeFile file
renameFile ("76" ++ file) file
else do
removeFile $ "6" ++ file
error "The function did not create the needed file!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
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."
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))
quarterSinFade :: FilePath -> IO ()
quarterSinFade file = if isJust (showE "sox")
then do
pos <- extremeS1 file
upp <- upperBnd file
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "4" ++ file, "fade", "q", show pos ++ "s", "=" ++ show upp ++ "s", show (upp - pos) ++ "s"] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "4" ++ file
if e1
then do
removeFile $ "4" ++ file
error "File was not created with \"fade\" effect!"
else error "File was not created with \"fade\" effect!"
else do
e2 <- doesFileExist $ "4" ++ file
if e2
then return ()
else error "The initial file was not changed!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
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."
recA :: FilePath -> Double -> IO ()
recA file x | take 5 os == "mingw" =
if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) ["-t","waveaudio","-d","-b16", "-c1", "-esigned-integer", "-L", file, "trim", "0.5", showFFloat Nothing x $ show 0] ""
if code /= ExitSuccess
then do
e0 <- doesFileExist file
if e0
then do
removeFile file
error $ "The file " ++ file ++ " was not recorded!"
else do
error $ "The file " ++ file ++ " was not recorded!"
else do
e1 <- doesFileExist file
if e1
then return ()
else error $ "The file " ++ file ++ " was not recorded!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
| otherwise = if isJust (showE "rec")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "rec")) ["-b16", "-c1", "-esigned-integer", "-L", file, "trim", "0.5", showFFloat Nothing x $ show 0] ""
if code /= ExitSuccess
then do
e0 <- doesFileExist file
if e0
then do
removeFile file
error $ "The file " ++ file ++ " was not recorded!"
else do
error $ "The file " ++ file ++ " was not recorded!"
else do
e1 <- doesFileExist file
if e1
then return ()
else error $ "The file " ++ file ++ " was not recorded!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
resampleA :: FilePath -> Int -> IO ()
resampleA file frequency = if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "3" ++ file, "rate", "-s", "-I", show frequency] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "3" ++ file
if e1
then do
removeFile $ "3" ++ file
error "File was not created with \"rate\" effect!"
else error "File was not created with \"rate\" effect!"
else do
e2 <- doesFileExist $ "3" ++ file
if e2
then return ()
else error "The initial file was not changed!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
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."
playA :: FilePath -> IO ()
playA file | take 5 os == "mingw" =
if isJust (showE "sox")
then readProcessWithExitCode (fromJust (showE "sox")) [file, "-t", "waveaudio", "-d"] "" >> return ()
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
| otherwise = 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."
noiseProfB :: FilePath -> IO ()
noiseProfB file = if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", "0", "0.05", "noiseprof",file ++ ".b.prof"] ""
if code /= ExitSuccess
then do
e0 <- doesFileExist $ file ++ ".b.prof"
if e0
then do
removeFile $ file ++ ".b.prof"
error $ "The noise profile " ++ file ++ ".b.prof was not created!"
else error $ "The noise profile " ++ file ++ ".b.prof was not created!"
else do
e1 <- doesFileExist $ file ++ ".b.prof"
if e1
then return ()
else error $ "The noise profile " ++ file ++ ".b.prof was not created!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
noiseProfE :: FilePath -> IO ()
noiseProfE file = if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", "-0.05", "0.05", "noiseprof",file ++ ".e.prof"] ""
if code /= ExitSuccess
then do
e0 <- doesFileExist $ file ++ ".e.prof"
if e0
then do
removeFile $ file ++ ".e.prof"
error $ "The noise profile " ++ file ++ ".e.prof was not created!"
else error $ "The noise profile " ++ file ++ ".e.prof was not created!"
else do
e1 <- doesFileExist $ file ++ ".e.prof"
if e1
then return ()
else error $ "The noise profile " ++ file ++ ".e.prof was not created!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
noiseReduceB :: FilePath -> IO ()
noiseReduceB file = if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "_" ++ file, "noisered", file ++ ".b.prof"] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "_" ++ file
if e1
then do
removeFile $ "_" ++ file
error "File was not created with \"noisered\" effect!"
else error "File was not created with \"noisered\" effect!"
else do
e2 <- doesFileExist $ "_" ++ file
if e2
then return ()
else error "The initial file was not changed!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
noiseReduceE :: FilePath -> IO ()
noiseReduceE file = if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "_." ++ file, "noisered", file ++ ".e.prof"] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "_." ++ file
if e1
then do
removeFile $ "_." ++ file
error "File was not created with \"noisered\" effect!"
else error "File was not created with \"noisered\" effect!"
else do
e2 <- doesFileExist $ "_." ++ file
if e2
then return ()
else error "The initial file was not changed!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
volS :: FilePath -> Double -> IO ()
volS file amplitude = if isJust (showE "sox")
then do
norm file
e0 <- doesFileExist $ "8" ++ file
if e0
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) ["8" ++ file, "8." ++ file, "vol", showFFloat Nothing amplitude $ show 0, "amplitude"] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "8." ++ file
if e1
then do
removeFile $ "8." ++ file
removeFile $ "8" ++ file
error "File was not created with \"vol\" effect!"
else do
removeFile $ "8" ++ file
error "File was not created with \"vol\" effect!"
else do
e2 <- doesFileExist $ "8." ++ file
if e2
then return ()
else do
removeFile $ "8" ++ file
error "The initial file was not changed!"
else error "The initial file was not changed!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
volS2 :: FilePath -> FilePath -> IO ()
volS2 fileA fileB = if isJust (showE "sox")
then do
upp <- upperBnd fileB
amplMax <- selMA fileB (0, upp) True
amplMin <- selMA fileB (0, upp) False
let ampl = read (fst . maxAbs $ (amplMax, amplMin))::Double
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [fileA, "8." ++ tail fileA, "vol", showFFloat Nothing ampl $ show 0, "amplitude"] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "8." ++ tail fileA
if e1
then do
removeFile $ "8." ++ tail fileA
error "File was not created with \"vol\" effect!"
else error "File was not created with \"vol\" effect!"
else do
file8e <- doesFileExist $ "8." ++ tail fileA
if file8e
then return ()
else error "The initial file was not changed!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
sincA :: FilePath -> IO ()
sincA file = if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "4." ++ file, "sinc", "-a", "50", "-I", "0.07k-11k"] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "4." ++ file
if e1
then do
removeFile $ "4." ++ file
error "File was not created with \"sinc\" effect!"
else error "File was not created with \"sinc\" effect!"
else do
e0 <- doesFileExist $ "4." ++ file
if e0
then return ()
else error "The initial file was not changed!"
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."
sampleAn :: FilePath -> Integer -> IO (String, String)
sampleAn file pos = if isJust (showE "sox") && isJust (showE "soxi")
then onException (do
(_, hout, _) <- readProcessWithExitCode (fromJust (showE "soxi")) ["-s", file] ""
let length0 = read hout::Integer
f param = do
(_, _, herr) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", show param ++ "s", "1s", "stat"] ""
let lns = map (last . words) . drop 3 . take 5 . lines $ herr in return (head lns, last lns)
if compare length0 (fromIntegral pos) == GT
then f pos
else f (length0 - 1)) (error "SoX cannot determine the number of the samples in the file! May be it is a RAW file and it needs additional parameters to be processed.")
else error "SoX is not properly installed in your system. Please, install it properly and then call the function again."