-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 792e3d1
Showing
24 changed files
with
6,189 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
-- | | ||
-- Module : DobutokO.Sound.DIS5G6G | ||
-- Copyright : (c) OleksandrZhabenko 2020 | ||
-- License : MIT | ||
-- Stability : Experimental | ||
-- Maintainer : olexandr543@yahoo.com | ||
-- | ||
-- Helps to create experimental music from a file (or its part) and a Ukrainian text. | ||
-- It can also generate a timbre for the notes. Uses SoX inside. | ||
|
||
{-# OPTIONS_GHC -threaded #-} | ||
|
||
module DobutokO.Sound.DIS5G6G ( | ||
-- ** Auxiliary functions | ||
syllableStr | ||
-- *** Working with Intervals, Durations, Strengths and StrengthDb | ||
, intervalsFromString | ||
, vStrToVInt | ||
, strToInt | ||
, durationsAver | ||
, str2Durat1 | ||
, str2Durations | ||
, str2Vol1 | ||
, str2Volume | ||
, doublesAveragedA | ||
, doublesAveragedG | ||
, equalize2Vec | ||
, intervalsFromStringG | ||
, silentSound2G | ||
, strengthsAver | ||
, strengthsDbAver | ||
-- * New generalized 6G functions that works with Strengths | ||
, apply6G | ||
, apply6G2 | ||
, apply6GS | ||
, apply6GS2 | ||
) where | ||
|
||
import CaseBi (getBFst') | ||
import Numeric | ||
import Data.Maybe (fromJust) | ||
import qualified Data.Vector as V | ||
import System.Process | ||
import EndOfExe | ||
import Melodics.Ukrainian (convertToProperUkrainian) | ||
import MMSyn7l | ||
import DobutokO.Sound.IntermediateF | ||
import DobutokO.Sound.Functional.Params | ||
import DobutokO.Sound.Decibel | ||
|
||
-- | Generatlized version of the 'intervalsFromString' with a possibility to specify your own 'Intervals'. | ||
intervalsFromStringG :: Intervals -> String -> Intervals | ||
intervalsFromStringG v = vStrToVIntG v . convertToProperUkrainian | ||
|
||
-- | The default way to get 'Intervals' from a converted Ukrainian text. | ||
vStrToVInt :: V.Vector String -> Intervals | ||
vStrToVInt = V.map (strToIntG defInt) | ||
|
||
-- | The default way to get number of semi-tones between notes in a single element of 'Intervals'. | ||
strToInt :: String -> Int | ||
strToInt = strToIntG defInt | ||
{-# INLINE strToInt #-} | ||
|
||
--------------------------------------------------------------------------------------------------------------------- | ||
|
||
-- | Arithmetic average for the 'V.Vector' is used as a weight for a duration. | ||
doublesAveragedA :: V.Vector Float -> Float -> V.Vector Float | ||
doublesAveragedA v4 y3 | ||
| V.null v4 || y3 == 0 = V.empty | ||
| otherwise = let aver = V.sum v4 / fromIntegral (V.length v4) in if aver == 0.0 then doublesAveragedA (V.filter (/= 0.0) v4) y3 | ||
else V.map (\t4 -> t4 * y3 / aver) v4 | ||
|
||
-- | Geometric average for the 'V.Vector' is used as a weight for a strength. | ||
doublesAveragedG :: V.Vector Float -> Float -> V.Vector Float | ||
doublesAveragedG v4 y3 | ||
| V.null v4 || y3 == 0 = V.empty | ||
| otherwise = let aver = V.product v4 ** (fromIntegral 1 / (fromIntegral (V.length v4))) in if aver == 0.0 then doublesAveragedG (V.filter (/= 0.0) v4) y3 | ||
else V.map (\t4 -> t4 * y3 / aver) v4 | ||
|
||
-- | 'Durations' accounting the desired average duration. | ||
durationsAver :: Durations -> Float -> Durations | ||
durationsAver = doublesAveragedA | ||
|
||
-- | 'Strengths' accounting the desired average strength. | ||
strengthsAver :: Strengths -> Float -> Strengths | ||
strengthsAver = doublesAveragedG | ||
|
||
-- | 'StrengthsDb' accounting the desired average strength in dB. | ||
strengthsDbAver :: StrengthsDb -> Float -> StrengthsDb | ||
strengthsDbAver = doublesAveragedG | ||
|
||
-- | Auxiliar function to make all vectors in a 'V.Vector' equal by length (the minimum one). | ||
equalize2Vec :: V.Vector (V.Vector a) -> V.Vector (V.Vector a) | ||
equalize2Vec v = let min = V.minimum . V.map V.length $ v in V.map (V.unsafeSlice 0 min) v | ||
|
||
-- | A full conversion to the 'Durations' from a Ukrainian text. | ||
str2Durations :: String -> Float -> Durations | ||
str2Durations xs y | ||
| compare y 0.0 == GT && not (null xs) = durationsAver (V.map str2Durat1 . convertToProperUkrainian $ xs) y | ||
| otherwise = V.empty | ||
|
||
-- | A conversion to the 'Float' that is used inside 'str2Durations'. | ||
str2Durat1 :: String -> Float | ||
str2Durat1 = getBFst' ((-0.153016), V.fromList [("-", (-0.101995)), ("0", (-0.051020)), ("1", (-0.153016)), ("а", 0.138231), ("б", 0.057143), | ||
("в", 0.082268), ("г", 0.076825), ("д", 0.072063), ("дж", 0.048934), ("дз", 0.055601), ("е", 0.093605), ("ж", 0.070658), ("з", 0.056054), | ||
("и", 0.099955), ("й", 0.057143), ("к", 0.045351), ("л", 0.064036), ("м", 0.077370), ("н", 0.074240), ("о", 0.116463), ("п", 0.134830), | ||
("р", 0.049206), ("с", 0.074603), ("сь", 0.074558), ("т", 0.110658), ("у", 0.109070), ("ф", 0.062268), ("х", 0.077188), ("ц", 0.053061), | ||
("ць", 0.089342), ("ч", 0.057596), ("ш", 0.066077), ("ь", 0.020227), ("і", 0.094150), ("ґ", 0.062948)]) | ||
|
||
-- | A full conversion to the 'Strengths' from a Ukrainian text. | ||
str2Volume :: String -> Strengths | ||
str2Volume = V.map (getBFst' (0.0, V.fromList [("а", 0.890533), ("б", 0.211334), ("в", (-0.630859)), ("г", (-0.757599)), ("д", 0.884613), ("дж", 0.768127), | ||
("дз", (-0.731262)), ("е", (-0.742523)), ("ж", (-0.588959)), ("з", (-0.528870)), ("и", 0.770935), ("й", (-0.708008)), ("к", (-0.443085)), | ||
("л", 0.572632), ("м", (-0.782349)), ("н", (-0.797607)), ("о", (-0.579559)), ("п", 0.124908), ("р", 0.647369), ("с", 0.155640), ("сь", (-0.207764)), | ||
("т", -0.304443), ("у", 0.718262), ("ф", (-0.374359)), ("х", (-0.251160)), ("ц", (-0.392365)), ("ць", 0.381348), ("ч", (-0.189240)), | ||
("ш", 0.251221), ("ь", 0.495483), ("і", (-0.682709)), ("ґ", 0.557098)])) . convertToProperUkrainian | ||
|
||
-- | A conversion to the 'Float' that is used inside 'str2Volume'. | ||
str2Vol1 :: String -> Float | ||
str2Vol1 = getBFst' (0.0, V.fromList [("а", 0.890533), ("б", 0.211334), ("в", (-0.630859)), ("г", (-0.757599)), ("д", 0.884613), ("дж", 0.768127), | ||
("дз", (-0.731262)), ("е", (-0.742523)), ("ж", (-0.588959)), ("з", (-0.528870)), ("и", 0.770935), ("й", (-0.708008)), ("к", (-0.443085)), | ||
("л", 0.572632), ("м", (-0.782349)), ("н", (-0.797607)), ("о", (-0.579559)), ("п", 0.124908), ("р", 0.647369), ("с", 0.155640), ("сь", (-0.207764)), | ||
("т", -0.304443), ("у", 0.718262), ("ф", (-0.374359)), ("х", (-0.251160)), ("ц", (-0.392365)), ("ць", 0.381348), ("ч", (-0.189240)), | ||
("ш", 0.251221), ("ь", 0.495483), ("і", (-0.682709)), ("ґ", 0.557098)]) . V.unsafeHead . convertToProperUkrainian | ||
|
||
-- | For the given non-existing 'FilePath' for a sound file supported by SoX generates a silence of the specified duration and quality (see, | ||
-- 'soxBasicParams'). | ||
silentSound2G :: FilePath -> Float -> String -> IO () | ||
silentSound2G file y4 ys = do | ||
_ <- readProcessWithExitCode (fromJust (showE "sox")) | ||
((if null ys then id else soxBasicParams ys) ["-r22040","-n",file,"synth", showFFloat (Just 1) y4 "","sine","440.0","vol","0"]) "" | ||
putStr "" | ||
|
||
-- | After producing sounds as WAV or FLAC files you can apply to them volume adjustments using 'Strengths'. The first 'String' is used accordingly to | ||
-- 'soxBasicParams' and the second one -- as a prefix of the filenames for the files that the function is applied to. The files must not be silent ones. | ||
-- Otherwise, it leads to likely noise sounding or errors. | ||
apply6G :: Strengths -> String -> String -> IO () | ||
apply6G v6 ys zs | ||
| V.null v6 = putStrLn "Nothing changed, because the vector of volume adjustments is empty! " | ||
| otherwise = do | ||
dir0v <- listVDirectory3G ys zs | ||
V.imapM_ (\i file -> soxE file ["norm","vol", showFFloat (Just 4) (V.unsafeIndex v6 (i `rem` V.length v6)) ""]) dir0v | ||
|
||
-- | Variant of the 'apply6G' where you use as a 'Strengths' parameter that one obtained from a Ukrainian text provided as a first 'String' argument. | ||
-- It uses 'str2Volume' inside. The files must not be silent ones. Otherwise, it leads to likely noise sounding or errors. | ||
apply6GS :: String -> String -> String -> IO () | ||
apply6GS xs = apply6G (str2Volume xs) | ||
|
||
-- | Variant of the 'apply6G' function which can be applied also to the silent files. Whether a file is silent is defined using the 'Float' argument | ||
-- so that if the maximum by absolute value amplitude is less by absolute value than the 'Float' argument then the file is not changed. | ||
apply6G2 :: Strengths -> String -> String -> Float -> IO () | ||
apply6G2 v6 ys zs limV | ||
| V.null v6 = putStrLn "Nothing changed, because the vector of volume adjustments is empty! " | ||
| otherwise = do | ||
dir0v <- listVDirectory3G ys zs | ||
V.imapM_ (\i file -> apply6GSilentFile file limV (V.unsafeIndex v6 (i `rem` V.length v6))) dir0v | ||
|
||
-- | Variant of the 'apply6G2' where you use as a 'Strengths' parameter that one obtained from a Ukrainian text provided as the first 'String' argument. | ||
-- It uses 'str2Volume' inside. | ||
apply6GS2 :: String -> String -> String -> Float -> IO () | ||
apply6GS2 xs = apply6G2 (str2Volume xs) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
-- | | ||
-- Module : DobutokO.Sound.Decibel | ||
-- Copyright : (c) OleksandrZhabenko 2020 | ||
-- License : MIT | ||
-- Stability : Experimental | ||
-- Maintainer : olexandr543@yahoo.com | ||
-- | ||
-- Helps to create experimental music from a file (or its part) and a Ukrainian text. | ||
-- It can also generate a timbre for the notes. Uses SoX inside. | ||
|
||
{-# OPTIONS_GHC -threaded #-} | ||
|
||
module DobutokO.Sound.Decibel ( | ||
-- * Type synonym with different semantics | ||
StrengthsDb | ||
-- * Working with StrengthsDb and Strengths and others | ||
, dBOmegaRatio | ||
, strength2dB_Abs | ||
, strengthdB2ampl | ||
, strengths2dB | ||
, strengthsDb2ampl | ||
) where | ||
|
||
import qualified Data.Vector as V | ||
import DobutokO.Sound.Functional.Params (Strengths) | ||
|
||
-- | Is used to represent a set of volumes in the dB scale for SoX \"vol\" effect. Usually, the zero value corresponds to the sound with volume | ||
-- level equal by absolute value to 1.0 (the extremum one). So for most cases, its elements are negative numbers not less than (-120). | ||
type StrengthsDb = V.Vector Float | ||
|
||
-- | Returns the frequency for which its ratio with the second 'Float' argument being under lg and being multiplied with 20 returns | ||
-- the first 'Float' argument. For example, @dBOmegaRatio 6 440 ~ 880@ (actually, 877.9154185863069). | ||
dBOmegaRatio :: Float -> Float -> Float | ||
dBOmegaRatio dB omega0 = omega0 * 10 ** (dB / fromIntegral 20) | ||
|
||
-- | Converts the absolute value of the argument to dB value compared to 1.0. Usually, is less than 0. The argument should not be equal to zero (0), | ||
-- otherwise, it is equal to -'Infinity'. | ||
strength2dB_Abs :: Float -> Float | ||
strength2dB_Abs vol = 20 * logBase 10 (abs vol) | ||
|
||
-- | Converts the absolute value of the argument from dB value to amplitude with 0 equivalent to amplitude of 1.0 (or -1.0 for inverted sound). | ||
-- Usually, is used for negative arguments (or at least not positive ones). | ||
strengthdB2ampl :: Float -> Float | ||
strengthdB2ampl dB = 10 ** (dB / fromIntegral 20) | ||
|
||
-- | Converts the 'V.Vector' of the absolute values of the argument to the 'V.Vector' of dB values compared to 1.0. | ||
-- Usually, its elements are less than 0. If some element in the argument is equal to zero (0), the corresponding resulting element is equal to -'Infinity'. | ||
strengths2dB :: Strengths -> StrengthsDb | ||
strengths2dB v = V.map strength2dB_Abs v | ||
|
||
-- | Converts the 'V.Vector' of dB values to the 'V.Vector' of the amplitudes with 0 being equivalent to amplitude of 1.0 (or -1.0 for inverted sound). | ||
-- Usually, is used for negative elements of the first argument (or at least not positive ones). | ||
strengthsDb2ampl :: StrengthsDb -> Strengths | ||
strengthsDb2ampl v = V.map strengthdB2ampl v | ||
|
Oops, something went wrong.