packages feed

dobutokO2 0.18.0.0 → 0.19.0.0

raw patch · 6 files changed

+229/−15 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ DobutokO.Sound.IntermediateF: doubleLtoV :: Ord a => [[a]] -> Vector a
+ DobutokO.Sound.IntermediateF: filterToBnds :: Int -> Int -> [Int] -> [Int]
+ DobutokO.Sound.IntermediateF: isOddAsElem :: Eq a => a -> Vector [a] -> Bool
+ DobutokO.Sound.IntermediateF: maxLinV :: Ord a => Vector [a] -> Maybe a
+ DobutokO.Sound.IntermediateF: minLinV :: Ord a => Vector [a] -> Maybe a
+ DobutokO.Sound.ParseList: canBePreParseV :: Vector String -> Bool
+ DobutokO.Sound.ParseList: containsExt :: [String] -> Bool
+ DobutokO.Sound.ParseList: containsExtV :: Vector String -> Bool
+ DobutokO.Sound.ParseList: parseStoLInts :: String -> [Int]
+ DobutokO.Sound.ParseList: parseTup :: String -> [String]
+ DobutokO.Sound.ParseList: parseTupV :: String -> Vector String
+ DobutokO.Sound.ParseList: parseV :: Vector String -> Maybe [Int]

Files

CHANGELOG.md view
@@ -170,5 +170,11 @@  ## 0.18.0.0 -- 2020-03-26 -* Eighteenth version. Added three new funcions to the DobutokO.Sound.IntermediateF module for recording and playing of the files.+* Eighteenth version. Added three new functions to the DobutokO.Sound.IntermediateF module for recording and playing of the files. Some documentation improvements.++## 0.19.0.0 -- 2020-03-27++* Nineteenth version. Added a new module DobutokO.Sound.ParseList to parse entered list of Int. Added the possibility to use "99" and "999" first command line+options that allows to play and edit with SoX effects applied respectively the sequence of the "result\*wav" files in the current directory. Added functions+to realize the functionality to different modules. Some documentation improvements.
DobutokO/Sound/Executable.hs view
@@ -25,16 +25,17 @@ import Control.Exception (onException) import System.Environment (getArgs) import Data.List (isPrefixOf)-import Data.Maybe (fromJust)+import Data.Maybe (fromJust,isNothing) import Data.Char (isDigit,isSpace) import System.Process import EndOfExe (showE)-import qualified Data.Vector as V (Vector (..),generate,fromList,length,imapM_,snoc,toList,unsafeSlice)+import qualified Data.Vector as V (Vector (..),generate,fromList,length,imapM_,snoc,toList,unsafeSlice,mapM_,unsafeIndex) import System.Directory import SoXBasics import Processing_mmsyn7ukr import DobutokO.Sound hiding (dobutokO2, recAndProcess)-import DobutokO.Sound.IntermediateF (pAnR_)+import DobutokO.Sound.IntermediateF +import DobutokO.Sound.ParseList (parseStoLInts)  -- | Function that actually makes processing in the @dobutokO2@ executable. 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.@@ -44,10 +45,12 @@   let arg1 = concat . take 1 $ arggs       file = concat . drop 1 . take 2 $ arggs       args = unwords . drop 2 $ arggs+      argss = drop 1 arggs   exist2 <- doesFileExist file   getBFst' (dobutokO2H exist2 args file, V.fromList . fmap (\(xs, f) -> (xs,f exist2 args file)) $ [("0",o2help),("1",dobutokO2H1),("11",dobutokO2H11),     ("2",dobutokO2H2),("21",dobutokO2H21),("3",dobutokO2H3),("31",dobutokO2H31),("4",dobutokO2H4),("41",dobutokO2H41),("5",dobutokO2H5),-      ("51",dobutokO2H51),("61",dobutokO2H61),("7",dobutokO2H7),("8",dobutokO2H8),("80",dobutokO2H80),("9",dobutokO2H9)]) arg1+      ("51",dobutokO2H51),("61",dobutokO2H61),("7",dobutokO2H7),("8",dobutokO2H8),("80",dobutokO2H80),("9",dobutokO2H9),("99",dobutokO2H99 argss),+         ("999",dobutokO2H999 argss)]) arg1  dobutokO2H1 :: Bool -> String -> FilePath -> IO () dobutokO2H1 exist2 args file = do@@ -224,12 +227,38 @@ dobutokO2H9 _ _ _ = pAnR_ {-# INLINE dobutokO2H9 #-} -dobutokO2H99 :: Bool -> String -> FilePath -> IO ()-dobutokO2H99 exist2 args file = do-  undefined+dobutokO2H99 :: [String] -> Bool -> String -> FilePath -> IO ()+dobutokO2H99 argss _ _ file = do+  dir0V <- listVDirectory+  let l0 = V.length dir0V+  putStrLn $ "You have available " ++ show l0 ++ " files that can be played. The minimum index further is 0, the maximum is " ++ show (l0 - 1)+  list1 <- recAndProcess file (99::Int)+  let yss = divideToStr list1+      v01 = V.fromList yss+      mxE = if isNothing (maxLinV v01) then (l0 - 1) else fromJust (maxLinV v01)+      mnE = if isNothing (minLinV v01) then 0 else fromJust (minLinV v01)+      zss = map (filterToBnds mnE mxE) yss+      v1 = doubleLtoV zss+  V.mapM_ (\idx -> playE (V.unsafeIndex dir0V idx) argss) v1 {-# INLINE dobutokO2H99 #-} +dobutokO2H999 :: [String] -> Bool -> String -> FilePath -> IO ()+dobutokO2H999 argss _ _ file = do+  dir0V <- listVDirectory+  let l0 = V.length dir0V+  putStrLn $ "You have available " ++ show l0 ++ " files that can be processed. The minimum index further is 0, the maximum is " ++ show (l0 - 1)+  list1 <- recAndProcess file (999::Int)+  let yss = divideToStr list1+      v01 = V.fromList yss+      mxE = if isNothing (maxLinV v01) then 0 else fromJust (maxLinV v01)+      mnE = if isNothing (minLinV v01) then 0 else fromJust (minLinV v01)+      zss = map (filterToBnds mnE mxE) yss+      v1 = doubleLtoV zss+  V.mapM_ (\idx -> soxE1 (V.unsafeIndex dir0V idx) argss) v1+{-# INLINE dobutokO2H999 #-} +divideToStr :: String -> [[Int]]+divideToStr = map parseStoLInts . lines  isDataStr :: String -> Bool isDataStr = null . filter (== '@')@@ -321,7 +350,7 @@ recAndProcess :: FilePath -> Int -> IO String recAndProcess file x =   getBFst' (processD, V.fromList [(0,processD0 file),(1,processD1),(2,processD2 file),(3,processD3),(4,processD4),(5,processD5),(7,processD7),-    (8,processD8),(9,processD9),(11,processD_1)]) x+    (8,processD8),(9,processD9),(11,processD_1),(99,processD99),(999,processD999)]) x  processD_1 :: IO String processD_1 = onException (do@@ -542,3 +571,29 @@     putStrLn "_______________________________________________________________________"     processD) {-# INLINE processD #-}++processD99 :: IO String+processD99 = onException (do+  putStr "Please, input the lists of Int in Haskell syntaxis (e. g. [1,3..56], or [3..45], or [2..]) of the indeces for the files to be played "+  putStr "with SoX effects applied to. The lists must be separated with newline (just press \"Enter\"), empty lists are ignored. If index is "+  putStrLn "element of several input lists then if its number of occurrences in all the lists is odd, then it is played, otherwise it is not. "+  putStrLn "To end the input, just press the combination that means end of input (e. g. for Unices, it's probably Ctrl + D). "+  wws <- getContents+  return wws) (do+    putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."+    putStrLn "_______________________________________________________________________"+    processD)+{-# INLINE processD99 #-}++processD999 :: IO String+processD999 = onException (do+  putStr "Please, input the lists of Int in Haskell syntaxis (e. g. [1,3..56], or [3..45], or [2..]) of the indeces for the files to be processed "+  putStr "with SoX effects applied to. The lists must be separated with newline (just press \"Enter\"), empty lists are ignored. If index is "+  putStrLn "element of several input lists then if its number of occurrences in all the lists is odd, then it is played, otherwise it is not. "+  putStrLn "To end the input, just press the combination that means end of input (e. g. for Unices, it's probably Ctrl + D). "+  wws <- getContents+  return wws) (do+    putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."+    putStrLn "_______________________________________________________________________"+    processD)+{-# INLINE processD999 #-}
DobutokO/Sound/IntermediateF.hs view
@@ -40,6 +40,11 @@   , playCollect1Dec   , playCollectDec   , replaceWithHQs+  , isOddAsElem+  , maxLinV+  , minLinV+  , doubleLtoV+  , filterToBnds   -- ** SoX effects application   -- *** With \"reverb\" as the first   , reverbE@@ -59,7 +64,7 @@ import qualified Data.List as L (sort) import Control.Exception (onException) import Control.Exception.FinalException (FinalException (NotRecorded,ExecutableNotProperlyInstalled),catchEnd)-import Data.List (isPrefixOf,isSuffixOf,(\\))+import Data.List (isPrefixOf,isSuffixOf,(\\),maximum,minimum) import Data.Char (isDigit,isSpace) import qualified Data.Vector as V  import System.Directory@@ -69,6 +74,7 @@ import Data.Maybe (fromJust,isJust) import System.Exit (ExitCode (ExitSuccess)) import System.Info (os)+import DobutokO.Sound.ParseList (parseStoLInts)  -- | Gets sizes of the \"result\*.wav\" files in the current directory.  getFileRSizes :: IO (V.Vector Integer)@@ -460,3 +466,40 @@                  | otherwise = if isJust (showE "play")    then readProcessWithExitCode (fromJust (showE "play")) ([file] ++ arggs) "" >> return ()   else catchEnd ExecutableNotProperlyInstalled++-------------------------------------------------------------------------------------------  ++-- | A predicate to decide whether an element @a@ belongs to the odd number of the lists of @a@ in the 'V.Vector'. +isOddAsElem :: Eq a => a -> V.Vector [a] -> Bool+isOddAsElem x v+  | V.null v = False+  | otherwise = (V.length . V.findIndices (elem x) $ v) `rem` 2 == 1++-- | All @[a]@ must be finite. To obtain @Just a0@ as a result, at least one of the @[a]@ must be not empty and 'V.Vector' must have finite length.+-- If 'V.Vector' is 'V.empty' or all @[a]@ are null (the vector has finite length), then the result is 'Nothing'. Otherwise, it will run infinitely+-- just until it runs over the available memory.+maxLinV :: Ord a => V.Vector [a] -> Maybe a+maxLinV v+  | V.all null v  || V.null v = Nothing+  | otherwise = Just (V.maximum . V.map maximum . V.filter (not . null) $ v)++-- | All @[a]@ must be finite. To obtain @Just a0@ as a result, at least one of the @[a]@ must be not empty and 'V.Vector' must have finite length.+-- If 'V.Vector' is 'V.empty' or all @[a]@ are null (the vector has finite length), then the result is 'Nothing'. Otherwise, it will run infinitely+-- just until it runs over the available memory.+minLinV :: Ord a => V.Vector [a] -> Maybe a+minLinV v+  | V.all null v || V.null v = Nothing+  | otherwise = Just (V.minimum . V.map minimum . V.filter (not . null) $ v)++-- | Applied to list of @[a]@ where a is an instance for 'Ord' class gives a sorted in the ascending order 'V.Vector' of @a@, each of them being unique.+doubleLtoV :: Ord a => [[a]] -> V.Vector a+doubleLtoV xss = V.fromList . shortenL . L.sort . concat $ xss+   where shortenL z1@(z:_)+          | length (takeWhile (== z) z1) `rem` 2 == 1 = z:shortenL (dropWhile (== z) z1)+          | otherwise = shortenL (dropWhile (== z) z1)+         shortenL _ = []++-- | Filters 'Int' elements in a list so that they are limited with the first two 'Int' arguments of the function as a lower and a higher bounds.+filterToBnds :: Int -> Int -> [Int] -> [Int]+filterToBnds lbnd hbnd xs = filter (\x -> compare x lbnd /= LT && compare x hbnd /= GT) xs+
+ DobutokO/Sound/ParseList.hs view
@@ -0,0 +1,83 @@+-- |+-- Module      :  DobutokO.Sound.ParseList+-- Copyright   :  (c) OleksandrZhabenko 2020+-- License     :  MIT+-- Stability   :  Experimental+-- Maintainer  :  olexandr543@yahoo.com+--+-- A program and a library to create experimental music+-- from a mono audio and a Ukrainian text.++{-# OPTIONS_GHC -threaded #-}++module DobutokO.Sound.ParseList where ++import Data.Char (isSpace)+import qualified Data.Vector as V+import Text.Read (lex,readMaybe)+import Data.Maybe (isNothing,fromJust)++parseTup :: String -> [String]+parseTup xs = map (dropWhile isSpace . fst) (takeWhile (/= ("","")) . iterate (head . lex . snd) $ head (lex xs))++parseTupV :: String -> V.Vector String+parseTupV = V.fromList . parseTup++containsExt :: [String] -> Bool+containsExt = elem ".." ++containsExtV :: V.Vector String -> Bool+containsExtV = V.elem ".."++canBePreParseV :: V.Vector String -> Bool+canBePreParseV v = not (V.elem "(" v || V.elem "-" v || V.elem ")" v)++parseV :: V.Vector String -> Maybe [Int]+parseV v+ | V.findIndices (== "..") v == V.singleton 2 && V.length v == 4 = +    if V.unsafeIndex v 0 == "[" && V.unsafeIndex v 3 == "]"+      then let ins1 = readMaybe (V.unsafeIndex v 1)::Maybe Int in+        case ins1 of+          Just ins -> Just [ins..]+          Nothing  -> Nothing+      else Nothing+ | V.findIndices (== "..") v == V.singleton 2 && V.length v == 5 =+    if V.unsafeIndex v 0 == "[" && V.unsafeIndex v 4 == "]"+      then let ins1 = readMaybe (V.unsafeIndex v 1)::Maybe Int +               ins2 = readMaybe (V.unsafeIndex v 3)::Maybe Int in+        case (ins1,ins2) of+          (Just ins01,Just ins02) -> if ins02 >= ins01 then Just [ins01..ins02] else Nothing+          _                       -> Nothing+      else Nothing+ | V.findIndices (== "..") v == V.singleton 4 && V.length v == 6 =+    if V.unsafeIndex v 0 == "[" && V.unsafeIndex v 2 == "," && V.unsafeIndex v 5 == "]" +      then let ins1 = readMaybe (V.unsafeIndex v 1)::Maybe Int +               ins2 = readMaybe (V.unsafeIndex v 3)::Maybe Int in+        case (ins1,ins2) of+          (Just ins01,Just ins02) -> Just [ins01,ins02..]+          _                       -> Nothing+      else Nothing+ | V.findIndices (== "..") v == V.singleton 4 && V.length v == 7 =+    if V.unsafeIndex v 0 == "[" && V.unsafeIndex v 2 == "," && V.unsafeIndex v 6 == "]" +      then let ins1 = readMaybe (V.unsafeIndex v 1)::Maybe Int +               ins2 = readMaybe (V.unsafeIndex v 3)::Maybe Int+               ins3 = readMaybe (V.unsafeIndex v 5)::Maybe Int in+        case (ins1,ins2,ins3) of+          (Just ins01,Just ins02,Just ins03) -> if null [ins01,ins02..ins03] then Nothing else Just [ins01,ins02..ins03]+          _                       -> Nothing+      else Nothing+ | V.unsafeIndex v 0 == "[" && V.unsafeIndex v (V.length v - 1) == "]" && V.length v `rem` 2 == 1 &&+    (V.toList . V.findIndices (== ",") $ v) == [2,4..(V.length v - 2)] =+      let insV1 = V.imap (\i _ -> readMaybe (V.unsafeIndex v (2 * i + 1))::Maybe Int) (V.unsafeSlice 0 (V.length v `quot` 2) v) in+       if V.any isNothing insV1+         then Nothing+         else Just (V.toList . V.mapMaybe id $ insV1)+ | otherwise = Nothing++-- | Parses a 'Strting' being a list of Ints written with Haskell rules, e. g. \"[1..]\", \"[2,4..45]\", \"[3,5,6,7,8,3]\" etc. into a list of 'Int'.+-- If it is not possible or list is empty, returns []. Preceding whitespaces are ignored.+parseStoLInts :: String -> [Int]+parseStoLInts xs+  | canBePreParseV . parseTupV . dropWhile isSpace $ xs =+     if isNothing . parseV $ (parseTupV . dropWhile isSpace $ xs) then [] else fromJust . parseV $ (parseTupV . dropWhile isSpace $ xs)+  | otherwise = []
README.markdown view
@@ -13,8 +13,12 @@  For the executable you enter in the terminal: -dobutokO2 { 0 | 1 | 11 | 2 | 21 | 3 | 31 | 4 | 41 | 5 | 51 | 6 | 7 | 8 | 80 | 9 } {fileName} {Ukrainian text}+dobutokO2 { 0 | 1 | 11 | 2 | 21 | 3 | 31 | 4 | 41 | 5 | 51 | 6 | 7 } {fileName} {Ukrainian text} +OR:++dobutokO2 { 8 | 80 | 9 | 99 | 999 }+   where filename is:   the full name of the file to be recorded in the current directory or   the full absolute path to the sound .wav file (or other one format@@ -44,7 +48,30 @@      some of them by other one(s) or their sequences. This allows to create files,        then edit them using this first command line option (possibly for several          times) and at last create a resulting melody file with "8" or "80" options.-  ++  "99" -> the program takes a filename (it is a first command line argument and it is+     ignored) and the rest of the command line argument (they are treated as command+       line arguments to the SoX 'play' command). Then the program prompts you to+         specify the needed indeces for the "result\*.wav" files in the current+           directory (e. g. they can be obtained by executing the dobutokO2 with+             the first command line argument less than "8", or produced by some+               other means). You can specify multiple lists of Int to select the+                 needed files to be played with effects. Afterwards, the program+                   just plays these selected files applying the specified SoX+                     effects to them consequently. For example:+    dobutokO2 9 reverb -w+                       will play the selected (during execution) files with the+                         SoX "reverb -w" effect. For more information on effects,+                           please, refer to the SoX documentation.++  "999" -> similarly to "99", but instead of playing the files, SoX actually+      applies to them these effects and overwrites the files with the obtained ones.+        It is convenient way to test the sounding effects with firstly run the+          dobutokO2 with "99" first command line argument, and then, if suitable,+            with "999" one. Be aware, that after running with the latter one, the+              program cannot restore the files that were changed to their previous+                state, so be careful while running.+                              In more details:    "0" -> the program just converts multiline Ukrainian text from stdin@@ -113,7 +140,7 @@            repeat all the process of creation of "result\*" files. Be aware and use              with care! -  "9" -> see the information above.+  "9", "99", or "999" -> see the information above.                _  -> the program behaves like for the "5" option, but generates      obertones using additional String and allows maximum control over
dobutokO2.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                dobutokO2-version:             0.18.0.0+version:             0.19.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@@ -17,7 +17,7 @@ cabal-version:       >=1.10  library-  exposed-modules:     Main, DobutokO.Sound, DobutokO.Sound.Functional, DobutokO.Sound.Executable, DobutokO.Sound.IntermediateF+  exposed-modules:     Main, DobutokO.Sound, DobutokO.Sound.Functional, DobutokO.Sound.Executable, DobutokO.Sound.IntermediateF, DobutokO.Sound.ParseList   -- other-modules:   -- other-extensions:   build-depends:       base >=4.7 && <4.14, vector >=0.11 && <0.14, process >=1.4 && <1.8, mmsyn3 >=0.1.4 && <1, mmsyn7s >=0.6.6 && <1, directory >=1.2.7 && <1.6, mmsyn7ukr >=0.15.3 && <1, mmsyn2 >=0.1.7 && <1, mmsyn6ukr >=0.6.3.1 && <1