module SoXBasics (
maxAbs
, getMaxA
, getMinA
, selMaxAbs
, selMA
, extremeS
, extremeS1
, soxStat
, upperBnd
, durationA
, sampleAn
, alterVadB
, alterVadE
, alterVadHelp
, opFile
, norm
, normL
, gainL
, quarterSinFade
, silenceBoth
, recA
, recB
, resampleA
, noiseProfB
, noiseProfE
, noiseReduceB
, noiseReduceE
, noiseReduceBU
, noiseReduceEU
, 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)
import Control.Exception.FinalException
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 do
catchEnd ExecutableNotProperlyInstalled
return []
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 do
catchEnd ExecutableNotProperlyInstalled
return []
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 catchEnd ExecutableNotProperlyInstalled
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
catchEnd MaybePartiallyTrimmed
else catchEnd MaybePartiallyTrimmed
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
catchEnd MaybePartiallyTrimmed
else catchEnd MaybePartiallyTrimmed
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
catchEnd (NotCreatedWithEffect "norm")
else catchEnd (NotCreatedWithEffect "norm")
else do
e2 <- doesFileExist $ "8" ++ file
if e2
then return ()
else catchEnd (InitialFileNotChanged file)
else catchEnd ExecutableNotProperlyInstalled
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
catchEnd (NotCreatedWithEffect "gain -n")
else catchEnd (NotCreatedWithEffect "gain -n")
else do
e2 <- doesFileExist $ "9" ++ file
if e2
then return ()
else catchEnd (InitialFileNotChanged file)
else catchEnd ExecutableNotProperlyInstalled
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
catchEnd (NotCreatedWithEffect "gain -b")
else catchEnd (NotCreatedWithEffect "gain -b")
else do
e2 <- doesFileExist $ "9" ++ file
if e2
then return ()
else catchEnd (InitialFileNotChanged file)
else catchEnd ExecutableNotProperlyInstalled
soxStat :: FilePath -> IO ()
soxStat file = if isJust (showE "sox")
then do
(_, _, herr) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "stat"] ""
putStrLn herr
else catchEnd ExecutableNotProperlyInstalled
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
catchEnd (NotCreated file)
else do
catchEnd (NotCreated 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
catchEnd (NotCreated file)
else do
removeFile $ "6" ++ file
catchEnd (NotCreated 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
catchEnd (NotCreated file)
else catchEnd ExecutableNotProperlyInstalled
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 catchEnd ExecutableNotProperlyInstalled >> return (0::Int)
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
catchEnd (NotCreatedWithEffect "fade q")
else catchEnd (NotCreatedWithEffect "fade q")
else do
e2 <- doesFileExist $ "4" ++ file
if e2
then return ()
else catchEnd (InitialFileNotChanged file)
else catchEnd ExecutableNotProperlyInstalled
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 catchEnd ExecutableNotProperlyInstalled
recA :: FilePath -> Double -> IO ()
recA file x | isJust (showE "sox") && take 5 os == "mingw" = 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
catchEnd (NotRecorded file)
else catchEnd (NotRecorded file)
else do
e1 <- doesFileExist file
if e1
then return ()
else catchEnd (NotRecorded file)
| isJust (showE "rec") = 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
catchEnd (NotRecorded file)
else catchEnd (NotRecorded file)
else do
e1 <- doesFileExist file
if e1
then return ()
else catchEnd (NotRecorded file)
| otherwise = catchEnd ExecutableNotProperlyInstalled
recB :: FilePath -> (Double, Double) -> IO ()
recB file (x, y) | isJust (showE "sox") && take 5 os == "mingw" = do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) ["-t","waveaudio","-d","-b16", "-c1", "-esigned-integer", "-L", file, "trim", showFFloat Nothing y $ show 0, showFFloat Nothing x $ show 0] ""
if code /= ExitSuccess
then do
e0 <- doesFileExist file
if e0
then do
removeFile file
catchEnd (NotRecorded file)
else catchEnd (NotRecorded file)
else do
e1 <- doesFileExist file
if e1
then return ()
else catchEnd (NotRecorded file)
| isJust (showE "rec") = do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "rec")) ["-b16", "-c1", "-esigned-integer", "-L", file, "trim", showFFloat Nothing y $ show 0, showFFloat Nothing x $ show 0] ""
if code /= ExitSuccess
then do
e0 <- doesFileExist file
if e0
then do
removeFile file
catchEnd (NotRecorded file)
else catchEnd (NotRecorded file)
else do
e1 <- doesFileExist file
if e1
then return ()
else catchEnd (NotRecorded file)
| otherwise = catchEnd ExecutableNotProperlyInstalled
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
catchEnd (NotCreatedWithEffect "rate")
else catchEnd (NotCreatedWithEffect "rate")
else do
e2 <- doesFileExist $ "3" ++ file
if e2
then return ()
else catchEnd (InitialFileNotChanged file)
else catchEnd ExecutableNotProperlyInstalled
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 catchEnd ExecutableNotProperlyInstalled >> return 0.0
playA :: FilePath -> IO ()
playA file | take 5 os == "mingw" =
if isJust (showE "sox")
then readProcessWithExitCode (fromJust (showE "sox")) [file, "-t", "waveaudio", "-d"] "" >> return ()
else catchEnd ExecutableNotProperlyInstalled
| otherwise = if isJust (showE "play")
then readProcessWithExitCode (fromJust (showE "play")) [file] "" >> return ()
else catchEnd ExecutableNotProperlyInstalled
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"
catchEnd (NoiseProfileNotCreatedB file)
else catchEnd (NoiseProfileNotCreatedB file)
else do
e1 <- doesFileExist $ file ++ ".b.prof"
if e1
then return ()
else catchEnd (NoiseProfileNotCreatedB file)
else catchEnd ExecutableNotProperlyInstalled
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"
catchEnd (NoiseProfileNotCreatedE file)
else catchEnd (NoiseProfileNotCreatedE file)
else do
e1 <- doesFileExist $ file ++ ".e.prof"
if e1
then return ()
else catchEnd (NoiseProfileNotCreatedE file)
else catchEnd ExecutableNotProperlyInstalled
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
catchEnd (NotCreatedWithEffect "noisered")
else catchEnd (NotCreatedWithEffect "noisered")
else do
e2 <- doesFileExist $ "_" ++ file
if e2
then return ()
else catchEnd (InitialFileNotChanged file)
else catchEnd ExecutableNotProperlyInstalled
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
catchEnd (NotCreatedWithEffect "noisered")
else catchEnd (NotCreatedWithEffect "noisered")
else do
e2 <- doesFileExist $ "_." ++ file
if e2
then return ()
else catchEnd (InitialFileNotChanged file)
else catchEnd ExecutableNotProperlyInstalled
noiseReduceBU :: FilePath -> Double -> IO ()
noiseReduceBU file amount = if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "_" ++ file, "noisered", file ++ ".b.prof", showFFloat (Just 4) amount $ show 0] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "_" ++ file
if e1
then do
removeFile $ "_" ++ file
catchEnd (NotCreatedWithEffect "noisered")
else catchEnd (NotCreatedWithEffect "noisered")
else do
e2 <- doesFileExist $ "_" ++ file
if e2
then return ()
else catchEnd (InitialFileNotChanged file)
else catchEnd ExecutableNotProperlyInstalled
noiseReduceEU :: FilePath -> Double -> IO ()
noiseReduceEU file amount = if isJust (showE "sox")
then do
(code, _, _) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "_." ++ file, "noisered", file ++ ".e.prof", showFFloat (Just 4) amount $ show 0] ""
if code /= ExitSuccess
then do
e1 <- doesFileExist $ "_." ++ file
if e1
then do
removeFile $ "_." ++ file
catchEnd (NotCreatedWithEffect "noisered")
else catchEnd (NotCreatedWithEffect "noisered")
else do
e2 <- doesFileExist $ "_." ++ file
if e2
then return ()
else catchEnd (InitialFileNotChanged file)
else catchEnd ExecutableNotProperlyInstalled
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
catchEnd (NotCreatedWithEffect "vol")
else do
removeFile $ "8" ++ file
catchEnd (NotCreatedWithEffect "vol")
else do
e2 <- doesFileExist $ "8." ++ file
if e2
then return ()
else do
removeFile $ "8" ++ file
catchEnd (InitialFileNotChanged file)
else catchEnd (InitialFileNotChanged file)
else catchEnd ExecutableNotProperlyInstalled
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
catchEnd (NotCreatedWithEffect "vol")
else catchEnd (NotCreatedWithEffect "vol")
else do
file8e <- doesFileExist $ "8." ++ tail fileA
if file8e
then return ()
else catchEnd (InitialFileNotChanged fileA)
else catchEnd ExecutableNotProperlyInstalled
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
catchEnd (NotCreatedWithEffect "sinc")
else catchEnd (NotCreatedWithEffect "sinc")
else do
e0 <- doesFileExist $ "4." ++ file
if e0
then return ()
else catchEnd (InitialFileNotChanged file)
else catchEnd ExecutableNotProperlyInstalled
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)) (catchEnd (NotEnoughData file))
else catchEnd ExecutableNotProperlyInstalled >> return ("","")