packages feed

dobutokO2 0.25.0.0 → 0.26.0.0

raw patch · 3 files changed

+124/−10 lines, 3 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ DobutokO.Sound.Functional: elemsOverlapOvers :: OvertonesO -> OvertonesO -> Bool
+ DobutokO.Sound.Functional: fAddFElems :: OvertonesO -> Double -> (Double -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> Double -> OvertonesO
+ DobutokO.Sound.Functional: fRemoveFElems :: OvertonesO -> Double -> (Double -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> Double -> OvertonesO
+ DobutokO.Sound.Functional: freqsOverlapOvers :: OvertonesO -> OvertonesO -> Bool
+ DobutokO.Sound.Functional: gAdd02 :: Double -> (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional: gAdd03 :: (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional: gAdds01 :: OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional: gAdds02 :: Double -> OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional: gRem01 :: (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional: gRem02 :: Double -> (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO

Files

CHANGELOG.md view
@@ -250,3 +250,8 @@ ## 0.25.0.0 -- 2020-04-09  * Twenty-fifth version. Added more possibilities to edit function f from the DobutokO.Sound.Functional module. ++## 0.26.0.0 -- 2020-04-09++* Twenty-sixth version. Added more possibilities to edit function f from the DobutokO.Sound.Functional module. Now they include also gRem functions and+possibilities to work with two OvertonesO. Some code and documentation improvements in the DobutokO.Sound.Functional module. 
DobutokO/Sound/Functional.hs view
@@ -96,11 +96,11 @@   , doubleVecFromVecOfDouble   , helpF1   , helpF0-  -- * Working with 'OvertonesO' and function f+  -- * Working with OvertonesO and function f   , maybeFFromStrVec   , fVecCoefs   , showFFromStrVec-  -- * Functions to edit 'OvertonesO' and function f (since 0.25.0.0)+  -- * Functions to edit OvertonesO and function f (since 0.25.0.0)   , renormF   , renormFD   , sameOvertone@@ -110,6 +110,17 @@   , fAddFElem   , fRemoveFElem   , gAdd01+  , gAdd02+  , gAdd03+  , gRem01+  , gRem02+  -- ** Working with two OvertonesO+  , fAddFElems+  , fRemoveFElems+  , freqsOverlapOvers+  , elemsOverlapOvers+  , gAdds01+  , gAdds02 ) where  import Text.Read (readMaybe)@@ -1004,7 +1015,8 @@  | V.null v = V.empty  | otherwise =     let v1 = V.fromList . sortBy (\(x1,y1) (x2,y2)-> compare (abs y2) (abs y1)) . V.toList $ v in-      V.map (\(x,y) -> (x, y / (snd . V.unsafeIndex v1 $ 0))) v1+      if (\(x,y) -> y == 0.0) . V.unsafeIndex v1 $ 0 then V.empty+      else V.map (\(x,y) -> (x, y / (snd . V.unsafeIndex v1 $ 0))) v1  -- | Renormalizes amplitudes for the frequencies so that the maximum one of them (if 'OvertonesO' is not 'V.empty') is equal by the absolute value -- to 'Double' argument and the mutual ratios of the amplitudes are preserved.@@ -1013,7 +1025,8 @@  | V.null v = V.empty  | otherwise =     let v1 = V.fromList . sortBy (\(x1,y1) (x2,y2)-> compare (abs y2) (abs y1)) . V.toList $ v in-      V.map (\(x,y) -> (x, ampl0 * y / (snd . V.unsafeIndex v1 $ 0))) v1      +      if (\(x,y) -> y == 0.0) . V.unsafeIndex v1 $ 0 then V.empty+      else V.map (\(x,y) -> (x, ampl0 * y / (snd . V.unsafeIndex v1 $ 0))) v1  -- | Predicate to check whether all tuples in a 'V.Vector' have the same first element. sameOvertone :: OvertonesO -> Bool@@ -1026,25 +1039,34 @@ sameOvertoneL xs@((x,y):_) = all (\(xn,_) -> xn == x) xs sameOvertoneL _ = False --- | @g :: (Double,Double) -> OvertonesO -> OvertonesO@ is a function that defines how the new element is added to the 'OvertonesO'.+-- | @g :: (Double,Double) -> OvertonesO -> OvertonesO@ is a function that defines how the new element is added to the 'OvertonesO'. It depends+-- only on the element being added and the actual 'OvertonesO'. It does not depend on the 'Double' argument for @f :: Double -> OvertonesO@+-- so for different 'Double' for @f@ it gives the same result. sameFreqF :: Double -> (Double,Double) -> (Double -> OvertonesO) -> ((Double,Double) -> OvertonesO -> OvertonesO) -> OvertonesO sameFreqF freq (noteN0,amplN0) f g = g (noteN0,amplN0) (f freq)  -- | @g :: (Double,Double) -> OvertonesO -> OvertonesO@ is a function that defines how the new element is added to the 'OvertonesO'. -- Variant of 'sameFreqF' where g depends only on the elements of the 'OvertonesO', which first elements in the tuples equal to the first element--- in the @(Double,Double)@.+-- in the @(Double,Double)@. It does not depend on the 'Double' argument for @f :: Double -> OvertonesO@+-- so for different 'Double' for @f@ it gives the same result. sameFreqFI :: Double -> (Double,Double) -> (Double -> OvertonesO) -> ((Double,Double) -> OvertonesO -> OvertonesO) -> OvertonesO sameFreqFI freq (noteN0,amplN0) f g = g (noteN0,amplN0) . V.filter (\(x,y) -> x == noteN0) $ f freq  -- | @gAdd :: (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO@ is a function that defines how the element is added--- to the 'OvertonesO'.+-- to the 'OvertonesO'. Unlike for 'sameFreqF', it depends also on the 'Double' argument for @f :: Double -> OvertonesO@. 'fAddFElem' is+-- actually a functional or operator (in mathematical sense), it changes the function @f@ (in some point) and returns the new one.+-- @gAdd@ allows not only to insert an element if missing, but to change all the 'OvertonesO' system. So depending on the complexity,+-- it can reproduce rather comlex behaviour. fAddFElem :: (Double, Double) -> Double -> (Double -> OvertonesO) -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) ->   (Double -> OvertonesO) fAddFElem (noteN,amplN) freq f gAdd = \t -> gAdd (noteN,amplN) t f  -- | @gRem:: (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO@ is a function that defines how the element is removed--- from the 'OvertonesO'.-fRemoveFElem :: (Double, Double) -> Double -> (Double -> OvertonesO) -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) ->+-- from the 'OvertonesO'. Unlike for 'sameFreqF', it depends also on the 'Double' argument for @f :: Double -> OvertonesO@. 'fRemoveFElem' is+-- actually a functional or operator (in mathematical sense), it changes the function @f@ (in some point) and returns the new one.+-- @gRem@ allows not only to delet an element if existing, but to change all the 'OvertonesO' system. So depending on the complexity,+-- it can reproduce rather comlex behaviour.+fRemoveFElem :: (Double, Double) -> Double -> (Double -> OvertonesO) -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) ->    (Double -> OvertonesO) fRemoveFElem (noteN,amplN) freq f gRem = \t -> gRem (noteN,amplN) t f @@ -1058,3 +1080,90 @@      let v2 = V.findIndices (\(x,_) -> x == note) $ v1 in        if V.null v2 then V.cons (note,ampl) (f freq)        else renormF . V.imap (\i (t,w) -> if i `V.elem` v2 then (t,w + ampl / fromIntegral (V.length v2)) else (t,w)) $ v1++-- | Can be used to produce an example of the function @gAdd@ for the 'fAddFElem'. Similar to 'gAdd01', but uses its first argument+-- to renorm the result of the 'gAdd01' so that its maximum by absolute value amplitude equals to the first argument.+gAdd02 :: Double -> (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO+gAdd02 amplMax (note,ampl) freq f = renormFD amplMax . gAdd01 (note,ampl) freq $ f ++-- | Example of the function @gAdd@. for the 'fAddFElem'. If the frequency is not already in the 'OvertonesO' then the corresponding element is added and+-- the 'OvertonesO' are renormed with 'renormF'. Otherwise, the element is tried to be inserted with a new frequency between the greatest by an absulute+-- values notes as an intermediate value with the respective amplitude, or if there is only one element, to produce two elements in+-- the resulting 'V.Vector' with two consequent harmonics.+gAdd03 :: (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO+gAdd03 (note,ampl) freq f + | V.null . f $ freq = V.singleton (note,ampl)+ | otherwise =+    let v1 = renormF . f $ freq in+     let v2 = V.findIndices (\(x,_) -> x == note) $ v1 in+       if V.null v2 then renormF . V.cons (note,ampl) $ f freq+       else+        let xs = sortBy (\(x1,y1) (x2,y2)-> compare (abs x2) (abs x1)) . V.toList $ v1+            l = V.length v1+            ys = if compare l 1 == GT then ((fst . head $ xs) + (fst . head . tail $ xs) / 2,ampl):xs+                 else [(note,((snd . V.unsafeIndex v1 $ 0) + ampl) / 2),(2 * note,(abs ((snd . V.unsafeIndex v1 $ 0) - ampl)) / 2)] in+                   renormF . V.fromList $ ys++-- | Example of the function gRem for the 'fRemoveFElem'. If the element is already in the 'OvertonesO' then it is removed (if there are more than 5+-- elements already) and 'OvertonesO' are renormalized. Otherwise, all the same for the element already existing elements become less in an amlitude+-- for a numbers that in sum equal to amplitude of the removed element.+gRem01 :: (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO+gRem01 (note,ampl) freq f+  | V.null . f $ freq = V.empty+  | otherwise =+     let v1 = renormF . f $ freq in+     let v2 = V.findIndices (\(x,y) -> x == note && y == ampl) $ v1 in+       if V.null v2 then+       if compare (V.length v1) 5 == GT then renormF . V.unsafeSlice 0 (V.length v1 - 1) $ v1+       else v1+       else renormF . V.imap (\i (t,w) -> if i `V.elem` v2 then (t,w - ampl / fromIntegral (V.length v2)) else (t,w)) $ v1++-- | Can be used to produce an example of the function @gRem@ for the 'fRemoveFElem'. Similar to 'gRem01', but uses its first argument+-- to renorm the result of the 'gRem01' so that its maximum by absolute value amplitude equals to the first argument.+gRem02 :: Double -> (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO+gRem02 amplMax (note,ampl) freq f = renormFD amplMax . gAdd01 (note,ampl) freq $ f ++-- | Similar to 'fAddFElem', but instead of one element @(Double,Double)@ it deals with a 'V.Vector' of such elements that is 'OvertonesO'. +fAddFElems :: OvertonesO -> Double -> (Double -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) ->+  (Double -> OvertonesO)+fAddFElems v freq f gAdds = \t -> gAdds v t f++-- | Similar to 'fRemoveFElem', but instead of one element @(Double,Double)@ it deals with a 'V.Vector' of such elements that is 'OvertonesO'. +fRemoveFElems :: OvertonesO -> Double -> (Double -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> +  (Double -> OvertonesO)+fRemoveFElems v freq f gRems = \t -> gRems v t f++-- | Binary predicate to check whether two given 'OvertonesO' both have the elements with the same first element in the tuples. If 'True' then+-- this means that 'OvertonesO' are at least partially overlaped by the first elements in the tuples (meaning frequencies). +freqsOverlapOvers :: OvertonesO -> OvertonesO -> Bool+freqsOverlapOvers v1 v2 =+  let [v11,v21] = map (V.uniq . V.map fst) [v1,v2]+      [l1,l2]  = map V.length [v11,v21] in compare (V.length . V.uniq . V.concat $ [v11,v21]) (l1 + l2) == LT++-- | Similar to 'freqsOverlapOvers', but checks whether the whole tuples are the same instead of the first elements in the tuples are the same.+elemsOverlapOvers :: OvertonesO -> OvertonesO -> Bool+elemsOverlapOvers v1 v2 =+  let [v11,v21] = map V.uniq [v1,v2]+      [l1,l2]  = map V.length [v11,v21] in compare (V.length . V.uniq . V.concat $ [v11,v21]) (l1 + l2) == LT++-- | Example of the function @gAdds@ for the 'fAddFElems'. +gAdds01 :: OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO+gAdds01 v0 freq f + | V.null . f $ freq = v0+ | freqsOverlapOvers v0 (f freq) =+     let ys = sortBy (\(x1,y1) (x2,y2) -> compare x1 x2) . V.toList $ v0+         h ys+          | null ys = []+          | otherwise = (fst . break (/= head ys) $ ys):h (snd . break (/= head ys) $ ys)+         h1 ys = map (\zs -> (sum . map snd $ zs) / fromIntegral (length zs)) . h $ ys+         h2 ys = map (fst . head) (h ys)+         v2   = V.fromList . zip (h2 ys) $ (h1 ys)+         us = sortBy (\(x1,y1) (x2,y2) -> compare x1 x2) . V.toList $ f freq+         v3   = V.fromList . zip (h2 us) $ (h1 us) in renormF . V.concat $ [v2,v3]+ | otherwise = renormF . V.concat $ [v0, f freq]++-- | Can be used to produce an example of the function @gAdds@ for the 'fAddFElems'. Similar to 'gAdds01', but uses its first argument+-- to renorm the result of the 'gAdds01' so that its maximum by absolute value amplitude equals to the first argument.+gAdds02 :: Double -> OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO+gAdds02 amplMax v0 freq f = renormFD amplMax . gAdds01 v0 freq $ f +
dobutokO2.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/  name:                dobutokO2-version:             0.25.0.0+version:             0.26.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