dobutokO2 0.40.0.0 → 0.41.0.0
raw patch · 19 files changed
+4022/−4101 lines, 19 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- DobutokO.Sound: chetvirkyTA :: NotePairs
- DobutokO.Sound: desyatkyTA :: NotePairs
- DobutokO.Sound: dev'yatkyTA :: NotePairs
- DobutokO.Sound: dviykyTA :: NotePairs
- DobutokO.Sound: liftInOctave :: Int -> Double -> Maybe Double
- DobutokO.Sound: liftInOctaveV :: Int -> Vector Double -> Vector Double
- DobutokO.Sound: octaveDown :: Double -> Double
- DobutokO.Sound: octaveUp :: Double -> Double
- DobutokO.Sound: octavesTA :: NotePairs
- DobutokO.Sound: odynadtsyatkyTA :: NotePairs
- DobutokO.Sound: overSoXSynth2 :: Double -> String -> IO ()
- DobutokO.Sound: overSoXSynth2DN :: Double -> Double -> String -> IO ()
- DobutokO.Sound: overSoXSynthDN :: Double -> String -> IO ()
- DobutokO.Sound: overSoXSynthN :: Int -> Double -> Double -> String -> Vector Double -> IO ()
- DobutokO.Sound: overSoXSynthN2 :: Int -> Double -> Double -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: overSoXSynthN24G :: Int -> Double -> Durations -> String -> Vector Double -> IO ()
- DobutokO.Sound: overSoXSynthN24GS :: Int -> Double -> Double -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: overSoXSynthN3 :: Int -> Double -> Double -> Double -> String -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: overSoXSynthN34G :: Int -> Double -> Double -> Durations -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: overSoXSynthN34GS :: Int -> Double -> Double -> Double -> String -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: overSoXSynthN35G :: Int -> Double -> Double -> Durations -> String -> Intervals -> Vector Double -> IO ()
- DobutokO.Sound: overSoXSynthN35GS :: Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> Vector Double -> IO ()
- DobutokO.Sound: overSoXSynthN4G :: Int -> Double -> Durations -> Vector Double -> IO ()
- DobutokO.Sound: overSoXSynthN4GS :: Int -> Double -> Double -> String -> Vector Double -> IO ()
- DobutokO.Sound: overSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen2 :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen2E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen2E4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen2E4GPar :: FilePath -> Params -> Double -> Durations -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen2E4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen2E4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen2EPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E4G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E4GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E4GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E4GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E5G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E5GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E5GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E5GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> Intervals -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E6G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> Strengths -> Double -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E6GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> Strengths -> Double -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E6GS :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> String -> Double -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E6GSPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> String -> Double -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E6GSu :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> Intervals -> String -> Double -> IO ()
- DobutokO.Sound: overSoXSynthNGen3E6GSuPar :: FilePath -> Params -> Double -> Double -> Double -> String -> Intervals -> String -> Double -> IO ()
- DobutokO.Sound: overSoXSynthNGen3EPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGenE4G :: FilePath -> Int -> Int -> Double -> Durations -> IO ()
- DobutokO.Sound: overSoXSynthNGenE4GPar :: FilePath -> Params -> Double -> Durations -> IO ()
- DobutokO.Sound: overSoXSynthNGenE4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGenE4GSPar :: FilePath -> Params -> Double -> Double -> String -> IO ()
- DobutokO.Sound: overSoXSynthNGenEPar :: FilePath -> Params -> Double -> Double -> String -> IO ()
- DobutokO.Sound: overTones2 :: Double -> String -> OvertonesO
- DobutokO.Sound: p'yatirkyTA :: NotePairs
- DobutokO.Sound: shistkyTA :: NotePairs
- DobutokO.Sound: signsFromString :: Int -> String -> Vector Int
- DobutokO.Sound: simkyTA :: NotePairs
- DobutokO.Sound: triykyTA :: NotePairs
- DobutokO.Sound: uniqOverSoXSynth :: Double -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynth2 :: Double -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN :: Int -> Double -> Double -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN3 :: Int -> Double -> Double -> String -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN34G :: Int -> Double -> Durations -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN34GS :: Int -> Double -> Double -> String -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN4 :: Int -> Double -> Double -> Double -> String -> String -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN44G :: Int -> Double -> Double -> Durations -> String -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN44GS :: Int -> Double -> Double -> Double -> String -> String -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN45G :: Int -> Double -> Double -> Durations -> String -> String -> Intervals -> Vector Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN45GS :: Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> Vector Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN46GSu :: Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> Vector Double -> String -> Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN4G :: Int -> Double -> Durations -> String -> Vector Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthN4GS :: Int -> Double -> Double -> String -> String -> Vector Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen3E4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen3E4GPar :: FilePath -> Params -> Double -> Durations -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen3E4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen3E4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen3EPar :: FilePath -> Params -> Double -> Double -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E4G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E4GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E4GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E4GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E5G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E5GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E5GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E5GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E6G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> Intervals -> Strengths -> Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E6GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> Intervals -> Strengths -> Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E6GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> String -> Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E6GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> String -> Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E6GSu :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> String -> Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4E6GSuPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> Intervals -> String -> String -> Double -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGen4EPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGenE4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGenE4GPar :: FilePath -> Params -> Double -> Durations -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGenE4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGenE4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()
- DobutokO.Sound: uniqOverSoXSynthNGenEPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()
- DobutokO.Sound: uniqOvertonesV :: Double -> String -> OvertonesO
- DobutokO.Sound: uniqOvertonesV2 :: Double -> String -> String -> OvertonesO
- DobutokO.Sound: visimkyTA :: NotePairs
- DobutokO.Sound.Executable: recAndProcess :: FilePath -> Int -> IO String
- DobutokO.Sound.Functional: P2 :: Int -> Int -> Params
- DobutokO.Sound.Functional: P2s :: Int -> Int -> String -> Params
- DobutokO.Sound.Functional: P32sf :: Int -> Int -> Int -> String -> String -> Params
- DobutokO.Sound.Functional: P3lf :: Int -> Int -> [Int] -> Params
- DobutokO.Sound.Functional: P3sf :: Int -> Int -> Int -> String -> Params
- DobutokO.Sound.Functional: P4lsf :: Int -> Int -> Int -> [Int] -> String -> Params
- DobutokO.Sound.Functional: adjust_dbVol :: [String] -> Double -> [String]
- DobutokO.Sound.Functional: apply6G :: Strengths -> String -> String -> IO ()
- DobutokO.Sound.Functional: apply6G2 :: Strengths -> String -> String -> Double -> IO ()
- DobutokO.Sound.Functional: apply6GS :: String -> String -> String -> IO ()
- DobutokO.Sound.Functional: apply6GS2 :: String -> String -> String -> Double -> IO ()
- DobutokO.Sound.Functional: apply6GSilentFile :: FilePath -> Double -> Double -> IO ()
- DobutokO.Sound.Functional: apply6Gf :: Double -> FilePath -> IO ()
- DobutokO.Sound.Functional: closestNote :: Double -> Double
- DobutokO.Sound.Functional: dBOmegaRatio :: Double -> Double -> Double
- DobutokO.Sound.Functional: dNote :: Int -> Double -> Maybe Double
- DobutokO.Sound.Functional: data Params
- DobutokO.Sound.Functional: defInt :: Intervals
- DobutokO.Sound.Functional: doubleVecFromVecOfDouble :: (Double -> OvertonesO) -> Double -> Vector (Maybe Double) -> Vector OvertonesO
- DobutokO.Sound.Functional: doublesAveragedA :: Vector Double -> Double -> Vector Double
- DobutokO.Sound.Functional: doublesAveragedG :: Vector Double -> Double -> Vector Double
- DobutokO.Sound.Functional: duration1000 :: FilePath -> IO Int
- DobutokO.Sound.Functional: durationsAver :: Durations -> Double -> Durations
- DobutokO.Sound.Functional: elemCloseP :: Double -> Params -> Bool
- DobutokO.Sound.Functional: elemP :: Double -> Params -> Bool
- DobutokO.Sound.Functional: elemsOverlapOvers :: OvertonesO -> OvertonesO -> Bool
- DobutokO.Sound.Functional: endFromResult :: IO ()
- DobutokO.Sound.Functional: endFromResult2G :: String -> IO ()
- DobutokO.Sound.Functional: enkuDown :: Int -> Double -> Double
- DobutokO.Sound.Functional: enkuUp :: Int -> Double -> Double
- DobutokO.Sound.Functional: equalize2Vec :: Vector (Vector a) -> Vector (Vector a)
- DobutokO.Sound.Functional: fAddFElem :: (Double, Double) -> (Double -> OvertonesO) -> ((Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> Double -> OvertonesO
- DobutokO.Sound.Functional: fAddFElems :: OvertonesO -> (Double -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> Double -> OvertonesO
- DobutokO.Sound.Functional: fChangeFElem :: (Double, Double) -> Double -> (Double -> (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Double -> OvertonesO) -> Double -> OvertonesO
- DobutokO.Sound.Functional: fChangeFElems :: OvertonesO -> Double -> (Double -> OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Double -> OvertonesO) -> Double -> OvertonesO
- DobutokO.Sound.Functional: fRemoveFElem :: (Double, Double) -> (Double -> OvertonesO) -> ((Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> Double -> OvertonesO
- DobutokO.Sound.Functional: fRemoveFElems :: OvertonesO -> (Double -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> Double -> OvertonesO
- DobutokO.Sound.Functional: fVecCoefs :: Int -> Double -> String -> Vector Double
- DobutokO.Sound.Functional: filterInParams :: Params -> Maybe (Vector Double)
- DobutokO.Sound.Functional: freqsFromFile :: FilePath -> Int -> IO (Vector Int)
- DobutokO.Sound.Functional: freqsOverlapOvers :: OvertonesO -> OvertonesO -> Bool
- DobutokO.Sound.Functional: gAdd01 :: (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
- DobutokO.Sound.Functional: gAdd02 :: Double -> (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
- DobutokO.Sound.Functional: gAdd03 :: (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
- DobutokO.Sound.Functional: gAdd04 :: (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
- DobutokO.Sound.Functional: gRem03 :: (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
- DobutokO.Sound.Functional: h1 :: (Double -> OvertonesO) -> (Double, Double) -> Int -> IO ()
- DobutokO.Sound.Functional: h2 :: OvertonesO -> (Double, Double) -> Int -> Int -> Double -> IO ()
- DobutokO.Sound.Functional: h2Params :: OvertonesO -> (Double, Double) -> Params -> Double -> IO ()
- DobutokO.Sound.Functional: helpF0 :: Int -> String
- DobutokO.Sound.Functional: helpF1 :: Vector (Double -> Double) -> Vector Double -> Vector Int -> Vector (Maybe Double)
- DobutokO.Sound.Functional: instance GHC.Classes.Eq DobutokO.Sound.Functional.Params
- DobutokO.Sound.Functional: instance GHC.Classes.Ord DobutokO.Sound.Functional.Params
- DobutokO.Sound.Functional: instance GHC.Show.Show DobutokO.Sound.Functional.Params
- DobutokO.Sound.Functional: intervalsFromString :: String -> Intervals
- DobutokO.Sound.Functional: intervalsFromStringG :: Intervals -> String -> Intervals
- DobutokO.Sound.Functional: isListParams :: [Int] -> Params -> Bool
- DobutokO.Sound.Functional: isStrParams :: String -> Params -> Bool
- DobutokO.Sound.Functional: lengthP :: Params -> Int
- DobutokO.Sound.Functional: liftInEnku :: Int -> Int -> Double -> Maybe Double
- DobutokO.Sound.Functional: liftInEnkuV :: Int -> Int -> Vector Double -> Vector Double
- DobutokO.Sound.Functional: liftInParams :: Double -> Params -> Double
- DobutokO.Sound.Functional: liftInParamsV :: Params -> Vector Double -> Vector Double
- DobutokO.Sound.Functional: maybeFFromStrVec :: Int -> Double -> String -> Maybe (Double, Double -> Vector (Double, Double))
- DobutokO.Sound.Functional: mixTest :: IO ()
- DobutokO.Sound.Functional: mixTest2 :: Int -> Int -> IO ()
- DobutokO.Sound.Functional: mixTest22G :: Int -> Int -> String -> IO ()
- DobutokO.Sound.Functional: mixTest2G :: String -> IO ()
- DobutokO.Sound.Functional: nOfZeroesLog :: Int -> Maybe Int
- DobutokO.Sound.Functional: neighbourNotes :: Double -> Vector Double -> (Double, Double)
- DobutokO.Sound.Functional: nkyT :: Int -> NotePairs
- DobutokO.Sound.Functional: notes :: Vector Double
- DobutokO.Sound.Functional: numVZeroesPre :: Vector a -> Int
- DobutokO.Sound.Functional: octavesT :: NotePairs
- DobutokO.Sound.Functional: overConcat :: Vector OvertonesO -> OvertonesO
- DobutokO.Sound.Functional: overMeloPar :: (Double -> OvertonesO) -> (Double -> Double) -> Params -> Double -> Double -> Double -> IO ()
- DobutokO.Sound.Functional: overSoXSynth :: Double -> IO ()
- DobutokO.Sound.Functional: overSoXSynthGen2FDN_SG2GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> String -> String -> ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()
- DobutokO.Sound.Functional: overSoXSynthGen2FDN_SG4GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Durations -> String -> ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()
- DobutokO.Sound.Functional: overSoXSynthGen2FDN_SG6GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Durations -> String -> ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> Strengths -> Double -> IO ()
- DobutokO.Sound.Functional: overSoXSynthGen2FDN_Sf3G2GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Double -> String -> String -> ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()
- DobutokO.Sound.Functional: overSoXSynthGen2FDN_Sf3GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Double -> String -> String -> ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()) -> IO ()
- DobutokO.Sound.Functional: overSoXSynthGen2FDN_SfPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()
- DobutokO.Sound.Functional: overTones :: Double -> OvertonesO
- DobutokO.Sound.Functional: partialTest_k :: OvertonesO -> Int -> String -> IO ()
- DobutokO.Sound.Functional: partialTest_k1G :: OvertonesO -> Int -> String -> Vector Double -> IO ()
- DobutokO.Sound.Functional: partialTest_k2G :: OvertonesO -> Int -> String -> Vector Double -> String -> IO ()
- DobutokO.Sound.Functional: prependZeroes :: Int -> String -> String
- DobutokO.Sound.Functional: pureQuintNote :: Double -> Double
- DobutokO.Sound.Functional: renormF :: OvertonesO -> OvertonesO
- DobutokO.Sound.Functional: renormFD :: Double -> OvertonesO -> OvertonesO
- DobutokO.Sound.Functional: sameFreqF :: Double -> (Double, Double) -> (Double -> OvertonesO) -> ((Double, Double) -> OvertonesO -> OvertonesO) -> OvertonesO
- DobutokO.Sound.Functional: sameFreqFI :: Double -> (Double, Double) -> (Double -> OvertonesO) -> ((Double, Double) -> OvertonesO -> OvertonesO) -> OvertonesO
- DobutokO.Sound.Functional: sameOvertone :: OvertonesO -> Bool
- DobutokO.Sound.Functional: sameOvertoneL :: [(Double, Double)] -> Bool
- DobutokO.Sound.Functional: showD :: Params -> String
- DobutokO.Sound.Functional: showFFromStrVec :: Int -> Double -> String -> String
- DobutokO.Sound.Functional: silentSound2G :: FilePath -> Double -> String -> IO ()
- DobutokO.Sound.Functional: sortNoDup :: Ord a => [a] -> [a]
- DobutokO.Sound.Functional: soundGen3G :: FilePath -> (Double -> OvertonesO) -> Double -> String -> ((Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> ((Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3GMN :: Int64 -> Int64 -> FilePath -> (Double -> OvertonesO) -> Double -> String -> ((Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> ((Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_O :: Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_O2 :: ((Double -> OvertonesO, Int -> Double -> OvertonesO, Int -> Double -> OvertonesO) -> Vector (Int, Int) -> Vector (Double, Double -> OvertonesO)) -> Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_O2G :: ((Vector (Double -> OvertonesO), Vector (Int -> Double -> OvertonesO), Vector (Int -> Double -> OvertonesO)) -> Vector (Int, Int) -> Vector (Double, Double -> OvertonesO)) -> Vector (Double -> OvertonesO) -> Vector (Int -> Double -> OvertonesO) -> Vector (Int -> Double -> OvertonesO) -> Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_O2GMN :: Int64 -> Int64 -> ((Vector (Double -> OvertonesO), Vector (Int -> Double -> OvertonesO), Vector (Int -> Double -> OvertonesO)) -> Vector (Int, Int) -> Vector (Double, Double -> OvertonesO)) -> Vector (Double -> OvertonesO) -> Vector (Int -> Double -> OvertonesO) -> Vector (Int -> Double -> OvertonesO) -> Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_O2GMNPar :: Int64 -> Int64 -> ((Vector (Double -> OvertonesO), Vector (Int -> Double -> OvertonesO), Vector (Int -> Double -> OvertonesO)) -> Vector (Int, Int) -> Vector (Double, Double -> OvertonesO)) -> Vector (Double -> OvertonesO) -> Vector (Int -> Double -> OvertonesO) -> Vector (Int -> Double -> OvertonesO) -> Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_O2GPar :: ((Vector (Double -> OvertonesO), Vector (Int -> Double -> OvertonesO), Vector (Int -> Double -> OvertonesO)) -> Vector (Int, Int) -> Vector (Double, Double -> OvertonesO)) -> Vector (Double -> OvertonesO) -> Vector (Int -> Double -> OvertonesO) -> Vector (Int -> Double -> OvertonesO) -> Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_O2MN :: Int64 -> Int64 -> ((Double -> OvertonesO, Int -> Double -> OvertonesO, Int -> Double -> OvertonesO) -> Vector (Int, Int) -> Vector (Double, Double -> OvertonesO)) -> Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_O2MNPar :: Int64 -> Int64 -> ((Double -> OvertonesO, Int -> Double -> OvertonesO, Int -> Double -> OvertonesO) -> Vector (Int, Int) -> Vector (Double, Double -> OvertonesO)) -> Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_O2Par :: ((Double -> OvertonesO, Int -> Double -> OvertonesO, Int -> Double -> OvertonesO) -> Vector (Int, Int) -> Vector (Double, Double -> OvertonesO)) -> Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_OMN :: Int64 -> Int64 -> Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_OMNPar :: Int64 -> Int64 -> Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGen3G_OPar :: Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()
- DobutokO.Sound.Functional: soundGenF32G :: Vector (Double -> Double) -> Vector Double -> Vector Int -> (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Vector Double -> String -> IO ()
- DobutokO.Sound.Functional: splitHelp1 :: Int -> Int -> Int -> Int -> OvertonesO -> (Double, Double) -> Vector OvertonesO
- DobutokO.Sound.Functional: splitHelp2 :: (OvertonesO -> OvertonesO) -> Int -> Int -> Int -> Int -> OvertonesO -> (Double, Double) -> Vector OvertonesO
- DobutokO.Sound.Functional: splitO :: Int -> OvertonesO -> Vector OvertonesO
- DobutokO.Sound.Functional: splitO2 :: (OvertonesO -> OvertonesO) -> Int -> OvertonesO -> Vector OvertonesO
- DobutokO.Sound.Functional: splitOG1 :: String -> Int -> OvertonesO -> Vector OvertonesO
- DobutokO.Sound.Functional: splitOG12 :: (Int, Int, Int, Int) -> Vector (String, Int -> OvertonesO -> (Int, Int, Int, Int)) -> String -> Int -> OvertonesO -> Vector OvertonesO
- DobutokO.Sound.Functional: splitOG12S :: (Int, Int, Int, Int) -> Vector (String, Int -> OvertonesO -> (Int, Int, Int, Int)) -> String -> Int -> OvertonesO -> Vector OvertonesO
- DobutokO.Sound.Functional: splitOG2 :: (OvertonesO -> OvertonesO) -> String -> Int -> OvertonesO -> Vector OvertonesO
- DobutokO.Sound.Functional: splitOG22 :: (Int, Int, Int, Int) -> Vector (String, Int -> OvertonesO -> (Int, Int, Int, Int)) -> (OvertonesO -> OvertonesO) -> String -> Int -> OvertonesO -> Vector OvertonesO
- DobutokO.Sound.Functional: splitOG22S :: (Int, Int, Int, Int) -> Vector (String, Int -> OvertonesO -> (Int, Int, Int, Int)) -> (OvertonesO -> OvertonesO) -> String -> Int -> OvertonesO -> Vector OvertonesO
- DobutokO.Sound.Functional: str2Durat1 :: String -> Double
- DobutokO.Sound.Functional: str2Durations :: String -> Double -> Durations
- DobutokO.Sound.Functional: str2DurationsDef :: Int -> String -> Double -> Durations
- DobutokO.Sound.Functional: str2Vol1 :: String -> Double
- DobutokO.Sound.Functional: str2Volume :: String -> Strengths
- DobutokO.Sound.Functional: strToInt :: String -> Int
- DobutokO.Sound.Functional: strToIntG :: Intervals -> String -> Int
- DobutokO.Sound.Functional: strength2dB_Abs :: Double -> Double
- DobutokO.Sound.Functional: strengthdB2ampl :: Double -> Double
- DobutokO.Sound.Functional: strengths2dB :: Strengths -> StrengthsDb
- DobutokO.Sound.Functional: strengthsAver :: Strengths -> Double -> Strengths
- DobutokO.Sound.Functional: strengthsDb2ampl :: StrengthsDb -> Strengths
- DobutokO.Sound.Functional: strengthsDbAver :: StrengthsDb -> Double -> StrengthsDb
- DobutokO.Sound.Functional: syllableStr :: Int -> String -> [Int]
- DobutokO.Sound.Functional: testSoundGen2G :: FilePath -> (Double -> OvertonesO) -> Double -> String -> IO ()
- DobutokO.Sound.Functional: testSoundGen2GMN :: Int64 -> Int64 -> FilePath -> (Double -> OvertonesO) -> Double -> String -> IO ()
- DobutokO.Sound.Functional: toneD :: Int -> Int -> Int -> [Int] -> Bool
- DobutokO.Sound.Functional: toneE :: Int -> Int -> Int -> [Int] -> Bool
- DobutokO.Sound.Functional: type Durations = Vector Double
- DobutokO.Sound.Functional: type Intervals = Vector Int
- DobutokO.Sound.Functional: type NotePairs = Vector (Double, Double)
- DobutokO.Sound.Functional: type OvertonesO = Vector (Double, Double)
- DobutokO.Sound.Functional: type SoundsO = Vector (Double, Double)
- DobutokO.Sound.Functional: type Strengths = Vector Double
- DobutokO.Sound.Functional: type StrengthsDb = Vector Double
- DobutokO.Sound.Functional: vStrToVInt :: Vector String -> Intervals
- DobutokO.Sound.Functional: vStrToVIntG :: Intervals -> Vector String -> Intervals
- DobutokO.Sound.Functional: whichEnka :: Int -> Double -> Maybe Int
- DobutokO.Sound.Functional: whichOctave :: Double -> Maybe Int
- DobutokO.Sound.Functional: whichOctaveG :: Double -> Maybe Int
+ DobutokO.Sound.DIS5G6G: apply6G :: Strengths -> String -> String -> IO ()
+ DobutokO.Sound.DIS5G6G: apply6G2 :: Strengths -> String -> String -> Double -> IO ()
+ DobutokO.Sound.DIS5G6G: apply6GS :: String -> String -> String -> IO ()
+ DobutokO.Sound.DIS5G6G: apply6GS2 :: String -> String -> String -> Double -> IO ()
+ DobutokO.Sound.DIS5G6G: doublesAveragedA :: Vector Double -> Double -> Vector Double
+ DobutokO.Sound.DIS5G6G: doublesAveragedG :: Vector Double -> Double -> Vector Double
+ DobutokO.Sound.DIS5G6G: durationsAver :: Durations -> Double -> Durations
+ DobutokO.Sound.DIS5G6G: equalize2Vec :: Vector (Vector a) -> Vector (Vector a)
+ DobutokO.Sound.DIS5G6G: intervalsFromString :: String -> Intervals
+ DobutokO.Sound.DIS5G6G: intervalsFromStringG :: Intervals -> String -> Intervals
+ DobutokO.Sound.DIS5G6G: silentSound2G :: FilePath -> Double -> String -> IO ()
+ DobutokO.Sound.DIS5G6G: str2Durat1 :: String -> Double
+ DobutokO.Sound.DIS5G6G: str2Durations :: String -> Double -> Durations
+ DobutokO.Sound.DIS5G6G: str2Vol1 :: String -> Double
+ DobutokO.Sound.DIS5G6G: str2Volume :: String -> Strengths
+ DobutokO.Sound.DIS5G6G: strToInt :: String -> Int
+ DobutokO.Sound.DIS5G6G: strengthsAver :: Strengths -> Double -> Strengths
+ DobutokO.Sound.DIS5G6G: strengthsDbAver :: StrengthsDb -> Double -> StrengthsDb
+ DobutokO.Sound.DIS5G6G: syllableStr :: Int -> String -> [Int]
+ DobutokO.Sound.DIS5G6G: vStrToVInt :: Vector String -> Intervals
+ DobutokO.Sound.Decibel: dBOmegaRatio :: Double -> Double -> Double
+ DobutokO.Sound.Decibel: strength2dB_Abs :: Double -> Double
+ DobutokO.Sound.Decibel: strengthdB2ampl :: Double -> Double
+ DobutokO.Sound.Decibel: strengths2dB :: Strengths -> StrengthsDb
+ DobutokO.Sound.Decibel: strengthsDb2ampl :: StrengthsDb -> Strengths
+ DobutokO.Sound.Decibel: type StrengthsDb = Vector Double
+ DobutokO.Sound.Extended: chetvirkyTA :: NotePairs
+ DobutokO.Sound.Extended: desyatkyTA :: NotePairs
+ DobutokO.Sound.Extended: dev'yatkyTA :: NotePairs
+ DobutokO.Sound.Extended: dviykyTA :: NotePairs
+ DobutokO.Sound.Extended: octavesTA :: NotePairs
+ DobutokO.Sound.Extended: odynadtsyatkyTA :: NotePairs
+ DobutokO.Sound.Extended: p'yatirkyTA :: NotePairs
+ DobutokO.Sound.Extended: shistkyTA :: NotePairs
+ DobutokO.Sound.Extended: simkyTA :: NotePairs
+ DobutokO.Sound.Extended: triykyTA :: NotePairs
+ DobutokO.Sound.Extended: visimkyTA :: NotePairs
+ DobutokO.Sound.FunctionF: fVecCoefs :: Int -> Double -> String -> Vector Double
+ DobutokO.Sound.FunctionF: maybeFFromStrVec :: Int -> Double -> String -> Maybe (Double, Double -> Vector (Double, Double))
+ DobutokO.Sound.FunctionF: showFFromStrVec :: Int -> Double -> String -> String
+ DobutokO.Sound.Functional.Basics: adjust_dbVol :: [String] -> Double -> [String]
+ DobutokO.Sound.Functional.Basics: closestNote :: Double -> Double
+ DobutokO.Sound.Functional.Basics: dNote :: Int -> Double -> Maybe Double
+ DobutokO.Sound.Functional.Basics: duration1000 :: FilePath -> IO Int
+ DobutokO.Sound.Functional.Basics: endFromResult :: IO ()
+ DobutokO.Sound.Functional.Basics: endFromResult2G :: String -> IO ()
+ DobutokO.Sound.Functional.Basics: enkuDown :: Int -> Double -> Double
+ DobutokO.Sound.Functional.Basics: enkuUp :: Int -> Double -> Double
+ DobutokO.Sound.Functional.Basics: freqsFromFile :: FilePath -> Int -> IO (Vector Int)
+ DobutokO.Sound.Functional.Basics: liftInEnku :: Int -> Int -> Double -> Maybe Double
+ DobutokO.Sound.Functional.Basics: liftInEnkuV :: Int -> Int -> Vector Double -> Vector Double
+ DobutokO.Sound.Functional.Basics: mixTest :: IO ()
+ DobutokO.Sound.Functional.Basics: mixTest2 :: Int -> Int -> IO ()
+ DobutokO.Sound.Functional.Basics: mixTest22G :: Int -> Int -> String -> IO ()
+ DobutokO.Sound.Functional.Basics: mixTest2G :: String -> IO ()
+ DobutokO.Sound.Functional.Basics: nOfZeroesLog :: Int -> Maybe Int
+ DobutokO.Sound.Functional.Basics: neighbourNotes :: Double -> Vector Double -> (Double, Double)
+ DobutokO.Sound.Functional.Basics: nkyT :: Int -> NotePairs
+ DobutokO.Sound.Functional.Basics: notes :: Vector Double
+ DobutokO.Sound.Functional.Basics: numVZeroesPre :: Vector a -> Int
+ DobutokO.Sound.Functional.Basics: octavesT :: NotePairs
+ DobutokO.Sound.Functional.Basics: overSoXSynth :: Double -> IO ()
+ DobutokO.Sound.Functional.Basics: overTones :: Double -> OvertonesO
+ DobutokO.Sound.Functional.Basics: partialTest_k :: OvertonesO -> Int -> String -> IO ()
+ DobutokO.Sound.Functional.Basics: partialTest_k1G :: OvertonesO -> Int -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Functional.Basics: partialTest_k2G :: OvertonesO -> Int -> String -> Vector Double -> String -> IO ()
+ DobutokO.Sound.Functional.Basics: prependZeroes :: Int -> String -> String
+ DobutokO.Sound.Functional.Basics: pureQuintNote :: Double -> Double
+ DobutokO.Sound.Functional.Basics: type NotePairs = Vector (Double, Double)
+ DobutokO.Sound.Functional.Basics: type OvertonesO = Vector (Double, Double)
+ DobutokO.Sound.Functional.Basics: type SoundsO = Vector (Double, Double)
+ DobutokO.Sound.Functional.Basics: whichEnka :: Int -> Double -> Maybe Int
+ DobutokO.Sound.Functional.Basics: whichOctave :: Double -> Maybe Int
+ DobutokO.Sound.Functional.Basics: whichOctaveG :: Double -> Maybe Int
+ DobutokO.Sound.Functional.Elements: elemsOverlapOvers :: OvertonesO -> OvertonesO -> Bool
+ DobutokO.Sound.Functional.Elements: fAddFElem :: (Double, Double) -> (Double -> OvertonesO) -> ((Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> Double -> OvertonesO
+ DobutokO.Sound.Functional.Elements: fAddFElems :: OvertonesO -> (Double -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> Double -> OvertonesO
+ DobutokO.Sound.Functional.Elements: fChangeFElem :: (Double, Double) -> Double -> (Double -> (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Double -> OvertonesO) -> Double -> OvertonesO
+ DobutokO.Sound.Functional.Elements: fChangeFElems :: OvertonesO -> Double -> (Double -> OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Double -> OvertonesO) -> Double -> OvertonesO
+ DobutokO.Sound.Functional.Elements: fRemoveFElem :: (Double, Double) -> (Double -> OvertonesO) -> ((Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> Double -> OvertonesO
+ DobutokO.Sound.Functional.Elements: fRemoveFElems :: OvertonesO -> (Double -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> Double -> OvertonesO
+ DobutokO.Sound.Functional.Elements: freqsOverlapOvers :: OvertonesO -> OvertonesO -> Bool
+ DobutokO.Sound.Functional.Elements: gAdd01 :: (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional.Elements: gAdd02 :: Double -> (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional.Elements: gAdd03 :: (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional.Elements: gAdd04 :: (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional.Elements: gAdds01 :: OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional.Elements: gAdds02 :: Double -> OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional.Elements: gRem01 :: (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional.Elements: gRem02 :: Double -> (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional.Elements: gRem03 :: (Double, Double) -> Double -> (Double -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional.Elements: renormF :: OvertonesO -> OvertonesO
+ DobutokO.Sound.Functional.Elements: renormFD :: Double -> OvertonesO -> OvertonesO
+ DobutokO.Sound.Functional.Elements: sameFreqF :: Double -> (Double, Double) -> (Double -> OvertonesO) -> ((Double, Double) -> OvertonesO -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional.Elements: sameFreqFI :: Double -> (Double, Double) -> (Double -> OvertonesO) -> ((Double, Double) -> OvertonesO -> OvertonesO) -> OvertonesO
+ DobutokO.Sound.Functional.Elements: sameOvertone :: OvertonesO -> Bool
+ DobutokO.Sound.Functional.Elements: sameOvertoneL :: [(Double, Double)] -> Bool
+ DobutokO.Sound.Functional.Params: P2 :: Int -> Int -> Params
+ DobutokO.Sound.Functional.Params: P2s :: Int -> Int -> String -> Params
+ DobutokO.Sound.Functional.Params: P32sf :: Int -> Int -> Int -> String -> String -> Params
+ DobutokO.Sound.Functional.Params: P3lf :: Int -> Int -> [Int] -> Params
+ DobutokO.Sound.Functional.Params: P3sf :: Int -> Int -> Int -> String -> Params
+ DobutokO.Sound.Functional.Params: P4lsf :: Int -> Int -> Int -> [Int] -> String -> Params
+ DobutokO.Sound.Functional.Params: apply6GSilentFile :: FilePath -> Double -> Double -> IO ()
+ DobutokO.Sound.Functional.Params: apply6Gf :: Double -> FilePath -> IO ()
+ DobutokO.Sound.Functional.Params: data Params
+ DobutokO.Sound.Functional.Params: defInt :: Intervals
+ DobutokO.Sound.Functional.Params: doubleVecFromVecOfDouble :: (Double -> OvertonesO) -> Double -> Vector (Maybe Double) -> Vector OvertonesO
+ DobutokO.Sound.Functional.Params: elemCloseP :: Double -> Params -> Bool
+ DobutokO.Sound.Functional.Params: elemP :: Double -> Params -> Bool
+ DobutokO.Sound.Functional.Params: filterInParams :: Params -> Maybe (Vector Double)
+ DobutokO.Sound.Functional.Params: helpF0 :: Int -> String
+ DobutokO.Sound.Functional.Params: helpF1 :: Vector (Double -> Double) -> Vector Double -> Vector Int -> Vector (Maybe Double)
+ DobutokO.Sound.Functional.Params: instance GHC.Classes.Eq DobutokO.Sound.Functional.Params.Params
+ DobutokO.Sound.Functional.Params: instance GHC.Classes.Ord DobutokO.Sound.Functional.Params.Params
+ DobutokO.Sound.Functional.Params: instance GHC.Show.Show DobutokO.Sound.Functional.Params.Params
+ DobutokO.Sound.Functional.Params: intervalsFromString :: String -> Intervals
+ DobutokO.Sound.Functional.Params: isListParams :: [Int] -> Params -> Bool
+ DobutokO.Sound.Functional.Params: isStrParams :: String -> Params -> Bool
+ DobutokO.Sound.Functional.Params: lengthP :: Params -> Int
+ DobutokO.Sound.Functional.Params: liftInParams :: Double -> Params -> Double
+ DobutokO.Sound.Functional.Params: liftInParamsV :: Params -> Vector Double -> Vector Double
+ DobutokO.Sound.Functional.Params: overMeloPar :: (Double -> OvertonesO) -> (Double -> Double) -> Params -> Double -> Double -> Double -> IO ()
+ DobutokO.Sound.Functional.Params: overSoXSynth2FDN_Sf :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()
+ DobutokO.Sound.Functional.Params: overSoXSynth2FDN_Sf3 :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()
+ DobutokO.Sound.Functional.Params: overSoXSynth2FDN_Sf32G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> Vector Double -> String -> IO ()
+ DobutokO.Sound.Functional.Params: overSoXSynthGen2FDN_SG2GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> String -> String -> ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()
+ DobutokO.Sound.Functional.Params: overSoXSynthGen2FDN_SG4GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Durations -> String -> ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()
+ DobutokO.Sound.Functional.Params: overSoXSynthGen2FDN_SG6GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Durations -> String -> ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> Strengths -> Double -> IO ()
+ DobutokO.Sound.Functional.Params: overSoXSynthGen2FDN_Sf3G2GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Double -> String -> String -> ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()
+ DobutokO.Sound.Functional.Params: overSoXSynthGen2FDN_Sf3GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Double -> String -> String -> ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()) -> IO ()
+ DobutokO.Sound.Functional.Params: overSoXSynthGen2FDN_SfPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()
+ DobutokO.Sound.Functional.Params: showD :: Params -> String
+ DobutokO.Sound.Functional.Params: signsFromString :: Int -> String -> Vector Int
+ DobutokO.Sound.Functional.Params: sortNoDup :: Ord a => [a] -> [a]
+ DobutokO.Sound.Functional.Params: soundGenF32G :: Vector (Double -> Double) -> Vector Double -> Vector Int -> (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Vector Double -> String -> IO ()
+ DobutokO.Sound.Functional.Params: str2DurationsDef :: Int -> String -> Double -> Durations
+ DobutokO.Sound.Functional.Params: strToIntG :: Intervals -> String -> Int
+ DobutokO.Sound.Functional.Params: syllableStr :: Int -> String -> [Int]
+ DobutokO.Sound.Functional.Params: toneD :: Int -> Int -> Int -> [Int] -> Bool
+ DobutokO.Sound.Functional.Params: toneE :: Int -> Int -> Int -> [Int] -> Bool
+ DobutokO.Sound.Functional.Params: type Durations = Vector Double
+ DobutokO.Sound.Functional.Params: type Intervals = Vector Int
+ DobutokO.Sound.Functional.Params: type Strengths = Vector Double
+ DobutokO.Sound.Functional.Params: vStrToVIntG :: Intervals -> Vector String -> Intervals
+ DobutokO.Sound.Functional.Split: overConcat :: Vector OvertonesO -> OvertonesO
+ DobutokO.Sound.Functional.Split: splitHelp1 :: Int -> Int -> Int -> Int -> OvertonesO -> (Double, Double) -> Vector OvertonesO
+ DobutokO.Sound.Functional.Split: splitHelp2 :: (OvertonesO -> OvertonesO) -> Int -> Int -> Int -> Int -> OvertonesO -> (Double, Double) -> Vector OvertonesO
+ DobutokO.Sound.Functional.Split: splitO :: Int -> OvertonesO -> Vector OvertonesO
+ DobutokO.Sound.Functional.Split: splitO2 :: (OvertonesO -> OvertonesO) -> Int -> OvertonesO -> Vector OvertonesO
+ DobutokO.Sound.Functional.Split: splitOG1 :: String -> Int -> OvertonesO -> Vector OvertonesO
+ DobutokO.Sound.Functional.Split: splitOG12 :: (Int, Int, Int, Int) -> Vector (String, Int -> OvertonesO -> (Int, Int, Int, Int)) -> String -> Int -> OvertonesO -> Vector OvertonesO
+ DobutokO.Sound.Functional.Split: splitOG12S :: (Int, Int, Int, Int) -> Vector (String, Int -> OvertonesO -> (Int, Int, Int, Int)) -> String -> Int -> OvertonesO -> Vector OvertonesO
+ DobutokO.Sound.Functional.Split: splitOG2 :: (OvertonesO -> OvertonesO) -> String -> Int -> OvertonesO -> Vector OvertonesO
+ DobutokO.Sound.Functional.Split: splitOG22 :: (Int, Int, Int, Int) -> Vector (String, Int -> OvertonesO -> (Int, Int, Int, Int)) -> (OvertonesO -> OvertonesO) -> String -> Int -> OvertonesO -> Vector OvertonesO
+ DobutokO.Sound.Functional.Split: splitOG22S :: (Int, Int, Int, Int) -> Vector (String, Int -> OvertonesO -> (Int, Int, Int, Int)) -> (OvertonesO -> OvertonesO) -> String -> Int -> OvertonesO -> Vector OvertonesO
+ DobutokO.Sound.Octaves: liftInOctave :: Int -> Double -> Maybe Double
+ DobutokO.Sound.Octaves: liftInOctaveV :: Int -> Vector Double -> Vector Double
+ DobutokO.Sound.Octaves: octaveDown :: Double -> Double
+ DobutokO.Sound.Octaves: octaveUp :: Double -> Double
+ DobutokO.Sound.Overtones: overSoXSynth2 :: Double -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynth2DN :: Double -> Double -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthDN :: Double -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthN :: Int -> Double -> Double -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthN2 :: Int -> Double -> Double -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthN24G :: Int -> Double -> Durations -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthN24GS :: Int -> Double -> Double -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthN3 :: Int -> Double -> Double -> Double -> String -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthN34G :: Int -> Double -> Double -> Durations -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthN34GS :: Int -> Double -> Double -> Double -> String -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthN35G :: Int -> Double -> Double -> Durations -> String -> Intervals -> Vector Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthN35GS :: Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthN4G :: Int -> Double -> Durations -> Vector Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthN4GS :: Int -> Double -> Double -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen2 :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen2E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen2E4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen2E4GPar :: FilePath -> Params -> Double -> Durations -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen2E4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen2E4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen2EPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E4G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E4GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E4GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E4GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E5G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E5GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E5GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E5GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> Intervals -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E6G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> Strengths -> Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E6GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> Strengths -> Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E6GS :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> String -> Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E6GSPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> String -> Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E6GSu :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> Intervals -> String -> Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3E6GSuPar :: FilePath -> Params -> Double -> Double -> Double -> String -> Intervals -> String -> Double -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGen3EPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGenE4G :: FilePath -> Int -> Int -> Double -> Durations -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGenE4GPar :: FilePath -> Params -> Double -> Durations -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGenE4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGenE4GSPar :: FilePath -> Params -> Double -> Double -> String -> IO ()
+ DobutokO.Sound.Overtones: overSoXSynthNGenEPar :: FilePath -> Params -> Double -> Double -> String -> IO ()
+ DobutokO.Sound.Overtones: overTones2 :: Double -> String -> OvertonesO
+ DobutokO.Sound.Process: d3H :: String -> String
+ DobutokO.Sound.Process: d4H :: String -> String
+ DobutokO.Sound.Process: d5H :: String -> String
+ DobutokO.Sound.Process: d7H :: String -> String
+ DobutokO.Sound.Process: d8H :: String -> String
+ DobutokO.Sound.Process: d9H :: String -> String
+ DobutokO.Sound.Process: processD1 :: IO String
+ DobutokO.Sound.Process: processD2 :: FilePath -> IO String
+ DobutokO.Sound.Process: recAndProcess :: FilePath -> Int -> IO String
+ DobutokO.Sound.Uniq: uniqOverSoXSynth :: Double -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynth2 :: Double -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN :: Int -> Double -> Double -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN3 :: Int -> Double -> Double -> String -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN34G :: Int -> Double -> Durations -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN34GS :: Int -> Double -> Double -> String -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN4 :: Int -> Double -> Double -> Double -> String -> String -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN44G :: Int -> Double -> Double -> Durations -> String -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN44GS :: Int -> Double -> Double -> Double -> String -> String -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN45G :: Int -> Double -> Double -> Durations -> String -> String -> Intervals -> Vector Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN45GS :: Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN46GS :: Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> Vector Double -> String -> Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN46GSu :: Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> Vector Double -> String -> Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN4G :: Int -> Double -> Durations -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthN4GS :: Int -> Double -> Double -> String -> String -> Vector Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen3E4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen3E4GPar :: FilePath -> Params -> Double -> Durations -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen3E4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen3E4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen3EPar :: FilePath -> Params -> Double -> Double -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E4G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E4GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E4GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E4GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E5G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E5GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E5GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E5GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E6G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> Intervals -> Strengths -> Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E6GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> Intervals -> Strengths -> Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E6GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> String -> Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E6GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> String -> Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E6GSu :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> String -> Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4E6GSuPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> Intervals -> String -> String -> Double -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGen4EPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGenE4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGenE4GPar :: FilePath -> Params -> Double -> Durations -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGenE4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGenE4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOverSoXSynthNGenEPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()
+ DobutokO.Sound.Uniq: uniqOvertonesV :: Double -> String -> OvertonesO
+ DobutokO.Sound.Uniq: uniqOvertonesV2 :: Double -> String -> String -> OvertonesO
- DobutokO.Sound.Functional: overSoXSynthGen2FDN4G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Durations -> String -> IO ()
+ DobutokO.Sound.Functional: overSoXSynthGen2FDN4G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Durations -> String -> IO ()
- DobutokO.Sound.Functional: overSoXSynthGen2FDN_SG4G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Durations -> String -> ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()
+ DobutokO.Sound.Functional: overSoXSynthGen2FDN_SG4G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Durations -> String -> ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()
- DobutokO.Sound.Functional: overSoXSynthGen2FDN_SG6G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Durations -> String -> ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> Strengths -> Double -> IO ()
+ DobutokO.Sound.Functional: overSoXSynthGen2FDN_SG6G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Durations -> String -> ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> Strengths -> Double -> IO ()
Files
- CHANGELOG.md +7/−0
- DobutokO/Sound.hs +0/−1421
- DobutokO/Sound/DIS5G6G.hs +162/−0
- DobutokO/Sound/Decibel.hs +55/−0
- DobutokO/Sound/Executable.hs +7/−248
- DobutokO/Sound/Extended.hs +64/−0
- DobutokO/Sound/FunctionF.hs +81/−0
- DobutokO/Sound/Functional.hs +626/−2427
- DobutokO/Sound/Functional/Basics.hs +383/−0
- DobutokO/Sound/Functional/Elements.hs +248/−0
- DobutokO/Sound/Functional/Params.hs +534/−0
- DobutokO/Sound/Functional/Split.hs +175/−0
- DobutokO/Sound/IntermediateF.hs +1/−3
- DobutokO/Sound/Octaves.hs +63/−0
- DobutokO/Sound/Overtones.hs +644/−0
- DobutokO/Sound/Process.hs +272/−0
- DobutokO/Sound/Uniq.hs +691/−0
- README.markdown +7/−0
- dobutokO2.cabal +2/−2
CHANGELOG.md view
@@ -379,3 +379,10 @@ * Fourtieth version. Added mmsyn7l as a dependency. Moved some functions from DobutokO.Sound.IntermediateF module to MMSyn7l module. This allows to use their functionality without necessary installation of the dobutokO2 package (only mmsyn7* series using).++## 0.41.0.0 -- 2020-05-20++* Fourty-first version. Completely changed the modules structure added new ones and rearranged the existing, module DobutokO.Sound splitted into three +different modules: DobutokO.Sound.Overtones, DobutokO.Sound.Uniq and DobutokO.Sound.Octaves. This was done to simplify compilation and to produce more +logical and semantic structure. The most complicated functions from DobutokO.Sound.Functional module are moved to a new package dobutokO3. Some code +improvements.
− DobutokO/Sound.hs
@@ -1,1421 +0,0 @@--- |--- Module : DobutokO.Sound--- 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.--{-# LANGUAGE BangPatterns, LambdaCase #-}-{-# OPTIONS_GHC -threaded #-}--module DobutokO.Sound (- -- * Library and executable functions- -- ** For the fixed timbre- overSoXSynthN- -- *** For the fixed timbre with different signs for harmonics coefficients- , overTones2- , overSoXSynth2- , overSoXSynthN2- , overSoXSynthN3- -- *** Use additional parameters- , overSoXSynthDN- , overSoXSynth2DN- -- *** Use a file for information- , overSoXSynthNGen- , overSoXSynthNGen2- , overSoXSynthNGen3- -- ** For the unique for the String structure timbre- , uniqOvertonesV- , uniqOverSoXSynth- , uniqOverSoXSynthN- -- *** For the unique for the String structure timbre with different signs for harmonics coefficients- , uniqOvertonesV2- , uniqOverSoXSynth2- , uniqOverSoXSynthN3- , uniqOverSoXSynthN4- -- *** Use a file for information- , uniqOverSoXSynthNGen- , uniqOverSoXSynthNGen3- , uniqOverSoXSynthNGen4- -- ** Work with octaves- , octaveUp- , octaveDown- , liftInOctave- , liftInOctaveV- -- ** Even more extended- , dviykyTA- , triykyTA- , chetvirkyTA- , p'yatirkyTA- , shistkyTA- , simkyTA- , visimkyTA- , dev'yatkyTA- , desyatkyTA- , odynadtsyatkyTA- , octavesTA- -- * Extended generation using enky functionality- -- ** With somewhat fixed timbre- , overSoXSynthNGenE- , overSoXSynthNGen2E- , overSoXSynthNGen3E- -- ** With usage of additional information in the Ukrainian text- , uniqOverSoXSynthNGenE- , uniqOverSoXSynthNGen3E- , uniqOverSoXSynthNGen4E- -- * Auxiliary functions- , signsFromString- -- * New 4G functions to work with Durations- , overSoXSynthN4G- , overSoXSynthN24G- , overSoXSynthN34G- , overSoXSynthNGenE4G- , overSoXSynthNGen2E4G- , overSoXSynthNGen3E4G- , uniqOverSoXSynthN4G- , uniqOverSoXSynthN34G- , uniqOverSoXSynthN44G- , uniqOverSoXSynthNGenE4G- , uniqOverSoXSynthNGen3E4G- , uniqOverSoXSynthNGen4E4G- -- ** 4G with speech-like composition- , overSoXSynthN4GS- , overSoXSynthN24GS- , overSoXSynthN34GS- , overSoXSynthNGenE4GS- , overSoXSynthNGen2E4GS- , overSoXSynthNGen3E4GS- , uniqOverSoXSynthN4GS- , uniqOverSoXSynthN34GS- , uniqOverSoXSynthN44GS- , uniqOverSoXSynthNGenE4GS- , uniqOverSoXSynthNGen3E4GS- , uniqOverSoXSynthNGen4E4GS- -- * New 5G functions to work also with Intervals- , overSoXSynthN35G- , overSoXSynthNGen3E5G- , uniqOverSoXSynthN45G- , uniqOverSoXSynthNGen4E5G- -- ** 5G with obtained from the text arbitraty length Intervals- , overSoXSynthN35GS- , overSoXSynthNGen3E5GS- , uniqOverSoXSynthN45GS- , uniqOverSoXSynthNGen4E5GS- -- * New 6G function to work also with Strengths- , overSoXSynthNGen3E6G- , uniqOverSoXSynthNGen4E6G- -- ** 6G with obtained from the text arbitrary length Strengths- , overSoXSynthNGen3E6GS- , overSoXSynthNGen3E6GSu- , uniqOverSoXSynthN46GSu- , uniqOverSoXSynthNGen4E6GS- , uniqOverSoXSynthNGen4E6GSu- -- * New generalized functions working with Params- , overSoXSynthNGenEPar- , overSoXSynthNGenE4GSPar- , overSoXSynthNGenE4GPar- , overSoXSynthNGen2EPar- , overSoXSynthNGen2E4GSPar- , overSoXSynthNGen2E4GPar- , overSoXSynthNGen3EPar- , overSoXSynthNGen3E4GSPar- , overSoXSynthNGen3E4GPar- , overSoXSynthNGen3E5GPar- , overSoXSynthNGen3E5GSPar- , overSoXSynthNGen3E6GPar- , overSoXSynthNGen3E6GSPar- , overSoXSynthNGen3E6GSuPar- -- ** With overtones obtained from the additional Ukrainian text- , uniqOverSoXSynthNGenEPar- , uniqOverSoXSynthNGenE4GSPar- , uniqOverSoXSynthNGenE4GPar- , uniqOverSoXSynthNGen3EPar- , uniqOverSoXSynthNGen3E4GSPar- , uniqOverSoXSynthNGen3E4GPar- , uniqOverSoXSynthNGen4EPar- , uniqOverSoXSynthNGen4E4GSPar- , uniqOverSoXSynthNGen4E4GPar- , uniqOverSoXSynthNGen4E5GPar- , uniqOverSoXSynthNGen4E5GSPar- , uniqOverSoXSynthNGen4E6GPar- , uniqOverSoXSynthNGen4E6GSPar- , uniqOverSoXSynthNGen4E6GSuPar- -) where--import CaseBi (getBFst')-import System.Exit (ExitCode(ExitSuccess))-import Numeric (showFFloat)-import Control.Exception (onException)-import System.Environment (getArgs)-import Data.List (isPrefixOf,sort,sortBy,nubBy)-import Data.Maybe (isJust,isNothing,fromJust,maybe)-import Data.Char (isDigit)-import qualified Data.Vector as V-import System.Process-import EndOfExe (showE)-import MMSyn7.Syllable -import MMSyn7s-import System.Directory-import SoXBasics-import Processing_mmsyn7ukr-import Melodics.Ukrainian (convertToProperUkrainian)-import DobutokO.Sound.Functional--dviykyTA :: NotePairs-dviykyTA = V.generate 107 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 1)))--triykyTA :: NotePairs-triykyTA = V.generate 106 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 2)))--chetvirkyTA :: NotePairs-chetvirkyTA = V.generate 105 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 3)))--p'yatirkyTA :: NotePairs-p'yatirkyTA = V.generate 104 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 4)))--shistkyTA :: NotePairs-shistkyTA = V.generate 103 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 5)))--simkyTA :: NotePairs-simkyTA = V.generate 102 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 6)))--visimkyTA :: NotePairs-visimkyTA = V.generate 101 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 7)))--dev'yatkyTA :: NotePairs-dev'yatkyTA = V.generate 100 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 8)))--desyatkyTA :: NotePairs-desyatkyTA = V.generate 99 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 9)))--odynadtsyatkyTA :: NotePairs-odynadtsyatkyTA = V.generate 98 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 10)))--octavesTA :: NotePairs-octavesTA = V.generate 97 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 11)))-------------------------------------------------------------------------------------------------------------------------------- | Returns an analogous note in the higher octave (its frequency in Hz).-octaveUp :: Double -> Double-octaveUp x = 2 * x-{-# INLINE octaveUp #-}----- | Returns an analogous note in the lower octave (its frequency in Hz).-octaveDown :: Double -> Double-octaveDown x = x / 2-{-# INLINE octaveDown #-}---------------------------------------------------------------------------------------------------------------------------------- --- | Function lifts the given frequency to the given number of the octave (in American notation, from 0 to 8). This number is an 'Int' parameter.--- The function also takes into account the lower pure quint for the closest note.--- If it is not practical to determine the number, then the function returns 'Nothing'.-liftInOctave :: Int -> Double -> Maybe Double-liftInOctave n x- | compare n 0 == LT || compare n 8 == GT = Nothing- | compare (closestNote x) 24.4996 == GT =- case compare (fromJust . whichOctave $ x) n of- EQ -> Just (closestNote x)- LT -> let z = logBase 2.0 (V.unsafeIndex notes (n * 12) / closestNote x)- z1 = truncate z in- if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001- then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) octaveUp $ closestNote x)- else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) octaveUp $ closestNote x)- _ -> let z = logBase 2.0 (closestNote x / V.unsafeIndex notes (n * 12))- z1 = truncate z in- if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001- then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) octaveDown $ closestNote x)- else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) octaveDown $ closestNote x)- | otherwise = Nothing---- | Function lifts the 'V.Vector' of 'Double' representing frequencies to the given octave with the 'Int' number. Better to use numbers in the range [1..8].--- The function also takes into account the lower pure quint for the obtained note behaviour. If it is not practical to determine the octave, the resulting--- frequency is omitted from the resulting 'V.Vector'.-liftInOctaveV :: Int -> V.Vector Double -> V.Vector Double-liftInOctaveV n = V.mapMaybe (liftInOctave n)-------------------------------------------------------------------------------------------------------------------------------------- | For the given frequency of the note it generates a 'V.Vector' of the tuples, each one of which contains the harmonics' frequency and amplitude. For every given--- 'String' structure of the uniqueness (see the documentation for @mmsyn7s@ package and its 'MMSyn7.Syllable' module) it produces the unique timbre.-uniqOvertonesV :: Double -> String -> OvertonesO-uniqOvertonesV note xs =- let ys = uniquenessPeriods xs- z = sum ys- v = V.fromList . fmap (\y -> fromIntegral y / fromIntegral z) $ ys- z2 = V.length v- v2 = V.generate z2 (\i -> V.unsafeIndex v i / fromIntegral (i + 1)) in- V.takeWhile (\(!u,!z) -> compare u (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.unsafeSlice 1 (z2 - 1) .- V.zip (V.generate z2 (\i -> note * fromIntegral (i + 1))) $ v2---- | Additional function to produce signs from the given 'String' of the Ukrainian text. Ukrainian vowels and voiced consonants gives \"+\" sign (+1), voiceless--- and sonorous consonants gives \"-\" sign (-1). Voiceless2 gives "0". Other symbols are not taken into account.-signsFromString :: Int -> String -> V.Vector Int-signsFromString n1 =- V.take n1 . V.fromList . concatMap (fmap (\case- Vowel _ -> 1- Voiced _ -> 1- VoicedP _ -> 1- Voiceless _ -> (-1)- VoicelessP _ -> (-1)- Sonorous _ -> (-1)- SonorousP _ -> (-1)- _ -> 0) . concatMap representProlonged) . syllablesUkrP . take (3 * n1) . cycle ---- | For the given frequency of the note and a Ukrainian text it generates a 'V.Vector' of the tuples, each one of which contains--- the harmonics' frequency and amplitude. The 'String' is used to produce the signs for harmonics coefficients.-overTones2 :: Double -> String -> OvertonesO-overTones2 note ts =- V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.filter (\(_, t4) -> t4 /= 0.0) .- V.zip (V.generate 1024 (\i -> note * fromIntegral (i + 2))) $ (V.generate 1024 (\i -> fromIntegral (V.unsafeIndex (signsFromString 1024 ts)- (i + 1)) / fromIntegral ((i + 1) * (i + 1))))---- | For the given frequency of the note it generates a 'V.Vector' of the tuples, each one of which contains the harmonics' frequency and amplitude. For every given--- first 'String' argument structure of the uniqueness (see the documentation for @mmsyn7s@ package and its 'MMSyn7.Syllable' module) it produces the unique timbre.--- The second 'String' is used to produce the signs for harmonics coefficients.-uniqOvertonesV2 :: Double -> String -> String -> OvertonesO-uniqOvertonesV2 note xs ts = - let ys = uniquenessPeriods xs- z = sum ys- v = V.fromList . fmap (\y -> fromIntegral y / fromIntegral z) $ ys- z2 = V.length v- v2 = V.generate z2 (\i -> (V.unsafeIndex (V.map fromIntegral . signsFromString z2 $ ts) i) * V.unsafeIndex v i / fromIntegral (i + 1)) in- V.takeWhile (\(!u,!z) -> compare u (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.filter (\(_, t4) -> t4 /= 0.0) .- V.unsafeSlice 1 (z2 - 1) . V.zip (V.generate z2 (\i -> note * fromIntegral (i + 1))) $ v2---- | Similar to 'overSoXSynth' except that takes not necessarily pure lower quint note as the second one, but the one specified by the 'String' parameter--- as an argument to 'dNote'. If you begin the 'String' with space characters, or \"сь\", or \"ць\", or dash, or apostrophe, or soft sign, than there will--- be no interval and the sound will be solely one with its 'OvertonesO'.-overSoXSynthDN :: Double -> String -> IO ()-overSoXSynthDN x = overSoXSynth2DN x 0.5---- | Similar to 'overSoXSynthDN' except that the resulting duration is specified by the second 'Double' parameter in seconds. For 'overSoXSynthDN'--- it is equal to 0.5.-overSoXSynth2DN :: Double -> Double -> String -> IO ()-overSoXSynth2DN x y zs- | V.null . convertToProperUkrainian $ zs = overSoXSynth x- | otherwise = do- let note0 = closestNote x- note1 = dNote (V.unsafeIndex (intervalsFromString zs) 0) note0- v0 = overTones note0- v1 = maybe V.empty overTones note1- overSoXSynthHelp vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", showFFloat (Just 4) y "","sine", showFFloat (Just 4) noteN "",- "vol", showFFloat (Just 4) amplN ""] "") vec- overSoXSynthHelp2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", showFFloat (Just 4) y "","sine", showFFloat (Just 4) noteN "",- "vol", showFFloat (Just 4) amplN ""] "") vec- _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", showFFloat (Just 4) y "","sine",- showFFloat (Just 4) note0 "", "vol","0.5"] ""- if isNothing note1 then overSoXSynthHelp v0- else do - _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB.wav", "synth", showFFloat (Just 4) y "","sine",- showFFloat (Just 4) (fromJust note1) "", "vol","0.5"] ""- overSoXSynthHelp v0- overSoXSynthHelp2 v1- mixTest---- | For the given frequency it generates a musical sound with a timbre. The main component of the sound includes the lower pure quint,--- which can be in the same octave or in the one with the number lower by one. Please, check before executing--- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.--- The 'String' argument is used to define signs of the harmonics coefficients for Overtones.-overSoXSynth2 :: Double -> String -> IO ()-overSoXSynth2 x tts = do- let note0 = closestNote x- note1 = pureQuintNote note0- v0 = overTones2 note0 tts- v1 = overTones2 note1 tts- overSoXSynthHelp vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN "",- "vol", showFFloat (Just 4) amplN ""] "") vec- overSoXSynthHelp2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN "",- "vol", showFFloat (Just 4) amplN ""] "") vec- _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test01.wav", "synth", "0.5","sine", showFFloat (Just 4) note0 "",- "synth", "0.5","sine", "mix", showFFloat (Just 4) note1 "", "vol","0.5"] ""- overSoXSynthHelp v0- overSoXSynthHelp2 v1- mixTest ---- | Function to create a melody for the given arguments. 'String' is used to provide a rhythm. The main component of the sound includes the lower pure quint, which--- can be in the same octave or in the one with the number lower by one. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude--- for Overtones. If it is set to 1.0 the overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results--- in their becoming more silent ones. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing--- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.-overSoXSynthN :: Int -> Double -> Double -> String -> V.Vector Double -> IO ()-overSoXSynthN n ampL time3 zs = overSoXSynthN4G n ampL (str2DurationsDef n zs time3)---- | Function to create a melody for the given arguments. 'Durations' is used to provide a rhythm. -overSoXSynthN4G :: Int -> Double -> Durations -> V.Vector Double -> IO ()-overSoXSynthN4G n ampL v2 vec0- | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "- | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT = - let zeroN = numVZeroesPre vec0- v21 = V.filter (/=0.0) v2- m = V.length v2 in V.imapM_ (\j x -> do - let note0 = closestNote x -- zs is obtained from the command line arguments- note1 = pureQuintNote note0- v0 = overTones note0- v1 = overTones note1- overSoXSynthHelpN vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec- overSoXSynthHelpN2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec - soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++ prependZeroes zeroN "1" ++- ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "", "synth",- showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", "mix", showFFloat (Just 4) note02 "", "vol",if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT - then "0.5" else "0"] ""- soxSynthHelpMain note0 note1- overSoXSynthHelpN v0- overSoXSynthHelpN2 v1- mixTest2 zeroN j) vec0- | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in- if abs ampL1 < 0.01 then overSoXSynthN4G n 0.01 v2 vec0- else overSoXSynthN4G n ampL1 v2 vec0---- | Variant of the 'overSoXSynthN4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition.-overSoXSynthN4GS :: Int -> Double -> Double -> String -> V.Vector Double -> IO ()-overSoXSynthN4GS n ampL time3 zs = overSoXSynthN4G n ampL (str2Durations zs time3)---- | Function to create a melody for the given arguments. 'String' is used to provide a rhythm. The main component of the sound includes the lower pure quint, which--- can be in the same octave or in the one with the number lower by one. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude--- for Overtones. If it is set to 1.0 the overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results--- in their becoming more silent ones. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing--- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.-overSoXSynthN2 :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()-overSoXSynthN2 n ampL time3 zs = overSoXSynthN24G n ampL (str2DurationsDef n zs time3)- --- | Function to create a melody for the given arguments. 'Durations' is used to provide a rhythm. -overSoXSynthN24G :: Int -> Double -> Durations -> String -> V.Vector Double -> IO ()-overSoXSynthN24G n ampL v2 tts vec0- | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "- | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT = - let v21 = V.filter (/= 0.0) v2- zeroN = numVZeroesPre vec0- m = V.length v21 in V.imapM_ (\j x -> do - let note0 = closestNote x -- zs is obtained from the command line arguments- note1 = pureQuintNote note0- v0 = overTones2 note0 tts- v1 = overTones2 note1 tts- overSoXSynthHelpN vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine",showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec- overSoXSynthHelpN2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec - soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++ prependZeroes zeroN "1" ++- ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "",- "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", "mix", showFFloat (Just 4) note02 "", "vol",- if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""- soxSynthHelpMain note0 note1- overSoXSynthHelpN v0- overSoXSynthHelpN2 v1- mixTest2 zeroN j) vec0- | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in- if abs ampL1 < 0.01 then overSoXSynthN24G n 0.01 v2 tts vec0- else overSoXSynthN24G n ampL1 v2 tts vec0 ---- | Variant of the 'overSoXSynthN24G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition.-overSoXSynthN24GS :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()-overSoXSynthN24GS n ampL time3 zs = overSoXSynthN24G n ampL (str2Durations zs time3)---- | Function to create a melody for the given arguments. 'String' is used to provide a rhythm. The main component of the sound includes the lower pure quint, which--- can be in the same octave or in the one with the number lower by one. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude--- for Overtones. If it is set to 1.0 the overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results--- in their becoming more silent ones. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing--- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.--- The third 'String' argument is used to define the intervals for the notes if any.--- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of--- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones.--- The last one is experimental feature.-overSoXSynthN3 :: Int -> Double -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()-overSoXSynthN3 n ampL time3 dAmpl zs = overSoXSynthN34G n ampL dAmpl (str2DurationsDef n zs time3)---- | Function to create a melody for the given arguments. 'Duraitons' is used to provide a rhythm. -overSoXSynthN34G :: Int -> Double -> Double -> Durations -> String -> String -> V.Vector Double -> IO ()-overSoXSynthN34G n ampL dAmpl v2 tts vs vec0- | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "- | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT = - let v21 = V.filter (/= 0.0) v2- m = V.length v21- zeroN = numVZeroesPre vec0- v3 = intervalsFromString vs- l = length vs in V.imapM_ (\j x -> do - let note0 = closestNote x -- zs is obtained from the command line arguments- note1 = dNote (V.unsafeIndex v3 (j `rem` l)) note0- v0 = overTones2 note0 tts- v1 = if isNothing note1 then V.empty- else overTones2 (fromJust note1) tts- overSoXSynthHelpN vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine",showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec- overSoXSynthHelpN2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl * amplN * ampL > 1.0 then 1.0- else dAmpl * amplN * ampL) "" else "0"] "") vec - soxSynthHelpMain0 note01 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++ prependZeroes zeroN "1" ++ ".wav",- "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "", "vol",- if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""- soxSynthHelpMain1 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB" ++- prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note02 "",- "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / 2) "" else "0"] ""- if isNothing note1 then do { soxSynthHelpMain0 note0- ; overSoXSynthHelpN v0 }- else do { soxSynthHelpMain0 note0- ; soxSynthHelpMain1 (fromJust note1)- ; overSoXSynthHelpN v0- ; overSoXSynthHelpN2 v1}- paths0 <- listDirectory "."- let paths = sort . filter (isPrefixOf "test") $ paths0- _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result0" ++ prependZeroes zeroN (show j) ++ ".wav","vol","0.3"]) ""- mapM_ removeFile paths) vec0- | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in- if abs ampL1 < 0.01 then overSoXSynthN34G n 0.01 dAmpl v2 tts vs vec0- else overSoXSynthN34G n ampL1 dAmpl v2 tts vs vec0---- | Generalized variant of the 'overSoXSynthN34G' where you specify your own 'Intervals'. For more information, please, refer to 'intervalsFromStringG'.-overSoXSynthN35G :: Int -> Double -> Double -> Durations -> String -> Intervals -> V.Vector Double -> IO ()-overSoXSynthN35G n ampL dAmpl v2 tts v3 vec0- | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "- | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT = - let v21 = V.filter (/=0.0) v2- m = V.length v21- zeroN = numVZeroesPre vec0- l = V.length v3 in V.imapM_ (\j x -> do - let note0 = closestNote x -- zs is obtained from the command line arguments- note1 = dNote (V.unsafeIndex v3 (j `rem` l)) note0- v0 = overTones2 note0 tts- v1 = if isNothing note1 then V.empty- else overTones2 (fromJust note1) tts- overSoXSynthHelpN vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine",showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec- overSoXSynthHelpN2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl * amplN * ampL > 1.0 then 1.0- else dAmpl * amplN * ampL) "" else "0"] "") vec - soxSynthHelpMain0 note01 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++ prependZeroes zeroN "1" ++ ".wav",- "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "", "vol",- if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""- soxSynthHelpMain1 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB" ++- prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note02 "",- "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / 2) "" else "0"] ""- if isNothing note1 then do { soxSynthHelpMain0 note0- ; overSoXSynthHelpN v0 }- else do { soxSynthHelpMain0 note0- ; soxSynthHelpMain1 (fromJust note1)- ; overSoXSynthHelpN v0- ; overSoXSynthHelpN2 v1}- paths0 <- listDirectory "."- let paths = sort . filter (isPrefixOf "test") $ paths0- _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result0" ++ prependZeroes zeroN (show j) ++ ".wav","vol","0.3"]) ""- mapM_ removeFile paths) vec0- | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in- if abs ampL1 < 0.01 then overSoXSynthN35G n 0.01 dAmpl v2 tts v3 vec0- else overSoXSynthN35G n ampL1 dAmpl v2 tts v3 vec0---- | Variant of the 'overSoXSynthN34G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition.-overSoXSynthN34GS :: Int -> Double -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()-overSoXSynthN34GS n ampL time3 dAmpl zs = overSoXSynthN34G n ampL dAmpl (str2Durations zs time3)---- | Variant of the 'overSoXSynthN34G' where intervals are obtained from the basic 'Intervals' with the length no more than 29 and a Ukrainian text --- specified as the last 'String' argument so that you can produce 'Intervals' of the arbitrary length. For more information, please, refer to --- 'intervalsFromStringG' and 'strToIntG'.-overSoXSynthN35GS :: Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> V.Vector Double -> IO ()-overSoXSynthN35GS n ampL time3 dAmpl zs tts v3 vs = overSoXSynthN35G n ampL dAmpl (str2Durations zs time3) tts (intervalsFromStringG v3 vs)---- | Similar to 'overSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts--- the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]). The first 'Double' argument from--- the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the overTones amplitudes are just maximum ones,--- otherwise they are multiplied by the parameter and this results in their becoming more silent ones.--- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.------ For better usage the 'FilePath' should be a filepath for the .wav file.-overSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> IO ()-overSoXSynthNGen file m = overSoXSynthNGenE file m 12- --- | Similar to 'overSoXSynthNGen', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'overSoXSynthNGen'. To obtain--- its modifications, please, use 2, 3, 4, 6, or 9.-overSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> IO ()-overSoXSynthNGenE file m ku ampL time3 zs = do- n <- duration1000 file- nGenE4Gi n file m ku ampL (str2DurationsDef n zs time3)---- | Generalized version of the 'overSoXSynthNGenE' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGenEPar :: FilePath -> Params -> Double -> Double -> String -> IO ()-overSoXSynthNGenEPar file params ampL time3 zs = do- n <- duration1000 file- nGenE4GiPar n file params ampL (str2DurationsDef n zs time3)---- | Variant of the 'overSoXSynthNGenE4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition.-overSoXSynthNGenE4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> IO ()-overSoXSynthNGenE4GS file m ku ampL time3 zs = do- n <- duration1000 file- nGenE4Gi n file m ku ampL (str2Durations zs time3)---- | Generalized version of the 'overSoXSynthNGenE4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGenE4GSPar :: FilePath -> Params -> Double -> Double -> String -> IO ()-overSoXSynthNGenE4GSPar file params ampL time3 zs = do- n <- duration1000 file- nGenE4GiPar n file params ampL (str2Durations zs time3) ---- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.-nGenE4Gi :: Int -> FilePath -> Int -> Int -> Double -> Durations -> IO ()-nGenE4Gi n file m ku ampL v2 = do- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- overSoXSynthN4G n ampL v2 vecB- endFromResult - --- | Generalized version of the 'nGenE4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-nGenE4GiPar :: Int -> FilePath -> Params -> Double -> Durations -> IO ()-nGenE4GiPar n file params ampL v2 = do- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- overSoXSynthN4G n ampL v2 vecB- endFromResult - --- | 4G genaralized version of the 'overSoXSynthNGenE' where you provide your own 'Durations'.-overSoXSynthNGenE4G :: FilePath -> Int -> Int -> Double -> Durations -> IO ()-overSoXSynthNGenE4G file m ku ampL v2 = do- n <- duration1000 file- nGenE4Gi n file m ku ampL v2---- | Generalized version of the 'overSoXSynthNGenE4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGenE4GPar :: FilePath -> Params -> Double -> Durations -> IO ()-overSoXSynthNGenE4GPar file params ampL v2 = do- n <- duration1000 file- nGenE4GiPar n file params ampL v2 ---- | Similar to 'overSoXSynthN2', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts--- the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]). The first 'Double' argument from--- the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the overTones amplitudes are just maximum ones,--- otherwise they are multiplied by the parameter and this results in their becoming more silent ones.--- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.--- --- For better usage the 'FilePath' should be a filepath for the .wav file.--- The second 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.-overSoXSynthNGen2 :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()-overSoXSynthNGen2 file m = overSoXSynthNGen2E file m 12- --- | Similar to 'overSoXSynthNGen2', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'overSoXSynthNGen2'. To obtain--- its modifications, please, use 2, 3, 4, 6, or 9.-overSoXSynthNGen2E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()-overSoXSynthNGen2E file m ku ampL time3 zs tts = do- n <- duration1000 file- nGen2E4Gi n file m ku ampL (str2DurationsDef n zs time3) tts---- | Generalized version of the 'overSoXSynthNGen2E' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGen2EPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()-overSoXSynthNGen2EPar file params ampL time3 zs tts = do- n <- duration1000 file- nGen2E4GiPar n file params ampL (str2DurationsDef n zs time3) tts ---- | Variant of the 'overSoXSynthNGen2E4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition.-overSoXSynthNGen2E4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()-overSoXSynthNGen2E4GS file m ku ampL time3 zs tts = do- n <- duration1000 file- nGen2E4Gi n file m ku ampL (str2Durations zs time3) tts---- | Generalized version of the 'overSoXSynthNGen2E4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGen2E4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()-overSoXSynthNGen2E4GSPar file params ampL time3 zs tts = do- n <- duration1000 file- nGen2E4GiPar n file params ampL (str2Durations zs time3) tts---- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.-nGen2E4Gi :: Int -> FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()-nGen2E4Gi n file m ku ampL v2 tts = do- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- overSoXSynthN24G n ampL v2 tts vecB- endFromResult ---- | Generalized version of the 'nGen2E4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-nGen2E4GiPar :: Int -> FilePath -> Params -> Double -> Durations -> String -> IO ()-nGen2E4GiPar n file params ampL v2 tts = do- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- overSoXSynthN24G n ampL v2 tts vecB- endFromResult - --- | 4G genaralized version of the 'overSoXSynthNGen2E' where you provide your own 'Durations'.-overSoXSynthNGen2E4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()-overSoXSynthNGen2E4G file m ku ampL v2 tts = do- n <- duration1000 file- nGen2E4Gi n file m ku ampL v2 tts---- | Generalized version of the 'overSoXSynthNGen2E4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGen2E4GPar :: FilePath -> Params -> Double -> Durations -> String -> IO ()-overSoXSynthNGen2E4GPar file params ampL v2 tts = do- n <- duration1000 file- nGen2E4GiPar n file params ampL v2 tts ---- | Similar to 'overSoXSynthN2', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts--- the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]). The first 'Double' argument from--- the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the overTones amplitudes are just maximum ones,--- otherwise they are multiplied by the parameter and this results in their becoming more silent ones.--- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.--- --- For better usage the 'FilePath' should be a filepath for the .wav file.--- The second 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.--- The third 'String' argument is used to define the intervals for the notes if any.--- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of--- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones.--- The last one is experimental feature.-overSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()-overSoXSynthNGen3 file m = overSoXSynthNGen3E file m 12- --- | Similar to 'overSoXSynthNGen3', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'overSoXSynthNGen3'. To obtain--- its modifications, please, use 2, 3, 4, 6, or 9.-overSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()-overSoXSynthNGen3E file m ku ampL time3 dAmpl zs tts vs = do- n <- duration1000 file- nGen3E4Gi n file m ku ampL dAmpl (str2DurationsDef n zs time3) tts vs---- | Generalized version of the 'overSoXSynthNGen3E' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGen3EPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> IO ()-overSoXSynthNGen3EPar file params ampL time3 dAmpl zs tts vs = do- n <- duration1000 file- nGen3E4GiPar n file params ampL dAmpl (str2DurationsDef n zs time3) tts vs ---- | Variant of the 'overSoXSynthNGen3E4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthNGen3E4GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()-overSoXSynthNGen3E4GS file m ku ampL time3 dAmpl zs tts vs = do- n <- duration1000 file- nGen3E4Gi n file m ku ampL dAmpl (str2Durations zs time3) tts vs ---- | Generalized version of the 'overSoXSynthNGen3E4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGen3E4GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> IO ()-overSoXSynthNGen3E4GSPar file params ampL time3 dAmpl zs tts vs = do- n <- duration1000 file- nGen3E4GiPar n file params ampL dAmpl (str2Durations zs time3) tts vs ---- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.-nGen3E4Gi :: Int -> FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> IO ()-nGen3E4Gi n file m ku ampL dAmpl v2 tts vs = do - vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- overSoXSynthN34G n ampL dAmpl v2 tts vs vecB- endFromResult ---- | Generalized version of the 'nGen3E4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-nGen3E4GiPar :: Int -> FilePath -> Params -> Double -> Double -> Durations -> String -> String -> IO ()-nGen3E4GiPar n file params ampL dAmpl v2 tts vs = do - vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- overSoXSynthN34G n ampL dAmpl v2 tts vs vecB- endFromResult ---- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.-nGen3E5Gi :: Int -> FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> IO ()-nGen3E5Gi n file m ku ampL dAmpl v2 tts v3 = do - vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- overSoXSynthN35G n ampL dAmpl v2 tts v3 vecB- endFromResult - --- | Generalized version of the 'nGen3E5Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-nGen3E5GiPar :: Int -> FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> IO ()-nGen3E5GiPar n file params ampL dAmpl v2 tts v3 = do - vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- overSoXSynthN35G n ampL dAmpl v2 tts v3 vecB- endFromResult ---- | 4G generalized function for 'overSoXSynthNGen3E' where you provide your own 'Durations'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthNGen3E4G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> IO ()-overSoXSynthNGen3E4G file m ku ampL dAmpl v2 tts vs = do- n <- duration1000 file- nGen3E4Gi n file m ku ampL dAmpl v2 tts vs---- | Generalized version of the 'overSoXSynthNGen3E4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGen3E4GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> IO ()-overSoXSynthNGen3E4GPar file params ampL dAmpl v2 tts vs = do- n <- duration1000 file- nGen3E4GiPar n file params ampL dAmpl v2 tts vs ---- | 5G generalized function for 'overSoXSynthNGen3E4G' where you provide your own 'Intervals'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthNGen3E5G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> IO ()-overSoXSynthNGen3E5G file m ku ampL dAmpl v2 tts v3 = do- n <- duration1000 file- nGen3E5Gi n file m ku ampL dAmpl v2 tts v3 ---- | Generalized version of the 'overSoXSynthNGen3E5G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGen3E5GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> IO ()-overSoXSynthNGen3E5GPar file params ampL dAmpl v2 tts v3 = do- n <- duration1000 file- nGen3E5GiPar n file params ampL dAmpl v2 tts v3 ---- | Variant of the 'overSoXSynthNGen3E5G' where 'Intervals' are obtained from the basic 'Intervals' with the length no more than 29 and a Ukrainian text --- specified as the last 'String' argument so that you can produce 'Intervals' of the arbitrary length. For more information, please, refer to --- 'intervalsFromStringG' and 'strToIntG'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthNGen3E5GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> IO ()-overSoXSynthNGen3E5GS file m ku ampL time3 dAmpl zs tts v3 vs = do- n <- duration1000 file- nGen3E5Gi n file m ku ampL dAmpl (str2Durations zs time3) tts (intervalsFromStringG v3 vs)---- | Generalized version of the 'overSoXSynthNGen3E5GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGen3E5GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> Intervals -> String -> IO ()-overSoXSynthNGen3E5GSPar file params ampL time3 dAmpl zs tts v3 vs = do- n <- duration1000 file- nGen3E5GiPar n file params ampL dAmpl (str2Durations zs time3) tts (intervalsFromStringG v3 vs) - --- | 6G generalized function for 'overSoXSynthNGen3E5G' where you provide your own 'Strengths'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthNGen3E6G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> Strengths -> Double -> IO ()-overSoXSynthNGen3E6G file m ku ampL dAmpl v2 tts v3 v6 limV = - overSoXSynthNGen3E5G file m ku ampL dAmpl v2 tts v3 >> apply6G2 v6 "221w" "result" limV >> endFromResult---- | Generalized version of the 'overSoXSynthNGen3E6G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGen3E6GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> Strengths -> Double -> IO ()-overSoXSynthNGen3E6GPar file params ampL dAmpl v2 tts v3 v6 limV = - overSoXSynthNGen3E5GPar file params ampL dAmpl v2 tts v3 >> apply6G2 v6 "221w" "result" limV >> endFromResult ---- | A variant of 'overSoXSynthNGen3E6G' where 'Strengths' are obtained from a Ukrainian text specified as the last 'String' argument. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthNGen3E6GS :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> String -> Double -> IO ()-overSoXSynthNGen3E6GS file m ku ampL dAmpl v2 tts v3 xxs limV = overSoXSynthNGen3E6G file m ku ampL dAmpl v2 tts v3 (str2Volume xxs) limV---- | Generalized version of the 'overSoXSynthNGen3E6GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGen3E6GSPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> String -> Double -> IO ()-overSoXSynthNGen3E6GSPar file params ampL dAmpl v2 tts v3 xxs limV = overSoXSynthNGen3E6GPar file params ampL dAmpl v2 tts v3 (str2Volume xxs) limV---- | A variant of 'overSoXSynthNGen3E6GS' where 'Strengths' and 'Durations' are obtained from the same Ukrainian text specified as --- the last 'String' argument. The third 'Double' argument is an average duration of the sounds in seconds. --- Note that 'Int' arguments are used by 'liftInEnku' in that order so it returns a 'Maybe' number (actually frequency) for --- the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthNGen3E6GSu :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> Intervals -> String -> Double -> IO ()-overSoXSynthNGen3E6GSu file m ku ampL dAmpl time3 tts v3 xxs = overSoXSynthNGen3E6G file m ku ampL dAmpl (str2Durations xxs time3) tts v3 (str2Volume xxs)---- | Generalized version of the 'overSoXSynthNGen3E6GSu' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthNGen3E6GSuPar :: FilePath -> Params -> Double -> Double -> Double -> String -> Intervals -> String -> Double -> IO ()-overSoXSynthNGen3E6GSuPar file params ampL dAmpl time3 tts v3 xxs = overSoXSynthNGen3E6GPar file params ampL dAmpl (str2Durations xxs time3) tts v3 (str2Volume xxs)- --- | For the given frequency and a Ukrainian text it generates a musical sound with the timbre obtained from the Ukrainian text (see the--- documentation for @mmsyn7s@ package). The timbre for another given text usually differs, but can be the same. The last one is only--- if the uniqueness structure and length are the same for both 'String'. Otherwise, they differs. This gives an opportunity to practically--- and quickly synthesize differently sounding intervals. The main component of the sound includes the lower pure quint, which can be in--- the same octave or in the one with the number lower by one. Please, check before executing --- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.-uniqOverSoXSynth :: Double -> String -> IO ()-uniqOverSoXSynth x wws = do- let note0 = closestNote x- note1 = pureQuintNote note0- v0 = uniqOvertonesV note0 wws- v1 = uniqOvertonesV note1 wws- _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test-.wav", "synth", "0.5","sine", showFFloat (Just 4) note0 "",- "synth", "0.5","sine", "mix", showFFloat (Just 4) note1 "", "vol","0.5"] ""- uniqOverSoXSynthHelp v0- uniqOverSoXSynthHelp2 v1- mixTest--uniqOverSoXSynthHelp1 :: String -> OvertonesO -> IO ()-uniqOverSoXSynthHelp1 xs = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", xs ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN "", "vol", showFFloat (Just 4) amplN ""] "") --uniqOverSoXSynthHelp :: OvertonesO -> IO ()-uniqOverSoXSynthHelp = uniqOverSoXSynthHelp1 "test0"--uniqOverSoXSynthHelp2 :: OvertonesO -> IO ()-uniqOverSoXSynthHelp2 = uniqOverSoXSynthHelp1 "test1"---- | For the given frequency and a Ukrainian text it generates a musical sound with the timbre obtained from the Ukrainian text (see the--- documentation for @mmsyn7s@ package). The timbre for another given text usually differs, but can be the same. The last one is only--- if the uniqueness structure and length are the same for both 'String'. Otherwise, they differs. This gives an opportunity to practically--- and quickly synthesize differently sounding intervals. The main component of the sound includes the lower pure quint, which can be in--- the same octave or in the one with the number lower by one. Please, check before executing --- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.--- The second 'String' argument is used to define signs for the harmonics coefficients for Overtones.-uniqOverSoXSynth2 :: Double -> String -> String -> IO ()-uniqOverSoXSynth2 x wws tts = do- let note0 = closestNote x- note1 = pureQuintNote note0- v0 = uniqOvertonesV2 note0 wws tts- v1 = uniqOvertonesV2 note1 wws tts- _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test-.wav", "synth", "0.5","sine", showFFloat (Just 4) note0 "", "synth",- "0.5","sine", "mix", showFFloat (Just 4) note1 "", "vol","0.5"] ""- uniqOverSoXSynthHelp v0- uniqOverSoXSynthHelp2 v1- mixTest---- | Function to create a melody for the given arguments. The first 'String' is used to provide a rhythm. The second one -- to provide a timbre.--- The timbre for another given text usually differs, but can be the same. This gives an opportunity to practically and quickly--- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones.--- If it is set to 1.0 the overTones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in--- their becoming more silent ones. The main component of the sound is in the given octave with a number given--- by 'Int' parameter. Besides, another main component of the sound includes the lower pure quint, which can be in the same octave or in the one with--- the number lower by one. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing--- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.-uniqOverSoXSynthN :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()-uniqOverSoXSynthN n ampL time3 zs = uniqOverSoXSynthN4G n ampL (str2DurationsDef n zs time3)---- | Variant of the 'uniqOverSoXSynthN4G' function where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition.-uniqOverSoXSynthN4GS :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()-uniqOverSoXSynthN4GS n ampL time3 zs = uniqOverSoXSynthN4G n ampL (str2Durations zs time3)---- | 4G generalized variant of the 'uniqOverSoXSynthN' where you specify your own 'Durations'.-uniqOverSoXSynthN4G :: Int -> Double -> Durations -> String -> V.Vector Double -> IO ()-uniqOverSoXSynthN4G n ampL v2 wws vec0- | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "- | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =- let v21 = V.filter (/= 0.0) v2- m = V.length v21- zeroN = numVZeroesPre vec0 in V.imapM_ (\j x -> do - let note0 = closestNote x- note1 = pureQuintNote note0- v0 = uniqOvertonesV note0 wws- v1 = uniqOvertonesV note1 wws- uniqOverSoXSynthHelpN = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT - then showFFloat (Just 4) (amplN * ampL) "" else "0"] "")- uniqOverSoXSynthHelpN2 = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT - then showFFloat (Just 4) (amplN * ampL) "" else "0"] "")- soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++- prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) "","sine", "mix", showFFloat (Just 4) note02 "", "vol",- if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""- soxSynthHelpMain note0 note1- uniqOverSoXSynthHelpN v0- uniqOverSoXSynthHelpN2 v1- mixTest2 zeroN j) vec0- | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in- if abs ampL1 < 0.01 then uniqOverSoXSynthN4G n 0.01 v2 wws vec0- else uniqOverSoXSynthN4G n ampL1 v2 wws vec0---- | Function to create a melody for the given arguments. The first 'String' is used to provide a rhythm. The second one -- to provide a timbre.--- The timbre for another given text usually differs, but can be the same. This gives an opportunity to practically and quickly--- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones.--- If it is set to 1.0 the overTones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in--- their becoming more silent ones. The main component of the sound is in the given octave with a number given--- by 'Int' parameter. Besides, another main component of the sound includes the lower pure quint, which can be in the same octave or in the one with--- the number lower by one. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing--- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.--- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.-uniqOverSoXSynthN3 :: Int -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()-uniqOverSoXSynthN3 n ampL time3 zs = uniqOverSoXSynthN34G n ampL (str2DurationsDef n zs time3)---- | Variant of the 'uniqOverSoXSynthN34G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition.-uniqOverSoXSynthN34GS :: Int -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()-uniqOverSoXSynthN34GS n ampL time3 zs = uniqOverSoXSynthN34G n ampL (str2Durations zs time3)---- | 4G generalized variant of the 'uniqOverSoXSynthN3' where you specify your own 'Durations'. -uniqOverSoXSynthN34G :: Int -> Double -> Durations -> String -> String -> V.Vector Double -> IO ()-uniqOverSoXSynthN34G n ampL v2 wws tts vec0- | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "- | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =- let v21 = V.filter (/=0.0) v2- m = V.length v2- zeroN = numVZeroesPre vec0 in V.imapM_ (\j x -> do - let note0 = closestNote x -- zs ? vec0 -- are they related to the one object? No, they are obtained from different sources.- note1 = pureQuintNote note0- v0 = uniqOvertonesV2 note0 wws tts- v1 = uniqOvertonesV2 note1 wws tts- uniqOverSoXSynthHelpN vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec- uniqOverSoXSynthHelpN2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec - soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++- prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "",- "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", "mix", showFFloat (Just 4) note02 "", "vol",- if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""- soxSynthHelpMain note0 note1- uniqOverSoXSynthHelpN v0- uniqOverSoXSynthHelpN2 v1- mixTest2 zeroN j) vec0- | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in- if abs ampL1 < 0.01 then uniqOverSoXSynthN34G n 0.01 v2 wws tts vec0- else uniqOverSoXSynthN34G n ampL1 v2 wws tts vec0 ---- | Function to create a melody for the given arguments. The first 'String' is used to provide a rhythm. The second one -- to provide a timbre.--- The timbre for another given text usually differs, but can be the same. This gives an opportunity to practically and quickly--- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones.--- If it is set to 1.0 the overTones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in--- their becoming more silent ones. The main component of the sound is in the given octave with a number given--- by 'Int' parameter. Besides, another main component of the sound includes the lower pure quint, which can be in the same octave or in the one with--- the number lower by one. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing--- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.--- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.--- The fourth 'String' argument is used to define the intervals for the notes if any.--- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of--- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones.--- The last one is experimental feature.-uniqOverSoXSynthN4 :: Int -> Double -> Double -> Double -> String -> String -> String -> String -> V.Vector Double -> IO ()-uniqOverSoXSynthN4 n ampL time3 dAmpl zs = uniqOverSoXSynthN44G n ampL dAmpl (str2DurationsDef n zs time3)---- | Variant of the 'uniqOverSoXSynthN44G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition.-uniqOverSoXSynthN44GS :: Int -> Double -> Double -> Double -> String -> String -> String -> String -> V.Vector Double -> IO ()-uniqOverSoXSynthN44GS n ampL time3 dAmpl zs = uniqOverSoXSynthN44G n ampL dAmpl (str2Durations zs time3)---- | 4G generalized variant of the 'uniqOverSoXSynthN4' where you specify your own 'Durations'. -uniqOverSoXSynthN44G :: Int -> Double -> Double -> Durations -> String -> String -> String -> V.Vector Double -> IO ()-uniqOverSoXSynthN44G n ampL dAmpl v2 wws tts vs = uniqOverSoXSynthN45G n ampL dAmpl v2 wws tts (intervalsFromString vs)- --- | 5G generalized variant of the 'uniqOverSoXSynthN44G' where you specify your own 'Intervals'. -uniqOverSoXSynthN45G :: Int -> Double -> Double -> Durations -> String -> String -> Intervals -> V.Vector Double -> IO ()-uniqOverSoXSynthN45G n ampL dAmpl v2 wws tts v3 vec0- | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "- | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =- let v21 = V.filter (/=0.0) v2- m = V.length v2- zeroN = numVZeroesPre vec0- l = V.length v3 in V.imapM_ (\j x -> do - let note0 = closestNote x- note1 = dNote (V.unsafeIndex v3 (j `rem` l)) note0- v0 = uniqOvertonesV2 note0 wws tts- v1 = if isNothing note1 then V.empty- else uniqOvertonesV2 (fromJust note1) wws tts- uniqOverSoXSynthHelpN = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine",showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") - uniqOverSoXSynthHelpN2 = V.imapM_ (\i (noteN, amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl * amplN * ampL > 1.0 then 1.0- else dAmpl * amplN * ampL) "" else "0"] "") - soxSynthHelpMain0 note01 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++- prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "",- "vol",if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""- soxSynthHelpMain1 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB" ++- prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note02 "",- "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / 2) "" else "0"] ""- if isNothing note1 then do { soxSynthHelpMain0 note0- ; uniqOverSoXSynthHelpN v0 }- else do { soxSynthHelpMain0 note0- ; soxSynthHelpMain1 (fromJust note1)- ; uniqOverSoXSynthHelpN v0- ; uniqOverSoXSynthHelpN2 v1}- mixTest2 zeroN j) vec0- | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in- if abs ampL1 < 0.01 then uniqOverSoXSynthN45G n 0.01 dAmpl v2 wws tts v3 vec0- else uniqOverSoXSynthN45G n ampL1 dAmpl v2 wws tts v3 vec0 ---- | 6G generalized variant of the 'uniqOverSoXSynthN45G' where you specify your own 'Strengths' and a limit (as the last 'Double') when less volume level --- sound files are treated as a silent ones and are not adjusted. -uniqOverSoXSynthN46G :: Int -> Double -> Double -> Durations -> String -> String -> Intervals -> V.Vector Double -> Strengths -> Double -> IO ()-uniqOverSoXSynthN46G n ampL dAmpl v2 wws tts v3 vec0 v6 limV- | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "- | V.null v6 = putStrLn "You did not provide a volume adjustments vector! "- | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =- let v21 = V.filter (/=0.0) v2- m = V.length v2- zeroN = numVZeroesPre vec0- l = V.length v3 in V.imapM_ (\j x -> do - let note0 = closestNote x- note1 = dNote (V.unsafeIndex v3 (j `rem` l)) note0- v0 = uniqOvertonesV2 note0 wws tts- v1 = if isNothing note1 then V.empty- else uniqOvertonesV2 (fromJust note1) wws tts- uniqOverSoXSynthHelpN = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine",showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") - uniqOverSoXSynthHelpN2 = V.imapM_ (\i (noteN, amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",- "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl * amplN * ampL > 1.0 then 1.0- else dAmpl * amplN * ampL) "" else "0"] "") - soxSynthHelpMain0 note01 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++- prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "",- "vol",if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""- soxSynthHelpMain1 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB" ++- prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note02 "",- "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / 2) "" else "0"] ""- if isNothing note1 then do { soxSynthHelpMain0 note0- ; uniqOverSoXSynthHelpN v0 }- else do { soxSynthHelpMain0 note0- ; soxSynthHelpMain1 (fromJust note1)- ; uniqOverSoXSynthHelpN v0- ; uniqOverSoXSynthHelpN2 v1}- mixTest2 zeroN j- apply6GSilentFile ("result" ++ prependZeroes zeroN (show j) ++ ".wav") limV (V.unsafeIndex v6 (j `rem` V.length v6))) vec0- | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in- if abs ampL1 < 0.01 then uniqOverSoXSynthN46G n 0.01 dAmpl v2 wws tts v3 vec0 v6 limV- else uniqOverSoXSynthN46G n ampL1 dAmpl v2 wws tts v3 vec0 v6 limV---- | Variant of the 'uniqOverSoXSynthN45G' where 'Intervals' are obtained from the 'String' using 'intervalsFromStringG' function. Helps to create a speech-like --- composition.-uniqOverSoXSynthN45GS :: Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> V.Vector Double -> IO ()-uniqOverSoXSynthN45GS n ampL time3 dAmpl zs wws tts v3 vs = uniqOverSoXSynthN45G n ampL dAmpl (str2Durations zs time3) wws tts (intervalsFromStringG v3 vs) ---- | Variant of the 'uniqOverSoXSynthN46G' where 'Strengths' are obtained from the 'String' using 'str2Volume' function. Helps to create a speech-like --- composition.-uniqOverSoXSynthN46GS :: Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> V.Vector Double -> String ->- Double -> IO ()-uniqOverSoXSynthN46GS n ampL time3 dAmpl zs wws tts v3 vs vec0 xxs limV = - uniqOverSoXSynthN46G n ampL dAmpl (str2Durations zs time3) wws tts (intervalsFromStringG v3 vs) vec0 (str2Volume xxs) limV---- | A variant of 'uniqOverSoXSynthN46GS' where 'Strengths' and 'Durations' are obtained from the same Ukrainian text specified as --- the last 'String' argument. The second 'Double' argument is an average duration of the sounds in seconds. --- Note that 'Int' arguments are used by 'liftInEnku' in that order so it returns a 'Maybe' number (actually frequency) for --- the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthN46GSu :: Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> V.Vector Double -> String -> Double -> IO ()-uniqOverSoXSynthN46GSu n ampL time3 dAmpl wws tts v5 vs vec0 xxs limV = - uniqOverSoXSynthN46G n ampL dAmpl (str2Durations xxs time3) wws tts (intervalsFromStringG v5 vs) vec0 (str2Volume xxs) limV---- | Similar to 'uniqOverSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. --- Besides, the function lifts the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]).--- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the--- overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones.--- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.------ For better usage the 'FilePath' should be a filepath for the .wav file.-uniqOverSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()-uniqOverSoXSynthNGen file m = uniqOverSoXSynthNGenE file m 12---- | Similar to 'uniqOverSoXSynthNGen', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOverSoXSynthNGen'. To obtain--- its modifications, please, use 2, 3, 4, 6, or 9. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()-uniqOverSoXSynthNGenE file m ku ampL time3 zs wws = do- n <- duration1000 file- unGenNE4Gi n file m ku ampL (str2DurationsDef n zs time3) wws---- | Generalized version of the 'uniqOverSoXSynthNGenE' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGenEPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()-uniqOverSoXSynthNGenEPar file params ampL time3 zs wws = do- n <- duration1000 file- unGenNE4GiPar n file params ampL (str2DurationsDef n zs time3) wws ---- | Variant of the 'uniqOverSoXSynthNGenE4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGenE4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()-uniqOverSoXSynthNGenE4GS file m ku ampL time3 zs wws = do- n <- duration1000 file- unGenNE4Gi n file m ku ampL (str2Durations zs time3) wws- --- | Generalized version of the 'uniqOverSoXSynthNGenE4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGenE4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()-uniqOverSoXSynthNGenE4GSPar file params ampL time3 zs wws = do- n <- duration1000 file- unGenNE4GiPar n file params ampL (str2Durations zs time3) wws ---- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.-unGenNE4Gi :: Int -> FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()-unGenNE4Gi n file m ku ampL v2 wws = do- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- uniqOverSoXSynthN4G n ampL v2 wws vecB- endFromResult---- | Generalized version of the 'unGenNE4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-unGenNE4GiPar :: Int -> FilePath -> Params -> Double -> Durations -> String -> IO ()-unGenNE4GiPar n file params ampL v2 wws = do- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- uniqOverSoXSynthN4G n ampL v2 wws vecB- endFromResult ---- | 4G genaralized version of the 'uniqOverSoXSynthNGenE' where you provide your own 'Durations'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGenE4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()-uniqOverSoXSynthNGenE4G file m ku ampL v2 wws = do- n <- duration1000 file- unGenNE4Gi n file m ku ampL v2 wws---- | Generalized version of the 'uniqOverSoXSynthNGenE4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGenE4GPar :: FilePath -> Params -> Double -> Durations -> String -> IO ()-uniqOverSoXSynthNGenE4GPar file params ampL v2 wws = do- n <- duration1000 file- unGenNE4GiPar n file params ampL v2 wws ---- | Similar to 'uniqOverSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. --- Besides, the function lifts the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]).--- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the--- overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones.--- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.------ For better usage the 'FilePath' should be a filepath for the .wav file.--- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.-uniqOverSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen3 file m = uniqOverSoXSynthNGen3E file m 12---- | Similar to 'uniqOverSoXSynthNGen3', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOverSoXSynthNGen3'. To obtain--- its modifications, please, use 2, 3, 4, 6, or 9. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen3E file m ku ampL time3 zs wws tts = do- n <- duration1000 file- unGenN3E4Gi n file m ku ampL (str2DurationsDef n zs time3) wws tts---- | Generalized version of the 'uniqOverSoXSynthNGen3E' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGen3EPar :: FilePath -> Params -> Double -> Double -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen3EPar file params ampL time3 zs wws tts = do- n <- duration1000 file- unGenN3E4GiPar n file params ampL (str2DurationsDef n zs time3) wws tts ---- | Variant of the 'uniqOverSoXSynthNGen3E4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGen3E4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen3E4GS file m ku ampL time3 zs wws tts = do- n <- duration1000 file- unGenN3E4Gi n file m ku ampL (str2Durations zs time3) wws tts---- | Generalized version of the 'uniqOverSoXSynthNGen3E4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGen3E4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen3E4GSPar file params ampL time3 zs wws tts = do- n <- duration1000 file- unGenN3E4GiPar n file params ampL (str2Durations zs time3) wws tts---- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.-unGenN3E4Gi :: Int -> FilePath -> Int -> Int -> Double -> Durations -> String -> String -> IO ()-unGenN3E4Gi n file m ku ampL v2 wws tts = do- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- uniqOverSoXSynthN34G n ampL v2 wws tts vecB- endFromResult---- | Generalized version of the 'unGenN3E4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-unGenN3E4GiPar :: Int -> FilePath -> Params -> Double -> Durations -> String -> String -> IO ()-unGenN3E4GiPar n file params ampL v2 wws tts = do- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- uniqOverSoXSynthN34G n ampL v2 wws tts vecB- endFromResult ---- | 4G genaralized version of the 'uniqOverSoXSynthNGen3E' where you provide your own 'Durations'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGen3E4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> String -> IO ()-uniqOverSoXSynthNGen3E4G file m ku ampL v2 wws tts = do- n <- duration1000 file- unGenN3E4Gi n file m ku ampL v2 wws tts- --- | Generalized version of the 'uniqOverSoXSynthNGen3E4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGen3E4GPar :: FilePath -> Params -> Double -> Durations -> String -> String -> IO ()-uniqOverSoXSynthNGen3E4GPar file params ampL v2 wws tts = do- n <- duration1000 file- unGenN3E4GiPar n file params ampL v2 wws tts ---- | Similar to 'uniqOverSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. --- Besides, the function lifts the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]).--- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the--- overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones.--- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.------ For better usage the 'FilePath' should be a filepath for the .wav file.--- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.--- The fourth 'String' argument is used to define the intervals for the notes if any.--- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of--- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones.--- The last one is an experimental feature.-uniqOverSoXSynthNGen4 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen4 file m = uniqOverSoXSynthNGen4E file m 12---- | Similar to 'uniqOverSoXSynthNGen4', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained--- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOverSoXSynthNGen4'. To obtain--- its modifications, please, use 2, 3, 4, 6, or 9. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGen4E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen4E file m ku ampL time3 dAmpl zs wws tts vs = do- n <- duration1000 file- unGenN4E4Gi n file m ku ampL dAmpl (str2DurationsDef n zs time3) wws tts vs---- | Generalized version of the 'uniqOverSoXSynthNGen4E' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGen4EPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen4EPar file params ampL time3 dAmpl zs wws tts vs = do- n <- duration1000 file- unGenN4E4GiPar n file params ampL dAmpl (str2DurationsDef n zs time3) wws tts vs ---- | Variant of the 'uniqOverSoXSynthNGen4E4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like --- composition. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGen4E4GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen4E4GS file m ku ampL time3 dAmpl zs wws tts vs = do- n <- duration1000 file- unGenN4E4Gi n file m ku ampL dAmpl (str2Durations zs time3) wws tts vs---- | Generalized version of the 'uniqOverSoXSynthNGen4E4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGen4E4GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen4E4GSPar file params ampL time3 dAmpl zs wws tts vs = do- n <- duration1000 file- unGenN4E4GiPar n file params ampL dAmpl (str2Durations zs time3) wws tts vs ---- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.-unGenN4E4Gi :: Int -> FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> String -> IO ()-unGenN4E4Gi n file m ku ampL dAmpl v2 wws tts vs = do- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- uniqOverSoXSynthN44G n ampL dAmpl v2 wws tts vs vecB- endFromResult---- | Generalized version of the 'unGenN4E4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-unGenN4E4GiPar :: Int -> FilePath -> Params -> Double -> Double -> Durations -> String -> String -> String -> IO ()-unGenN4E4GiPar n file params ampL dAmpl v2 wws tts vs = do- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- uniqOverSoXSynthN44G n ampL dAmpl v2 wws tts vs vecB- endFromResult ---- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.-unGenN4E5Gi :: Int -> FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()-unGenN4E5Gi n file m ku ampL dAmpl v2 wws tts v3 = do- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- uniqOverSoXSynthN45G n ampL dAmpl v2 wws tts v3 vecB- endFromResult---- | Generalized version of the 'unGenN4E5Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-unGenN4E5GiPar :: Int -> FilePath -> Params -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()-unGenN4E5GiPar n file params ampL dAmpl v2 wws tts v3 = do- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- uniqOverSoXSynthN45G n ampL dAmpl v2 wws tts v3 vecB- endFromResult - --- | 4G genaralized version of the 'uniqOverSoXSynthNGen4E' where you provide your own 'Durations'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGen4E4G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen4E4G file m ku ampL dAmpl v2 wws tts vs = do- n <- duration1000 file- unGenN4E4Gi n file m ku ampL dAmpl v2 wws tts vs---- | Generalized version of the 'uniqOverSoXSynthNGen4E4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGen4E4GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> String -> IO ()-uniqOverSoXSynthNGen4E4GPar file params ampL dAmpl v2 wws tts vs = do- n <- duration1000 file- unGenN4E4GiPar n file params ampL dAmpl v2 wws tts vs---- | 5G genaralized version of the 'uniqOverSoXSynthNGen4E' where you provide your own 'Durations' and 'Intervals'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGen4E5G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()-uniqOverSoXSynthNGen4E5G file m ku ampL dAmpl v2 wws tts v3 = do- n <- duration1000 file- unGenN4E5Gi n file m ku ampL dAmpl v2 wws tts v3---- | Generalized version of the 'uniqOverSoXSynthNGen4E5G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGen4E5GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()-uniqOverSoXSynthNGen4E5GPar file params ampL dAmpl v2 wws tts v3 = do- n <- duration1000 file- unGenN4E5GiPar n file params ampL dAmpl v2 wws tts v3 ---- | Variant of the 'uniqOverSoXSynthNGen4E5G' where 'Intervals' are obtained from the 'String' using 'intervalsFromStringG' function. Helps to create a speech-like --- composition. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGen4E5GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> IO ()-uniqOverSoXSynthNGen4E5GS file m ku ampL time3 dAmpl zs wws tts v3 vs = do- n <- duration1000 file- unGenN4E5Gi n file m ku ampL dAmpl (str2Durations zs time3) wws tts (intervalsFromStringG v3 vs)---- | Generalized version of the 'uniqOverSoXSynthNGen4E5GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGen4E5GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> IO ()-uniqOverSoXSynthNGen4E5GSPar file params ampL time3 dAmpl zs wws tts v3 vs = do- n <- duration1000 file- unGenN4E5GiPar n file params ampL dAmpl (str2Durations zs time3) wws tts (intervalsFromStringG v3 vs) ---- | 6G generalized function for 'uniqOverSoXSynthNGen4E5G' where you provide your own 'Strengths'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGen4E6G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> Intervals -> Strengths -> Double -> IO ()-uniqOverSoXSynthNGen4E6G file m ku ampL dAmpl v2 wws tts v3 v6 limV = - uniqOverSoXSynthNGen4E5G file m ku ampL dAmpl v2 wws tts v3 >> apply6G2 v6 "221w" "result" limV >> endFromResult---- | Generalized version of the 'uniqOverSoXSynthNGen4E6G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGen4E6GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> Intervals -> Strengths -> Double -> IO ()-uniqOverSoXSynthNGen4E6GPar file params ampL dAmpl v2 wws tts v3 v6 limV = - uniqOverSoXSynthNGen4E5GPar file params ampL dAmpl v2 wws tts v3 >> apply6G2 v6 "221w" "result" limV >> endFromResult ---- | A variant of 'uniqOverSoXSynthNGen4E6G' where 'Strengths' are obtained from a Ukrainian text specified as the last 'String' argument. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGen4E6GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> - String -> Double -> IO ()-uniqOverSoXSynthNGen4E6GS file m ku ampL time3 dAmpl zs wws tts v5 vs xxs limV = - uniqOverSoXSynthNGen4E6G file m ku ampL dAmpl (str2Durations zs time3) wws tts (intervalsFromStringG v5 vs) (str2Volume xxs) limV---- | Generalized version of the 'uniqOverSoXSynthNGen4E6GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGen4E6GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> - String -> Double -> IO ()-uniqOverSoXSynthNGen4E6GSPar file params ampL time3 dAmpl zs wws tts v5 vs xxs limV = - uniqOverSoXSynthNGen4E6GPar file params ampL dAmpl (str2Durations zs time3) wws tts (intervalsFromStringG v5 vs) (str2Volume xxs) limV - --- | A variant of 'uniqOverSoXSynthNGen4E6GS' where 'Strengths' and 'Durations' are obtained from the same Ukrainian text specified as --- the last 'String' argument. The second 'Double' argument is an average duration of the sounds in seconds. --- Note that 'Int' arguments are used by 'liftInEnku' in that order so it returns a 'Maybe' number (actually frequency) for --- the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-uniqOverSoXSynthNGen4E6GSu :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> String -> Double -> IO ()-uniqOverSoXSynthNGen4E6GSu file m ku ampL time3 dAmpl wws tts v5 vs xxs limV = - uniqOverSoXSynthNGen4E6G file m ku ampL dAmpl (str2Durations xxs time3) wws tts (intervalsFromStringG v5 vs) (str2Volume xxs) limV- --- | Generalized version of the 'uniqOverSoXSynthNGen4E6GSu' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-uniqOverSoXSynthNGen4E6GSuPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> Intervals -> String -> String -> Double -> IO ()-uniqOverSoXSynthNGen4E6GSuPar file params ampL time3 dAmpl wws tts v5 vs xxs limV = - uniqOverSoXSynthNGen4E6GPar file params ampL dAmpl (str2Durations xxs time3) wws tts (intervalsFromStringG v5 vs) (str2Volume xxs) limV
+ DobutokO/Sound/DIS5G6G.hs view
@@ -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 Double -> Double -> V.Vector Double+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 Double -> Double -> V.Vector Double+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 -> Double -> Durations+durationsAver = doublesAveragedA++-- | 'Strengths' accounting the desired average strength.+strengthsAver :: Strengths -> Double -> Strengths+strengthsAver = doublesAveragedG++-- | 'StrengthsDb' accounting the desired average strength in dB.+strengthsDbAver :: StrengthsDb -> Double -> 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 -> Double -> 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 'Double' that is used inside 'str2Durations'.+str2Durat1 :: String -> Double+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 'Double' that is used inside 'str2Volume'.+str2Vol1 :: String -> Double+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 -> Double -> 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 'Double' argument +-- so that if the maximum by absolute value amplitude is less by absolute value than the 'Double' argument then the file is not changed.+apply6G2 :: Strengths -> String -> String -> Double -> 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 -> Double -> IO ()+apply6GS2 xs = apply6G2 (str2Volume xs)+
+ DobutokO/Sound/Decibel.hs view
@@ -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 Double++-- | Returns the frequency for which its ratio with the second 'Double' argument being under lg and being multiplied with 20 returns +-- the first 'Double' argument. For example, @dBOmegaRatio 6 440 ~ 880@ (actually, 877.9154185863069).+dBOmegaRatio :: Double -> Double -> Double+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 :: Double -> Double+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 :: Double -> Double+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+
DobutokO/Sound/Executable.hs view
@@ -14,7 +14,6 @@ module DobutokO.Sound.Executable ( -- * Basic functions for the executable dobutokO2- , recAndProcess , dobutokO2H7 , dobutokO2H9 , dobutokO2H92@@ -25,22 +24,19 @@ import System.Exit (ExitCode (ExitSuccess)) import qualified Data.List as L (groupBy,sort) import CaseBi (getBFst')-import Numeric (showFFloat) import Control.Exception (onException) import System.Environment (getArgs) import Data.List (isPrefixOf)-import Data.Maybe (fromJust,isNothing,fromMaybe)-import Data.Char (isDigit,isSpace)+import Data.Maybe (fromJust,fromMaybe) import System.Process import EndOfExe (showE)-import qualified Data.Vector as V (Vector (..),generate,fromList,length,imapM_,snoc,toList,unsafeSlice,mapM_,imap,unsafeIndex,map,filter,singleton)+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.Overtones+import DobutokO.Sound.Uniq import DobutokO.Sound.IntermediateF import DobutokO.Sound.ParseList (parseStoLInts)-import DobutokO.Sound.Functional+import DobutokO.Sound.Process -- | Function that actually makes processing in the @dobutokO2@ executable. Please, check before executing -- whether there is no \"x.wav\", \"test*\", \"result*\" and \"end*\" files in the current directory, because they can be overwritten.@@ -385,246 +381,9 @@ putStrLn ys dobutokO2H00 :: Bool -> String -> FilePath -> IO ()-dobutokO2H00 exist2 = fadeAllE+dobutokO2H00 _ = fadeAllE {-# INLINE dobutokO2H00 #-} dobutokO2H002 :: Bool -> String -> FilePath -> IO ()-dobutokO2H002 exist2 = fadeAllEMilN 2+dobutokO2H002 _ = fadeAllEMilN 2 {-# INLINE dobutokO2H002 #-}---------------------------------------------------------------------------------------------------------------------------------------------------------- | Function records and processes the sound data needed to generate the \"end.wav\" file in the 'dobutokO2' function. Please, check before executing--- whether there is no \"x.wav\" file in the current directory, because it can be overwritten.-recAndProcess :: FilePath -> Int -> IO String-recAndProcess file =- 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),(99,processD99),(999,processD99)])--processD_1 :: IO String-processD_1 = onException (do- putStr "Please, specify two \'Int\' numbers (with intermediate space character between them): the first one is a number of different notes there will be "- putStr "in the result, and the second one is a number of enky, to which you would like all the main components (not taking into account their "- putStr "respective lower bases of the intervals if any will exist) should belong. "- putStrLn "If you specify as the first one 2 (possibly the simplest case), then to the second one you can define a number in the range [3..53]. "- putStrLn "If you specify as the first one 3, then to the second one you can define a number in the range [2..35]. "- putStrLn "If you specify as the first one 4, then to the second one you can define a number in the range [2..26]. "- putStrLn "If you specify as the first one 6, then to the second one you can define a number in the range [1..17]. "- putStrLn "If you specify as the first one 9, then to the second one you can define a number in the range [1..11]. "- enka0 <- getLine- let enka1 = take 2 . words . filter (\x -> isDigit x || isSpace x) $ enka0- enka2 = read (head . take 1 $ enka1)::Int- enka3- | enka2 == 2 = if compare ((read (take 2 . head . tail $ enka1)::Int) `rem` 53) 3 == LT then 28 else (read (take 2 . head . tail $ enka1)::Int)- `rem` 53- | enka2 == 3 = if compare ((read (take 2 . head . tail $ enka1)::Int) `rem` 35) 2 == LT then 19 else (read (take 2 . head . tail $ enka1)::Int)- `rem` 35- | enka2 == 4 = if compare ((read (take 2 . head . tail $ enka1)::Int) `rem` 26) 2 == LT then 14 else (read (take 2 . head . tail $ enka1)::Int)- `rem` 26- | enka2 == 6 = if compare ((read (take 2 . head . tail $ enka1)::Int) `rem` 17) 1 == LT then 9 else (read (take 2 . head . tail $ enka1)::Int)- `rem` 17- | enka2 == 9 = if compare ((read (take 2 . head . tail $ enka1)::Int) `rem` 11) 1 == LT then 6 else (read (take 2 . head . tail $ enka1)::Int)- `rem` 11- | otherwise = error "Not valid number in the second place. "- return $ show enka2 ++ " " ++ show enka3 ) (do- putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."- putStrLn "_______________________________________________________________________"- processD3)-{-# INLINE processD_1 #-}--processD0 :: FilePath -> IO String-processD0 file = onException (readProcessWithExitCode (fromJust (showE "sox")) [file, "x.wav", "-r22050", "channels", "1"] "" >> putStrLn "" >> return "") (do- exist <- doesFileExist "x.wav"- if exist then removeFile "x.wav"- else putStr ""- putStrLn ""- putStr "The process was not successful may be because of the not valid data OR SoX cannot convert the given file to the .wav format. "- putStrLn "Interrupt the program and start again with the valid file. "- putStrLn "_______________________________________________________________________"- processD0 file)-{-# INLINE processD0 #-}- -processD1 :: IO String-processD1 = onException (do- tempeRa 0- putStrLn "Please, specify, how many seconds long sound data you would like to record."- time <- getLine- let time0 = read (filter (\t -> isDigit t || t == '.') time)::Double- putStrLn "Please, wait for 0.5 second and produce the needed sound now."- recA "x.wav" time0- putStrLn ""- return "") (do- dir0 <- listDirectory "."- let paths5 = filter (isPrefixOf "nx.") dir0- paths6 = filter (== "x.wav") dir0- paths = paths5 ++ paths6- mapM_ removeFile paths- putStrLn ""- putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."- putStrLn "_______________________________________________________________________"- processD1)-{-# INLINE processD1 #-}--processD2 :: FilePath -> IO String-processD2 file = onException (do - exist3 <- doesFileExist file- if exist3 then return ""- else do- putStr "Please, specify the control parameter for the SoX \"noisered\" effect in the range from 0.0 to 1.0. "- putStrLn "The greater value causes more reduction with possibly removing some important sound data. The default value is 0.5 "- putStrLn "To use the default value, you can simply press Enter."- ctrlN <- getLine- let addit = dropWhile (/= '.') . filter (\t -> isDigit t || t == '.') $ ctrlN- noiseP = if null ctrlN then ""- else tail addit- controlNoiseReduction $ '0':noiseP - norm "_x.wav" - if "nx." `isPrefixOf` file - then putStr "" - else renameFile "8_x.wav" file - removeFile "x.wav" - removeFile "_x.wav" - dir <- listDirectory "." - let paths4 = filter (isPrefixOf "nx.") dir- mapM_ removeFile paths4 - putStrLn "" - return "") (do- putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."- putStrLn "_______________________________________________________________________"- processD2 file)-{-# INLINE processD2 #-}--processD3 :: IO String-processD3 = onException (do- putStr "Please, specify the octave number, to which you would like all the main components (not taking into account their respective lower pure quints) "- putStrLn "should belong. The number should be better in the range [1..8]"- fmap d3H getLine) (do- putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."- putStrLn "_______________________________________________________________________"- processD3)-{-# INLINE processD3 #-}--d3H :: String -> String-d3H xs = show $ (read (take 1 xs)::Int) `rem` 9-{-# INLINE d3H #-}--processD4 :: IO String-processD4 = onException (do- putStr "Please, specify the amplitude for the generated overtones as an Int number in the range [0..99]. "- putStrLn "The default one is 99"- putStrLn "To use the default value, you can simply press Enter."- fmap d4H getLine) (do- putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."- putStrLn "_______________________________________________________________________"- processD4)-{-# INLINE processD4 #-}--d4H :: String -> String-d4H xs- | null xs = "1.0"- | otherwise = let amplOb = (read (take 2 . filter isDigit $ xs)::Int) `rem` 100 in- case amplOb of- 99 -> "1.0"- _ -> if compare (amplOb `quot` 9) 1 == LT then "0.0" ++ show (amplOb + 1)- else "0." ++ show (amplOb + 1)-{-# INLINE d4H #-}--processD5 :: IO String-processD5 = onException (do- putStr "Please, specify the basic duration for the generated sounds as a Double number in the range [0.1..4.0]. "- putStrLn "The default one is 0.5"- putStrLn "To use the default value, you can simply press Enter."- fmap d5H getLine) (do- putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."- putStrLn "_______________________________________________________________________"- processD5)-{-# INLINE processD5 #-}--d5H :: String -> String-d5H xs- | null xs = "0.5"- | otherwise = let time1 = (read (filter (\z -> isDigit z || z == '.') xs)::Double) in- if compare time1 0.1 /= LT && compare time1 4.0 /= GT then showFFloat (Just 4) time1 $ show 0- else let mantissa = time1 - (fromIntegral . truncate $ time1)- ceilP = (truncate time1::Int) `rem` 4 in- if ceilP == 0 then "0." ++ showFFloat (Just 4) mantissa (show 0)- else show ceilP ++ "." ++ showFFloat (Just 4) mantissa (show 0)-{-# INLINE d5H #-}--processD7 :: IO String-processD7 = onException (do- putStrLn "Please, input the Ukrainian text that will be used to define signs for the harmonics coefficients to produce a special timbre for the notes: "- fmap d7H getLine) (do- putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."- putStrLn "_______________________________________________________________________"- processD7)-{-# INLINE processD7 #-}--d7H :: String -> String-d7H xs- | null xs = "або"- | otherwise = xs-{-# INLINE d7H #-}--processD8 :: IO String-processD8 = onException (do- putStr "Please, specify in how many times the amplitude for the second lower note (if any) is greater than the amplitude for the main note. "- putStrLn "The number is in the range [0.1..2.0]. The default one is 1.0"- putStrLn "To use the default value, you can simply press Enter."- fmap d8H getLine) (do- putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."- putStrLn "_______________________________________________________________________"- processD8)-{-# INLINE processD8 #-}--d8H :: String -> String-d8H xs- | null xs = "1.0"- | otherwise = let dAmpl1 = (read (filter (\z -> isDigit z || z == '.') xs)::Double) in- if compare dAmpl1 0.1 /= LT && compare dAmpl1 2.0 /= GT then showFFloat (Just 4) dAmpl1 $ show 0- else let mantissa = dAmpl1 - (fromIntegral . truncate $ dAmpl1)- ceilP = (truncate dAmpl1::Int) `rem` 2 in- if ceilP == 0 then "0." ++ showFFloat (Just 4) mantissa (show 0)- else show ceilP ++ "." ++ showFFloat (Just 4) mantissa (show 0)-{-# INLINE d8H #-}--processD9 :: IO String-processD9 = onException (do- putStrLn "Please, input the Ukrainian text that will be used to define the intervals to be used to produce the lower note for the given main one. "- putStrLn "The default one is \"й\". "- putStrLn "To use the default value, you can simply press Enter."- fmap d9H getLine) (do- putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."- putStrLn "_______________________________________________________________________"- processD9)-{-# INLINE processD9 #-}--d9H :: String -> String-d9H xs- | null xs = "й"- | otherwise = xs-{-# INLINE d9H #-}--processD :: IO String-processD = onException (do- putStrLn "Please, input the Ukrainian text that will be used to create a special timbre for the notes: "- getLine) (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 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 indices 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 an "- 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 the end of input (e. g. for Unices, it's probably Ctrl + D). "- getContents) (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 #-}------------------------------------------------------------------------------------------------ -
+ DobutokO/Sound/Extended.hs view
@@ -0,0 +1,64 @@+-- |+-- Module : DobutokO.Sound.Extended+-- 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.Extended (+ -- * Even more extended+ dviykyTA+ , triykyTA+ , chetvirkyTA+ , p'yatirkyTA+ , shistkyTA+ , simkyTA+ , visimkyTA+ , dev'yatkyTA+ , desyatkyTA+ , odynadtsyatkyTA+ , octavesTA+) where++import qualified Data.Vector as V+import DobutokO.Sound.Functional.Basics (NotePairs,notes)++dviykyTA :: NotePairs+dviykyTA = V.generate 107 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 1)))++triykyTA :: NotePairs+triykyTA = V.generate 106 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 2)))++chetvirkyTA :: NotePairs+chetvirkyTA = V.generate 105 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 3)))++p'yatirkyTA :: NotePairs+p'yatirkyTA = V.generate 104 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 4)))++shistkyTA :: NotePairs+shistkyTA = V.generate 103 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 5)))++simkyTA :: NotePairs+simkyTA = V.generate 102 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 6)))++visimkyTA :: NotePairs+visimkyTA = V.generate 101 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 7)))++dev'yatkyTA :: NotePairs+dev'yatkyTA = V.generate 100 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 8)))++desyatkyTA :: NotePairs+desyatkyTA = V.generate 99 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 9)))++odynadtsyatkyTA :: NotePairs+odynadtsyatkyTA = V.generate 98 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 10)))++octavesTA :: NotePairs+octavesTA = V.generate 97 (\i -> (V.unsafeIndex notes i, V.unsafeIndex notes (i + 11)))++--------------------------------------------------------------------------------------------------------------------------
+ DobutokO/Sound/FunctionF.hs view
@@ -0,0 +1,81 @@+-- |+-- Module : DobutokO.Sound.FunctionF+-- 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.FunctionF (+ -- * Working with OvertonesO and function f+ maybeFFromStrVec+ , fVecCoefs+ , showFFromStrVec+) where++import Text.Read (readMaybe)+import Data.Maybe (isNothing,fromJust,fromMaybe)+import Numeric+import qualified Data.Vector as V+import DobutokO.Sound.Functional.Basics++-- | Gets a function @f::Double -> OvertonesO@ that can be used further. Has two variants with usage of 'closestNote' ('Int' argument is greater than 0)v+-- and without it ('Int' argument is less than 0). For both cases 'String' must be in a form list of tuples of pairs of 'Double' to get somewhat+-- reasonable result. The function @f@ can be shown using a special printing function 'showFFromStrVec'. It is a simplest multiplicative (somewhat+-- acoustically and musically reasonable) form for the function that can provide such a result that fits into the given data.+--+-- > let (y,f1) = fromJust (maybeFFromStrVec 1 3583.9783 "[(25.368,0.2486356),(37.259,0.6464867),(486.153,0.374618646),(789.563,0.463486461)]") in (y,f1 3583.9783)+-- >+-- > (3520.0,[(25.829079975681818,0.2486356),(37.936206670369316,0.6464867),(494.9891484317899,0.374618646),(803.9138234326421,0.463486461)])+-- >+-- > let (y,f1) = fromJust (maybeFFromStrVec (-1) 3583.9783 "[(25.368,0.2486356),(37.259,0.6464867),(486.153,0.374618646),(789.563,0.463486461)]") in (y,f1 3583.9783)+-- > +-- > (3583.9783,[(25.368,0.2486356),(37.259,0.6464867),(486.153,0.374618646),(789.563,0.463486461)])+-- +maybeFFromStrVec :: Int -> Double -> String -> Maybe (Double,(Double -> V.Vector (Double,Double)))+maybeFFromStrVec n x ys+ | n == 0 || null ys = Nothing+ | n > 0 = + let y = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+ v = readMaybe ys::Maybe (V.Vector (Double,Double))+ v2 = fromMaybe V.empty v+ v3 = V.map (\(t,_) -> t / y) v2 in+ if V.null v3 then Nothing+ else Just (y,(\t1 -> V.imap (\i (_,ampl2) -> ((V.unsafeIndex v3 i) * t1,ampl2)) v2))+ | otherwise = + let y = (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+ v = readMaybe ys::Maybe (V.Vector (Double,Double))+ v2 = fromMaybe V.empty v+ v3 = V.map (\(t,_) -> t / y) v2 in+ if V.null v3 then Nothing+ else Just (y,(\t1 -> V.imap (\i (_,ampl2) -> ((V.unsafeIndex v3 i) * t1,ampl2)) v2))++-- | Gets multiplication coefficients for @f::Double -> Vector (Double,Double)@ from the 'maybeFFromStrVec' with the same arguments.+fVecCoefs :: Int -> Double -> String -> V.Vector Double+fVecCoefs n x ys =+ let rs = maybeFFromStrVec n x ys in+ case rs of+ Nothing -> V.empty+ _ ->+ let (_,f1) = fromJust rs in+ V.map fst (f1 1)++-- | Experimental 'show' for @f::Double -> Vector (Double,Double)@ that is used only for visualisation. It is correct only with 'maybeFFromStrVec' or+-- equivalent function. Because the shape of the @f@ is known the function can be defined.+-- +-- > showFFromStrVec (-1) 440 "[(25.358,0.3598),(489.35,0.4588962),(795.35,0.6853)]"+-- > +-- > "(440.00,(\t -> <(0.05763181818181818 * t, 0.3598),(1.112159090909091 * t, 0.4588962),(1.8076136363636364 * t, 0.6853)>))"+-- +showFFromStrVec :: Int -> Double -> String -> String+showFFromStrVec n x ys+ | isNothing . maybeFFromStrVec n x $ ys = ""+ | otherwise =+ let (y,f) = fromJust . maybeFFromStrVec n x $ ys+ l = length ("(" ++ (showFFloat Nothing y "") ++ ",(\t -> <(" ++ concat (V.toList . V.map (\z -> (showFFloat Nothing (fst z) $+ " * t, " ++ (showFFloat Nothing (snd z) "),("))) $ (f 1))) in take (l - 2) ("(" ++ (showFFloat Nothing y "") ++ ",(\t -> <("+ ++ concat (V.toList . V.map (\z -> (showFFloat Nothing (fst z) " * t, " ++ (showFFloat Nothing (snd z) "),("))) $ (f 1))) ++ ">))"
DobutokO/Sound/Functional.hs view
@@ -12,2430 +12,629 @@ {-# OPTIONS_GHC -threaded #-} module DobutokO.Sound.Functional (- Params (..)- -- * Type synonyms with different semantics- , SoundsO- , OvertonesO- , NotePairs- , Durations- , Strengths- , StrengthsDb- , Intervals- -- * Work with notes (general)- , notes- , neighbourNotes- , closestNote- , pureQuintNote - , overTones - -- * Work with enky (extension to octaves functionality)- , nkyT- , whichOctave- , whichOctaveG- , whichEnka - , enkuUp - , enkuDown - , liftInEnkuV- , liftInEnku- -- ** Work with octaves- , octavesT- -- * Combining intermediate files- , mixTest- , mixTest2- -- * Working with files- , freqsFromFile- , endFromResult- -- * Work with overtones- , overSoXSynth - -- * Use additional function as a parameter- , overSoXSynth2FDN- , overSoXSynth2FDN_B- -- ** Just simple function application- , overSoXSynth2FDN_S- -- *** With additional filtering- , overSoXSynth2FDN_Sf- , overSoXSynth2FDN_Sf3- -- * Use additional function and Ukrainian texts and generates melody- , overSoXSynthGen2FDN- , overSoXSynthGen2FDN_B- , overSoXSynthGen2FDN_S- , overSoXSynthGen2FDN_Sf- , overSoXSynthGen2FDN_Sf3- , dNote- -- * 1G generalized functions with dB volume overtones adjustments- , overSoXSynth2FDN1G- , overSoXSynth2FDN_B1G- , overSoXSynth2FDN_S1G- , overSoXSynth2FDN_Sf1G- , overSoXSynth2FDN_Sf31G- , partialTest_k1G- -- * 2G generalized functions with additional sound quality specifying- , overSoXSynth2FDN2G- , overSoXSynth2FDN_B2G- , overSoXSynth2FDN_S2G- , overSoXSynth2FDN_Sf2G- , overSoXSynth2FDN_Sf32G- , partialTest_k2G- , soundGenF32G- -- ** 2G generalized functions for melody producing- , overSoXSynthGen2FDN_SG2G- , overSoXSynthGen2FDN_Sf3G2G- -- ** 2G generalized auxiliary functions- , mixTest2G- , mixTest22G- , endFromResult2G- -- * Generalized functions with several functional parameters- , soundGenF3- , overSoXSynthGen2FDN_SG- , overSoXSynthGen2FDN_Sf3G- -- ** 1G generalized function with db volume overtones adjustments and several functional parameters- , soundGenF31G- -- ** Auxiliary functions- , adjust_dbVol- , partialTest_k- , prependZeroes - , nOfZeroesLog - , numVZeroesPre- , syllableStr - , helpF1- , helpF0- , doubleVecFromVecOfDouble- -- *** Working with Intervals- , intervalsFromString - , vStrToVInt - , strToInt- -- * Working with OvertonesO and function f- , maybeFFromStrVec- , fVecCoefs- , showFFromStrVec- -- * Functions to edit OvertonesO and function f (since 0.25.0.0)- , renormF- , renormFD- , sameOvertone- , sameOvertoneL - , sameFreqF- , sameFreqFI- , fAddFElem- , fRemoveFElem- , fChangeFElem- , gAdd01- , gAdd02- , gAdd03- , gAdd04- , gRem01- , gRem02- , gRem03- -- ** Working with two OvertonesO- , fAddFElems- , fRemoveFElems- , fChangeFElems- , freqsOverlapOvers- , elemsOverlapOvers- , gAdds01- , gAdds02- -- * Splitting and concatenating OvertonesO- , splitO- , splitO2- , overConcat- -- ** Generalization of the previous ones splitting functions- , splitHelp1- , splitHelp2- , splitOG1- , splitOG2- , splitOG12- , splitOG12S- , splitOG22- , splitOG22S- -- * New functions for the version 0.36.0.0- , duration1000- , durationsAver- , str2Durat1- , str2Durations- , str2DurationsDef- , str2Vol1- , str2Volume- , defInt- , doublesAveragedA- , doublesAveragedG- , equalize2Vec- , intervalsFromStringG- , overSoXSynthGen2FDN4G- , overSoXSynthGen2FDN_SG4G- , overSoXSynthGen2FDN_SG4GS- , silentSound2G- , strToIntG- , strengthsAver- , strengthsDbAver- , vStrToVIntG- -- * New generalized 5G functions that works with Intervals- , overSoXSynth2FDN5G- , overSoXSynth2FDN_B5G- , overSoXSynth2FDN_S5G- , overSoXSynth2FDN_Sf35G- -- * New generalized 6G functions that works with Strengths- , apply6Gf- , apply6G- , apply6G2- , apply6GS- , apply6GS2- , apply6GSilentFile- , overSoXSynth2FDN6G- , overSoXSynth2FDN6GS- , overSoXSynth2FDN_B6G- , overSoXSynth2FDN_B6GS- , overSoXSynth2FDN_S6G- , overSoXSynth2FDN_S6GS- , overSoXSynth2FDN_Sf36G- , overSoXSynth2FDN_Sf36GS- , overSoXSynthGen2FDN_SG6G- , overSoXSynthGen2FDN_SG6GS- , overSoXSynthGen2FDN_SG6GSu- -- * Working with StrengthsDb and Strengths and others- , dBOmegaRatio- , strength2dB_Abs- , strengthdB2ampl- , strengths2dB- , strengthsDb2ampl- -- * New generalizations for scales and modes with Params- , filterInParams- , sortNoDup- , toneD- , toneE- , liftInParams- , liftInParamsV- , lengthP- , elemP- , elemCloseP- , showD- , isStrParams- , isListParams- -- ** Application of the Params- , overSoXSynthGen2FDN_SG4GPar- , overSoXSynthGen2FDN_SG6GPar- , overSoXSynthGen2FDN_SG2GPar- , overSoXSynthGen2FDN_SfPar- , overSoXSynthGen2FDN_Sf3GPar- , overSoXSynthGen2FDN_Sf3G2GPar - -- * Another way to generalize the simple functions- , testSoundGen2G- , soundGen3G- , soundGen3G_O- , soundGen3G_O2- , soundGen3G_O2G- -- ** With MN control- , testSoundGen2GMN- , soundGen3GMN- , soundGen3G_OMN- , soundGen3G_O2MN- , soundGen3G_O2GMN- , h1- , h2- -- ** New with Params control- , soundGen3G_OPar- , soundGen3G_O2Par- , soundGen3G_O2GPar- , soundGen3G_OMNPar- , soundGen3G_O2MNPar- , soundGen3G_O2GMNPar- , h2Params- -- * Creating melody from overtones- , overMeloPar-) where--import Text.Read (readMaybe)-import CaseBi (getBFst')-import Data.Char (isDigit,isAsciiLower)-import System.Exit (ExitCode( ExitSuccess ))-import Numeric-import Data.List (isPrefixOf,sort,sortBy,nubBy)-import Data.Maybe (isNothing,fromJust,isJust,fromMaybe,maybe)-import qualified Data.Vector as V-import System.Process-import EndOfExe-import System.Directory-import Melodics.Ukrainian (convertToProperUkrainian)-import SoXBasics (durationA,upperBnd,selMaxAbs)-import MMSyn7l-import MMSyn7.Syllable -import DobutokO.Sound.IntermediateF-import GHC.Int (Int64)-import DobutokO.Sound.Keyboard----- | Representation of the scales and modes for the notes. Can be extended further, but for a lot of situations the following realization is sufficient. --- See, for example, 'filterInParams' and so on. 'String' is (are) used as a general classification name, for some of them there are provided two --- 'String' to classify. Lists are used to specify remainders in some meaning. See also, 'liftInParams' and 'toneE' ('toneD') functions, 'elemP' and --- 'elemCloseP', 'lengthP' and 'showD'.-data Params = P2 Int Int | P2s Int Int String | P3sf Int Int Int String | P4lsf Int Int Int [Int] String | P32sf Int Int Int String String - | P3lf Int Int [Int] deriving (Eq, Ord, Show)---- | Is used to represent a sequence of intervals, each note being a 'Double' value (its frequency in Hz).-type SoundsO = V.Vector (Double, Double)---- | Is used to represent a set of overtones for the single sound, the first 'Double' value is a frequency and the second one -- an amplitude.-type OvertonesO = V.Vector (Double, Double)---- | Is used to represent a set of pairs of notes for each element of which the 'Double' values (notes frequencies in Hz) are somewhat--- musically connected one with another..-type NotePairs = V.Vector (Double, Double)---- | Is used to represent a set of durations parameters of the sounds and pauses. The positive value corresponds to the sound --- and the negative one -- to the pause.-type Durations = V.Vector Double---- | Is used to represent a set of volumes in the amplitude scale for SoX \"vol\" effect.-type Strengths = V.Vector Double---- | 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 Double---- | Is used to represent a set of intervals for notes (each element is a number of semi-tones between parts of interval). --- Positive values corresponds to lower notes and negative to higher ones.-type Intervals = V.Vector Int---- | Similar to 'overSoXSynth2DN' but instead of 'overTones' function, it uses volatile function @f::Double -> Vector (Double, Double)@ with--- somewhat sophisticated mechanism to normalize the resulting 'V.Vector' elements @(Double, Double)@. The last one is an experimental feature, so--- it is your responsibility to provide a function so that it does not lead to clipping. In such a case, the result of application of the--- 'convertToProperUkrainian' to the 'String' parameter must not be 'V.empty'. 'Int' argument is an index of the element to be taken from --- the 'intervalsFromString' applied to the 'String' argument. To obtain compatible with versions prior to 0.20.0.0 behaviour, use for the 'Int' 0.------ Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function.--- But for a lot of functions this works well.--- --- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN'.-overSoXSynth2FDN :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()-overSoXSynth2FDN f (x, y) j zs = overSoXSynth2FDN1G f (x, y) j zs (V.replicate (V.length . f . closestNote $ if x /= 0.0 - then abs x else V.unsafeIndex notes 0) 0.0)---- | Is used internally in the 'readProcessWithExitCode' to adjust volume for the sound with additional dB value given by 'Double' argument.-adjust_dbVol :: [String] -> Double -> [String]-adjust_dbVol xss y- | y == 0.0 = xss- | otherwise = xss ++ ["vol",showFFloat Nothing y "dB"]---- | Returns the frequency for which its ratio with the second 'Double' argument being under lg and being multiplied with 20 returns --- the first 'Double' argument. For example, @dBOmegaRatio 6 440 ~ 880@ (actually, 877.9154185863069).-dBOmegaRatio :: Double -> Double -> Double-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 :: Double -> Double-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 :: Double -> Double-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---- | 'V.Vector' of 'Double' is a vector of dB volume adjustments for the corresponding harmonices (overtones).-overSoXSynth2FDN1G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> IO ()-overSoXSynth2FDN1G f (x, y) j zs vdB = overSoXSynth2FDN2G f (x, y) j zs vdB []- --- | Similar to 'overSoXSynth2FDN1G', but additionally allows to specify by the second 'String' argument a quality changes to the generated files--- (please, see 'soxBasicParams'). Since version 0.36.0.0 the function supports generation of the pauses.-overSoXSynth2FDN2G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> String -> IO ()-overSoXSynth2FDN2G f (x, y) j zs vdB ys- | V.null . convertToProperUkrainian $ zs = overSoXSynth x- | otherwise = do- let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- l0 = length zs- note1 = dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) note0- g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> x1 == x2) . V.toList . V.map (\(noteX, !amplX) ->- if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,- abs (amplX - (fromIntegral . truncate $ amplX)))) . f- g k = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .- V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 k) $ 0), z0)) . g0 $ k - v0 = g note0- v1 = maybe V.empty g note1- ts = showFFloat (Just 4) (abs y) "" - overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", - showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")- overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) (adjust_dbVol ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", - showFFloat Nothing noteN "","vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"] (V.unsafeIndex vdB i))) "") vec- _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts, - "sine", showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- if isNothing note1 then overSoXSynthHelp v0- else do - _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts, - "sine", showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- overSoXSynthHelp v0- overSoXSynthHelp2 v1 vdB- if null ys then mixTest else mixTest2G ys ---- | Similar to 'overSoXSynth2FDN2G', but additionally allows to specify by the 'Intervals' argument to specify your own intervals. For more information, --- please, refer to 'intervalsFromStringG'.-overSoXSynth2FDN5G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> IO ()-overSoXSynth2FDN5G f (x, y) j v5 vdB ys- | V.null v5 = overSoXSynth x- | otherwise = do- let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- l0 = V.length v5- note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0- g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> x1 == x2) . V.toList . V.map (\(noteX, !amplX) ->- if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,- abs (amplX - (fromIntegral . truncate $ amplX)))) . f- g k = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .- V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 k) $ 0), z0)) . g0 $ k - v0 = g note0- v1 = maybe V.empty g note1- ts = showFFloat (Just 4) (abs y) "" - overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", - showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")- overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) (adjust_dbVol ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", - showFFloat Nothing noteN "","vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"] (V.unsafeIndex vdB i))) "") vec- _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts, - "sine", showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- if isNothing note1 then overSoXSynthHelp v0- else do - _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts, - "sine", showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- overSoXSynthHelp v0- overSoXSynthHelp2 v1 vdB- if null ys then mixTest else mixTest2G ys ---- | Generalized variant of the 'overSoXSynth2FDN5G' with afterwards 'apply6Gf' usage. -overSoXSynth2FDN6G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> Double -> IO ()-overSoXSynth2FDN6G f (x, y) j v5 vdB ys vol- | V.null v5 = overSoXSynth x- | otherwise = do- let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- l0 = V.length v5- note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0- g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> x1 == x2) . V.toList . V.map (\(noteX, !amplX) ->- if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,- abs (amplX - (fromIntegral . truncate $ amplX)))) . f- g k = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .- V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 k) $ 0), z0)) . g0 $ k - v0 = g note0- v1 = maybe V.empty g note1- ts = showFFloat (Just 4) (abs y) "" - overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", - showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")- overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) (adjust_dbVol ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", - showFFloat Nothing noteN "","vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"] (V.unsafeIndex vdB i))) "") vec- _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts, - "sine", showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- if isNothing note1 then overSoXSynthHelp v0- else do - _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts, - "sine", showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- overSoXSynthHelp v0- overSoXSynthHelp2 v1 vdB- if null ys then mixTest else mixTest2G ys- if compare y 0.0 == GT then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr ""---- | A variant of the 'overSoXSynth2FDN6G' where volume adjustment is obtained from a Ukrainian text.-overSoXSynth2FDN6GS :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> String -> V.Vector Double -> String -> String -> IO ()-overSoXSynth2FDN6GS f (x, y) j v5 xs vdB ys xxs - | V.null . convertToProperUkrainian $ xxs = putStrLn "You provided no information to obtain volume adjustment! "- | otherwise = overSoXSynth2FDN6G f (x, y) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs)- --- | Uses additional 'Int' parameters. The first one is a number of enka (see 'nkyT'). The second one defines, to which n-th elements set--- (see 'nkyT') belongs the obtained higher notes in the intervals. To obtain reasonable results, please, use for the first one 2, 3, 4, 6, 9, or 12.--- The first 'String' parameter is used to produce durations of the notes. The second one is used to define intervals. A 'Double' parameter is a--- basic sound duration, it defines tempo of the melody in general.-overSoXSynthGen2FDN :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()-overSoXSynthGen2FDN file m ku f y zs wws = overSoXSynthGen2FDN_SG file m ku f y zs wws overSoXSynth2FDN---- | Generalized variant of the 'overSoXSynthGen2FDN' with your own specified 'Durations' for the sounds and pauses. --- Instead of using a Ukrainian text to specify a durations for the sounds (and a rhythm --- respectively) you provide your own rhythm as 'Durations'. Positive values correspond to durations of the sounds generated --- and negative values -- to durations of the pauses respectively. -overSoXSynthGen2FDN4G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Durations -> String -> IO ()-overSoXSynthGen2FDN4G file m ku f y v2 wws = overSoXSynthGen2FDN_SG4G file m ku f y v2 wws overSoXSynth2FDN---- | Gets 'V.Vector' of 'Int' frequencies from the given 'FilePath' using SoX. The frequencies are \"rough\" according to the SoX documentation and--- the duration is too small so they can be definitely other than expected ones. Is used as a source of variable numbers (somewhat close each to another--- in their order but not neccessarily). .-freqsFromFile :: FilePath -> Int -> IO (V.Vector Int)-freqsFromFile file n = V.generateM n (\k -> do {- (_, _, herr) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", showFFloat Nothing (fromIntegral k * 0.001) "",- "0.001", "stat"] ""- ; let line0s = lines herr- noteN0 = takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s- ; if null noteN0 then return (11440::Int)- else let noteN1 = read (takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s)::Int in return noteN1 })---- | Combines (mixes) all \"test\*" files in the given directory. The files should be similar in parameters and must be sound files for SoX to work--- on them properly. Afterwards, the function deletes these combined files.-mixTest :: IO ()-mixTest = do- paths0 <- listDirectory "."- let paths = filter (isPrefixOf "test") $ paths0- _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""- mapM_ removeFile paths---- | Similar to 'mixTest', but allows to change the sound quality parameters for the resulting file. For more information, please, refer to--- 'soxBasicParams'.-mixTest2G :: String -> IO ()-mixTest2G ys = do- paths0 <- listDirectory "."- let paths = filter (isPrefixOf "test") $ paths0- _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ soxBasicParams ys ["","result.wav","vol","0.3"]) ""- mapM_ removeFile paths---- | Combines (mixes) all \"test\*" files in the given directory. The files should be similar in parameters and must be sound files for SoX to work--- on them properly. Afterwards, the function deletes these combined files. The name of the resulting file depends on the first two command line--- arguments so that it is easy to produce unique names for the consequent call for the function.-mixTest2 :: Int -> Int -> IO ()-mixTest2 zeroN j = do- paths0 <- listDirectory "."- let paths = filter (isPrefixOf "test") $ paths0- _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result" ++ prependZeroes zeroN (show j) ++ ".wav",- "vol","0.3"]) ""- mapM_ removeFile paths---- | Similar to 'mixTest', but allows to change the sound quality parameters for the resulting file. For more information, please, refer to--- 'soxBasicParams'. The name of the resulting file depends on the first two command line--- arguments so that it is easy to produce unique names for the consequent call for the function.-mixTest22G :: Int -> Int -> String -> IO ()-mixTest22G zeroN j ys = do- paths0 <- listDirectory "."- let paths = filter (isPrefixOf "test") $ paths0- _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ soxBasicParams ys ["","result" ++ prependZeroes zeroN (show j) ++- ".wav","vol","0.3"]) ""- mapM_ removeFile paths ---- | Gets an \"end.wav\" file from the intermediate \"result\*.wav\" files in the current directory. If it is not successful, produces the notification--- message and exits without error. If you would like to create the file if there are too many intermediate ones, please, run--- \"dobutokO2 8\" or \"dobutokO2 80\" in the current directory.-endFromResult :: IO ()-endFromResult = do- path2s <- listDirectory "."- let paths3 = sort . filter (isPrefixOf "result") $ path2s- (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""- case code of- ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "- _ -> do- exi <- doesFileExist "end.wav"- if exi then removeFile "end.wav"- else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>- putStrLn "Use them manually as needed."---- | Similar to 'endFromResult', but uses additional 'String' argument to change sound quality parameters. For more information, please, refer to--- 'soxBasicParams'.-endFromResult2G :: String -> IO ()-endFromResult2G ys = do- path2s <- listDirectory "."- let paths3 = sort . filter (isPrefixOf "result") $ path2s- (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ soxBasicParams ys ["","end.wav"]) ""- case code of- ExitSuccess -> putStrLn $ "The final file \"end." ++ if drop 3 ys == "f" then "flac" else "wav" ++ "\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "- _ -> do- exi <- doesFileExist $ "end." ++ if drop 3 ys == "f" then "flac" else "wav"- if exi then removeFile $ "end." ++ if drop 3 ys == "f" then "flac" else "wav"- else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>- putStrLn "Use them manually as needed." ---- | Creates part of the needed \"test\*\.wav" files in the current directory. -partialTest_k :: OvertonesO -> Int -> String -> IO ()-partialTest_k vec k ts = partialTest_k2G vec k ts V.empty []---- | Generalized version of the 'partialTest_k' with the additional volume adjustment in dB given by 'V.Vector' of 'Double'.-partialTest_k1G :: OvertonesO -> Int -> String -> V.Vector Double -> IO ()-partialTest_k1G vec k ts vdB = partialTest_k2G vec k ts vdB []---- | Generalized version of the 'partialTest_k1G' with a possibility to change sound quality parameters using the additional second 'String' argument.--- For more information, please, refer to 'soxBasicParams'.-partialTest_k2G :: OvertonesO -> Int -> String -> V.Vector Double -> String -> IO ()-partialTest_k2G vec k ts vdB ys =- let l = V.length vec- zeroN = numVZeroesPre vec in V.imapM_ (\i (noteN, !amplN) -> if i /= 0 && i `rem` 50 == 0- then do- _ <- readProcessWithExitCode (fromJust (showE "sox")) (soxBasicParams ys (adjust_dbVol ["-r22050", "-n", "test" ++ show k ++ show (i + 2) ++ ".wav",- "synth", ts,"sine", showFFloat Nothing (abs noteN) "", "vol", showFFloat Nothing amplN ""]- (V.unsafeIndex vdB i))) ""- path1s <- listDirectory "."- let path2s = sort . filter (isPrefixOf $ "test" ++ show k) $ path1s- (code,_,herr0) <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ path2s ++ soxBasicParams ys ["","test-" ++ show k ++- prependZeroes zeroN (show (i `quot` 50)) ++ ".wav"]) ""- case code of- ExitSuccess -> mapM_ removeFile path2s- _ -> do- exi <- doesFileExist $ "test-" ++ show k ++ prependZeroes zeroN (show (i `quot` 50)) ++ if drop 3 ys == "f" then ".flac" else ".wav"- if exi then putStrLn (herr0) >> removeFile ("test-" ++ show k ++ prependZeroes zeroN (show (i `quot` 50)) ++ if drop 3 ys == "f" then ".flac" else ".wav")- else putStrLn herr0- else readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ((if V.null vdB then id - else (\wwws -> adjust_dbVol wwws (V.unsafeIndex vdB i))) ["-r22050", "-n", "test" ++ show k ++ show (i + 2) ++ ".wav",- "synth", ts,"sine", showFFloat Nothing (abs noteN) "", "vol", showFFloat Nothing amplN ""])) "" >> putStr "") vec ---- | Generates a 'V.Vector' of 'OvertonesO' that represents the sound. -doubleVecFromVecOfDouble :: (Double -> OvertonesO) -> Double -> V.Vector (Maybe Double) -> V.Vector OvertonesO-doubleVecFromVecOfDouble f t0 =- V.map (\note1 -> if isNothing note1 then V.empty else V.filter (\(_,!z) -> compare (abs z) t0 == GT) . f . fromJust $ note1)- --- | Similar to 'overSoXSynth2DN' but instead of 'overTones' function, it uses volatile function @f::Double -> Vector (Double, Double)@ with--- somewhat sophisticated mechanism to normalize the resulting 'V.Vector' elements @(Double, Double)@. The last one is experimental feature, so--- it is your responsibility to provide a function so that it does not lead to clipping. In such a case, the result of application of the--- 'convertToProperUkrainian' to the 'String' parameter must not be 'V.empty'. The function also tries to perform filtering to avoid possible beating.--- The third 'Double' parameter in the tuple is used as a limit for frequencies difference in Hz to be filtered out from the resulting sound. It is--- considered to be from the range @[0.1..10.0]@. An 'Int' parameter is used to define the needed interval. To obtain compatible with versions prior--- to 0.20.0.0 behaviour, use for the 'Int' 0.------ Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function.--- But for a lot of functions this works well.--- --- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_B'.-overSoXSynth2FDN_B :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()-overSoXSynth2FDN_B f (x, y, limB) j zs = overSoXSynth2FDN_B1G f (x, y, limB) j zs (V.replicate (V.length . f . closestNote $ if x /= 0.0 then abs x else V.unsafeIndex notes 0) 0.0)---- | 'V.Vector' of 'Double' is a vector of dB volume adjustments for the corresponding harmonices (overtones).-overSoXSynth2FDN_B1G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> V.Vector Double -> IO ()-overSoXSynth2FDN_B1G f (x, y, limB) j zs vdB = overSoXSynth2FDN_B2G f (x, y, limB) j zs vdB []---- | Generalized version of the 'overSoXSynth2FDN_B1G' with a possibility to specify sound quality parameters using additional second 'String'--- argument. For more information, please, refer to 'soxBasicParams'. -overSoXSynth2FDN_B2G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> V.Vector Double -> String -> IO ()-overSoXSynth2FDN_B2G f (x, y, limB) j zs vdB ys- | V.null . convertToProperUkrainian $ zs = overSoXSynth x- | otherwise = do- let limA0 = abs ((limB / 10) - (fromIntegral . truncate $ (limB / 10))) * 10- limA = if compare limA0 0.1 == LT then 0.1 else limA0- l0 = length zs- note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- note1 = dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) note0- g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> compare (abs (x1 - x2)) limA == LT) . V.toList . V.map (\(noteX, !amplX) ->- if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,- abs (amplX - (fromIntegral . truncate $ amplX)))) . f- v0 = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .- V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 note0) $ 0), z0)) . g0 $ note0 - v1 = if isNothing note1 then V.empty- else V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .- V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 . fromJust $ note1) $ 0), z0)) . g0 . fromJust $ note1- ts = showFFloat (Just 4) (abs y) "" - overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", - showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")- overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) ((if V.null vdB then id else (\wwws -> adjust_dbVol wwws (V.unsafeIndex vdB i))) - ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat Nothing noteN "", "vol", - if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"])) "") vec- _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",- showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- if isNothing note1 then overSoXSynthHelp v0- else do - _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",- showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- overSoXSynthHelp v0- overSoXSynthHelp2 v1 vdB- if null ys then mixTest else mixTest2G ys ---- | Generalized version of the 'overSoXSynth2FDN_B2G' with a possibility to specify your own 'Intervals'. For more information, please, --- refer to 'intervalsFromStringG'.-overSoXSynth2FDN_B5G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> IO ()-overSoXSynth2FDN_B5G f (x, y, limB) j v5 vdB ys- | V.null v5 = overSoXSynth x- | otherwise = do- let limA0 = abs ((limB / 10) - (fromIntegral . truncate $ (limB / 10))) * 10- limA = if compare limA0 0.1 == LT then 0.1 else limA0- l0 = V.length v5- note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0- g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> compare (abs (x1 - x2)) limA == LT) . V.toList . V.map (\(noteX, !amplX) ->- if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,- abs (amplX - (fromIntegral . truncate $ amplX)))) . f- v0 = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .- V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 note0) $ 0), z0)) . g0 $ note0 - v1 = if isNothing note1 then V.empty- else V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .- V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 . fromJust $ note1) $ 0), z0)) . g0 . fromJust $ note1- ts = showFFloat (Just 4) (abs y) "" - overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", - showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")- overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) ((if V.null vdB then id else (\wwws -> adjust_dbVol wwws (V.unsafeIndex vdB i))) - ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat Nothing noteN "", "vol", - if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"])) "") vec- _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",- showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- if isNothing note1 then overSoXSynthHelp v0- else do - _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",- showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- overSoXSynthHelp v0- overSoXSynthHelp2 v1 vdB- if null ys then mixTest else mixTest2G ys ---- | Generalized variant of the 'overSoXSynth2FDN_B5G' with afterwards 'apply6G' usage. -overSoXSynth2FDN_B6G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> Double -> IO ()-overSoXSynth2FDN_B6G f (x, y, limB) j v5 vdB ys vol - | V.null v5 = overSoXSynth x- | otherwise = do- let limA0 = abs ((limB / 10) - (fromIntegral . truncate $ (limB / 10))) * 10- limA = if compare limA0 0.1 == LT then 0.1 else limA0- l0 = V.length v5- note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0- g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> compare (abs (x1 - x2)) limA == LT) . V.toList . V.map (\(noteX, !amplX) ->- if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,- abs (amplX - (fromIntegral . truncate $ amplX)))) . f- v0 = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .- V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 note0) $ 0), z0)) . g0 $ note0 - v1 = if isNothing note1 then V.empty- else V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .- V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 . fromJust $ note1) $ 0), z0)) . g0 . fromJust $ note1- ts = showFFloat (Just 4) (abs y) "" - overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", - showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")- overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ((if null ys then id else soxBasicParams ys) ((if V.null vdB then id else (\wwws -> adjust_dbVol wwws (V.unsafeIndex vdB i))) - ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat Nothing noteN "", "vol", - if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"])) "") vec- _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",- showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- if isNothing note1 then overSoXSynthHelp v0- else do - _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",- showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- overSoXSynthHelp v0- overSoXSynthHelp2 v1 vdB- if null ys then mixTest else mixTest2G ys - if compare y 0.0 == GT then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr ""---- | A variant of the 'overSoXSynth2FDN_B6G' where volume adjustment is obtained from a Ukrainian text.-overSoXSynth2FDN_B6GS :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> String -> V.Vector Double -> String -> String -> IO ()-overSoXSynth2FDN_B6GS f (x, y, limB) j v5 xs vdB ys xxs- | V.null . convertToProperUkrainian $ xxs = putStrLn "You provided no information to obtain volume adjustment! "- | otherwise = overSoXSynth2FDN_B6G f (x, y, limB) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs)---- | Uses additional 'Int' parameters. The first one is a number of enka (see 'nkyT'). The second one defines, to which n-th elements set--- (see 'nkyT') belongs the obtained higher notes in the intervals. To obtain reasonable results, please, use for the first one 2, 3, 4, 6, 9, or 12.--- The first 'String' parameter is used to produce durations of the notes. The second one is used to define intervals. The first 'Double' parameter is a--- basic sound duration, it defines tempo of the melody in general. The second one is a limit for frequencies difference in Hz to be filtered out from the--- resulting sound. It is considered to be from the range @[0.1..10.0]@.-overSoXSynthGen2FDN_B :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Double -> String -> String -> IO ()-overSoXSynthGen2FDN_B file m ku f y limB zs wws = overSoXSynthGen2FDN_Sf3G file m ku f y limB zs wws overSoXSynth2FDN_B---- | Similar to 'overSoXSynth2FDN' but it does not make any normalizing transformations with the 'V.Vector' argument. To be used properly, it is needed--- that every second element in the tuple in the 'V.Vector' argument must be in the range [-1.0..1.0] and every first element must be in between--- 16.351597831287414 and 7902.132820097988 (Hz). An 'Int' parameter is used to define an interval. To obtain compatible with versions prior to--- 0.20.0.0 behaviour, use for the 'Int' 0.------ Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function.--- But for a lot of functions this works well.--- --- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_S'.-overSoXSynth2FDN_S :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()-overSoXSynth2FDN_S f (x, y) j zs = overSoXSynth2FDN_S2G f (x, y) j zs V.empty []---- | Generalized version of the 'overSoXSynth2FDN_S' with the additional volume adjustment in dB for overtones given by 'V.Vector' of 'Double'.-overSoXSynth2FDN_S1G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> IO ()-overSoXSynth2FDN_S1G f (x, y) j zs vdB = overSoXSynth2FDN_S2G f (x, y) j zs vdB []- --- | Generalized version of the 'overSoXSynth2FDN_S1G' with a possibility to specify sound quality parameters using the second 'String' argument.--- For more information, please, refer to 'soxBasicParams'.-overSoXSynth2FDN_S2G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> String -> IO ()-overSoXSynth2FDN_S2G f (x, y) j zs vdB ys- | V.null . convertToProperUkrainian $ zs = overSoXSynth x- | otherwise = do- let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- l0 = length zs- note1 = dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) note0- v0 = f note0- v1 = maybe V.empty f note1- ts = showFFloat (Just 4) (abs y) ""- _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",- showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- if isNothing note1 then partialTest_k2G v0 0 ts vdB ys- else do - _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",- showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- partialTest_k2G v0 0 ts vdB ys- partialTest_k2G v1 1 ts vdB ys- if null ys then mixTest else mixTest2G ys - --- | Generalized version of the 'overSoXSynth2FDN_S2G' where you specify your own 'Intervals'. For more information, please, refer --- to 'intervalsFromStringG'.-overSoXSynth2FDN_S5G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> IO ()-overSoXSynth2FDN_S5G f (x, y) j v5 vdB ys- | V.null v5 = overSoXSynth x- | otherwise = do- let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- l0 = V.length v5- note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0- v0 = f note0- v1 = maybe V.empty f note1- ts = showFFloat (Just 4) (abs y) ""- _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",- showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- if isNothing note1 then partialTest_k2G v0 0 ts vdB ys- else do - _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",- showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- partialTest_k2G v0 0 ts vdB ys- partialTest_k2G v1 1 ts vdB ys- if null ys then mixTest else mixTest2G ys ---- | Generalized variant of the 'overSoXSynth2FDN_S5G' with afterwards 'apply6G' usage. Arguments for the latter is the three last function arguments.-overSoXSynth2FDN_S6G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> Double -> IO ()-overSoXSynth2FDN_S6G f (x, y) j v5 vdB ys vol- | V.null v5 = overSoXSynth x- | otherwise = do- let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- l0 = V.length v5- note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0- v0 = f note0- v1 = maybe V.empty f note1- ts = showFFloat (Just 4) (abs y) ""- _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",- showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- if isNothing note1 then partialTest_k2G v0 0 ts vdB ys- else do - _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",- showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""- partialTest_k2G v0 0 ts vdB ys- partialTest_k2G v1 1 ts vdB ys- if null ys then mixTest else mixTest2G ys - if compare y 0.0 == GT then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr ""- --- | A variant of the 'overSoXSynth2FDN_S6G' where volume adjustment is obtained from a Ukrainian text.-overSoXSynth2FDN_S6GS :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> String -> V.Vector Double -> String -> String -> IO ()-overSoXSynth2FDN_S6GS f (x, y) j v5 xs vdB ys xxs- | V.null . convertToProperUkrainian $ xxs = putStrLn "You provided no information to obtain volume adjustment! "- | otherwise = overSoXSynth2FDN_S6G f (x, y) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs)---- | Similar to 'overSoXSynthGen2FDN', but instead of 'overSoXSynth2FDN' uses 'overSoXSynth2FDN_S' function. Note that the first 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthGen2FDN_SG :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> - ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()-overSoXSynthGen2FDN_SG file m ku f y zs wws h = do- n <- duration1000 file- overSoXSynthGen2FDN_SG4G file m ku f y (str2DurationsDef n zs y) wws h---- | Generalized version of the 'overSoXSynthGen2FDN_SG' where instead of using a Ukrainian text to specify a durations for the sounds (and a rhythm --- respectively) you provide your own rhythm as 'Durations'. Positive values correspond to durations of the sounds generated --- and negative values -- to durations of the pauses respectively. Please, use a function @h :: ((Double -> OvertonesO) -> (Double, Double) -> --- Int -> String -> IO ())@ such that it can create for the given values accorgingly sounds and pauses. Otherwise, please, check whether at --- least it can deal with such arguments without errors. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthGen2FDN_SG4G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Durations -> String -> - ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()-overSoXSynthGen2FDN_SG4G file m ku f y v2 wws h = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- zeroN = numVZeroesPre vecB in V.imapM_ (\j x -> do- h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws- renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult ---- | Generalized version of the 'overSoXSynthGen2FDN_SG4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthGen2FDN_SG4GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Durations -> String -> - ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()-overSoXSynthGen2FDN_SG4GPar file params f y v2 wws h = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- zeroN = numVZeroesPre vecB in V.imapM_ (\j x -> do- h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws- renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult ---- | Auxiliary function to get from a sound file specified a duration parameter @n@ that can be used further.-duration1000 :: FilePath -> IO Int-duration1000 file = fmap (\t -> truncate (t / 0.001)) . durationA $ file---- | A variant of the 'overSoXSynthGen2FDN_SG4G' where instead of providing your own durations as 'Durations' you use a Ukrainian text and --- a function treats each symbol in it as a duration parameter with its sign. Positive values correspond to durations of the sounds generated --- and negative values -- to durations of the pauses respectively. Please, use a function @h :: ((Double -> OvertonesO) -> (Double, Double) -> --- Int -> String -> IO ())@ such that it can create for the given values accorgingly sounds and pauses. Otherwise, please, check whether at --- least it can deal with such arguments without errors.-overSoXSynthGen2FDN_SG4GS :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> - ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()-overSoXSynthGen2FDN_SG4GS file m ku f y zs = overSoXSynthGen2FDN_SG4G file m ku f y (str2Durations zs y)---- | 6G generalized variant of the 'overSoXSynthGen2FDN_SG4G' with volume adjustments given by 'Strengths'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthGen2FDN_SG6G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Durations -> String -> - ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> Strengths -> Double -> IO ()-overSoXSynthGen2FDN_SG6G file m ku f y v2 wws h v6 limV- | V.null v6 = putStrLn "You did not provide a volume adjustments vector! "- | otherwise = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- zeroN = numVZeroesPre vecB in V.imapM_ (\j x -> do- h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws- renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav"- apply6GSilentFile ("result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") limV (V.unsafeIndex v6 (j `rem` V.length v6))) vecB- endFromResult ---- | Generalized version of the 'overSoXSynthGen2FDN_SG6G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthGen2FDN_SG6GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Durations -> String -> - ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> Strengths -> Double -> IO ()-overSoXSynthGen2FDN_SG6GPar file params f y v2 wws h v6 limV- | V.null v6 = putStrLn "You did not provide a volume adjustments vector! "- | otherwise = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- zeroN = numVZeroesPre vecB in V.imapM_ (\j x -> do- h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws- renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav"- apply6GSilentFile ("result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") limV (V.unsafeIndex v6 (j `rem` V.length v6))) vecB- endFromResult ---- | A variant of the 'overSoXSynthGen2FDN_SG6G' where 'Strengths' are obtained from a Ukrainian text and 'str2Volume'.-overSoXSynthGen2FDN_SG6GS :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> - ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> String -> Double -> IO ()-overSoXSynthGen2FDN_SG6GS file m ku f y zs wws h zzs = overSoXSynthGen2FDN_SG6G file m ku f y (str2Durations zs y) wws h (str2Volume zzs) ---- | A variant of the 'overSoXSynthGen2FDN_SG6GS' where 'Strengths' are obtained from the same Ukrainian text as also 'Durations' so the last --- 'String' argument is omitted (it is equal to the first one). Helps to create a speech-like composition.-overSoXSynthGen2FDN_SG6GSu :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> - ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> Double -> IO ()-overSoXSynthGen2FDN_SG6GSu file m ku f y zs wws h = overSoXSynthGen2FDN_SG6G file m ku f y (str2Durations zs y) wws h (str2Volume zs)---- | A default way to get 'Durations' for the sounds up to 0.35.2.0 version of the package including. It is based on the number of Ukrainian --- sounds representations (see, 'convertToProperUkrainian') in a Ukrainian syllables or somewhat generated by the same rules as they. --- The rhythm using the function is very often not binary but its ratios are almost always a ratios of the small natural numbers (1, 2, 3, 4, 5, 6, 7 etc.).-str2DurationsDef :: Int -> String -> Double -> Durations-str2DurationsDef n zs y = - let (t, ws) = splitAt 1 . syllableStr n $ zs in V.map (\yy -> y * fromIntegral (yy * length ws) / fromIntegral (head t)) . V.fromList $ ws ---- | Generalized variant of the 'overSoXSynthGen2FDN_SG' with a possibility to specify with the third 'String' argument sound quality parameters.--- Besides, the second from the end argument (a function) needs to be one more argument -- just also 'String'. --- For more information, please, refer to 'soxBasicParams'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthGen2FDN_SG2G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> ((Double -> OvertonesO) ->- (Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()-overSoXSynthGen2FDN_SG2G file m ku f y zs wws h ys = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do- h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws ys- renameFile ("result." ++ if drop 3 ys == "f" then "flac" else "wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++- if drop 3 ys == "f" then ".flac" else ".wav") vecB- endFromResult2G ys ---- | Generalized version of the 'overSoXSynthGen2FDN_SG2G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthGen2FDN_SG2GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> String -> String -> ((Double -> OvertonesO) ->- (Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()-overSoXSynthGen2FDN_SG2GPar file params f y zs wws h ys = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do- h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws ys- renameFile ("result." ++ if drop 3 ys == "f" then "flac" else "wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++- if drop 3 ys == "f" then ".flac" else ".wav") vecB- endFromResult2G ys ---- | Similar to 'overSoXSynthGen2FDN', but instead of 'overSoXSynth2FDN' uses 'overSoXSynth2FDN_S' function. -overSoXSynthGen2FDN_S :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()-overSoXSynthGen2FDN_S file m ku f y zs wws = overSoXSynthGen2FDN_SG file m ku f y zs wws overSoXSynth2FDN_S---- | Similar to 'overSoXSynth2FDN_S' but additionally the program filters out from the resulting 'V.Vector' after \"f\" application values that are smaller--- by absolute value than 0.001. An 'Int' parameter is used to define an interval. To obtain compatible with versions prior to--- 0.20.0.0 behaviour, use for the 'Int' 0.------ Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function.--- But for a lot of functions this works well.--- --- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_Sf'.-overSoXSynth2FDN_Sf :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()-overSoXSynth2FDN_Sf f (x, y) = overSoXSynth2FDN_Sf3 f (x, y, 0.001)---- | Generalized variant of the 'overSoXSynth2FDN_Sf' with a possibility to adjust volume using 'adjust_dbVol'. 'V.Vector' of 'Double' is--- used to specify adjustments in dB. For more information, please, refer to 'adjust_dbVol'.-overSoXSynth2FDN_Sf1G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> IO ()-overSoXSynth2FDN_Sf1G f (x, y) = overSoXSynth2FDN_Sf31G f (x, y, 0.001)---- | Generalized variant of the 'overSoXSynth2FDN_Sf1G' with a possibility to specify sound quality using the second 'String' argument.--- For more information, please, refer to 'soxBasicParams'.-overSoXSynth2FDN_Sf2G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> String -> IO ()-overSoXSynth2FDN_Sf2G f (x, y) = overSoXSynth2FDN_Sf32G f (x, y, 0.001)---- | Similar to 'overSoXSynthGen2FDN_S', but instead of 'overSoXSynth2FDN_S' uses 'overSoXSynth2FDN_Sf' function. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthGen2FDN_Sf :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()-overSoXSynthGen2FDN_Sf file m ku f y zs wws = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do- overSoXSynth2FDN_Sf f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws- renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult - --- | Generalized version of the 'overSoXSynthGen2FDN_Sf' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthGen2FDN_SfPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()-overSoXSynthGen2FDN_SfPar file params f y zs wws = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do- overSoXSynth2FDN_Sf f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws- renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult ---- | Similar to 'overSoXSynth2FDN_S' but additionally the program filters out from the resulting 'V.Vector' after \"f\" application values that are smaller--- than the third 'Double' parameter by an absolute value in the triple of @Double@'s. An 'Int' parameter is used to define an interval. To obtain compatible--- with versions prior to 0.20.0.0 behaviour, use for the 'Int' 0.------ Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function.--- But for a lot of functions this works well.--- --- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_Sf3'.-overSoXSynth2FDN_Sf3 :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()-overSoXSynth2FDN_Sf3 f (x, y, t0) j zs = overSoXSynth2FDN_Sf32G f (x, y, t0) j zs V.empty []- --- | Generalized variant of the 'overSoXSynth2FDN_Sf3' function with a possibility to adjust volume using 'adjust_dBVol'. 'V.Vector' of 'Double'--- specifies the needed adjustments in dB.-overSoXSynth2FDN_Sf31G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> V.Vector Double -> IO ()-overSoXSynth2FDN_Sf31G f (x, y, t0) j zs vdB = overSoXSynth2FDN_Sf32G f (x, y, t0) j zs vdB []---- | Generalized variant of the 'overSoXSynth2FDN_Sf31G' with a possibility to specify sound quality using the second 'String' parameter.--- For more information, please, refer to 'soxBasicParams'.-overSoXSynth2FDN_Sf32G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> V.Vector Double -> String -> IO ()-overSoXSynth2FDN_Sf32G f (x, y, t0) j zs vdB ys- | V.null . convertToProperUkrainian $ zs = overSoXSynth x- | otherwise = do- let l0 = length zs- soundGenF32G (V.fromList [\x -> closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0),\x -> fromMaybe (V.unsafeIndex notes 0)- (dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) (closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)))])- (V.replicate 2 x) (V.fromList [1,V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))]) f (x, y, t0) j vdB ys- if null ys then mixTest else mixTest2G ys---- | Generalized variant of the 'overSoXSynth2FDN_Sf31G' with a possibility to specify sound quality using the second 'String' parameter.--- For more information, please, refer to 'soxBasicParams'.-overSoXSynth2FDN_Sf35G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> IO ()-overSoXSynth2FDN_Sf35G f (x, y, t0) j v5 vdB ys- | V.null v5 = overSoXSynth x- | otherwise = do- let l0 = V.length v5- soundGenF32G (V.fromList [\x -> closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0),\x -> fromMaybe (V.unsafeIndex notes 0)- (dNote (V.unsafeIndex v5 (abs (j `rem` l0))) (closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)))])- (V.replicate 2 x) (V.fromList [1,V.unsafeIndex v5 (abs (j `rem` l0))]) f (x, y, t0) j vdB ys- if null ys then mixTest else mixTest2G ys ---- | Generalized variant of the 'overSoXSynth2FDN_Sf35G' with afterwards 'apply6G' usage.-overSoXSynth2FDN_Sf36G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> Double -> IO ()-overSoXSynth2FDN_Sf36G f (x, y, t0) j v5 vdB ys vol- | V.null v5 = overSoXSynth x- | otherwise = do- let l0 = V.length v5- soundGenF32G (V.fromList [\x -> closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0),\x -> fromMaybe (V.unsafeIndex notes 0)- (dNote (V.unsafeIndex v5 (abs (j `rem` l0))) (closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)))])- (V.replicate 2 x) (V.fromList [1,V.unsafeIndex v5 (abs (j `rem` l0))]) f (x, y, t0) j vdB ys- if null ys then mixTest else mixTest2G ys - if compare y 0.0 == GT then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr ""---- | A variant of the 'overSoXSynth2FDN_Sf36G' where volume adjustment is obtained from a Ukrainian text.-overSoXSynth2FDN_Sf36GS :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> String -> V.Vector Double -> String -> String -> IO ()-overSoXSynth2FDN_Sf36GS f (x, y, t0) j v5 xs vdB ys xxs- | V.null . convertToProperUkrainian $ xxs = putStrLn "You provided no information to obtain volume adjustment! "- | otherwise = overSoXSynth2FDN_Sf36G f (x, y, t0) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs)--helpF1 :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> V.Vector (Maybe Double)-helpF1 vf vd =- V.map (\(f1,x,i2) ->- case i2 of- 0 -> Nothing- _ -> Just $ f1 x) . V.zip3 vf vd--helpF0 :: Int -> String-helpF0 =- getBFst' ("ZZ0",V.fromList . zip [0..] $ (map (:[]) "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++ concatMap (\z -> map ((z:) . (:[])) "ABCDEFGHIJKLMNOPQRSTUVWXYZ")- "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) ---- | Can generate multiple notes with their respective overtones that are played simultaneously (e. g. it can be just one note with overtones,--- an interval with overtones, an accord with overtones etc.). This allows to get a rather complex or even complicated behaviour to obtain expressive--- and rich sound.-soundGenF3 :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> IO ()-soundGenF3 vf vd vi f (x, y, t0) j = soundGenF32G vf vd vi f (x, y, t0) j V.empty []---- | Generalized variant of the 'soundGenF3' with volume adjustment in dB given by the second @Vector Double@ for the overtones.-soundGenF31G :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> (Double -> OvertonesO) -> (Double, Double, Double) -> Int ->- V.Vector Double -> IO ()-soundGenF31G vf vd vi f (x, y, t0) j vdB = soundGenF32G vf vd vi f (x, y, t0) j vdB [] ---- | Generalized variant of the 'soundGenF31G' with a possibility to specify sound quality using the 'String' argument. For more information,--- please, refer to 'soxBasicParams'.-soundGenF32G :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> (Double -> OvertonesO) -> (Double, Double, Double) -> Int ->- V.Vector Double -> String -> IO ()-soundGenF32G vf vd vi f (x, y, t0) j vdB ys = do- let vD = helpF1 vf vd vi -- Vector of notes played simultaneously (e. g. just one, interval, accord etc.)- vDz = V.mapMaybe id vD -- The previous one without Nothings and Justs- ilDz = V.length vDz - 1- vNotes = doubleVecFromVecOfDouble f t0 (V.map Just vDz) -- Vector of vectors of pairs (freq,ampl) -- notes and their absence (V.empty) with overtones- ts = showFFloat (Just 4) (abs y) "" -- duration of the sound to be generated- V.imapM_ (\i note1 -> do- _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ((if V.null vdB - then id else (\wwws -> adjust_dbVol wwws (V.unsafeIndex vdB i))) ["-r22050", "-n", "test" ++ helpF0 i ++ ".wav", "synth",ts,- "sine", showFFloat Nothing (V.unsafeIndex vDz i) "","vol", if compare y 0.0 == GT then "1.0" else "0"])) ""- partialTest_k2G (V.unsafeIndex vNotes i) i ts vdB ys) vDz ---- | Similar to 'overSoXSynthGen2FDN_S', but instead of 'overSoXSynth2FDN_S' uses 'overSoXSynth2FDN_Sf3' function. -overSoXSynthGen2FDN_Sf3 :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Double -> String -> String -> IO ()-overSoXSynthGen2FDN_Sf3 file m ku f y t0 zs wws = overSoXSynthGen2FDN_Sf3G file m ku f y t0 zs wws overSoXSynth2FDN_Sf3---- | Similar to 'overSoXSynthGen2FDN_S', but instead of 'overSoXSynth2FDN_S' uses 'overSoXSynth2FDN_Sf3' function. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthGen2FDN_Sf3G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Double -> String -> String ->- ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()) -> IO ()-overSoXSynthGen2FDN_Sf3G file m ku f y t0 zs wws h = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do- h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2))), t0) j wws- renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult---- | Generalized version of the 'overSoXSynthGen2FDN_Sf3G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthGen2FDN_Sf3GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Double -> String -> String ->- ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()) -> IO ()-overSoXSynthGen2FDN_Sf3GPar file params f y t0 zs wws h = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do- h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2))), t0) j wws- renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult ---- | Generalized variant of the 'ovorSoXSynthGen2FDN_Sf3G' with a possibility to specify sound quality with the third 'String' argument.--- Besides, the second from the end argument (a function) needs to be one more argument -- just also 'String'. --- For more information, please, refer to 'soxBasicParams'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it --- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.-overSoXSynthGen2FDN_Sf3G2G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Double -> String -> String ->- ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()-overSoXSynthGen2FDN_Sf3G2G file m ku f y t0 zs wws h ys = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do- h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2))), t0) j wws ys- renameFile ("result." ++ if drop 3 ys == "f" then "flac" else "wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ if drop 3 ys == "f"- then ".flac" else ".wav") vecB- endFromResult2G ys ---- | Generalized version of the 'overSoXSynthGen2FDN_Sf3G2G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-overSoXSynthGen2FDN_Sf3G2GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Double -> String -> String ->- ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()-overSoXSynthGen2FDN_Sf3G2GPar file params f y t0 zs wws h ys = do- n <- duration1000 file- vecA <- freqsFromFile file n- let vecB = liftInParamsV params . V.map fromIntegral $ vecA- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do- h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2))), t0) j wws ys- renameFile ("result." ++ if drop 3 ys == "f" then "flac" else "wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ if drop 3 ys == "f"- then ".flac" else ".wav") vecB- endFromResult2G ys ---- | Function to get from the number of semi-tones and a note a 'Maybe' note for the second lower note in the interval if any. If there is--- no need to obtain such a note, then the result is 'Nothing'.-dNote :: Int -> Double -> Maybe Double-dNote n note- | n == 0 || compare note (V.unsafeIndex notes 0) == LT || compare note (V.unsafeIndex notes 107) == GT = Nothing- | otherwise = Just (note / 2 ** (fromIntegral n / 12))---- | 'V.Vector' of musical notes in Hz.-notes :: V.Vector Double--- notes V.! 57 = 440.0 -- A4 in Hz-notes = V.generate 108 (\t -> 440 * 2 ** (fromIntegral (t - 57) / 12))---- | Function returns either the nearest two musical notes if frequency is higher than one for C0 and lower than one for B8--- or the nearest note duplicated in a tuple.-neighbourNotes :: Double -> V.Vector Double -> (Double, Double)-neighbourNotes x v- | compare x (V.unsafeIndex v 0) /= GT = (V.unsafeIndex v 0, V.unsafeIndex v 0)- | compare x (V.unsafeIndex v (V.length v - 1)) /= LT = (V.unsafeIndex v (V.length v - 1), V.unsafeIndex v (V.length v - 1))- | compare (V.length v) 2 == GT = if compare x (V.unsafeIndex v (V.length v `quot` 2)) /= GT- then neighbourNotes x (V.unsafeSlice 0 (V.length v `quot` 2 + 1) v)- else neighbourNotes x (V.unsafeSlice (V.length v `quot` 2) (V.length v - (V.length v `quot` 2)) v)- | otherwise = (V.unsafeIndex v 0, V.unsafeIndex v (V.length v - 1))---- | Returns the closest note to the given frequency in Hz. -closestNote :: Double -> Double-closestNote x- | compare x 0.0 == GT =- let (x0, x2) = neighbourNotes x notes- r0 = x / x0- r2 = x2 / x in - if compare r2 r0 == GT- then x0- else x2- | otherwise = 0.0---- | Additional function to prepend zeroes to the given 'String'. The number of them are just that one to fulfill the length to the given 'Int' parameter.-prependZeroes :: Int -> String -> String -prependZeroes n xs - | if compare n 0 /= GT || null xs then True else compare n (length xs) /= GT = xs- | otherwise = replicate (n - length xs) '0' ++ xs-{-# INLINE prependZeroes #-} --nOfZeroesLog :: Int -> Maybe Int-nOfZeroesLog x- | compare x 0 /= GT = Nothing- | otherwise = Just (truncate (logBase 10 (fromIntegral x)) + 1)-{-# INLINE nOfZeroesLog #-} ---- | Is a minimal number of decimal places that are just enough to represent a length of the 'V.Vector' given. For an 'V.empty' returns 0.-numVZeroesPre :: V.Vector a -> Int-numVZeroesPre v = fromMaybe (0 :: Int) (nOfZeroesLog . V.length $ v)-{-# INLINE numVZeroesPre #-} ---- | Function is used to generate a rhythm of the resulting file \'end.wav\' from the Ukrainian text and a number of sounds either in the syllables or in the words without vowels.-syllableStr :: Int -> String -> [Int]-syllableStr n xs =- let ps = take n . cycle . concat . sylLengthsP2 . syllablesUkrP $ xs- y = sum ps in- case y of- 0 -> [0]- _ -> y:ps ---- | Similarly to 'liftInOctaveV' returns a 'V.Vector' 'Double' (actually frequencies) for the n-th elements set of notes (see 'nkyT') instead of octaves.--- A second 'Int' parameter defines that @n@. -liftInEnkuV :: Int -> Int -> V.Vector Double -> V.Vector Double-liftInEnkuV n ku = V.mapMaybe (liftInEnku n ku)---- | Similarly to 'liftInOctave' returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT').--- A second 'Int' parameter defines that @n@. Not all pairs return 'Just' @x@. -liftInEnku :: Int -> Int -> Double -> Maybe Double-liftInEnku n ku x- | compare n 0 == LT || compare n ((108 `quot` ku) - 1) == GT = Nothing- | getBFst' (False, V.fromList . zip [2,3,4,6,9,12] $ repeat True) ku && compare (closestNote x) 24.4996 == GT =- case compare (fromJust . whichEnka ku $ x) n of- EQ -> Just (closestNote x)- LT -> let z = logBase 2.0 (V.unsafeIndex notes (n * ku) / closestNote x)- z1 = truncate z in- if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001- then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) (enkuUp ku) $ closestNote x)- else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) (enkuUp ku) $ closestNote x)- _ -> let z = logBase 2.0 (closestNote x / V.unsafeIndex notes (n * ku))- z1 = truncate z in- if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001- then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) (enkuDown ku) $ closestNote x)- else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) (enkuDown ku) $ closestNote x)- | otherwise = Nothing---- | Similarly to 'whichOctave' returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT').--- An 'Int' parameter defines that @n@.-whichEnka :: Int -> Double -> Maybe Int-whichEnka n x- | getBFst' (False,V.fromList . zip [2,3,4,6,9,12] $ repeat True) n && compare (closestNote x) 24.4996 == GT = (\t ->- case isJust t of - True -> fmap (\z ->- case z of- 0 -> z- _ -> z - 1) t- _ -> Just ((108 `quot` n) - 1)) . V.findIndex (\(t1, t2) -> compare (closestNote x) t1 == LT) $ nkyT n- | otherwise = Nothing---- | Returns an analogous note in the higher n-th elements set (its frequency in Hz) (see 'nkyT'). An 'Int' parameter defines this @n@.-enkuUp :: Int -> Double -> Double-enkuUp n x- | getBFst' (False, V.fromList . zip [2..11] $ repeat True) n = 2 ** (fromIntegral n / 12) * x- | otherwise = 2 * x-{-# INLINE enkuUp #-} ---- | Returns an analogous note in the lower n-th elements set (its frequency in Hz) (see 'nkyT'). An 'Int' parameter defines this @n@.-enkuDown :: Int -> Double -> Double-enkuDown n x- | getBFst' (False, V.fromList . zip [2..11] $ repeat True) n = 2 ** (fromIntegral (-n) / 12) * x- | otherwise = x / 2-{-# INLINE enkuDown #-}------------------------------------------------------------------------------------------------------------------------ | Function is used to get numbers of intervals from a Ukrainian 'String'. It is used internally in the 'uniqOverSoXSynthN4' function.-intervalsFromString :: String -> Intervals-intervalsFromString = vStrToVIntG defInt . convertToProperUkrainian---- | 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)---- | Generatlized version of the 'vStrToVInt' with a possibility to specify your own 'Intervals'.-vStrToVIntG :: Intervals -> V.Vector String -> Intervals-vStrToVIntG v = V.map (strToIntG v)---- | 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 #-}---- | Default values for 'strToInt'. All the intervals are not greater than one full octave.-defInt :: Intervals-defInt = V.fromList [12,4,7,3,4,5,5,12,3,8,12,7,10,7,7,7,12,10,7,10,2,12,2,2,11,11,1,12,9]-{-# INLINE defInt #-}---- | Generatlized version of the 'strToInt' with a possibility to specify your own 'Intervals'.-strToIntG :: Intervals -> String -> Int-strToIntG v =- getBFst' (0, V.zip (V.fromList ["а","б","в","г","д","дж","дз","е","ж","з","и","й","к","л","м","н","о","п","р","с","т","у","ф","х","ц","ч","ш",- "і","ґ"]) v)-{-# INLINE strToIntG #-}--------------------------------------------------------------------------------------------------------------------------- | Arithmetic average for the 'V.Vector' is used as a weight for a duration. -doublesAveragedA :: V.Vector Double -> Double -> V.Vector Double-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 Double -> Double -> V.Vector Double-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 -> Double -> Durations-durationsAver = doublesAveragedA---- | 'Strengths' accounting the desired average strength.-strengthsAver :: Strengths -> Double -> Strengths-strengthsAver = doublesAveragedG---- | 'StrengthsDb' accounting the desired average strength in dB.-strengthsDbAver :: StrengthsDb -> Double -> 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 -> Double -> 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 'Double' that is used inside 'str2Durations'.-str2Durat1 :: String -> Double-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 'Double' that is used inside 'str2Volume'.-str2Vol1 :: String -> Double-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 -> Double -> 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---- | Apply volume adjustment to the sound file. It must not be silent. Otherwise, it leads to likely noise sounding or errors.-apply6Gf :: Double -> FilePath -> IO ()-apply6Gf vol file = soxE file ["norm","vol", showFFloat (Just 4) vol ""]- --- | 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)--apply6GSilentFile :: FilePath -> Double -> Double -> IO ()-apply6GSilentFile file limV vol = do- upp <- upperBnd file- ampL2 <- fmap ((\zz -> read zz::Double) . fst) (selMaxAbs file (0,upp))- if compare (abs ampL2) (abs limV) /= GT then putStr ""- else apply6Gf vol file---- | Variant of the 'apply6G' function which can be applied also to the silent files. Whether a file is silent is defined using the 'Double' argument --- so that if the maximum by absolute value amplitude is less by absolute value than the 'Double' argument then the file is not changed.-apply6G2 :: Strengths -> String -> String -> Double -> 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 -> Double -> IO ()-apply6GS2 xs = apply6G2 (str2Volume xs)----------------------------------------------------------------------------------------------------------------------------- | Returns a 'V.Vector' of tuples with the lowest and highest frequencies for the notes in the sets consisting of @n@ consequential notes--- (including semi-tones). An 'Int' parameter defines this @n@. It can be 2, 3, 4, 6, 9, or 12 (the last one is for default octaves, see 'octavesT').--- So for different valid @n@ you obtain doubles, triples and so on. The function being applied returns a 'V.Vector' of such sets with--- their respective lowest and highest frequencies.-nkyT :: Int -> NotePairs-nkyT n- | getBFst' (False,V.fromList . zip [2,3,4,6,9,12] $ repeat True) n = V.generate (108 `quot` n) (\i -> (V.unsafeIndex notes (i * n),- V.unsafeIndex notes (i * n + (n - 1))))- | otherwise = octavesT---- | Returns a 'V.Vector' of tuples with the lowest and highest frequencies for the notes in the octaves.-octavesT :: NotePairs-octavesT = V.generate 9 (\i -> (V.unsafeIndex notes (i * 12), V.unsafeIndex notes (i * 12 + 11)))---- | For the given frequency it generates a musical sound with a timbre. The main component of the sound includes the lower pure quint,--- which can be in the same octave or in the one with the number lower by one. 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.-overSoXSynth :: Double -> IO ()-overSoXSynth x = do- let note0 = if x /= 0.0 then closestNote (abs x) else V.unsafeIndex notes 0- note1 = pureQuintNote note0- v0 = overTones note0- v1 = overTones note1- overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat Nothing noteN "", "vol", showFFloat Nothing amplN ""] "")- overSoXSynthHelp2 = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))- ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat Nothing noteN "", "vol", showFFloat Nothing amplN ""] "")- _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test01.wav", "synth", "0.5","sine", showFFloat Nothing note0 "", "synth", "0.5","sine", "mix", showFFloat Nothing note1 "", "vol","0.5"] ""- overSoXSynthHelp v0- overSoXSynthHelp2 v1- mixTest ---- | Returns a pure quint lower than the given note.-pureQuintNote :: Double -> Double-pureQuintNote x = x / 2 ** (7 / 12)-{-# INLINE pureQuintNote #-}---- | For the given frequency of the note it generates a 'V.Vector' of the tuples, each one of which contains the harmonics' frequency and amplitude.-overTones :: Double -> OvertonesO-overTones note =- V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.zip (V.generate 1024 (\i ->- note * fromIntegral (i + 2))) $ (V.generate 1024 (\i -> 1 / fromIntegral ((i + 1) * (i + 1))))----------------------------------------------------------------------------------------- | Gets a function @f::Double -> OvertonesO@ that can be used further. Has two variants with usage of 'closestNote' ('Int' argument is greater than 0)v--- and without it ('Int' argument is less than 0). For both cases 'String' must be in a form list of tuples of pairs of 'Double' to get somewhat--- reasonable result. The function @f@ can be shown using a special printing function 'showFFromStrVec'. It is a simplest multiplicative (somewhat--- acoustically and musically reasonable) form for the function that can provide such a result that fits into the given data.------ > let (y,f1) = fromJust (maybeFFromStrVec 1 3583.9783 "[(25.368,0.2486356),(37.259,0.6464867),(486.153,0.374618646),(789.563,0.463486461)]") in (y,f1 3583.9783)--- >--- > (3520.0,[(25.829079975681818,0.2486356),(37.936206670369316,0.6464867),(494.9891484317899,0.374618646),(803.9138234326421,0.463486461)])--- >--- > let (y,f1) = fromJust (maybeFFromStrVec (-1) 3583.9783 "[(25.368,0.2486356),(37.259,0.6464867),(486.153,0.374618646),(789.563,0.463486461)]") in (y,f1 3583.9783)--- > --- > (3583.9783,[(25.368,0.2486356),(37.259,0.6464867),(486.153,0.374618646),(789.563,0.463486461)])--- -maybeFFromStrVec :: Int -> Double -> String -> Maybe (Double,(Double -> V.Vector (Double,Double)))-maybeFFromStrVec n x ys- | n == 0 || null ys = Nothing- | n > 0 = - let y = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- v = readMaybe ys::Maybe (V.Vector (Double,Double))- v2 = fromMaybe V.empty v- v3 = V.map (\(t,w) -> t / y) v2 in- if V.null v3 then Nothing- else Just (y,(\t1 -> V.imap (\i (t2,ampl2) -> ((V.unsafeIndex v3 i) * t1,ampl2)) v2))- | otherwise = - let y = (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- v = readMaybe ys::Maybe (V.Vector (Double,Double))- v2 = fromMaybe V.empty v- v3 = V.map (\(t,w) -> t / y) v2 in- if V.null v3 then Nothing- else Just (y,(\t1 -> V.imap (\i (t2,ampl2) -> ((V.unsafeIndex v3 i) * t1,ampl2)) v2))---- | Gets multiplication coefficients for @f::Double -> Vector (Double,Double)@ from the 'maybeFFromStrVec' with the same arguments.-fVecCoefs :: Int -> Double -> String -> V.Vector Double-fVecCoefs n x ys =- let rs = maybeFFromStrVec n x ys in- case rs of- Nothing -> V.empty- _ ->- let (y,f1) = fromJust rs in- V.map fst (f1 1)---- | Experimental 'show' for @f::Double -> Vector (Double,Double)@ that is used only for visualisation. It is correct only with 'maybeFFromStrVec' or--- equivalent function. Because the shape of the @f@ is known the function can be defined.--- --- > showFFromStrVec (-1) 440 "[(25.358,0.3598),(489.35,0.4588962),(795.35,0.6853)]"--- > --- > "(440.00,(\t -> <(0.05763181818181818 * t, 0.3598),(1.112159090909091 * t, 0.4588962),(1.8076136363636364 * t, 0.6853)>))"--- -showFFromStrVec :: Int -> Double -> String -> String-showFFromStrVec n x ys- | isNothing . maybeFFromStrVec n x $ ys = ""- | otherwise =- let (y,f) = fromJust . maybeFFromStrVec n x $ ys- l = length ("(" ++ (showFFloat Nothing y "") ++ ",(\t -> <(" ++ concat (V.toList . V.map (\z -> (showFFloat Nothing (fst z) $- " * t, " ++ (showFFloat Nothing (snd z) "),("))) $ (f 1))) in take (l - 2) ("(" ++ (showFFloat Nothing y "") ++ ",(\t -> <("- ++ concat (V.toList . V.map (\z -> (showFFloat Nothing (fst z) " * t, " ++ (showFFloat Nothing (snd z) "),("))) $ (f 1))) ++ ">))"---------------------------------------------------------------------------------------------- | 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 1.0 and the mutual ratios of the amplitudes are preserved.-renormF :: OvertonesO -> OvertonesO-renormF v- | V.null v = V.empty- | otherwise =- let v1 = V.fromList . sortBy (\(x1,y1) (x2,y2)-> compare (abs y2) (abs y1)) . V.toList $ v in- 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.-renormFD :: Double -> OvertonesO -> OvertonesO-renormFD ampl0 v- | V.null v = V.empty- | otherwise =- let v1 = V.fromList . sortBy (\(x1,y1) (x2,y2)-> compare (abs y2) (abs y1)) . V.toList $ v in- 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-sameOvertone v- | V.null v = False- | otherwise = V.all (\(x,_) -> x == (fst . V.unsafeIndex v $ 0)) v---- | Similar to 'sameOvertone', except that not the 'V.Vector' is checked but a corresponding list.-sameOvertoneL :: [(Double,Double)] -> Bool-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'. 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)@. 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'. 'fAddFElem' is --- actually a higher-order function, it changes the function @f@ and returns a new one. It can be an interesting task --- (in general) to look at such a function through a prism of notion of operator (mathematical, for example similar to that ones that --- are used for quantum mechanics and quantum field theory). --- @gAdd@ allows not only to insert an element if missing, but to change all the 'OvertonesO' system. So depending on the complexity,--- it can produce rather complex behaviour.-fAddFElem :: (Double, Double) -> (Double -> OvertonesO) -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) ->- (Double -> OvertonesO)-fAddFElem (noteN, amplN) 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' is--- actually a higher-order function, it changes the function @f@ and returns a new one. It can be an interesting task --- (in general) to look at such a function through a prism of notion of operator (mathematical, for example that ones that are used --- for quantum mechanics and quantum field theory). --- @gRem@ allows not only to delete an element if existing, but to change all the 'OvertonesO' system. So depending on the complexity,--- it can produce rather complex behaviour.-fRemoveFElem :: (Double, Double) -> (Double -> OvertonesO) -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> - (Double -> OvertonesO)-fRemoveFElem (noteN, amplN) f gRem t = gRem (noteN, amplN) t f---- | Changes elements of the 'OvertonesO' using two functions. It is a generalization of the 'fAddFElem' and 'fRemoveFElem' functions. For example, if the first --- of the two inner functional arguments acts as 'gAdd01' or similar, then it adds element to the 'OvertonesO', if it acts as 'gRem01', then it removes the element. --- Its behaviour is defined by the 'Double' parameter (meaning frequency, probably), so you can change elements depending on what point it is applied.-fChangeFElem :: (Double, Double) -> Double -> (Double -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO)) -> (Double -> OvertonesO) -> - (Double -> OvertonesO)-fChangeFElem (noteN, amplN) freq h f t = (h freq) (noteN, amplN) t f---- | Example of the function gAdd for the 'fAddFElem'. If the frequency is already in the 'OvertonesO' then the corresponding amplitude is divided--- equally between all the elements with the repeated given frequency from @(Double, Double)@. Otherwise, it is just concatenated to the 'OvertonesO'.-gAdd01 :: (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO-gAdd01 (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 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 = renormFD amplMax . gAdd01 (note,ampl) freq---- | 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 absolute--- 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 = renormFD amplMax . gAdd01 (note,ampl) freq---- | 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 -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) ->- (Double -> OvertonesO)-fAddFElems v 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 -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> - (Double -> OvertonesO)-fRemoveFElems v f gRems t = gRems v t f---- | Similar to 'fChangeFElem', but use another form of the changing function, so it can deal with not only single element of the 'OvertonesO', --- but also with several ones.-fChangeFElems :: OvertonesO -> Double -> (Double -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO)) -> (Double -> OvertonesO) -> - (Double -> OvertonesO)-fChangeFElems v freq h f t = (h freq) 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.map fst) [v1,v2]- v22 = V.filter (<= V.maximum v11) v21 in- if V.null v22 then False- else- let v12 = V.filter (>= V.minimum v21) v11- [v13,v23] = map (V.uniq . V.fromList . sort . V.toList) [v12,v22]- [l1,l2] = map V.length [v13,v23] in compare (V.length . V.uniq . V.fromList . sort . V.toList . V.concat $ [v13,v23]) (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 v22 = V.filter (\(x,_) -> x <= fst (V.maximumBy (\(x1,y) (t,u) -> compare x1 t) v1)) v2 in- if V.null v22 then False- else- let v12 = V.filter (\(x,_) -> x >= fst (V.minimumBy (\(x1,y) (t,u) -> compare x1 t) v2)) v1- [v13,v23] = map (V.uniq . V.fromList . sort . V.toList) [v12,v22]- [l1,l2] = map V.length [v13,v23] in compare (V.length . V.uniq . V.fromList . sort . V.toList . V.concat $ [v13,v23]) (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 = (takeWhile (not . (/= head ys)) ys):h (dropWhile (not . (/= head ys)) ys)- h1 = map (\zs -> (sum . map snd $ zs) / fromIntegral (length zs)) . h- 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 = renormFD amplMax . gAdds01 v0 freq---- | Example of the function @gAdd@. for the 'fAddFElem'. It tries to insert the given ('Double','Double') into the less dense frequency region.-gAdd04 :: (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO-gAdd04 (note,ampl) freq f - | V.null . f $ freq = V.singleton (note,ampl)- | otherwise =- let v1 = V.fromList . sortBy (\(x1,y1) (x2,y2) -> compare x1 x2) . V.toList . f $ freq- v2 = V.zipWith (\(x1,_) (x2,_) -> x2 - x1) v1 (V.unsafeSlice 1 (V.length v1 - 1) v1)- idxMax = V.maxIndex v2- newFreq = (fst (V.unsafeIndex v1 (idxMax + 1)) + fst (V.unsafeIndex v1 idxMax)) / 2 in (newFreq,ampl) `V.cons` v1---- | Example of the function @gRem@ for the 'fRemFElem'. It tries not to remove elements from the less than 6 elements 'OvertonesO' and to remove--- all the elements in the given range with the width of the twice as many as the second 'Double' in the first argument tuple and the centre--- in the first 'Double' in the tuple. Similar to somewhat bandreject filter but with more complex behaviour for the sound to be more complex.-gRem03 :: (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO-gRem03 (note,halfwidth) freq f =- let v1 = V.filter (\(x,y) -> compare (abs (x - note)) halfwidth /= GT) . f $ freq in- if compare (V.length v1) 5 /= GT then renormF . V.generate 5 $ (\i -> (fromIntegral (i + 1) * note, halfwidth / fromIntegral (i + 3))) - else v1- --- | Splits (with addition of the new overtones) a given 'OvertonesO' into a number @n@ (specified by the first 'Int' argument) of 'OvertonesO' --- (represented finally as a 'V.Vector' of them respectively) so that all except the first @n@ greatest by the absolute value of the amplitude --- tuples of Doubles are considered overtones for the greatest by the absolute value one in the given 'OvertonesO' and all the next @n - 1@ --- are treated as the greatest by the absolute value and each of them produces the similar by the @f :: Double -> OvertonesO@ function overtones.--- --- It is expected to obtain by such a conversion a splitted one sound into several simultaneous similar ones with different heights. --- To provide a rich result, the given first argument must be strictly less than the length of the given 'OvertonesO' minus one.-splitO :: Int -> OvertonesO -> V.Vector OvertonesO-splitO n v0 - | compare (V.length v0) (n + 1) == GT = - let v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0- (x0, y0) = V.unsafeIndex v1 0- v2 = V.unsafeSlice 1 (n - 1) v1- v31 = V.map (\t -> (fst t) / x0) v2- v32 = V.map (\t -> (snd t) / y0) v2- v3 = V.zip v31 v32- f1Tup (t1, w2) = V.imap (\ i (u1, u2) -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3- in V.map f1Tup (V.unsafeSlice 0 n v1)- | otherwise = V.singleton v0---- | Splits (with addition of the new overtones) a given 'OvertonesO' into a number of 'OvertonesO' (represented finally as a 'V.Vector' of them repsectively) --- so that it intermediately uses a special function before applying the \"similarization\" splitting function. Is a generalization of the 'splitO', --- which can be considered a 'splitO2' with a first command line argument equals to 'id'.--- --- It is expected to obtain by such a conversion a splitted one sound into several simultaneous similar (less or more, depending on @h :: OvertonesO -> OvertonesO@) --- ones with different heights. To provide a rich result, the given first argument must be strictly less than the length of the given 'OvertonesO' minus one.-splitO2 :: (OvertonesO -> OvertonesO) -> Int -> OvertonesO -> V.Vector OvertonesO-splitO2 h n v0- | compare (V.length v0) (n + 1) == GT = - let v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0- (x0, y0) = V.unsafeIndex v1 0- v2 = V.unsafeSlice 1 (n - 1) v1- v31 = V.map (\t -> (fst t) / x0) v2- v32 = V.map (\t -> (snd t) / y0) v2- v3 = V.zip v31 v32- f1Tup (t1, w2) = V.imap (\ i (u1, u2) -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3- in V.map f1Tup (h . V.unsafeSlice 0 n $ v1)- | otherwise = V.singleton v0---- | Generalized variant of the 'splitO' with the different splitting variants depending on the first two ASCII lower case letters in the 'String' argument.-splitOG1 :: String -> Int -> OvertonesO -> V.Vector OvertonesO-splitOG1 xs n v0 - | compare (V.length v0) (n + 1) == GT = - let c1s = take 2 . filter isAsciiLower $ xs- v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0- (x0, y0) = V.unsafeIndex v1 0 in- case c1s of- "ab" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,n - 1,V.length v0 - n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0) - "ac" -> let (k1,k2,k3,k4) = (1,n - 1,n - 1,V.length v0 - n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0) - "ad" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,0,n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0) - _ -> let (k1,k2,k3,k4) = (1,n - 1,0,n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0) - | otherwise = V.singleton v0---- | Auxiliary function that is used inside 'splitOG1'.-splitHelp1 :: Int -> Int -> Int -> Int -> OvertonesO -> (Double,Double) -> V.Vector OvertonesO-splitHelp1 x1 x2 x3 x4 v00 (y5,y6) = - let v2 = V.unsafeSlice x1 x2 v00- v31 = V.map (\t -> (fst t) / y5) v2- v32 = V.map (\t -> (snd t) / y6) v2- v3 = V.zip v31 v32- f1Tup (t1, w2) = V.imap (\ i (u1, u2) -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3- in V.map f1Tup (V.unsafeSlice x3 x4 v00)---- | Auxiliary function that is used inside 'splitOG2'.-splitHelp2 :: (OvertonesO -> OvertonesO) -> Int -> Int -> Int -> Int -> OvertonesO -> (Double,Double) -> V.Vector OvertonesO-splitHelp2 h1 x1 x2 x3 x4 v00 (y5,y6) = - let v2 = V.unsafeSlice x1 x2 v00- v31 = V.map (\t -> (fst t) / y5) v2- v32 = V.map (\t -> (snd t) / y6) v2- v3 = V.zip v31 v32- f1Tup (t1, w2) = V.imap (\ i (u1, u2) -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3- in V.map f1Tup (h1 . V.unsafeSlice x3 x4 $ v00) ---- | Generalized variant of the 'splitO2' with the different splitting variants depending on the first two ASCII lower case letters in the 'String' argument.-splitOG2 :: (OvertonesO -> OvertonesO) -> String -> Int -> OvertonesO -> V.Vector OvertonesO-splitOG2 h xs n v0- | compare (V.length v0) (n + 1) == GT = - let c1s = take 2 . filter isAsciiLower $ xs- v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0- (x0, y0) = V.unsafeIndex v1 0 in- case c1s of- "ab" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,n - 1,V.length v0 - n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) - "ac" -> let (k1,k2,k3,k4) = (1,n - 1,n - 1,V.length v0 - n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) - "ad" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,0,n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) - _ -> let (k1,k2,k3,k4) = (1,n - 1,0,n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) - | otherwise = V.singleton v0 ---- | Generalized variant of the 'splitOG1' with a possibility to specify a default value for splitting parameters as the first argument --- @(Int,Int,Int,Int)@ and the sorted by the first element in the tuple (actually a 'String') in ascending order 'V.Vector' (the second one). --- Each 'String' in the 'V.Vector' must be unique and consist of lowercase ASCII letters.-splitOG12 :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> String -> Int -> OvertonesO -> V.Vector OvertonesO-splitOG12 (x1,x2,x3,x4) vf xs n v0- | compare (V.length v0) (n + 1) == GT && not (V.null vf) = - let c1s = filter isAsciiLower $ xs- v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0- (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) vf) c1s in - splitHelp1 k1 k2 k3 k4 v1 (x0,y0) - | otherwise = V.singleton v0 ---- | Variant of the 'splitOG12' applied to the unsorted second argument. It sorts it internally. If you specify the already sorted second argument --- then it is better to use 'splitOG12'. Each 'String' in the 'V.Vector' must be unique and consist of lowercase ASCII letters.-splitOG12S :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> String -> Int -> OvertonesO -> V.Vector OvertonesO-splitOG12S (x1,x2,x3,x4) vf xs n v0- | compare (V.length v0) (n + 1) == GT && not (V.null vf) = - let c1s = filter isAsciiLower $ xs- v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0- v2 = V.fromList . sortBy (\(x1s,_) (x2s,_) -> compare x1s x2s) . V.toList $ vf- (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) v2) c1s in - splitHelp1 k1 k2 k3 k4 v1 (x0,y0) - | otherwise = V.singleton v0 ---- | Generalized variant of the 'splitOG2' with a possibility to specify a default value for splitting parameters as the first argument --- @(Int,Int,Int,Int)@ and the sorted by the first element in the tuple (actually a 'String') in ascending order 'V.Vector' (the second one). --- Each 'String' in the 'V.Vector' must be unique and consist of lowercase ASCII letters.-splitOG22 :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> (OvertonesO -> OvertonesO) -> String -> Int -> - OvertonesO -> V.Vector OvertonesO-splitOG22 (x1,x2,x3,x4) vf h xs n v0- | compare (V.length v0) (n + 1) == GT && not (V.null vf) = - let c1s = filter isAsciiLower $ xs- v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0- (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) vf) c1s in - splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) - | otherwise = V.singleton v0 - --- | Variant of the 'splitOG22' applied to the unsorted second argument. It sorts it internally. If you specify the already sorted second argument --- then it is better to use 'splitOG22'. Each 'String' in the 'V.Vector' must be unique and consist of lowercase ASCII letters.-splitOG22S :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> (OvertonesO -> OvertonesO) -> String -> Int -> - OvertonesO -> V.Vector OvertonesO-splitOG22S (x1,x2,x3,x4) vf h xs n v0- | compare (V.length v0) (n + 1) == GT && not (V.null vf) = - let c1s = filter isAsciiLower $ xs- v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0- v2 = V.fromList . sortBy (\(x1s,_) (x2s,_) -> compare x1s x2s) . V.toList $ vf- (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) v2) c1s in - splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) - | otherwise = V.singleton v0 ---- | Concatenates a 'V.Vector' of 'OvertonesO' into a single 'OvertonesO'. Can be easily used with 'splitO'.-overConcat :: V.Vector OvertonesO -> OvertonesO-overConcat = V.concat . V.toList------------------------------------------------------------------------------------------------------------------------ | Function can be used to determine to which octave (in the American notation for the notes, this is a number in the note written form,--- e. g. for C4 this is 4) the frequency belongs (to be more exact, the closest note for the given frequency -- see 'closestNote' taking into account--- its lower pure quint, which can lay in the lower by 1 octave). If it is not practical to determine the number, then the function returns 'Nothing'.-whichOctave :: Double -> Maybe Int-whichOctave x- | compare (closestNote x) 24.4996 == GT = (\t ->- case isJust t of - True -> fmap (\z ->- case z of- 0 -> z- _ -> z - 1) t- _ -> Just 8) . V.findIndex (\(t1, t2) -> compare (closestNote x) t1 == LT) $ octavesT- | otherwise = Nothing---- | Generalized version of the 'whichOctave'.-whichOctaveG :: Double -> Maybe Int-whichOctaveG x - | compare (closestNote x) (V.unsafeIndex notes 0) == GT && compare x (V.unsafeIndex notes 107) /= GT = (\t ->- case isJust t of - True -> fmap (\z ->- case z of- 0 -> z- _ -> z - 1) t- _ -> Just 8) . V.findIndex (\(t1, t2) -> compare (closestNote x) t1 == LT) $ octavesT- | otherwise = Nothing---- | A way to get from a 'Params' a corresponding 'V.Vector' of 'Double' (if any) and so to work with them further. May contain some issues --- so please, before production usage check thoroughly. --- For information there were used the following: --- --- https://en.wikipedia.org/wiki/Mode_(music)--- --- https://en.wikipedia.org/wiki/Ukrainian_Dorian_scale--- --- https://en.wikipedia.org/wiki/List_of_musical_scales_and_modes--- --- https://en.wikipedia.org/wiki/Octatonic_scale--- --- several other articles in the English Wikipedia --- --- and in Ukrainian: --- Смаглій Г., Маловик Л. Теорія музики : Підруч. для навч. закл. освіти, культури і мистецтв / Г.А. Смаглій. -- Х. : Вид-во \"Ранок\", 2013. -- 392 с. --- ISBN 978-617-09-1294-7--- -filterInParams :: Params -> Maybe (V.Vector Double)-filterInParams (P3lf n2 nL zs) -- generalized sound series, e. g. the chromatic ones etc.- | all (\n -> compare n 0 /= LT) ([nL,107 - nL - n2,n2 - 2] ++ zs) = - if V.null . V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) i) $ - (V.unsafeSlice nL n2 notes)- then Nothing- else Just (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) i) - (V.unsafeSlice nL n2 notes))- | otherwise = Nothing-filterInParams (P32sf nT n2 nL xs ys) -- dur and moll in various their modifications- | all (\n -> compare n 0 /= LT) [107 - nL - n2,nT,nL,nT - nL,nL + n2 - nT,n2 - 12] = - case xs of - "dur" -> getBFst' (Nothing,V.fromList . zip ["DoubleH","H","Full","Full moll","M","N"] $ fmap Just - [V.ifilter (\i _ -> toneD i nL nT [2,3,6,8,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneD i nL nT [1,3,5,9,10]) - (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12) `notElem` [1,3,5]) - (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12) `notElem` [1,6]) - (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneD i nL nT [1,3,5,9,11]) (V.unsafeSlice nL n2 notes), - V.ifilter (\i _ -> toneD i nL nT [1,3,5,8,10]) (V.unsafeSlice nL n2 notes)]) ys- "moll" -> getBFst' (Nothing,V.fromList . zip ["DoubleH1","H","Full","Full dur","M","N"] $ fmap Just - [V.ifilter (\i _ -> toneD i nL nT [1,4,5,9,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneD i nL nT [1,4,6,9,10]) - (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12) `notElem` [1,4,6]) - (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12) `notElem` [1,6]) - (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneD i nL nT [1,4,6,8,10]) (V.unsafeSlice nL n2 notes), - V.ifilter (\i _ -> toneD i nL nT [1,4,6,9,11]) (V.unsafeSlice nL n2 notes)]) ys- _ -> Nothing- | otherwise = Nothing-filterInParams (P4lsf nT n2 nL zs xs) - | all (\n -> compare n 0 /= LT) ([107 - nL - n2,nT,nL,nT - nL,nL + n2 - nT,n2 - 2] ++ zs) = - case xs of- "ditonic" -> - if (V.length . V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) - i) $ (V.unsafeSlice nL n2 notes)) /= 2 - then Nothing- else - if (V.unsafeIndex notes nT) `V.elem` (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 2 . sortNoDup . filter (< n2) $ zs) $ - replicate n2 True) i) (V.unsafeSlice nL n2 notes))- then Just (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 2 . sortNoDup . filter (< n2) $ zs) $ replicate n2 True) - i) (V.unsafeSlice nL n2 notes))- else Nothing- "tritonic" -> - if (V.length . V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) - i) $ (V.unsafeSlice nL n2 notes)) /= 3 - then Nothing- else - if (V.unsafeIndex notes nT) `V.elem` (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 3 . sortNoDup . filter (< n2) $ zs) $ - replicate n2 True) i) (V.unsafeSlice nL n2 notes))- then Just (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 3 . sortNoDup . filter (< n2) $ zs) $ replicate n2 True) - i) (V.unsafeSlice nL n2 notes))- else Nothing- "tetratonic" -> - if (V.length . V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) - i) $ (V.unsafeSlice nL n2 notes)) /= 4 - then Nothing- else - if (V.unsafeIndex notes nT) `V.elem` (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 4 . sortNoDup . filter (< n2) $ zs) $ - replicate n2 True) i) (V.unsafeSlice nL n2 notes))- then Just (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 4 . sortNoDup . filter (< n2) $ zs) $ replicate n2 True) - i) (V.unsafeSlice nL n2 notes))- else Nothing- "octatonic" -> - if (V.length . V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) - i) $ (V.unsafeSlice nL n2 notes)) /= 8 - then Nothing- else - if (V.unsafeIndex notes nT) `V.elem` (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 8 . sortNoDup . filter (< n2) $ zs) $ - replicate n2 True) i) (V.unsafeSlice nL n2 notes))- then Just (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 8 . sortNoDup . filter (< n2) $ zs) $ replicate n2 True) - i) (V.unsafeSlice nL n2 notes))- else Nothing- _ -> Nothing- | compare nL 0 /= LT && compare nL 107 /= GT && n2 == 1 && xs == "monotonic" = Just (V.singleton (V.unsafeIndex notes nL))- | otherwise = Nothing-filterInParams (P2 nL n2) - | all (\n -> compare n 0 /= LT) [107 - nL - n2,nL,n2 - 2] = Just (V.unsafeSlice nL n2 notes) - | otherwise = Nothing-filterInParams (P2s nL n2 xs) - | all (\n -> compare n 0 /= LT) [107 - nL - n2,nL,n2 - 12] = - getBFst' (Nothing,V.fromList . zip ["Egyptian pentatonic", "Prometheus hexatonic scale", "Ukrainian Dorian scale", "augmented hexatonic scale", - "blues major pentatonic", "blues minor pentatonic", "blues scale", "major hexatonic scale", "major pentatonic", "minor hexatonic scale", - "minor pentatonic", "tritone hexatonic scale", "two-semitone tritone hexatonic scale", "whole tone scale"] $ map Just - [V.ifilter (\i _ -> toneE i nL nL [0,2,5,7,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,2,4,6,9,10]) (V.unsafeSlice nL n2 notes), - V.ifilter (\i _ -> toneE i nL nL [0,2,3,6,7,9,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,3,4,7,8,11]) (V.unsafeSlice nL n2 notes), - V.ifilter (\i _ -> toneE i nL nL [0,2,5,7,9]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,3,5,8,10]) (V.unsafeSlice nL n2 notes), - V.ifilter (\i _ -> toneE i nL nL [0,3,5,6,7,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,3,5,6,7,10]) (V.unsafeSlice nL n2 notes), - V.ifilter (\i _ -> toneE i nL nL [0,2,4,5,7,9]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,2,4,7,9]) (V.unsafeSlice nL n2 notes), - V.ifilter (\i _ -> toneE i nL nL [0,2,3,5,7,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,3,5,7,10]) (V.unsafeSlice nL n2 notes), - V.ifilter (\i _ -> toneE i nL nL [0,1,4,6,7,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,1,3,7,8,9]) (V.unsafeSlice nL n2 notes), - V.ifilter (\i _ -> toneE i nL nL [0,2,4,6,8,10]) (V.unsafeSlice nL n2 notes)]) xs- | otherwise = Nothing-filterInParams (P3sf nT nL n2 xs) - | all (\n -> compare n 0 /= LT) [101 - nL,nT,nL,nT - nL,nL + 6 - nT] && n2 == 6 = - case xs of - "Dorian tetrachord" -> - if (nT - nL) `elem` [0,1,3,5] then Just (V.ifilter (\i _ -> toneE i nL nT [0,1,3,5]) (V.unsafeSlice nL 6 notes)) else Nothing- "Phrygian tetrachord" -> - if (nT - nL) `elem` [0,2,3,5] then Just (V.ifilter (\i _ -> toneE i nL nT [0,2,3,5]) (V.unsafeSlice nL 6 notes)) else Nothing- "Lydian tetrachord" -> - if (nT - nL) `elem` [0,2,4,5] then Just (V.ifilter (\i _ -> toneE i nL nT [0,2,4,5]) (V.unsafeSlice nL 6 notes)) else Nothing- _ -> Nothing- | all (\n -> compare n 0 /= LT) [94 - nL,nT,nL,nT - nL,nL + 13 - nT] && n2 == 13 = - getBFst' (Nothing, V.fromList . zip ["modern Aeolian mode", "modern Dorian mode", "modern Ionian mode", "modern Locrian mode", - "modern Lydian mode", "modern Mixolydian mode", "modern Phrygian mode"] $ fmap (h3 nT n2 nL) [[1,4,6,9,11], [1,4,6,8,11], [1,3,6,8,10], - [2,4,7,9,11], [1,3,5,8,10], [1,3,6,8,11], [2,4,6,9,11]]) xs- | otherwise = Nothing--h3 :: Int -> Int -> Int -> [Int] -> Maybe (V.Vector Double)-h3 nT n2 nL zs - | nT == nL = Just (V.ifilter (\i _ -> toneD i nL nT zs) (V.unsafeSlice nL n2 notes))- | otherwise = Nothing---- | For the list of @a@ from the @Ord@ class it builds a sorted in the ascending order list without duplicates.--- --- > sortNoDup [2,1,4,5,6,78,7,7,5,4,3,2,5,4,2,4,54,3,5,65,4,3,54,56,43,5,2] = [1,2,3,4,5,6,7,43,54,56,65,78]--- -sortNoDup :: Ord a => [a] -> [a]-sortNoDup = sortNoDup' . sort- where sortNoDup' (x:x1@(y:_)) - | x == y = sortNoDup' x1- | otherwise = x:sortNoDup' x1- sortNoDup' (x:_) = [x]- sortNoDup' _ = []---- | Checks whether its first 'Int' argument does not belong to those ones that are included into the list argument on the reminders basis. --- The opposite to 'toneE' with the same arguments.-toneD :: Int -> Int -> Int -> [Int] -> Bool-toneD i nL nT zs = getBFst' (True,V.fromList . zip zs $ replicate 12 False) ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12)---- | Checks whether its first 'Int' argument does belong to those ones that are included into the list argument on the reminders basis. --- The opposite to 'toneD' with the same arguments.-toneE :: Int -> Int -> Int -> [Int] -> Bool-toneE i nL nT zs = getBFst' (False,V.fromList . zip zs $ replicate 12 True) ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12)---- | Analogous to 'liftInEnku' lifts a frequency into a tonality (or something that can be treated alike one) specified by 'Params'. If not --- reasonably one exists then the result is 11440 (Hz).-liftInParams :: Double -> Params -> Double-liftInParams x params - | lengthP params == 0 || (isNothing . whichOctaveG $ x) = 11440.0 - | otherwise = - V.unsafeIndex (fromJust . filterInParams $ params) (V.minIndex . V.map (abs . log . (\t -> t / x)) . V.generate (lengthP params) $ - (\i -> V.unsafeIndex notes (12 * fromJust (whichOctaveG x)) * 2 ** (fromIntegral i / fromIntegral (lengthP params))))---- | Application of the 'liftInParams' to a 'V.Vector'. -liftInParamsV :: Params -> V.Vector Double -> V.Vector Double-liftInParamsV params = V.filter (/= 11440.0) . V.map (\x -> liftInParams x params)---- | Gets a length of the 'V.Vector' of 'Double' being represented as 'Params'. This is a number of the notes contained in the 'Params'.-lengthP :: Params -> Int-lengthP = fromMaybe 0 . fmap V.length . filterInParams---- | Check whether a given 'Double' value (frequency of a note) is in the vector of Doubles that corresponds to the given 'Params'.-elemP :: Double -> Params -> Bool-elemP note = fromMaybe False . fmap (note `V.elem`) . filterInParams---- | Check whether a given 'Double' value (frequency of the closest note to the given frequency) is in the vector of Doubles that --- corresponds to the given 'Params'.-elemCloseP :: Double -> Params -> Bool-elemCloseP note = fromMaybe False . fmap (closestNote note `V.elem`) . filterInParams---- | A way to show not the (somewhat algebraic) structure of the 'Params' (as the usual 'show' does), but the contained frequencies in it. -showD :: Params -> String-showD = show . filterInParams ------------------------------------------------------------------------------------------------------ | Tesing variant of the 'soundGen3G' with predefined three last functional arguments.-testSoundGen2G :: FilePath -> (Double -> OvertonesO) -> Double -> String -> IO ()- ---------------------- - -- f-testSoundGen2G = testSoundGen2GMN (-1) (-1)---- | Tesing variant of the 'soundGen3GMN' with predefined three last functional arguments.-testSoundGen2GMN :: Int64 -> Int64 -> FilePath -> (Double -> OvertonesO) -> Double -> String -> IO ()- ---------------------- - -- f-testSoundGen2GMN m n1 file f y zs = do- vecA0 <- fmap (V.map (`quotRem` 108)) ((if m == (-1) && n1 == (-1) then readFileDoubles else readFileDoublesMN m n1) file) -- >>= print- let n = V.length vecA0- freq0 j = V.unsafeIndex notes (snd . V.unsafeIndex vecA0 $ j `rem` n)- f0 t = V.fromList [(0.05763181818181818 * t, 0.3598),(1.112159090909091 * t, 0.4588962),(2 * t, 0.6853),(3 * t, 0.268),(4 * t, 0.6823),(5 * t, 0.53)]- fA1 j = fAddFElem (freq0 (j + 1),0.5) f0 gAdd04 - fR1 j = fRemoveFElem (freq0 (j + 1),0.5) f0 gRem03- vecB = V.imap (\j r -> (V.unsafeIndex notes (snd r),- case fst r of- 0 -> f0- 1 -> fA1 j- 2 -> fA1 j- 3 -> fA1 j- 4 -> fA1 j- _ -> fR1 j)) vecA0- v2 = str2DurationsDef n zs y - zeroN = numVZeroesPre vecB in V.imapM_ (\j (x,k) -> do- h1 (\u -> k (1.1 * freq0 j)) (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j - renameFile ("result.wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult---- | Generates a sequence of sounds with changing timbre. Uses several functions as parameters. -soundGen3G :: FilePath -> (Double -> OvertonesO) -> Double -> String -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) - -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Double -> OvertonesO) -> IO ()-soundGen3G = soundGen3GMN (-1) (-1)---- | Generates a sequence of sounds with changing timbre. Uses several functions as parameters. To specify how many sounds the resulting files --- will provide, you use first two 'Int64' arguments, the first of which is a number of dropped elements for 'readFileDoubles' and the second one --- is a number of produced sounds (and, respectively, number of taken elements).-soundGen3GMN :: Int64 -> Int64 -> FilePath -> (Double -> OvertonesO) -> Double -> String -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) - -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Double -> OvertonesO) -> IO ()-soundGen3GMN m n1 file f y zs gAdd gRem f0 = do- vecA0 <- fmap (V.map (`quotRem` 108)) ((if m == (-1) && n1 == (-1) then readFileDoubles else readFileDoublesMN m n1) file) -- >>= print- let n = V.length vecA0- freq0 j = V.unsafeIndex notes (snd . V.unsafeIndex vecA0 $ j `rem` n)- fA1 j = fAddFElem (freq0 (j + 1),0.5) f0 gAdd- fR1 j = fRemoveFElem (freq0 (j + 1),0.5) f0 gRem- vecB = V.imap (\j r -> (V.unsafeIndex notes (snd r),- case fst r of- 0 -> f0- 1 -> fA1 j- 2 -> fA1 j- 3 -> fA1 j- 4 -> fA1 j- _ -> fR1 j)) vecA0- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j (x,k) -> do- h1 (\u -> k (1.1 * freq0 j)) (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j - renameFile ("result.wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult---- | Generates a sequence of sounds with changing timbre. Uses several functions as parameters. Unlike the 'soundGen3G', the last two --- functions as arguments for their first argument have not ('Double','Double'), but 'V.Vector' of them so are applied to 'OvertonesO'. To --- provide a generalized functionality, it uses two additional functions @freq0 :: Int -> OvertonesO@ and @proj :: OvertonesO -> OvertonesO@ --- to define the first element to which are applied @gAdds@ and @gRems@ and the way to obtain a internal 'OvertonesO'.--- Besides, it lifts notes into specified with the first two 'Int' arguments enku (see 'liftInEnku'). --- The 'Double' argument is a average duration of the sounds.-soundGen3G_O :: Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) - -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> - (Double -> OvertonesO) -> IO ()-soundGen3G_O = soundGen3G_OMN (-1) (-1)---- | Generalized version of the 'soundGen3G_O' where 'liftInParams' is used instead of lifting with the 'liftInEnku'. This allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-soundGen3G_OPar :: Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) - -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> - (Double -> OvertonesO) -> IO ()-soundGen3G_OPar = soundGen3G_OMNPar (-1) (-1)---- | Generates a sequence of sounds with changing timbre. Uses several functions as parameters. To specify how many sounds the resulting files --- will provide, you use first two 'Int64' arguments, the first of which is a number of dropped elements for 'readFileDoubles' and the second one --- is a number of produced sounds (and, respectively, number of taken elements).-soundGen3G_OMN :: Int64 -> Int64 -> Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) - -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> - (Double -> OvertonesO) -> IO ()-soundGen3G_OMN m1 n1 m ku freq1 file f y zs gAdds gRems freq0 proj f0 = do- vecA0 <- fmap (V.map (`quotRem` 108)) ((if m1 == (-1) && n1 == (-1) then readFileDoubles else readFileDoublesMN m1 n1) file) -- >>= print- let n = V.length vecA0- fA1 j = fAddFElems (proj . freq0 $ j) f0 gAdds- fR1 j = fRemoveFElems (proj . freq0 $ j) f0 gRems- vecB = V.imap (\j r -> (V.unsafeIndex notes (snd r),- case fst r of- 0 -> f0- 1 -> fA1 j- 2 -> fA1 j- 3 -> fA1 j- 4 -> fA1 j- _ -> fR1 j)) vecA0- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j (x,k) -> do- h2 (k x) (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) m ku freq1- renameFile ("result.wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult ---- | Generalized version of the 'soundGen3G_OMN' where 'liftInParams' is used instead of lifting with the 'liftInEnku'. This allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-soundGen3G_OMNPar :: Int64 -> Int64 -> Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) - -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> - (Double -> OvertonesO) -> IO ()-soundGen3G_OMNPar m1 n1 params freq1 file f y zs gAdds gRems freq0 proj f0 = do- vecA0 <- fmap (V.map (`quotRem` 108)) ((if m1 == (-1) && n1 == (-1) then readFileDoubles else readFileDoublesMN m1 n1) file) -- >>= print- let n = V.length vecA0- fA1 j = fAddFElems (proj . freq0 $ j) f0 gAdds- fR1 j = fRemoveFElems (proj . freq0 $ j) f0 gRems- vecB = V.imap (\j r -> (V.unsafeIndex notes (snd r),- case fst r of- 0 -> f0- 1 -> fA1 j- 2 -> fA1 j- 3 -> fA1 j- 4 -> fA1 j- _ -> fR1 j)) vecA0- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j (x,k) -> do- h2Params (k x) (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) params freq1- renameFile ("result.wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult ---- | Generates a sequence of sounds with changing timbre. Is a generalized version of the 'soundGen3G_O', instead of predefined conversion function --- inside, it uses a user-defined one. --- --- > soundGen3G_O = soundGen3G_O2 --- with the first argument --- --- > conversionFII (f0,fA1,fR1) = imap (\j r -> (unsafeIndex notes (snd r),--- --- > case fst r of--- --- > 0 -> f0--- --- > 1 -> fA1 j--- --- > 2 -> fA1 j--- --- > 3 -> fA1 j--- --- > 4 -> fA1 j--- --- > _ -> fR1 j))--- --- -soundGen3G_O2 :: ((Double -> OvertonesO,Int -> Double -> OvertonesO,Int -> Double -> OvertonesO) -> V.Vector (Int,Int) -> - V.Vector (Double,Double -> OvertonesO)) -> Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> - (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> - (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()-soundGen3G_O2 = soundGen3G_O2MN (-1) (-1)---- | Generalized version of the 'soundGen3G_O2' where 'liftInParams' is used instead of lifting with the 'liftInEnku'. This allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-soundGen3G_O2Par :: ((Double -> OvertonesO,Int -> Double -> OvertonesO,Int -> Double -> OvertonesO) -> V.Vector (Int,Int) -> - V.Vector (Double,Double -> OvertonesO)) -> Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> - (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> - (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()-soundGen3G_O2Par = soundGen3G_O2MNPar (-1) (-1)---- | Generates a sequence of sounds with changing timbre. Is a generalized version of the 'soundGen3G_O2'. To specify how many sounds the resulting files --- will provide, you use first two 'Int64' arguments, the first of which is a number of dropped elements for 'readFileDoubles' and the second one --- is a number of produced sounds (and, respectively, number of taken elements).-soundGen3G_O2MN :: Int64 -> Int64 -> ((Double -> OvertonesO,Int -> Double -> OvertonesO,Int -> Double -> OvertonesO) -> V.Vector (Int,Int) -> - V.Vector (Double,Double -> OvertonesO)) -> Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> - (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> - (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()-soundGen3G_O2MN m1 n1 conversionFII m ku freq1 file f y zs gAdds gRems freq0 proj f0 = do- vecA0 <- fmap (V.map (`quotRem` 108)) ((if m1 == (-1) && n1 == (-1) then readFileDoubles else readFileDoublesMN m1 n1) file) -- >>= print- let n = V.length vecA0- fA1 j = fAddFElems (proj . freq0 $ j) f0 gAdds- fR1 j = fRemoveFElems (proj . freq0 $ j) f0 gRems- vecB = conversionFII (f0,fA1,fR1) vecA0- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j (x,k) -> do- h2 (k x) (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) m ku freq1- renameFile ("result.wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult---- | Generalized version of the 'soundGen3G_O2MN' where 'liftInParams' is used instead of lifting with the 'liftInEnku'. This allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-soundGen3G_O2MNPar :: Int64 -> Int64 -> ((Double -> OvertonesO,Int -> Double -> OvertonesO,Int -> Double -> OvertonesO) -> V.Vector (Int,Int) -> - V.Vector (Double,Double -> OvertonesO)) -> Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> - (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> - (Int -> OvertonesO) -> (OvertonesO -> OvertonesO) -> (Double -> OvertonesO) -> IO ()-soundGen3G_O2MNPar m1 n1 conversionFII params freq1 file f y zs gAdds gRems freq0 proj f0 = do- vecA0 <- fmap (V.map (`quotRem` 108)) ((if m1 == (-1) && n1 == (-1) then readFileDoubles else readFileDoublesMN m1 n1) file) -- >>= print- let n = V.length vecA0- fA1 j = fAddFElems (proj . freq0 $ j) f0 gAdds- fR1 j = fRemoveFElems (proj . freq0 $ j) f0 gRems- vecB = conversionFII (f0,fA1,fR1) vecA0- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j (x,k) -> do- h2Params (k x) (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) params freq1- renameFile ("result.wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult ---- | Generates a sequence of sounds with changing timbre. Is a generalized version of the 'soundGen3G_O2', but for the conversion function conversionFII as its --- tuple first argument uses not the tuple of the three functions, but a tuple of three 'V.Vector' of functions of the respective types, that allows to --- specify more comlex behaviour and different variants inside the function itself, not its inner function parts. 'V.Vector' as a data type is used --- instead of more common list because it has similar functionality and besides provides easier and quicker access to its elements. So these are the --- following vectors of functions: @vf :: Vector (Double -> OvertonesO)@ (no changing a function for timbre generation), --- @vfA :: Vector (Int -> Double -> OvertonesO)@ (for \"adding\" overtones to the function for timbre generation), --- and @vfR :: Vector (Int -> Double -> OvertonesO@ (for \"removing\" overtones from the function for timbre generation).--- -soundGen3G_O2G :: ((V.Vector (Double -> OvertonesO),V.Vector (Int -> Double -> OvertonesO),V.Vector (Int -> Double -> OvertonesO)) -> V.Vector (Int,Int) -> - V.Vector (Double,Double -> OvertonesO)) -> V.Vector (Double -> OvertonesO) -> V.Vector (Int -> Double -> OvertonesO) -> V.Vector (Int -> Double -> OvertonesO) -> - Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> - (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> - (Int -> OvertonesO) -> (Double -> OvertonesO) -> IO ()-soundGen3G_O2G = soundGen3G_O2GMN (-1) (-1)---- | Generalized version of the 'soundGen3G_O2G' where 'liftInParams' is used instead of lifting with the 'liftInEnku'. This allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-soundGen3G_O2GPar :: ((V.Vector (Double -> OvertonesO),V.Vector (Int -> Double -> OvertonesO),V.Vector (Int -> Double -> OvertonesO)) -> V.Vector (Int,Int) -> - V.Vector (Double,Double -> OvertonesO)) -> V.Vector (Double -> OvertonesO) -> V.Vector (Int -> Double -> OvertonesO) -> V.Vector (Int -> Double -> OvertonesO) -> - Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> - (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> - (Int -> OvertonesO) -> (Double -> OvertonesO) -> IO ()-soundGen3G_O2GPar = soundGen3G_O2GMNPar (-1) (-1)---- | Generates a sequence of sounds with changing timbre. Is a generalized version of the 'soundGen3G_O2G'. To specify how many sounds the resulting files --- will provide, you use first two 'Int64' arguments, the first of which is a number of dropped elements for 'readFileDoubles' and the second one --- is a number of produced sounds (and, respectively, number of taken elements).-soundGen3G_O2GMN :: Int64 -> Int64 -> ((V.Vector (Double -> OvertonesO),V.Vector (Int -> Double -> OvertonesO),V.Vector (Int -> Double -> OvertonesO)) -> V.Vector (Int,Int) -> - V.Vector (Double,Double -> OvertonesO)) -> V.Vector (Double -> OvertonesO) -> V.Vector (Int -> Double -> OvertonesO) -> V.Vector (Int -> Double -> OvertonesO) -> - Int -> Int -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> - (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> - (Int -> OvertonesO) -> (Double -> OvertonesO) -> IO ()-soundGen3G_O2GMN m1 n1 conversionFII vf vfA vfR m ku freq1 file f y zs gAdds gRems freq0 f0 = do- vecA0 <- fmap (V.map (`quotRem` 108)) ((if m1 == (-1) && n1 == (-1) then readFileDoubles else readFileDoublesMN m1 n1) file) -- >>= print- let n = V.length vecA0- vecB = conversionFII (vf,vfA,vfR) vecA0- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j (x,k) -> do- h2 (k x) (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) m ku freq1- renameFile ("result.wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult---- | Generalized version of the 'soundGen3G_O2GMN' where 'liftInParams' is used instead of lifting with the 'liftInEnku'. This allows e. g. to --- use some tonality. For more information, please, refer to 'filterInParams'.-soundGen3G_O2GMNPar :: Int64 -> Int64 -> ((V.Vector (Double -> OvertonesO),V.Vector (Int -> Double -> OvertonesO),V.Vector (Int -> Double -> OvertonesO)) -> V.Vector (Int,Int) -> - V.Vector (Double,Double -> OvertonesO)) -> V.Vector (Double -> OvertonesO) -> V.Vector (Int -> Double -> OvertonesO) -> V.Vector (Int -> Double -> OvertonesO) -> - Params -> Double -> FilePath -> (Double -> OvertonesO) -> Double -> String -> - (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> - (Int -> OvertonesO) -> (Double -> OvertonesO) -> IO ()-soundGen3G_O2GMNPar m1 n1 conversionFII vf vfA vfR params freq1 file f y zs gAdds gRems freq0 f0 = do- vecA0 <- fmap (V.map (`quotRem` 108)) ((if m1 == (-1) && n1 == (-1) then readFileDoubles else readFileDoublesMN m1 n1) file) -- >>= print- let n = V.length vecA0- vecB = conversionFII (vf,vfA,vfR) vecA0- zeroN = numVZeroesPre vecB- v2 = str2DurationsDef n zs y in V.imapM_ (\j (x,k) -> do- h2Params (k x) (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) params freq1- renameFile ("result.wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB- endFromResult ---- | For the given parameters generates a single sound with overtones or pause depending on the sign of the second element in the tuple of 'Double': --- if it is greater than zero then the sound is generated, if less -- the silence (pause), if it is equal to zero then it prints an informational message --- about a non-standard situation. -h1 :: (Double -> OvertonesO) -> (Double, Double) -> Int -> IO ()-h1 f (x, y) j = do- let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- v0 = f note0- ts = showFFloat (Just 4) (abs y) ""- case compare y 0.0 of- GT -> do - (_,_,herr) <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",showFFloat Nothing note0 ""] ""- print herr- partialTest_k v0 0 ts- mixTest- LT -> readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "result.wav", "synth", ts,"sine",showFFloat Nothing note0 "","vol","0"] "" >>= - \(_,_,herr) -> putStr herr- _ -> putStrLn "Zero length of the sound! " ---- | For the given parameters generates a single sound with overtones or pause depending on the sign of the second element in the tuple of 'Double': --- if it is greater than zero then the sound is generated, if less -- the silence (pause), if it is equal to zero then it prints an informational message --- about a non-standard situation. Unlike the 'h1' function, it lifts the frequency into the enku specified by the 'Int' arguments (see 'liftInEnku').-h2 :: OvertonesO -> (Double, Double) -> Int -> Int -> Double -> IO ()-h2 v (x, y) m ku freq1 = do- let note0 = fromMaybe freq1 . liftInEnku m ku . closestNote $ (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- ts = showFFloat (Just 4) (abs y) ""- case compare y 0.0 of- GT -> do - (_,_,herr) <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",showFFloat Nothing note0 ""] ""- print herr- partialTest_k v 0 ts- mixTest- LT -> readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "result.wav", "synth", ts,"sine",showFFloat Nothing note0 "","vol","0"] "" >>= - \(_,_,herr) -> putStr herr- _ -> putStrLn "Zero length of the sound! " ---- | For the given parameters generates a single sound with overtones or pause depending on the sign of the second element in a tuple of 'Double': --- if it is greater than zero then the sound is generated, if less -- the silence (pause), if it is equal to zero then it prints an informational message --- about a non-standard situation. Unlike the 'h1' function, it lifts into the requency specified by the 'Params' argument .-h2Params :: OvertonesO -> (Double, Double) -> Params -> Double -> IO ()-h2Params v (x, y) params freq1 = do- let note01 = flip liftInParams params (if x /= 0.0 then abs x else V.unsafeIndex notes 0)- ts = showFFloat (Just 4) (abs y) ""- note0 = if note01 == 11440.0 then freq1 else note01- case compare y 0.0 of- GT -> do - (_,_,herr) <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",showFFloat Nothing note0 ""] ""- print herr- partialTest_k v 0 ts- mixTest- LT -> readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "result.wav", "synth", ts,"sine",showFFloat Nothing note0 "","vol","0"] "" >>= - \(_,_,herr) -> putStr herr- _ -> putStrLn "Zero length of the sound! " ---- | Generates melody for the given parameters. The idea is that every application of the function @f :: Double -> OvertonesO@ to its argument --- possibly can produce multiple overtones being represented as 'V.Vector' of tuples of pairs of 'Double'. We can use the first element in the --- tuple to obtain a new sound parameters and the second one -- to obtain its new duration in the melody. Additional function @g :: Double -> Double@ --- is used to avoid the effect of becoming less and less -- closer to the zero for the higher overtones so the durations will become also less. --- Besides it allows to rescale the durations in a much more convenient way. --- --- The first 'Double' parameter is a multiplication coefficient to increase or to decrease the durations (values with an absolute values greater than --- one correspond to increasing inside the @g@. function applied afterwards with function composition and the values with an absolute values less --- than one and not equal to zero correspond to decreasing inside the @g@ function. --- The second 'Double' parameter is a usual frequency which is used instead of the 11440.0 (Hz) value. --- The third 'Double' parameter is a main argument -- the frequency for which the 'OvertonesO' are generated as a first step of the computation. -overMeloPar :: (Double -> OvertonesO) -> (Double -> Double) -> Params -> Double -> Double -> Double -> IO ()-overMeloPar f g params coeff freq0 freq = do - let v = f freq- vFreqs = V.map ((\z -> if z == 11440.0 then freq0 else z) . flip liftInParams params . fst) v- vD = V.map (g . (* coeff) . snd) v- v2 = V.map f vFreqs- vS = V.map (\z -> showFFloat (Just 4) (abs z) "") vD- h42 j (x,v3,y,ts) - | compare y 0.0 == GT = do - (_,_,herr) <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",showFFloat Nothing (fst x) ""] ""- print herr- partialTest_k v3 0 ts- mixTest- renameFile "result.wav" $ "result" ++ prependZeroes (numVZeroesPre v) (show j) ++ ".wav"- | compare y 0.0 == LT = do - (_,_,herr) <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "result.wav", "synth", ts,"sine",showFFloat Nothing (fst x) "","vol","0"] "" - putStr herr- renameFile "result.wav" $ "result" ++ prependZeroes (numVZeroesPre v) (show j) ++ ".wav"- | otherwise = putStrLn "Zero length of the sound! " - V.imapM_ (\j zz -> h42 j zz) . V.zip4 v v2 vD $ vS---- | Check whether for the given arguments there are the notes and whether 'String' is a name signature for the scale in 'Params' (can they be used --- together to correspond to a non-empty set of notes).-isStrParams :: String -> Params -> Bool-isStrParams xs (P2s x y zs) = if isJust (filterInParams (P2s x y zs)) then xs == zs else False-isStrParams xs (P3sf x y z zs) = if isJust (filterInParams (P3sf x y z zs)) then xs == zs else False-isStrParams xs (P4lsf x y z ts zs) = if isJust (filterInParams (P4lsf x y z ts zs)) then xs == zs else False-isStrParams xs (P32sf x y z zs ys) = if isJust (filterInParams (P32sf x y z zs ys)) then (xs == zs || xs == ys || xs == (ys ++ " " ++ zs)) else False-isStrParams _ _ = False---- | Check whether for the given arguments there are the notes and whether list of 'Int' is a part of the constructed 'Params' (can they be used --- together to correspond to a non-empty set of notes).-isListParams :: [Int] -> Params -> Bool-isListParams xs (P4lsf x y z ts zs) = if isJust (filterInParams (P4lsf x y z ts zs)) then xs == ts else False-isListParams xs (P3lf x y zs) = if isJust (filterInParams (P3lf x y zs)) then xs == zs else False-isListParams _ _ = False+ -- * Use additional function as a parameter+ overSoXSynth2FDN+ , overSoXSynth2FDN_B+ -- ** Just simple function application+ , overSoXSynth2FDN_S+ -- *** With additional filtering+ , overSoXSynth2FDN_Sf+ , overSoXSynth2FDN_Sf3+ -- * Use additional function and Ukrainian texts and generates melody+ , overSoXSynthGen2FDN+ , overSoXSynthGen2FDN_B+ , overSoXSynthGen2FDN_S+ , overSoXSynthGen2FDN_Sf+ , overSoXSynthGen2FDN_Sf3+ -- * 1G generalized functions with dB volume overtones adjustments+ , overSoXSynth2FDN1G+ , overSoXSynth2FDN_B1G+ , overSoXSynth2FDN_S1G+ , overSoXSynth2FDN_Sf1G+ , overSoXSynth2FDN_Sf31G+ -- * 2G generalized functions with additional sound quality specifying+ , overSoXSynth2FDN2G+ , overSoXSynth2FDN_B2G+ , overSoXSynth2FDN_S2G+ , overSoXSynth2FDN_Sf2G+ , overSoXSynth2FDN_Sf32G+ -- ** 2G generalized functions for melody producing+ , overSoXSynthGen2FDN_SG2G+ , overSoXSynthGen2FDN_Sf3G2G+ -- * Generalized functions with several functional parameters+ , soundGenF3+ , overSoXSynthGen2FDN_SG+ , overSoXSynthGen2FDN_Sf3G+ -- ** 1G generalized function with db volume overtones adjustments and several functional parameters+ , soundGenF31G+ -- * New functions for the version 0.36.0.0+ , overSoXSynthGen2FDN4G+ , overSoXSynthGen2FDN_SG4G+ , overSoXSynthGen2FDN_SG4GS+ -- * New generalized 5G functions that works with Intervals+ , overSoXSynth2FDN5G+ , overSoXSynth2FDN_B5G+ , overSoXSynth2FDN_S5G+ , overSoXSynth2FDN_Sf35G+ -- * New generalized 6G functions that works with Strengths+ , overSoXSynth2FDN6G+ , overSoXSynth2FDN6GS+ , overSoXSynth2FDN_B6G+ , overSoXSynth2FDN_B6GS+ , overSoXSynth2FDN_S6G+ , overSoXSynth2FDN_S6GS+ , overSoXSynth2FDN_Sf36G+ , overSoXSynth2FDN_Sf36GS+ , overSoXSynthGen2FDN_SG6G+ , overSoXSynthGen2FDN_SG6GS+ , overSoXSynthGen2FDN_SG6GSu+) where++import Numeric+import Data.List (nubBy)+import Data.Maybe (isNothing,fromJust,fromMaybe,maybe)+import qualified Data.Vector as V+import System.Process+import EndOfExe+import System.Directory+import Melodics.Ukrainian (convertToProperUkrainian)+import DobutokO.Sound.IntermediateF+import DobutokO.Sound.Functional.Basics+import DobutokO.Sound.Functional.Params+import DobutokO.Sound.DIS5G6G (intervalsFromStringG,str2Durations,str2Vol1,str2Volume)++-- | Similar to 'overSoXSynth2DN' but instead of 'overTones' function, it uses volatile function @f::Double -> Vector (Double, Double)@ with+-- somewhat sophisticated mechanism to normalize the resulting 'V.Vector' elements @(Double, Double)@. The last one is an experimental feature, so+-- it is your responsibility to provide a function so that it does not lead to clipping. In such a case, the result of application of the+-- 'convertToProperUkrainian' to the 'String' parameter must not be 'V.empty'. 'Int' argument is an index of the element to be taken from +-- the 'intervalsFromString' applied to the 'String' argument. To obtain compatible with versions prior to 0.20.0.0 behaviour, use for the 'Int' 0.+--+-- Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function.+-- But for a lot of functions this works well.+-- +-- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN'.+overSoXSynth2FDN :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()+overSoXSynth2FDN f (x, y) j zs = overSoXSynth2FDN1G f (x, y) j zs (V.replicate (V.length . f . closestNote $ if x /= 0.0 + then abs x else V.unsafeIndex notes 0) 0.0)++-- | 'V.Vector' of 'Double' is a vector of dB volume adjustments for the corresponding harmonices (overtones).+overSoXSynth2FDN1G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> IO ()+overSoXSynth2FDN1G f (x, y) j zs vdB = overSoXSynth2FDN2G f (x, y) j zs vdB []+ +-- | Similar to 'overSoXSynth2FDN1G', but additionally allows to specify by the second 'String' argument a quality changes to the generated files+-- (please, see 'soxBasicParams'). Since version 0.36.0.0 the function supports generation of the pauses.+overSoXSynth2FDN2G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> String -> IO ()+overSoXSynth2FDN2G f (x, y) j zs vdB ys+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x+ | otherwise = do+ let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+ l0 = length zs+ note1 = dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) note0+ g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> x1 == x2) . V.toList . V.map (\(noteX, !amplX) ->+ if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,+ abs (amplX - (fromIntegral . truncate $ amplX)))) . f+ g k = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .+ V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 k) $ 0), z0)) . g0 $ k + v0 = g note0+ v1 = maybe V.empty g note1+ ts = showFFloat (Just 4) (abs y) "" + overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", + showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")+ overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) (adjust_dbVol ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", + showFFloat Nothing noteN "","vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"] (V.unsafeIndex vdB i))) "") vec+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts, + "sine", showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ if isNothing note1 then overSoXSynthHelp v0+ else do + _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts, + "sine", showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ overSoXSynthHelp v0+ overSoXSynthHelp2 v1 vdB+ if null ys then mixTest else mixTest2G ys ++-- | Similar to 'overSoXSynth2FDN2G', but additionally allows to specify by the 'Intervals' argument to specify your own intervals. For more information, +-- please, refer to 'intervalsFromStringG'.+overSoXSynth2FDN5G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> IO ()+overSoXSynth2FDN5G f (x, y) j v5 vdB ys+ | V.null v5 = overSoXSynth x+ | otherwise = do+ let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+ l0 = V.length v5+ note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0+ g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> x1 == x2) . V.toList . V.map (\(noteX, !amplX) ->+ if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,+ abs (amplX - (fromIntegral . truncate $ amplX)))) . f+ g k = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .+ V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 k) $ 0), z0)) . g0 $ k + v0 = g note0+ v1 = maybe V.empty g note1+ ts = showFFloat (Just 4) (abs y) "" + overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", + showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")+ overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) (adjust_dbVol ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", + showFFloat Nothing noteN "","vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"] (V.unsafeIndex vdB i))) "") vec+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts, + "sine", showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ if isNothing note1 then overSoXSynthHelp v0+ else do + _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts, + "sine", showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ overSoXSynthHelp v0+ overSoXSynthHelp2 v1 vdB+ if null ys then mixTest else mixTest2G ys ++-- | Generalized variant of the 'overSoXSynth2FDN5G' with afterwards 'apply6Gf' usage. +overSoXSynth2FDN6G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> Double -> IO ()+overSoXSynth2FDN6G f (x, y) j v5 vdB ys vol+ | V.null v5 = overSoXSynth x+ | otherwise = do+ let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+ l0 = V.length v5+ note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0+ g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> x1 == x2) . V.toList . V.map (\(noteX, !amplX) ->+ if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,+ abs (amplX - (fromIntegral . truncate $ amplX)))) . f+ g k = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .+ V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 k) $ 0), z0)) . g0 $ k + v0 = g note0+ v1 = maybe V.empty g note1+ ts = showFFloat (Just 4) (abs y) "" + overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", + showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")+ overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) (adjust_dbVol ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", + showFFloat Nothing noteN "","vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"] (V.unsafeIndex vdB i))) "") vec+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts, + "sine", showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ if isNothing note1 then overSoXSynthHelp v0+ else do + _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts, + "sine", showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ overSoXSynthHelp v0+ overSoXSynthHelp2 v1 vdB+ if null ys then mixTest else mixTest2G ys+ if compare y 0.0 == GT then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr ""++-- | A variant of the 'overSoXSynth2FDN6G' where volume adjustment is obtained from a Ukrainian text.+overSoXSynth2FDN6GS :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> String -> V.Vector Double -> String -> String -> IO ()+overSoXSynth2FDN6GS f (x, y) j v5 xs vdB ys xxs + | V.null . convertToProperUkrainian $ xxs = putStrLn "You provided no information to obtain volume adjustment! "+ | otherwise = overSoXSynth2FDN6G f (x, y) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs)+ +-- | Uses additional 'Int' parameters. The first one is a number of enka (see 'nkyT'). The second one defines, to which n-th elements set+-- (see 'nkyT') belongs the obtained higher notes in the intervals. To obtain reasonable results, please, use for the first one 2, 3, 4, 6, 9, or 12.+-- The first 'String' parameter is used to produce durations of the notes. The second one is used to define intervals. A 'Double' parameter is a+-- basic sound duration, it defines tempo of the melody in general.+overSoXSynthGen2FDN :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()+overSoXSynthGen2FDN file m ku f y zs wws = overSoXSynthGen2FDN_SG file m ku f y zs wws overSoXSynth2FDN++-- | Generalized variant of the 'overSoXSynthGen2FDN' with your own specified 'Durations' for the sounds and pauses. +-- Instead of using a Ukrainian text to specify a durations for the sounds (and a rhythm +-- respectively) you provide your own rhythm as 'Durations'. Positive values correspond to durations of the sounds generated +-- and negative values -- to durations of the pauses respectively. +overSoXSynthGen2FDN4G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Durations -> String -> IO ()+overSoXSynthGen2FDN4G file m ku f v2 wws = overSoXSynthGen2FDN_SG4G file m ku f v2 wws overSoXSynth2FDN++-- | Similar to 'overSoXSynth2DN' but instead of 'overTones' function, it uses volatile function @f::Double -> Vector (Double, Double)@ with+-- somewhat sophisticated mechanism to normalize the resulting 'V.Vector' elements @(Double, Double)@. The last one is experimental feature, so+-- it is your responsibility to provide a function so that it does not lead to clipping. In such a case, the result of application of the+-- 'convertToProperUkrainian' to the 'String' parameter must not be 'V.empty'. The function also tries to perform filtering to avoid possible beating.+-- The third 'Double' parameter in the tuple is used as a limit for frequencies difference in Hz to be filtered out from the resulting sound. It is+-- considered to be from the range @[0.1..10.0]@. An 'Int' parameter is used to define the needed interval. To obtain compatible with versions prior+-- to 0.20.0.0 behaviour, use for the 'Int' 0.+--+-- Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function.+-- But for a lot of functions this works well.+-- +-- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_B'.+overSoXSynth2FDN_B :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()+overSoXSynth2FDN_B f (x, y, limB) j zs = overSoXSynth2FDN_B1G f (x, y, limB) j zs (V.replicate (V.length . f . closestNote $ if x /= 0.0 then abs x else V.unsafeIndex notes 0) 0.0)++-- | 'V.Vector' of 'Double' is a vector of dB volume adjustments for the corresponding harmonices (overtones).+overSoXSynth2FDN_B1G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> V.Vector Double -> IO ()+overSoXSynth2FDN_B1G f (x, y, limB) j zs vdB = overSoXSynth2FDN_B2G f (x, y, limB) j zs vdB []++-- | Generalized version of the 'overSoXSynth2FDN_B1G' with a possibility to specify sound quality parameters using additional second 'String'+-- argument. For more information, please, refer to 'soxBasicParams'. +overSoXSynth2FDN_B2G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> V.Vector Double -> String -> IO ()+overSoXSynth2FDN_B2G f (x, y, limB) j zs vdB ys+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x+ | otherwise = do+ let limA0 = abs ((limB / 10) - (fromIntegral . truncate $ (limB / 10))) * 10+ limA = if compare limA0 0.1 == LT then 0.1 else limA0+ l0 = length zs+ note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+ note1 = dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) note0+ g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> compare (abs (x1 - x2)) limA == LT) . V.toList . V.map (\(noteX, !amplX) ->+ if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,+ abs (amplX - (fromIntegral . truncate $ amplX)))) . f+ v0 = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .+ V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 note0) $ 0), z0)) . g0 $ note0 + v1 = if isNothing note1 then V.empty+ else V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .+ V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 . fromJust $ note1) $ 0), z0)) . g0 . fromJust $ note1+ ts = showFFloat (Just 4) (abs y) "" + overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", + showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")+ overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) ((if V.null vdB then id else (\wwws -> adjust_dbVol wwws (V.unsafeIndex vdB i))) + ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat Nothing noteN "", "vol", + if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"])) "") vec+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",+ showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ if isNothing note1 then overSoXSynthHelp v0+ else do + _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",+ showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ overSoXSynthHelp v0+ overSoXSynthHelp2 v1 vdB+ if null ys then mixTest else mixTest2G ys ++-- | Generalized version of the 'overSoXSynth2FDN_B2G' with a possibility to specify your own 'Intervals'. For more information, please, +-- refer to 'intervalsFromStringG'.+overSoXSynth2FDN_B5G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> IO ()+overSoXSynth2FDN_B5G f (x, y, limB) j v5 vdB ys+ | V.null v5 = overSoXSynth x+ | otherwise = do+ let limA0 = abs ((limB / 10) - (fromIntegral . truncate $ (limB / 10))) * 10+ limA = if compare limA0 0.1 == LT then 0.1 else limA0+ l0 = V.length v5+ note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+ note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0+ g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> compare (abs (x1 - x2)) limA == LT) . V.toList . V.map (\(noteX, !amplX) ->+ if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,+ abs (amplX - (fromIntegral . truncate $ amplX)))) . f+ v0 = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .+ V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 note0) $ 0), z0)) . g0 $ note0 + v1 = if isNothing note1 then V.empty+ else V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .+ V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 . fromJust $ note1) $ 0), z0)) . g0 . fromJust $ note1+ ts = showFFloat (Just 4) (abs y) "" + overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", + showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")+ overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) ((if V.null vdB then id else (\wwws -> adjust_dbVol wwws (V.unsafeIndex vdB i))) + ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat Nothing noteN "", "vol", + if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"])) "") vec+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",+ showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ if isNothing note1 then overSoXSynthHelp v0+ else do + _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",+ showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ overSoXSynthHelp v0+ overSoXSynthHelp2 v1 vdB+ if null ys then mixTest else mixTest2G ys ++-- | Generalized variant of the 'overSoXSynth2FDN_B5G' with afterwards 'apply6G' usage. +overSoXSynth2FDN_B6G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> Double -> IO ()+overSoXSynth2FDN_B6G f (x, y, limB) j v5 vdB ys vol + | V.null v5 = overSoXSynth x+ | otherwise = do+ let limA0 = abs ((limB / 10) - (fromIntegral . truncate $ (limB / 10))) * 10+ limA = if compare limA0 0.1 == LT then 0.1 else limA0+ l0 = V.length v5+ note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+ note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0+ g0 = V.fromList . nubBy (\(!x1,_) (!x2,_) -> compare (abs (x1 - x2)) limA == LT) . V.toList . V.map (\(noteX, !amplX) ->+ if noteX <= 0.0 then (2 * note0, abs (amplX - (fromIntegral . truncate $ amplX))) else (closestNote noteX,+ abs (amplX - (fromIntegral . truncate $ amplX)))) . f+ v0 = V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .+ V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 note0) $ 0), z0)) . g0 $ note0 + v1 = if isNothing note1 then V.empty+ else V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) .+ V.imap (\i (_,!z0) -> (fromIntegral (i + 1) * (fst . V.unsafeIndex (g0 . fromJust $ note1) $ 0), z0)) . g0 . fromJust $ note1+ ts = showFFloat (Just 4) (abs y) "" + overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", + showFFloat Nothing noteN "", "vol", if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"]) "")+ overSoXSynthHelp2 vec vdB = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ((if null ys then id else soxBasicParams ys) ((if V.null vdB then id else (\wwws -> adjust_dbVol wwws (V.unsafeIndex vdB i))) + ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", ts,"sine", showFFloat Nothing noteN "", "vol", + if compare y 0.0 == GT then showFFloat Nothing amplN "" else "0"])) "") vec+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",+ showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ if isNothing note1 then overSoXSynthHelp v0+ else do + _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",+ showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ overSoXSynthHelp v0+ overSoXSynthHelp2 v1 vdB+ if null ys then mixTest else mixTest2G ys + if compare y 0.0 == GT then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr ""++-- | A variant of the 'overSoXSynth2FDN_B6G' where volume adjustment is obtained from a Ukrainian text.+overSoXSynth2FDN_B6GS :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> String -> V.Vector Double -> String -> String -> IO ()+overSoXSynth2FDN_B6GS f (x, y, limB) j v5 xs vdB ys xxs+ | V.null . convertToProperUkrainian $ xxs = putStrLn "You provided no information to obtain volume adjustment! "+ | otherwise = overSoXSynth2FDN_B6G f (x, y, limB) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs)++-- | Uses additional 'Int' parameters. The first one is a number of enka (see 'nkyT'). The second one defines, to which n-th elements set+-- (see 'nkyT') belongs the obtained higher notes in the intervals. To obtain reasonable results, please, use for the first one 2, 3, 4, 6, 9, or 12.+-- The first 'String' parameter is used to produce durations of the notes. The second one is used to define intervals. The first 'Double' parameter is a+-- basic sound duration, it defines tempo of the melody in general. The second one is a limit for frequencies difference in Hz to be filtered out from the+-- resulting sound. It is considered to be from the range @[0.1..10.0]@.+overSoXSynthGen2FDN_B :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Double -> String -> String -> IO ()+overSoXSynthGen2FDN_B file m ku f y limB zs wws = overSoXSynthGen2FDN_Sf3G file m ku f y limB zs wws overSoXSynth2FDN_B++-- | Similar to 'overSoXSynth2FDN' but it does not make any normalizing transformations with the 'V.Vector' argument. To be used properly, it is needed+-- that every second element in the tuple in the 'V.Vector' argument must be in the range [-1.0..1.0] and every first element must be in between+-- 16.351597831287414 and 7902.132820097988 (Hz). An 'Int' parameter is used to define an interval. To obtain compatible with versions prior to+-- 0.20.0.0 behaviour, use for the 'Int' 0.+--+-- Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function.+-- But for a lot of functions this works well.+-- +-- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_S'.+overSoXSynth2FDN_S :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()+overSoXSynth2FDN_S f (x, y) j zs = overSoXSynth2FDN_S2G f (x, y) j zs V.empty []++-- | Generalized version of the 'overSoXSynth2FDN_S' with the additional volume adjustment in dB for overtones given by 'V.Vector' of 'Double'.+overSoXSynth2FDN_S1G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> IO ()+overSoXSynth2FDN_S1G f (x, y) j zs vdB = overSoXSynth2FDN_S2G f (x, y) j zs vdB []+ +-- | Generalized version of the 'overSoXSynth2FDN_S1G' with a possibility to specify sound quality parameters using the second 'String' argument.+-- For more information, please, refer to 'soxBasicParams'.+overSoXSynth2FDN_S2G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> String -> IO ()+overSoXSynth2FDN_S2G f (x, y) j zs vdB ys+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x+ | otherwise = do+ let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+ l0 = length zs+ note1 = dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) note0+ v0 = f note0+ v1 = maybe V.empty f note1+ ts = showFFloat (Just 4) (abs y) ""+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",+ showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ if isNothing note1 then partialTest_k2G v0 0 ts vdB ys+ else do + _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",+ showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ partialTest_k2G v0 0 ts vdB ys+ partialTest_k2G v1 1 ts vdB ys+ if null ys then mixTest else mixTest2G ys + +-- | Generalized version of the 'overSoXSynth2FDN_S2G' where you specify your own 'Intervals'. For more information, please, refer +-- to 'intervalsFromStringG'.+overSoXSynth2FDN_S5G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> IO ()+overSoXSynth2FDN_S5G f (x, y) j v5 vdB ys+ | V.null v5 = overSoXSynth x+ | otherwise = do+ let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+ l0 = V.length v5+ note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0+ v0 = f note0+ v1 = maybe V.empty f note1+ ts = showFFloat (Just 4) (abs y) ""+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",+ showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ if isNothing note1 then partialTest_k2G v0 0 ts vdB ys+ else do + _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",+ showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ partialTest_k2G v0 0 ts vdB ys+ partialTest_k2G v1 1 ts vdB ys+ if null ys then mixTest else mixTest2G ys ++-- | Generalized variant of the 'overSoXSynth2FDN_S5G' with afterwards 'apply6G' usage. Arguments for the latter is the three last function arguments.+overSoXSynth2FDN_S6G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> Double -> IO ()+overSoXSynth2FDN_S6G f (x, y) j v5 vdB ys vol+ | V.null v5 = overSoXSynth x+ | otherwise = do+ let note0 = closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)+ l0 = V.length v5+ note1 = dNote (V.unsafeIndex v5 (abs (j `rem` l0))) note0+ v0 = f note0+ v1 = maybe V.empty f note1+ ts = showFFloat (Just 4) (abs y) ""+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",+ showFFloat Nothing note0 "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ if isNothing note1 then partialTest_k2G v0 0 ts vdB ys+ else do + _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ["-r22050", "-n", "testB.wav", "synth", ts,"sine",+ showFFloat Nothing (fromJust note1) "","vol", if compare y 0.0 == GT then "1.0" else "0"]) ""+ partialTest_k2G v0 0 ts vdB ys+ partialTest_k2G v1 1 ts vdB ys+ if null ys then mixTest else mixTest2G ys + if compare y 0.0 == GT then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr ""+ +-- | A variant of the 'overSoXSynth2FDN_S6G' where volume adjustment is obtained from a Ukrainian text.+overSoXSynth2FDN_S6GS :: (Double -> OvertonesO) -> (Double, Double) -> Int -> Intervals -> String -> V.Vector Double -> String -> String -> IO ()+overSoXSynth2FDN_S6GS f (x, y) j v5 xs vdB ys xxs+ | V.null . convertToProperUkrainian $ xxs = putStrLn "You provided no information to obtain volume adjustment! "+ | otherwise = overSoXSynth2FDN_S6G f (x, y) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs)++-- | Similar to 'overSoXSynthGen2FDN', but instead of 'overSoXSynth2FDN' uses 'overSoXSynth2FDN_S' function. Note that the first 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthGen2FDN_SG :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> + ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()+overSoXSynthGen2FDN_SG file m ku f y zs wws h = do+ n <- duration1000 file+ overSoXSynthGen2FDN_SG4G file m ku f (str2DurationsDef n zs y) wws h++-- | Generalized version of the 'overSoXSynthGen2FDN_SG' where instead of using a Ukrainian text to specify a durations for the sounds (and a rhythm +-- respectively) you provide your own rhythm as 'Durations'. Positive values correspond to durations of the sounds generated +-- and negative values -- to durations of the pauses respectively. Please, use a function @h :: ((Double -> OvertonesO) -> (Double, Double) -> +-- Int -> String -> IO ())@ such that it can create for the given values accorgingly sounds and pauses. Otherwise, please, check whether at +-- least it can deal with such arguments without errors. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthGen2FDN_SG4G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Durations -> String -> + ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()+overSoXSynthGen2FDN_SG4G file m ku f v2 wws h = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ zeroN = numVZeroesPre vecB in V.imapM_ (\j x -> do+ h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws+ renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB+ endFromResult ++-- | A variant of the 'overSoXSynthGen2FDN_SG4G' where instead of providing your own durations as 'Durations' you use a Ukrainian text and +-- a function treats each symbol in it as a duration parameter with its sign. Positive values correspond to durations of the sounds generated +-- and negative values -- to durations of the pauses respectively. Please, use a function @h :: ((Double -> OvertonesO) -> (Double, Double) -> +-- Int -> String -> IO ())@ such that it can create for the given values accorgingly sounds and pauses. Otherwise, please, check whether at +-- least it can deal with such arguments without errors.+overSoXSynthGen2FDN_SG4GS :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> + ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()+overSoXSynthGen2FDN_SG4GS file m ku f y zs = overSoXSynthGen2FDN_SG4G file m ku f (str2Durations zs y)++-- | 6G generalized variant of the 'overSoXSynthGen2FDN_SG4G' with volume adjustments given by 'Strengths'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthGen2FDN_SG6G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Durations -> String -> + ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> Strengths -> Double -> IO ()+overSoXSynthGen2FDN_SG6G file m ku f v2 wws h v6 limV+ | V.null v6 = putStrLn "You did not provide a volume adjustments vector! "+ | otherwise = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ zeroN = numVZeroesPre vecB in V.imapM_ (\j x -> do+ h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws+ renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav"+ apply6GSilentFile ("result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") limV (V.unsafeIndex v6 (j `rem` V.length v6))) vecB+ endFromResult ++-- | A variant of the 'overSoXSynthGen2FDN_SG6G' where 'Strengths' are obtained from a Ukrainian text and 'str2Volume'.+overSoXSynthGen2FDN_SG6GS :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> + ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> String -> Double -> IO ()+overSoXSynthGen2FDN_SG6GS file m ku f y zs wws h zzs = overSoXSynthGen2FDN_SG6G file m ku f (str2Durations zs y) wws h (str2Volume zzs) ++-- | A variant of the 'overSoXSynthGen2FDN_SG6GS' where 'Strengths' are obtained from the same Ukrainian text as also 'Durations' so the last +-- 'String' argument is omitted (it is equal to the first one). Helps to create a speech-like composition.+overSoXSynthGen2FDN_SG6GSu :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> + ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> Double -> IO ()+overSoXSynthGen2FDN_SG6GSu file m ku f y zs wws h = overSoXSynthGen2FDN_SG6G file m ku f (str2Durations zs y) wws h (str2Volume zs)++-- | Generalized variant of the 'overSoXSynthGen2FDN_SG' with a possibility to specify with the third 'String' argument sound quality parameters.+-- Besides, the second from the end argument (a function) needs to be one more argument -- just also 'String'. +-- For more information, please, refer to 'soxBasicParams'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthGen2FDN_SG2G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> ((Double -> OvertonesO) ->+ (Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()+overSoXSynthGen2FDN_SG2G file m ku f y zs wws h ys = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ zeroN = numVZeroesPre vecB+ v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do+ h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws ys+ renameFile ("result." ++ if drop 3 ys == "f" then "flac" else "wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) +++ if drop 3 ys == "f" then ".flac" else ".wav") vecB+ endFromResult2G ys ++-- | Similar to 'overSoXSynthGen2FDN', but instead of 'overSoXSynth2FDN' uses 'overSoXSynth2FDN_S' function. +overSoXSynthGen2FDN_S :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()+overSoXSynthGen2FDN_S file m ku f y zs wws = overSoXSynthGen2FDN_SG file m ku f y zs wws overSoXSynth2FDN_S++-- | Generalized variant of the 'overSoXSynth2FDN_Sf' with a possibility to adjust volume using 'adjust_dbVol'. 'V.Vector' of 'Double' is+-- used to specify adjustments in dB. For more information, please, refer to 'adjust_dbVol'.+overSoXSynth2FDN_Sf1G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> IO ()+overSoXSynth2FDN_Sf1G f (x, y) = overSoXSynth2FDN_Sf31G f (x, y, 0.001)++-- | Generalized variant of the 'overSoXSynth2FDN_Sf1G' with a possibility to specify sound quality using the second 'String' argument.+-- For more information, please, refer to 'soxBasicParams'.+overSoXSynth2FDN_Sf2G :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> V.Vector Double -> String -> IO ()+overSoXSynth2FDN_Sf2G f (x, y) = overSoXSynth2FDN_Sf32G f (x, y, 0.001)++-- | Similar to 'overSoXSynthGen2FDN_S', but instead of 'overSoXSynth2FDN_S' uses 'overSoXSynth2FDN_Sf' function. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthGen2FDN_Sf :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()+overSoXSynthGen2FDN_Sf file m ku f y zs wws = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ zeroN = numVZeroesPre vecB+ v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do+ overSoXSynth2FDN_Sf f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws+ renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB+ endFromResult + +-- | Generalized variant of the 'overSoXSynth2FDN_Sf3' function with a possibility to adjust volume using 'adjust_dBVol'. 'V.Vector' of 'Double'+-- specifies the needed adjustments in dB.+overSoXSynth2FDN_Sf31G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> V.Vector Double -> IO ()+overSoXSynth2FDN_Sf31G f (x, y, t0) j zs vdB = overSoXSynth2FDN_Sf32G f (x, y, t0) j zs vdB []++-- | Generalized variant of the 'overSoXSynth2FDN_Sf31G' with a possibility to specify sound quality using the second 'String' parameter.+-- For more information, please, refer to 'soxBasicParams'.+overSoXSynth2FDN_Sf35G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> IO ()+overSoXSynth2FDN_Sf35G f (x, y, t0) j v5 vdB ys+ | V.null v5 = overSoXSynth x+ | otherwise = do+ let l0 = V.length v5+ soundGenF32G (V.fromList [\x -> closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0),\x -> fromMaybe (V.unsafeIndex notes 0)+ (dNote (V.unsafeIndex v5 (abs (j `rem` l0))) (closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)))])+ (V.replicate 2 x) (V.fromList [1,V.unsafeIndex v5 (abs (j `rem` l0))]) f (x, y, t0) j vdB ys+ if null ys then mixTest else mixTest2G ys ++-- | Generalized variant of the 'overSoXSynth2FDN_Sf35G' with afterwards 'apply6G' usage.+overSoXSynth2FDN_Sf36G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> V.Vector Double -> String -> Double -> IO ()+overSoXSynth2FDN_Sf36G f (x, y, t0) j v5 vdB ys vol+ | V.null v5 = overSoXSynth x+ | otherwise = do+ let l0 = V.length v5+ soundGenF32G (V.fromList [\x -> closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0),\x -> fromMaybe (V.unsafeIndex notes 0)+ (dNote (V.unsafeIndex v5 (abs (j `rem` l0))) (closestNote (if x /= 0.0 then abs x else V.unsafeIndex notes 0)))])+ (V.replicate 2 x) (V.fromList [1,V.unsafeIndex v5 (abs (j `rem` l0))]) f (x, y, t0) j vdB ys+ if null ys then mixTest else mixTest2G ys + if compare y 0.0 == GT then apply6Gf vol ("result." ++ if drop 3 ys == "f" then "flac" else "wav") else putStr ""++-- | A variant of the 'overSoXSynth2FDN_Sf36G' where volume adjustment is obtained from a Ukrainian text.+overSoXSynth2FDN_Sf36GS :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> Intervals -> String -> V.Vector Double -> String -> String -> IO ()+overSoXSynth2FDN_Sf36GS f (x, y, t0) j v5 xs vdB ys xxs+ | V.null . convertToProperUkrainian $ xxs = putStrLn "You provided no information to obtain volume adjustment! "+ | otherwise = overSoXSynth2FDN_Sf36G f (x, y, t0) j (intervalsFromStringG v5 xs) vdB ys (str2Vol1 xxs)++-- | Can generate multiple notes with their respective overtones that are played simultaneously (e. g. it can be just one note with overtones,+-- an interval with overtones, an accord with overtones etc.). This allows to get a rather complex or even complicated behaviour to obtain expressive+-- and rich sound.+soundGenF3 :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> IO ()+soundGenF3 vf vd vi f (x, y, t0) j = soundGenF32G vf vd vi f (x, y, t0) j V.empty []++-- | Generalized variant of the 'soundGenF3' with volume adjustment in dB given by the second @Vector Double@ for the overtones.+soundGenF31G :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> (Double -> OvertonesO) -> (Double, Double, Double) -> Int ->+ V.Vector Double -> IO ()+soundGenF31G vf vd vi f (x, y, t0) j vdB = soundGenF32G vf vd vi f (x, y, t0) j vdB [] ++-- | Similar to 'overSoXSynthGen2FDN_S', but instead of 'overSoXSynth2FDN_S' uses 'overSoXSynth2FDN_Sf3' function. +overSoXSynthGen2FDN_Sf3 :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Double -> String -> String -> IO ()+overSoXSynthGen2FDN_Sf3 file m ku f y t0 zs wws = overSoXSynthGen2FDN_Sf3G file m ku f y t0 zs wws overSoXSynth2FDN_Sf3++-- | Similar to 'overSoXSynthGen2FDN_S', but instead of 'overSoXSynth2FDN_S' uses 'overSoXSynth2FDN_Sf3' function. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthGen2FDN_Sf3G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Double -> String -> String ->+ ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()) -> IO ()+overSoXSynthGen2FDN_Sf3G file m ku f y t0 zs wws h = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ zeroN = numVZeroesPre vecB+ v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do+ h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2))), t0) j wws+ renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB+ endFromResult++-- | Generalized variant of the 'ovorSoXSynthGen2FDN_Sf3G' with a possibility to specify sound quality with the third 'String' argument.+-- Besides, the second from the end argument (a function) needs to be one more argument -- just also 'String'. +-- For more information, please, refer to 'soxBasicParams'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthGen2FDN_Sf3G2G :: FilePath -> Int -> Int -> (Double -> OvertonesO) -> Double -> Double -> String -> String ->+ ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()+overSoXSynthGen2FDN_Sf3G2G file m ku f y t0 zs wws h ys = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ zeroN = numVZeroesPre vecB+ v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do+ h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2))), t0) j wws ys+ renameFile ("result." ++ if drop 3 ys == "f" then "flac" else "wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ if drop 3 ys == "f"+ then ".flac" else ".wav") vecB+ endFromResult2G ys +
+ DobutokO/Sound/Functional/Basics.hs view
@@ -0,0 +1,383 @@+-- |+-- Module : DobutokO.Sound.Functional.Basics+-- 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. Is more complicated than+-- dobutokO2 and uses its functionality.++{-# LANGUAGE BangPatterns #-}+{-# OPTIONS_GHC -threaded #-}++module DobutokO.Sound.Functional.Basics (+ -- * Type synonyms with different semantics+ SoundsO+ , OvertonesO+ , NotePairs+ -- * Work with notes (general)+ , notes+ , neighbourNotes+ , closestNote+ , pureQuintNote + , overTones + -- * Work with overtones+ , overSoXSynth + -- * Work with enky (extension to octaves functionality)+ , nkyT+ , whichOctave+ , whichOctaveG+ , whichEnka + , enkuUp + , enkuDown + , liftInEnkuV+ , liftInEnku+ -- ** Work with octaves+ , octavesT+ -- * Combining intermediate files+ , mixTest+ , mixTest2+ -- * Working with files+ , freqsFromFile+ , endFromResult+ -- * Use additional function and Ukrainian texts and generates melody+ , dNote+ -- ** 2G generalized auxiliary functions+ , mixTest2G+ , mixTest22G+ , endFromResult2G+ -- ** Auxiliary functions+ , partialTest_k+ , partialTest_k1G+ , partialTest_k2G+ , prependZeroes + , nOfZeroesLog + , numVZeroesPre+ , duration1000+ , adjust_dbVol+) where++import CaseBi (getBFst')+import Data.Char (isDigit)+import System.Exit (ExitCode( ExitSuccess ))+import Numeric+import Data.List (isPrefixOf,sort)+import Data.Maybe (fromJust,isJust,fromMaybe)+import qualified Data.Vector as V+import SoXBasics (durationA)+import System.Process+import EndOfExe+import System.Directory+import DobutokO.Sound.IntermediateF++-- | Is used to represent a sequence of intervals, each note being a 'Double' value (its frequency in Hz).+type SoundsO = V.Vector (Double, Double)++-- | Is used to represent a set of overtones for the single sound, the first 'Double' value is a frequency and the second one -- an amplitude.+type OvertonesO = V.Vector (Double, Double)++-- | Is used to represent a set of pairs of notes for each element of which the 'Double' values (notes frequencies in Hz) are somewhat+-- musically connected one with another..+type NotePairs = V.Vector (Double, Double)++-- | Gets 'V.Vector' of 'Int' frequencies from the given 'FilePath' using SoX. The frequencies are \"rough\" according to the SoX documentation and+-- the duration is too small so they can be definitely other than expected ones. Is used as a source of variable numbers (somewhat close each to another+-- in their order but not neccessarily). .+freqsFromFile :: FilePath -> Int -> IO (V.Vector Int)+freqsFromFile file n = V.generateM n (\k -> do {+ (_, _, herr) <- readProcessWithExitCode (fromJust (showE "sox")) [file, "-n", "trim", showFFloat Nothing (fromIntegral k * 0.001) "",+ "0.001", "stat"] ""+ ; let line0s = lines herr+ noteN0 = takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s+ ; if null noteN0 then return (11440::Int)+ else let noteN1 = read (takeWhile isDigit . dropWhile (not . isDigit) . concat . drop 13 . take 14 $ line0s)::Int in return noteN1 })++-- | Combines (mixes) all \"test\*" files in the given directory. The files should be similar in parameters and must be sound files for SoX to work+-- on them properly. Afterwards, the function deletes these combined files.+mixTest :: IO ()+mixTest = do+ paths0 <- listDirectory "."+ let paths = filter (isPrefixOf "test") $ paths0+ _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result.wav","vol","0.3"]) ""+ mapM_ removeFile paths++-- | Similar to 'mixTest', but allows to change the sound quality parameters for the resulting file. For more information, please, refer to+-- 'soxBasicParams'.+mixTest2G :: String -> IO ()+mixTest2G ys = do+ paths0 <- listDirectory "."+ let paths = filter (isPrefixOf "test") $ paths0+ _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ soxBasicParams ys ["","result.wav","vol","0.3"]) ""+ mapM_ removeFile paths++-- | Combines (mixes) all \"test\*" files in the given directory. The files should be similar in parameters and must be sound files for SoX to work+-- on them properly. Afterwards, the function deletes these combined files. The name of the resulting file depends on the first two command line+-- arguments so that it is easy to produce unique names for the consequent call for the function.+mixTest2 :: Int -> Int -> IO ()+mixTest2 zeroN j = do+ paths0 <- listDirectory "."+ let paths = filter (isPrefixOf "test") $ paths0+ _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result" ++ prependZeroes zeroN (show j) ++ ".wav",+ "vol","0.3"]) ""+ mapM_ removeFile paths++-- | Similar to 'mixTest', but allows to change the sound quality parameters for the resulting file. For more information, please, refer to+-- 'soxBasicParams'. The name of the resulting file depends on the first two command line+-- arguments so that it is easy to produce unique names for the consequent call for the function.+mixTest22G :: Int -> Int -> String -> IO ()+mixTest22G zeroN j ys = do+ paths0 <- listDirectory "."+ let paths = filter (isPrefixOf "test") $ paths0+ _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ soxBasicParams ys ["","result" ++ prependZeroes zeroN (show j) +++ ".wav","vol","0.3"]) ""+ mapM_ removeFile paths ++-- | Gets an \"end.wav\" file from the intermediate \"result\*.wav\" files in the current directory. If it is not successful, produces the notification+-- message and exits without error. If you would like to create the file if there are too many intermediate ones, please, run+-- \"dobutokO2 8\" or \"dobutokO2 80\" in the current directory.+endFromResult :: IO ()+endFromResult = do+ path2s <- listDirectory "."+ let paths3 = sort . filter (isPrefixOf "result") $ path2s+ (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ ["end.wav"]) ""+ case code of+ ExitSuccess -> putStrLn "The final file \"end.wav\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "+ _ -> do+ exi <- doesFileExist "end.wav"+ if exi then removeFile "end.wav"+ else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>+ putStrLn "Use them manually as needed."++-- | Similar to 'endFromResult', but uses additional 'String' argument to change sound quality parameters. For more information, please, refer to+-- 'soxBasicParams'.+endFromResult2G :: String -> IO ()+endFromResult2G ys = do+ path2s <- listDirectory "."+ let paths3 = sort . filter (isPrefixOf "result") $ path2s+ (code,_,_) <- readProcessWithExitCode (fromJust (showE "sox")) (paths3 ++ soxBasicParams ys ["","end.wav"]) ""+ case code of+ ExitSuccess -> putStrLn $ "The final file \"end." ++ if drop 3 ys == "f" then "flac" else "wav" ++ "\" was successfully created. You can now manually change or delete \"result*\" files in the directory. "+ _ -> do+ exi <- doesFileExist $ "end." ++ if drop 3 ys == "f" then "flac" else "wav"+ if exi then removeFile $ "end." ++ if drop 3 ys == "f" then "flac" else "wav"+ else putStr "Your final file \"end.wav\" was not created by some reason, but the intermediate files in the respective order are present. " >>+ putStrLn "Use them manually as needed." ++-- | Creates part of the needed \"test\*\.wav" files in the current directory. +partialTest_k :: OvertonesO -> Int -> String -> IO ()+partialTest_k vec k ts = partialTest_k2G vec k ts V.empty []++-- | Generalized version of the 'partialTest_k' with the additional volume adjustment in dB given by 'V.Vector' of 'Double'.+partialTest_k1G :: OvertonesO -> Int -> String -> V.Vector Double -> IO ()+partialTest_k1G vec k ts vdB = partialTest_k2G vec k ts vdB []++-- | Generalized version of the 'partialTest_k1G' with a possibility to change sound quality parameters using the additional second 'String' argument.+-- For more information, please, refer to 'soxBasicParams'.+partialTest_k2G :: OvertonesO -> Int -> String -> V.Vector Double -> String -> IO ()+partialTest_k2G vec k ts vdB ys =+ let zeroN = numVZeroesPre vec in V.imapM_ (\i (noteN, !amplN) -> if i /= 0 && i `rem` 50 == 0+ then do+ _ <- readProcessWithExitCode (fromJust (showE "sox")) (soxBasicParams ys (adjust_dbVol ["-r22050", "-n", "test" ++ show k ++ show (i + 2) ++ ".wav",+ "synth", ts,"sine", showFFloat Nothing (abs noteN) "", "vol", showFFloat Nothing amplN ""]+ (V.unsafeIndex vdB i))) ""+ path1s <- listDirectory "."+ let path2s = sort . filter (isPrefixOf $ "test" ++ show k) $ path1s+ (code,_,herr0) <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ path2s ++ soxBasicParams ys ["","test-" ++ show k +++ prependZeroes zeroN (show (i `quot` 50)) ++ ".wav"]) ""+ case code of+ ExitSuccess -> mapM_ removeFile path2s+ _ -> do+ exi <- doesFileExist $ "test-" ++ show k ++ prependZeroes zeroN (show (i `quot` 50)) ++ if drop 3 ys == "f" then ".flac" else ".wav"+ if exi then putStrLn (herr0) >> removeFile ("test-" ++ show k ++ prependZeroes zeroN (show (i `quot` 50)) ++ if drop 3 ys == "f" then ".flac" else ".wav")+ else putStrLn herr0+ else readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ((if V.null vdB then id + else (\wwws -> adjust_dbVol wwws (V.unsafeIndex vdB i))) ["-r22050", "-n", "test" ++ show k ++ show (i + 2) ++ ".wav",+ "synth", ts,"sine", showFFloat Nothing (abs noteN) "", "vol", showFFloat Nothing amplN ""])) "" >> putStr "") vec++-- | Auxiliary function to get from a sound file specified a duration parameter @n@ that can be used further.+duration1000 :: FilePath -> IO Int+duration1000 file = fmap (\t -> truncate (t / 0.001)) . durationA $ file++-- | Function to get from the number of semi-tones and a note a 'Maybe' note for the second lower note in the interval if any. If there is+-- no need to obtain such a note, then the result is 'Nothing'.+dNote :: Int -> Double -> Maybe Double+dNote n note+ | n == 0 || compare note (V.unsafeIndex notes 0) == LT || compare note (V.unsafeIndex notes 107) == GT = Nothing+ | otherwise = Just (note / 2 ** (fromIntegral n / 12))++-- | 'V.Vector' of musical notes in Hz.+notes :: V.Vector Double+-- notes V.! 57 = 440.0 -- A4 in Hz+notes = V.generate 108 (\t -> 440 * 2 ** (fromIntegral (t - 57) / 12))++-- | Function returns either the nearest two musical notes if frequency is higher than one for C0 and lower than one for B8+-- or the nearest note duplicated in a tuple.+neighbourNotes :: Double -> V.Vector Double -> (Double, Double)+neighbourNotes x v+ | compare x (V.unsafeIndex v 0) /= GT = (V.unsafeIndex v 0, V.unsafeIndex v 0)+ | compare x (V.unsafeIndex v (V.length v - 1)) /= LT = (V.unsafeIndex v (V.length v - 1), V.unsafeIndex v (V.length v - 1))+ | compare (V.length v) 2 == GT = if compare x (V.unsafeIndex v (V.length v `quot` 2)) /= GT+ then neighbourNotes x (V.unsafeSlice 0 (V.length v `quot` 2 + 1) v)+ else neighbourNotes x (V.unsafeSlice (V.length v `quot` 2) (V.length v - (V.length v `quot` 2)) v)+ | otherwise = (V.unsafeIndex v 0, V.unsafeIndex v (V.length v - 1))++-- | Returns the closest note to the given frequency in Hz. +closestNote :: Double -> Double+closestNote x+ | compare x 0.0 == GT =+ let (x0, x2) = neighbourNotes x notes+ r0 = x / x0+ r2 = x2 / x in + if compare r2 r0 == GT+ then x0+ else x2+ | otherwise = 0.0++-- | Additional function to prepend zeroes to the given 'String'. The number of them are just that one to fulfill the length to the given 'Int' parameter.+prependZeroes :: Int -> String -> String +prependZeroes n xs + | if compare n 0 /= GT || null xs then True else compare n (length xs) /= GT = xs+ | otherwise = replicate (n - length xs) '0' ++ xs+{-# INLINE prependZeroes #-} ++nOfZeroesLog :: Int -> Maybe Int+nOfZeroesLog x+ | compare x 0 /= GT = Nothing+ | otherwise = Just (truncate (logBase 10 (fromIntegral x)) + 1)+{-# INLINE nOfZeroesLog #-} ++-- | Is a minimal number of decimal places that are just enough to represent a length of the 'V.Vector' given. For an 'V.empty' returns 0.+numVZeroesPre :: V.Vector a -> Int+numVZeroesPre v = fromMaybe (0 :: Int) (nOfZeroesLog . V.length $ v)+{-# INLINE numVZeroesPre #-} ++-- | Similarly to 'liftInOctaveV' returns a 'V.Vector' 'Double' (actually frequencies) for the n-th elements set of notes (see 'nkyT') instead of octaves.+-- A second 'Int' parameter defines that @n@. +liftInEnkuV :: Int -> Int -> V.Vector Double -> V.Vector Double+liftInEnkuV n ku = V.mapMaybe (liftInEnku n ku)++-- | Similarly to 'liftInOctave' returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT').+-- A second 'Int' parameter defines that @n@. Not all pairs return 'Just' @x@. +liftInEnku :: Int -> Int -> Double -> Maybe Double+liftInEnku n ku x+ | compare n 0 == LT || compare n ((108 `quot` ku) - 1) == GT = Nothing+ | getBFst' (False, V.fromList . zip [2,3,4,6,9,12] $ repeat True) ku && compare (closestNote x) 24.4996 == GT =+ case compare (fromJust . whichEnka ku $ x) n of+ EQ -> Just (closestNote x)+ LT -> let z = logBase 2.0 (V.unsafeIndex notes (n * ku) / closestNote x)+ z1 = truncate z in+ if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001+ then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) (enkuUp ku) $ closestNote x)+ else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) (enkuUp ku) $ closestNote x)+ _ -> let z = logBase 2.0 (closestNote x / V.unsafeIndex notes (n * ku))+ z1 = truncate z in+ if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001+ then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) (enkuDown ku) $ closestNote x)+ else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) (enkuDown ku) $ closestNote x)+ | otherwise = Nothing++-- | Similarly to 'whichOctave' returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT').+-- An 'Int' parameter defines that @n@.+whichEnka :: Int -> Double -> Maybe Int+whichEnka n x+ | getBFst' (False,V.fromList . zip [2,3,4,6,9,12] $ repeat True) n && compare (closestNote x) 24.4996 == GT = (\t ->+ case isJust t of + True -> fmap (\z ->+ case z of+ 0 -> z+ _ -> z - 1) t+ _ -> Just ((108 `quot` n) - 1)) . V.findIndex (\(t1, _) -> compare (closestNote x) t1 == LT) . nkyT $ n+ | otherwise = Nothing++-- | Returns an analogous note in the higher n-th elements set (its frequency in Hz) (see 'nkyT'). An 'Int' parameter defines this @n@.+enkuUp :: Int -> Double -> Double+enkuUp n x+ | getBFst' (False, V.fromList . zip [2..11] $ repeat True) n = 2 ** (fromIntegral n / 12) * x+ | otherwise = 2 * x+{-# INLINE enkuUp #-} ++-- | Returns an analogous note in the lower n-th elements set (its frequency in Hz) (see 'nkyT'). An 'Int' parameter defines this @n@.+enkuDown :: Int -> Double -> Double+enkuDown n x+ | getBFst' (False, V.fromList . zip [2..11] $ repeat True) n = 2 ** (fromIntegral (-n) / 12) * x+ | otherwise = x / 2+{-# INLINE enkuDown #-}++-- | Returns a 'V.Vector' of tuples with the lowest and highest frequencies for the notes in the sets consisting of @n@ consequential notes+-- (including semi-tones). An 'Int' parameter defines this @n@. It can be 2, 3, 4, 6, 9, or 12 (the last one is for default octaves, see 'octavesT').+-- So for different valid @n@ you obtain doubles, triples and so on. The function being applied returns a 'V.Vector' of such sets with+-- their respective lowest and highest frequencies.+nkyT :: Int -> NotePairs+nkyT n+ | getBFst' (False,V.fromList . zip [2,3,4,6,9,12] $ repeat True) n = V.generate (108 `quot` n) (\i -> (V.unsafeIndex notes (i * n),+ V.unsafeIndex notes (i * n + (n - 1))))+ | otherwise = octavesT++-- | Returns a 'V.Vector' of tuples with the lowest and highest frequencies for the notes in the octaves.+octavesT :: NotePairs+octavesT = V.generate 9 (\i -> (V.unsafeIndex notes (i * 12), V.unsafeIndex notes (i * 12 + 11)))++-- | For the given frequency it generates a musical sound with a timbre. The main component of the sound includes the lower pure quint,+-- which can be in the same octave or in the one with the number lower by one. 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.+overSoXSynth :: Double -> IO ()+overSoXSynth x = do+ let note0 = if x /= 0.0 then closestNote (abs x) else V.unsafeIndex notes 0+ note1 = pureQuintNote note0+ v0 = overTones note0+ v1 = overTones note1+ overSoXSynthHelp = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat Nothing noteN "", "vol", showFFloat Nothing amplN ""] "")+ overSoXSynthHelp2 = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat Nothing noteN "", "vol", showFFloat Nothing amplN ""] "")+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test01.wav", "synth", "0.5","sine", showFFloat Nothing note0 "", "synth", "0.5","sine", "mix", showFFloat Nothing note1 "", "vol","0.5"] ""+ overSoXSynthHelp v0+ overSoXSynthHelp2 v1+ mixTest ++-- | Returns a pure quint lower than the given note.+pureQuintNote :: Double -> Double+pureQuintNote x = x / 2 ** (7 / 12)+{-# INLINE pureQuintNote #-}++-- | For the given frequency of the note it generates a 'V.Vector' of the tuples, each one of which contains the harmonics' frequency and amplitude.+overTones :: Double -> OvertonesO+overTones note =+ V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.zip (V.generate 1024 (\i ->+ note * fromIntegral (i + 2))) $ (V.generate 1024 (\i -> 1 / fromIntegral ((i + 1) * (i + 1))))++-- | Function can be used to determine to which octave (in the American notation for the notes, this is a number in the note written form,+-- e. g. for C4 this is 4) the frequency belongs (to be more exact, the closest note for the given frequency -- see 'closestNote' taking into account+-- its lower pure quint, which can lay in the lower by 1 octave). If it is not practical to determine the number, then the function returns 'Nothing'.+whichOctave :: Double -> Maybe Int+whichOctave x+ | compare (closestNote x) 24.4996 == GT = (\t ->+ case isJust t of + True -> fmap (\z ->+ case z of+ 0 -> z+ _ -> z - 1) t+ _ -> Just 8) . V.findIndex (\(t1, _) -> compare (closestNote x) t1 == LT) $ octavesT+ | otherwise = Nothing++-- | Generalized version of the 'whichOctave'.+whichOctaveG :: Double -> Maybe Int+whichOctaveG x + | compare (closestNote x) (V.unsafeIndex notes 0) == GT && compare x (V.unsafeIndex notes 107) /= GT = (\t ->+ case isJust t of + True -> fmap (\z ->+ case z of+ 0 -> z+ _ -> z - 1) t+ _ -> Just 8) . V.findIndex (\(t1, _) -> compare (closestNote x) t1 == LT) $ octavesT+ | otherwise = Nothing++-- | Is used internally in the 'readProcessWithExitCode' to adjust volume for the sound with additional dB value given by 'Double' argument.+adjust_dbVol :: [String] -> Double -> [String]+adjust_dbVol xss y+ | y == 0.0 = xss+ | otherwise = xss ++ ["vol",showFFloat Nothing y "dB"]++
+ DobutokO/Sound/Functional/Elements.hs view
@@ -0,0 +1,248 @@+-- |+-- Module : DobutokO.Sound.Functional.Elements+-- 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.Functional.Elements (+ -- * Functions to edit OvertonesO and function f+ renormF+ , renormFD+ , sameOvertone+ , sameOvertoneL + , sameFreqF+ , sameFreqFI+ , fAddFElem+ , fRemoveFElem+ , fChangeFElem+ , gAdd01+ , gAdd02+ , gAdd03+ , gAdd04+ , gRem01+ , gRem02+ , gRem03+ -- ** Working with two OvertonesO+ , fAddFElems+ , fRemoveFElems+ , fChangeFElems+ , freqsOverlapOvers+ , elemsOverlapOvers+ , gAdds01+ , gAdds02+) where++import Data.List (sort,sortBy)+import qualified Data.Vector as V+import DobutokO.Sound.Functional.Basics++-- | 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 1.0 and the mutual ratios of the amplitudes are preserved.+renormF :: OvertonesO -> OvertonesO+renormF v+ | V.null v = V.empty+ | otherwise =+ let v1 = V.fromList . sortBy (\(_,y1) (_,y2)-> compare (abs y2) (abs y1)) . V.toList $ v in+ if (\(_,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.+renormFD :: Double -> OvertonesO -> OvertonesO+renormFD ampl0 v+ | V.null v = V.empty+ | otherwise =+ let v1 = V.fromList . sortBy (\(_,y1) (_,y2)-> compare (abs y2) (abs y1)) . V.toList $ v in+ if (\(_,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+sameOvertone v+ | V.null v = False+ | otherwise = V.all (\(x,_) -> x == (fst . V.unsafeIndex v $ 0)) v++-- | Similar to 'sameOvertone', except that not the 'V.Vector' is checked but a corresponding list.+sameOvertoneL :: [(Double,Double)] -> Bool+sameOvertoneL xs@((x,_):_) = 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'. 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)@. 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,_) -> x == noteN0) $ f freq++-- | @gAdd :: (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO@ is a function that defines how the element is added+-- to the 'OvertonesO'. 'fAddFElem' is +-- actually a higher-order function, it changes the function @f@ and returns a new one. It can be an interesting task +-- (in general) to look at such a function through a prism of notion of operator (mathematical, for example similar to that ones that +-- are used for quantum mechanics and quantum field theory). +-- @gAdd@ allows not only to insert an element if missing, but to change all the 'OvertonesO' system. So depending on the complexity,+-- it can produce rather complex behaviour.+fAddFElem :: (Double, Double) -> (Double -> OvertonesO) -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) ->+ (Double -> OvertonesO)+fAddFElem (noteN, amplN) 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' is+-- actually a higher-order function, it changes the function @f@ and returns a new one. It can be an interesting task +-- (in general) to look at such a function through a prism of notion of operator (mathematical, for example that ones that are used +-- for quantum mechanics and quantum field theory). +-- @gRem@ allows not only to delete an element if existing, but to change all the 'OvertonesO' system. So depending on the complexity,+-- it can produce rather complex behaviour.+fRemoveFElem :: (Double, Double) -> (Double -> OvertonesO) -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO) -> + (Double -> OvertonesO)+fRemoveFElem (noteN, amplN) f gRem t = gRem (noteN, amplN) t f++-- | Changes elements of the 'OvertonesO' using two functions. It is a generalization of the 'fAddFElem' and 'fRemoveFElem' functions. For example, if the first +-- of the two inner functional arguments acts as 'gAdd01' or similar, then it adds element to the 'OvertonesO', if it acts as 'gRem01', then it removes the element. +-- Its behaviour is defined by the 'Double' parameter (meaning frequency, probably), so you can change elements depending on what point it is applied.+fChangeFElem :: (Double, Double) -> Double -> (Double -> ((Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO)) -> (Double -> OvertonesO) -> + (Double -> OvertonesO)+fChangeFElem (noteN, amplN) freq h f t = (h freq) (noteN, amplN) t f++-- | Example of the function gAdd for the 'fAddFElem'. If the frequency is already in the 'OvertonesO' then the corresponding amplitude is divided+-- equally between all the elements with the repeated given frequency from @(Double, Double)@. Otherwise, it is just concatenated to the 'OvertonesO'.+gAdd01 :: (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO+gAdd01 (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 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 = renormFD amplMax . gAdd01 (note,ampl) freq++-- | 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 absolute+-- 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,_) (x2,_)-> 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 = renormFD amplMax . gAdd01 (note,ampl) freq++-- | 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 -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) ->+ (Double -> OvertonesO)+fAddFElems v 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 -> OvertonesO) -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO) -> + (Double -> OvertonesO)+fRemoveFElems v f gRems t = gRems v t f++-- | Similar to 'fChangeFElem', but use another form of the changing function, so it can deal with not only single element of the 'OvertonesO', +-- but also with several ones.+fChangeFElems :: OvertonesO -> Double -> (Double -> (OvertonesO -> Double -> (Double -> OvertonesO) -> OvertonesO)) -> (Double -> OvertonesO) -> + (Double -> OvertonesO)+fChangeFElems v freq h f t = (h freq) 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.map fst) [v1,v2]+ v22 = V.filter (<= V.maximum v11) v21 in+ if V.null v22 then False+ else+ let v12 = V.filter (>= V.minimum v21) v11+ [v13,v23] = map (V.uniq . V.fromList . sort . V.toList) [v12,v22]+ [l1,l2] = map V.length [v13,v23] in compare (V.length . V.uniq . V.fromList . sort . V.toList . V.concat $ [v13,v23]) (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 v22 = V.filter (\(x,_) -> x <= fst (V.maximumBy (\(x1,_) (t,_) -> compare x1 t) v1)) v2 in+ if V.null v22 then False+ else+ let v12 = V.filter (\(x,_) -> x >= fst (V.minimumBy (\(x1,_) (t,_) -> compare x1 t) v2)) v1+ [v13,v23] = map (V.uniq . V.fromList . sort . V.toList) [v12,v22]+ [l1,l2] = map V.length [v13,v23] in compare (V.length . V.uniq . V.fromList . sort . V.toList . V.concat $ [v13,v23]) (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,_) (x2,_) -> compare x1 x2) . V.toList $ v0+ h ys+ | null ys = []+ | otherwise = (takeWhile (not . (/= head ys)) ys):h (dropWhile (not . (/= head ys)) ys)+ h1 = map (\zs -> (sum . map snd $ zs) / fromIntegral (length zs)) . h+ h2 ys = map (fst . head) (h ys)+ v2 = V.fromList . zip (h2 ys) $ (h1 ys)+ us = sortBy (\(x1,_) (x2,_) -> 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 = renormFD amplMax . gAdds01 v0 freq++-- | Example of the function @gAdd@. for the 'fAddFElem'. It tries to insert the given ('Double','Double') into the less dense frequency region.+gAdd04 :: (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO+gAdd04 (note,ampl) freq f + | V.null . f $ freq = V.singleton (note,ampl)+ | otherwise =+ let v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare x1 x2) . V.toList . f $ freq+ v2 = V.zipWith (\(x1,_) (x2,_) -> x2 - x1) v1 (V.unsafeSlice 1 (V.length v1 - 1) v1)+ idxMax = V.maxIndex v2+ newFreq = (fst (V.unsafeIndex v1 (idxMax + 1)) + fst (V.unsafeIndex v1 idxMax)) / 2 in (newFreq,ampl) `V.cons` v1++-- | Example of the function @gRem@ for the 'fRemFElem'. It tries not to remove elements from the less than 6 elements 'OvertonesO' and to remove+-- all the elements in the given range with the width of the twice as many as the second 'Double' in the first argument tuple and the centre+-- in the first 'Double' in the tuple. Similar to somewhat bandreject filter but with more complex behaviour for the sound to be more complex.+gRem03 :: (Double,Double) -> Double -> (Double -> OvertonesO) -> OvertonesO+gRem03 (note,halfwidth) freq f =+ let v1 = V.filter (\(x,_) -> compare (abs (x - note)) halfwidth /= GT) . f $ freq in+ if compare (V.length v1) 5 /= GT then renormF . V.generate 5 $ (\i -> (fromIntegral (i + 1) * note, halfwidth / fromIntegral (i + 3))) + else v1+
+ DobutokO/Sound/Functional/Params.hs view
@@ -0,0 +1,534 @@+-- |+-- Module : DobutokO.Sound.Functional.Params+-- 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. Is more complicated than+-- dobutokO2 and uses its functionality.++{-# LANGUAGE BangPatterns, LambdaCase #-}+{-# OPTIONS_GHC -threaded #-}++module DobutokO.Sound.Functional.Params (+ Params (..)+ -- * Type synonyms with different semantics+ , Durations+ , Strengths+ , Intervals+ -- * New generalizations for scales and modes with Params+ , filterInParams+ , sortNoDup+ , toneD+ , toneE+ , liftInParams+ , liftInParamsV+ , lengthP+ , elemP+ , elemCloseP+ , showD+ , isStrParams+ , isListParams+ -- ** Application of the Params+ , overSoXSynthGen2FDN_SG4GPar+ , overSoXSynthGen2FDN_SG6GPar+ , overSoXSynthGen2FDN_SG2GPar+ , overSoXSynthGen2FDN_SfPar+ , overSoXSynthGen2FDN_Sf3GPar+ , overSoXSynthGen2FDN_Sf3G2GPar + -- * Creating melody from overtones+ , overMeloPar+ -- * Additional functions+ , str2DurationsDef+ , signsFromString+ , apply6Gf+ , apply6GSilentFile+ , vStrToVIntG+ , strToIntG+ , defInt+ , syllableStr+ , overSoXSynth2FDN_Sf+ , overSoXSynth2FDN_Sf3+ , overSoXSynth2FDN_Sf32G+ , intervalsFromString+ , soundGenF32G+ , helpF0+ , helpF1+ , doubleVecFromVecOfDouble+) where++import CaseBi (getBFst')+import Numeric+import Data.List (sort)+import Data.Maybe (isNothing,fromJust,isJust,fromMaybe)+import qualified Data.Vector as V+import System.Process+import EndOfExe+import System.Directory+import Melodics.Ukrainian (convertToProperUkrainian)+import SoXBasics (upperBnd,selMaxAbs)+import MMSyn7l+import MMSyn7.Syllable +import DobutokO.Sound.IntermediateF+import DobutokO.Sound.Functional.Basics++-- | Representation of the scales and modes for the notes. Can be extended further, but for a lot of situations the following realization is sufficient. +-- See, for example, 'filterInParams' and so on. 'String' is (are) used as a general classification name, for some of them there are provided two +-- 'String' to classify. Lists are used to specify remainders in some meaning. See also, 'liftInParams' and 'toneE' ('toneD') functions, 'elemP' and +-- 'elemCloseP', 'lengthP' and 'showD'.+data Params = P2 Int Int | P2s Int Int String | P3sf Int Int Int String | P4lsf Int Int Int [Int] String | P32sf Int Int Int String String + | P3lf Int Int [Int] deriving (Eq, Ord, Show)++-- | Is used to represent a set of durations parameters of the sounds and pauses. The positive value corresponds to the sound +-- and the negative one -- to the pause.+type Durations = V.Vector Double++-- | Is used to represent a set of volumes in the amplitude scale for SoX \"vol\" effect.+type Strengths = V.Vector Double++-- | Is used to represent a set of intervals for notes (each element is a number of semi-tones between parts of interval). +-- Positive values corresponds to lower notes and negative to higher ones.+type Intervals = V.Vector Int++-- | Additional function to produce signs from the given 'String' of the Ukrainian text. Ukrainian vowels and voiced consonants gives \"+\" sign (+1), voiceless+-- and sonorous consonants gives \"-\" sign (-1). Voiceless2 gives "0". Other symbols are not taken into account.+signsFromString :: Int -> String -> V.Vector Int+signsFromString n1 =+ V.take n1 . V.fromList . concatMap (fmap (\case+ Vowel _ -> 1+ Voiced _ -> 1+ VoicedP _ -> 1+ Voiceless _ -> (-1)+ VoicelessP _ -> (-1)+ Sonorous _ -> (-1)+ SonorousP _ -> (-1)+ _ -> 0) . concatMap representProlonged) . syllablesUkrP . take (3 * n1) . cycle + +-- | Generalized version of the 'overSoXSynthGen2FDN_SG4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthGen2FDN_SG4GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Durations -> String -> + ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> IO ()+overSoXSynthGen2FDN_SG4GPar file params f y v2 wws h = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ zeroN = numVZeroesPre vecB in V.imapM_ (\j x -> do+ h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws+ renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB+ endFromResult + +-- | Generalized version of the 'overSoXSynthGen2FDN_SG6G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthGen2FDN_SG6GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Durations -> String -> + ((Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()) -> Strengths -> Double -> IO ()+overSoXSynthGen2FDN_SG6GPar file params f y v2 wws h v6 limV+ | V.null v6 = putStrLn "You did not provide a volume adjustments vector! "+ | otherwise = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ zeroN = numVZeroesPre vecB in V.imapM_ (\j x -> do+ h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws+ renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav"+ apply6GSilentFile ("result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") limV (V.unsafeIndex v6 (j `rem` V.length v6))) vecB+ endFromResult ++-- | Generalized version of the 'overSoXSynthGen2FDN_SG2G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthGen2FDN_SG2GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> String -> String -> ((Double -> OvertonesO) ->+ (Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()+overSoXSynthGen2FDN_SG2GPar file params f y zs wws h ys = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ zeroN = numVZeroesPre vecB+ v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do+ h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws ys+ renameFile ("result." ++ if drop 3 ys == "f" then "flac" else "wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) +++ if drop 3 ys == "f" then ".flac" else ".wav") vecB+ endFromResult2G ys ++-- | Generalized version of the 'overSoXSynthGen2FDN_Sf' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthGen2FDN_SfPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> String -> String -> IO ()+overSoXSynthGen2FDN_SfPar file params f y zs wws = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ zeroN = numVZeroesPre vecB+ v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do+ overSoXSynth2FDN_Sf f (x, (V.unsafeIndex v2 (j `rem` (V.length v2)))) j wws+ renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB+ endFromResult + +-- | Generalized version of the 'overSoXSynthGen2FDN_Sf3G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthGen2FDN_Sf3GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Double -> String -> String ->+ ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()) -> IO ()+overSoXSynthGen2FDN_Sf3GPar file params f y t0 zs wws h = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ zeroN = numVZeroesPre vecB+ v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do+ h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2))), t0) j wws+ renameFile "result.wav" $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ ".wav") vecB+ endFromResult ++-- | Generalized version of the 'overSoXSynthGen2FDN_Sf3G2G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthGen2FDN_Sf3G2GPar :: FilePath -> Params -> (Double -> OvertonesO) -> Double -> Double -> String -> String ->+ ((Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> String -> IO ()) -> String -> IO ()+overSoXSynthGen2FDN_Sf3G2GPar file params f y t0 zs wws h ys = do+ n <- duration1000 file+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ zeroN = numVZeroesPre vecB+ v2 = str2DurationsDef n zs y in V.imapM_ (\j x -> do+ h f (x, (V.unsafeIndex v2 (j `rem` (V.length v2))), t0) j wws ys+ renameFile ("result." ++ if drop 3 ys == "f" then "flac" else "wav") $ "result0" ++ prependZeroes zeroN (show (j + 1)) ++ if drop 3 ys == "f"+ then ".flac" else ".wav") vecB+ endFromResult2G ys ++-- | A way to get from a 'Params' a corresponding 'V.Vector' of 'Double' (if any) and so to work with them further. May contain some issues +-- so please, before production usage check thoroughly. +-- For information there were used the following: +-- +-- https://en.wikipedia.org/wiki/Mode_(music)+-- +-- https://en.wikipedia.org/wiki/Ukrainian_Dorian_scale+-- +-- https://en.wikipedia.org/wiki/List_of_musical_scales_and_modes+-- +-- https://en.wikipedia.org/wiki/Octatonic_scale+-- +-- several other articles in the English Wikipedia +-- +-- and in Ukrainian: +-- Смаглій Г., Маловик Л. Теорія музики : Підруч. для навч. закл. освіти, культури і мистецтв / Г.А. Смаглій. -- Х. : Вид-во \"Ранок\", 2013. -- 392 с. +-- ISBN 978-617-09-1294-7+-- +filterInParams :: Params -> Maybe (V.Vector Double)+filterInParams (P3lf n2 nL zs) -- generalized sound series, e. g. the chromatic ones etc.+ | all (\n -> compare n 0 /= LT) ([nL,107 - nL - n2,n2 - 2] ++ zs) = + if V.null . V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) i) $ + (V.unsafeSlice nL n2 notes)+ then Nothing+ else Just (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) i) + (V.unsafeSlice nL n2 notes))+ | otherwise = Nothing+filterInParams (P32sf nT n2 nL xs ys) -- dur and moll in various their modifications+ | all (\n -> compare n 0 /= LT) [107 - nL - n2,nT,nL,nT - nL,nL + n2 - nT,n2 - 12] = + case xs of + "dur" -> getBFst' (Nothing,V.fromList . zip ["DoubleH","H","Full","Full moll","M","N"] $ fmap Just + [V.ifilter (\i _ -> toneD i nL nT [2,3,6,8,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneD i nL nT [1,3,5,9,10]) + (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12) `notElem` [1,3,5]) + (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12) `notElem` [1,6]) + (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneD i nL nT [1,3,5,9,11]) (V.unsafeSlice nL n2 notes), + V.ifilter (\i _ -> toneD i nL nT [1,3,5,8,10]) (V.unsafeSlice nL n2 notes)]) ys+ "moll" -> getBFst' (Nothing,V.fromList . zip ["DoubleH1","H","Full","Full dur","M","N"] $ fmap Just + [V.ifilter (\i _ -> toneD i nL nT [1,4,5,9,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneD i nL nT [1,4,6,9,10]) + (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12) `notElem` [1,4,6]) + (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12) `notElem` [1,6]) + (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneD i nL nT [1,4,6,8,10]) (V.unsafeSlice nL n2 notes), + V.ifilter (\i _ -> toneD i nL nT [1,4,6,9,11]) (V.unsafeSlice nL n2 notes)]) ys+ _ -> Nothing+ | otherwise = Nothing+filterInParams (P4lsf nT n2 nL zs xs) + | all (\n -> compare n 0 /= LT) ([107 - nL - n2,nT,nL,nT - nL,nL + n2 - nT,n2 - 2] ++ zs) = + case xs of+ "ditonic" -> + if (V.length . V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) + i) $ (V.unsafeSlice nL n2 notes)) /= 2 + then Nothing+ else + if (V.unsafeIndex notes nT) `V.elem` (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 2 . sortNoDup . filter (< n2) $ zs) $ + replicate n2 True) i) (V.unsafeSlice nL n2 notes))+ then Just (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 2 . sortNoDup . filter (< n2) $ zs) $ replicate n2 True) + i) (V.unsafeSlice nL n2 notes))+ else Nothing+ "tritonic" -> + if (V.length . V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) + i) $ (V.unsafeSlice nL n2 notes)) /= 3 + then Nothing+ else + if (V.unsafeIndex notes nT) `V.elem` (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 3 . sortNoDup . filter (< n2) $ zs) $ + replicate n2 True) i) (V.unsafeSlice nL n2 notes))+ then Just (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 3 . sortNoDup . filter (< n2) $ zs) $ replicate n2 True) + i) (V.unsafeSlice nL n2 notes))+ else Nothing+ "tetratonic" -> + if (V.length . V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) + i) $ (V.unsafeSlice nL n2 notes)) /= 4 + then Nothing+ else + if (V.unsafeIndex notes nT) `V.elem` (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 4 . sortNoDup . filter (< n2) $ zs) $ + replicate n2 True) i) (V.unsafeSlice nL n2 notes))+ then Just (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 4 . sortNoDup . filter (< n2) $ zs) $ replicate n2 True) + i) (V.unsafeSlice nL n2 notes))+ else Nothing+ "octatonic" -> + if (V.length . V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (sortNoDup . filter (< n2) $ zs) $ replicate n2 True) + i) $ (V.unsafeSlice nL n2 notes)) /= 8 + then Nothing+ else + if (V.unsafeIndex notes nT) `V.elem` (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 8 . sortNoDup . filter (< n2) $ zs) $ + replicate n2 True) i) (V.unsafeSlice nL n2 notes))+ then Just (V.ifilter (\i _ -> getBFst' (False,V.fromList . zip (take 8 . sortNoDup . filter (< n2) $ zs) $ replicate n2 True) + i) (V.unsafeSlice nL n2 notes))+ else Nothing+ _ -> Nothing+ | compare nL 0 /= LT && compare nL 107 /= GT && n2 == 1 && xs == "monotonic" = Just (V.singleton (V.unsafeIndex notes nL))+ | otherwise = Nothing+filterInParams (P2 nL n2) + | all (\n -> compare n 0 /= LT) [107 - nL - n2,nL,n2 - 2] = Just (V.unsafeSlice nL n2 notes) + | otherwise = Nothing+filterInParams (P2s nL n2 xs) + | all (\n -> compare n 0 /= LT) [107 - nL - n2,nL,n2 - 12] = + getBFst' (Nothing,V.fromList . zip ["Egyptian pentatonic", "Prometheus hexatonic scale", "Ukrainian Dorian scale", "augmented hexatonic scale", + "blues major pentatonic", "blues minor pentatonic", "blues scale", "major hexatonic scale", "major pentatonic", "minor hexatonic scale", + "minor pentatonic", "tritone hexatonic scale", "two-semitone tritone hexatonic scale", "whole tone scale"] $ map Just + [V.ifilter (\i _ -> toneE i nL nL [0,2,5,7,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,2,4,6,9,10]) (V.unsafeSlice nL n2 notes), + V.ifilter (\i _ -> toneE i nL nL [0,2,3,6,7,9,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,3,4,7,8,11]) (V.unsafeSlice nL n2 notes), + V.ifilter (\i _ -> toneE i nL nL [0,2,5,7,9]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,3,5,8,10]) (V.unsafeSlice nL n2 notes), + V.ifilter (\i _ -> toneE i nL nL [0,3,5,6,7,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,3,5,6,7,10]) (V.unsafeSlice nL n2 notes), + V.ifilter (\i _ -> toneE i nL nL [0,2,4,5,7,9]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,2,4,7,9]) (V.unsafeSlice nL n2 notes), + V.ifilter (\i _ -> toneE i nL nL [0,2,3,5,7,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,3,5,7,10]) (V.unsafeSlice nL n2 notes), + V.ifilter (\i _ -> toneE i nL nL [0,1,4,6,7,10]) (V.unsafeSlice nL n2 notes), V.ifilter (\i _ -> toneE i nL nL [0,1,3,7,8,9]) (V.unsafeSlice nL n2 notes), + V.ifilter (\i _ -> toneE i nL nL [0,2,4,6,8,10]) (V.unsafeSlice nL n2 notes)]) xs+ | otherwise = Nothing+filterInParams (P3sf nT nL n2 xs) + | all (\n -> compare n 0 /= LT) [101 - nL,nT,nL,nT - nL,nL + 6 - nT] && n2 == 6 = + case xs of + "Dorian tetrachord" -> + if (nT - nL) `elem` [0,1,3,5] then Just (V.ifilter (\i _ -> toneE i nL nT [0,1,3,5]) (V.unsafeSlice nL 6 notes)) else Nothing+ "Phrygian tetrachord" -> + if (nT - nL) `elem` [0,2,3,5] then Just (V.ifilter (\i _ -> toneE i nL nT [0,2,3,5]) (V.unsafeSlice nL 6 notes)) else Nothing+ "Lydian tetrachord" -> + if (nT - nL) `elem` [0,2,4,5] then Just (V.ifilter (\i _ -> toneE i nL nT [0,2,4,5]) (V.unsafeSlice nL 6 notes)) else Nothing+ _ -> Nothing+ | all (\n -> compare n 0 /= LT) [94 - nL,nT,nL,nT - nL,nL + 13 - nT] && n2 == 13 = + getBFst' (Nothing, V.fromList . zip ["modern Aeolian mode", "modern Dorian mode", "modern Ionian mode", "modern Locrian mode", + "modern Lydian mode", "modern Mixolydian mode", "modern Phrygian mode"] $ fmap (h3 nT n2 nL) [[1,4,6,9,11], [1,4,6,8,11], [1,3,6,8,10], + [2,4,7,9,11], [1,3,5,8,10], [1,3,6,8,11], [2,4,6,9,11]]) xs+ | otherwise = Nothing++h3 :: Int -> Int -> Int -> [Int] -> Maybe (V.Vector Double)+h3 nT n2 nL zs + | nT == nL = Just (V.ifilter (\i _ -> toneD i nL nT zs) (V.unsafeSlice nL n2 notes))+ | otherwise = Nothing++-- | For the list of @a@ from the @Ord@ class it builds a sorted in the ascending order list without duplicates.+-- +-- > sortNoDup [2,1,4,5,6,78,7,7,5,4,3,2,5,4,2,4,54,3,5,65,4,3,54,56,43,5,2] = [1,2,3,4,5,6,7,43,54,56,65,78]+-- +sortNoDup :: Ord a => [a] -> [a]+sortNoDup = sortNoDup' . sort+ where sortNoDup' (x:x1@(y:_)) + | x == y = sortNoDup' x1+ | otherwise = x:sortNoDup' x1+ sortNoDup' (x:_) = [x]+ sortNoDup' _ = []++-- | Checks whether its first 'Int' argument does not belong to those ones that are included into the list argument on the reminders basis. +-- The opposite to 'toneE' with the same arguments.+toneD :: Int -> Int -> Int -> [Int] -> Bool+toneD i nL nT zs = getBFst' (True,V.fromList . zip zs $ replicate 12 False) ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12)++-- | Checks whether its first 'Int' argument does belong to those ones that are included into the list argument on the reminders basis. +-- The opposite to 'toneD' with the same arguments.+toneE :: Int -> Int -> Int -> [Int] -> Bool+toneE i nL nT zs = getBFst' (False,V.fromList . zip zs $ replicate 12 True) ((nL + i - nT + (((nT - nL) `quot` 12) + 1) * 12) `rem` 12)++-- | Analogous to 'liftInEnku' lifts a frequency into a tonality (or something that can be treated alike one) specified by 'Params'. If not +-- reasonably one exists then the result is 11440 (Hz).+liftInParams :: Double -> Params -> Double+liftInParams x params + | lengthP params == 0 || (isNothing . whichOctaveG $ x) = 11440.0 + | otherwise = + V.unsafeIndex (fromJust . filterInParams $ params) (V.minIndex . V.map (abs . log . (\t -> t / x)) . V.generate (lengthP params) $ + (\i -> V.unsafeIndex notes (12 * fromJust (whichOctaveG x)) * 2 ** (fromIntegral i / fromIntegral (lengthP params))))++-- | Application of the 'liftInParams' to a 'V.Vector'. +liftInParamsV :: Params -> V.Vector Double -> V.Vector Double+liftInParamsV params = V.filter (/= 11440.0) . V.map (\x -> liftInParams x params)++-- | Gets a length of the 'V.Vector' of 'Double' being represented as 'Params'. This is a number of the notes contained in the 'Params'.+lengthP :: Params -> Int+lengthP = fromMaybe 0 . fmap V.length . filterInParams++-- | Check whether a given 'Double' value (frequency of a note) is in the vector of Doubles that corresponds to the given 'Params'.+elemP :: Double -> Params -> Bool+elemP note = fromMaybe False . fmap (note `V.elem`) . filterInParams++-- | Check whether a given 'Double' value (frequency of the closest note to the given frequency) is in the vector of Doubles that +-- corresponds to the given 'Params'.+elemCloseP :: Double -> Params -> Bool+elemCloseP note = fromMaybe False . fmap (closestNote note `V.elem`) . filterInParams++-- | A way to show not the (somewhat algebraic) structure of the 'Params' (as the usual 'show' does), but the contained frequencies in it. +showD :: Params -> String+showD = show . filterInParams ++-- | Check whether for the given arguments there are the notes and whether 'String' is a name signature for the scale in 'Params' (can they be used +-- together to correspond to a non-empty set of notes).+isStrParams :: String -> Params -> Bool+isStrParams xs (P2s x y zs) = if isJust (filterInParams (P2s x y zs)) then xs == zs else False+isStrParams xs (P3sf x y z zs) = if isJust (filterInParams (P3sf x y z zs)) then xs == zs else False+isStrParams xs (P4lsf x y z ts zs) = if isJust (filterInParams (P4lsf x y z ts zs)) then xs == zs else False+isStrParams xs (P32sf x y z zs ys) = if isJust (filterInParams (P32sf x y z zs ys)) then (xs == zs || xs == ys || xs == (ys ++ " " ++ zs)) else False+isStrParams _ _ = False++-- | Check whether for the given arguments there are the notes and whether list of 'Int' is a part of the constructed 'Params' (can they be used +-- together to correspond to a non-empty set of notes).+isListParams :: [Int] -> Params -> Bool+isListParams xs (P4lsf x y z ts zs) = if isJust (filterInParams (P4lsf x y z ts zs)) then xs == ts else False+isListParams xs (P3lf x y zs) = if isJust (filterInParams (P3lf x y zs)) then xs == zs else False+isListParams _ _ = False++-- | Generates melody for the given parameters. The idea is that every application of the function @f :: Double -> OvertonesO@ to its argument +-- possibly can produce multiple overtones being represented as 'V.Vector' of tuples of pairs of 'Double'. We can use the first element in the +-- tuple to obtain a new sound parameters and the second one -- to obtain its new duration in the melody. Additional function @g :: Double -> Double@ +-- is used to avoid the effect of becoming less and less -- closer to the zero for the higher overtones so the durations will become also less. +-- Besides it allows to rescale the durations in a much more convenient way. +-- +-- The first 'Double' parameter is a multiplication coefficient to increase or to decrease the durations (values with an absolute values greater than +-- one correspond to increasing inside the @g@. function applied afterwards with function composition and the values with an absolute values less +-- than one and not equal to zero correspond to decreasing inside the @g@ function. +-- The second 'Double' parameter is a usual frequency which is used instead of the 11440.0 (Hz) value. +-- The third 'Double' parameter is a main argument -- the frequency for which the 'OvertonesO' are generated as a first step of the computation. +overMeloPar :: (Double -> OvertonesO) -> (Double -> Double) -> Params -> Double -> Double -> Double -> IO ()+overMeloPar f g params coeff freq0 freq = do + let v = f freq+ vFreqs = V.map ((\z -> if z == 11440.0 then freq0 else z) . flip liftInParams params . fst) v+ vD = V.map (g . (* coeff) . snd) v+ v2 = V.map f vFreqs+ vS = V.map (\z -> showFFloat (Just 4) (abs z) "") vD+ h42 j (x,v3,y,ts) + | compare y 0.0 == GT = do + (_,_,herr) <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", ts,"sine",showFFloat Nothing (fst x) ""] ""+ print herr+ partialTest_k v3 0 ts+ mixTest+ renameFile "result.wav" $ "result" ++ prependZeroes (numVZeroesPre v) (show j) ++ ".wav"+ | compare y 0.0 == LT = do + (_,_,herr) <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "result.wav", "synth", ts,"sine",showFFloat Nothing (fst x) "","vol","0"] "" + putStr herr+ renameFile "result.wav" $ "result" ++ prependZeroes (numVZeroesPre v) (show j) ++ ".wav"+ | otherwise = putStrLn "Zero length of the sound! " + V.imapM_ (\j zz -> h42 j zz) . V.zip4 v v2 vD $ vS++-- | A default way to get 'Durations' for the sounds up to 0.35.2.0 version of the package including. It is based on the number of Ukrainian +-- sounds representations (see, 'convertToProperUkrainian') in a Ukrainian syllables or somewhat generated by the same rules as they. +-- The rhythm using the function is very often not binary but its ratios are almost always a ratios of the small natural numbers (1, 2, 3, 4, 5, 6, 7 etc.).+str2DurationsDef :: Int -> String -> Double -> Durations+str2DurationsDef n zs y = + let (t, ws) = splitAt 1 . syllableStr n $ zs in V.map (\yy -> y * fromIntegral (yy * length ws) / fromIntegral (head t)) . V.fromList $ ws + +apply6GSilentFile :: FilePath -> Double -> Double -> IO ()+apply6GSilentFile file limV vol = do+ upp <- upperBnd file+ ampL2 <- fmap ((\zz -> read zz::Double) . fst) (selMaxAbs file (0,upp))+ if compare (abs ampL2) (abs limV) /= GT then putStr ""+ else apply6Gf vol file++-- | Apply volume adjustment to the sound file. It must not be silent. Otherwise, it leads to likely noise sounding or errors.+apply6Gf :: Double -> FilePath -> IO ()+apply6Gf vol file = soxE file ["norm","vol", showFFloat (Just 4) vol ""] ++-- | Function is used to generate a rhythm of the resulting file \'end.wav\' from the Ukrainian text and a number of sounds either in the syllables or in the words without vowels.+syllableStr :: Int -> String -> [Int]+syllableStr n xs =+ let ps = take n . cycle . concat . sylLengthsP2 . syllablesUkrP $ xs+ y = sum ps in+ case y of+ 0 -> [0]+ _ -> y:ps ++-- | Similar to 'overSoXSynth2FDN_S' but additionally the program filters out from the resulting 'V.Vector' after \"f\" application values that are smaller+-- by absolute value than 0.001. An 'Int' parameter is used to define an interval. To obtain compatible with versions prior to+-- 0.20.0.0 behaviour, use for the 'Int' 0.+--+-- Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function.+-- But for a lot of functions this works well.+-- +-- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_Sf'.+overSoXSynth2FDN_Sf :: (Double -> OvertonesO) -> (Double, Double) -> Int -> String -> IO ()+overSoXSynth2FDN_Sf f (x, y) = overSoXSynth2FDN_Sf3 f (x, y, 0.001)++-- | Similar to 'overSoXSynth2FDN_S' but additionally the program filters out from the resulting 'V.Vector' after \"f\" application values that are smaller+-- than the third 'Double' parameter by an absolute value in the triple of @Double@'s. An 'Int' parameter is used to define an interval. To obtain compatible+-- with versions prior to 0.20.0.0 behaviour, use for the 'Int' 0.+--+-- Be aware that the result can be rather unpredictable (the program can even obtain segmentation fault) for not very suitable function.+-- But for a lot of functions this works well.+-- +-- It is recommended to fully simplify the computation for \"f\" function before using it in the 'overSoXSynth2FDN_Sf3'.+overSoXSynth2FDN_Sf3 :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> IO ()+overSoXSynth2FDN_Sf3 f (x, y, t0) j zs = overSoXSynth2FDN_Sf32G f (x, y, t0) j zs V.empty []++-- | Generalized variant of the 'overSoXSynth2FDN_Sf31G' with a possibility to specify sound quality using the second 'String' parameter.+-- For more information, please, refer to 'soxBasicParams'.+overSoXSynth2FDN_Sf32G :: (Double -> OvertonesO) -> (Double, Double, Double) -> Int -> String -> V.Vector Double -> String -> IO ()+overSoXSynth2FDN_Sf32G f (x, y, t0) j zs vdB ys+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x+ | otherwise = do+ let l0 = length zs+ soundGenF32G (V.fromList [\x2 -> closestNote (if x2 /= 0.0 then abs x2 else V.unsafeIndex notes 0),\x2 -> fromMaybe (V.unsafeIndex notes 0)+ (dNote (V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))) (closestNote (if x2 /= 0.0 then abs x2 else V.unsafeIndex notes 0)))])+ (V.replicate 2 x) (V.fromList [1,V.unsafeIndex (intervalsFromString zs) (abs (j `rem` l0))]) f (x, y, t0) j vdB ys+ if null ys then mixTest else mixTest2G ys++-- | Function is used to get numbers of intervals from a Ukrainian 'String'. It is used internally in the 'uniqOverSoXSynthN4' function.+intervalsFromString :: String -> Intervals+intervalsFromString = vStrToVIntG defInt . convertToProperUkrainian++-- | Generatlized version of the 'vStrToVInt' with a possibility to specify your own 'Intervals'.+vStrToVIntG :: Intervals -> V.Vector String -> Intervals+vStrToVIntG v = V.map (strToIntG v)++-- | Default values for 'strToInt'. All the intervals are not greater than one full octave.+defInt :: Intervals+defInt = V.fromList [12,4,7,3,4,5,5,12,3,8,12,7,10,7,7,7,12,10,7,10,2,12,2,2,11,11,1,12,9]+{-# INLINE defInt #-}++-- | Generatlized version of the 'strToInt' with a possibility to specify your own 'Intervals'.+strToIntG :: Intervals -> String -> Int+strToIntG v =+ getBFst' (0, V.zip (V.fromList ["а","б","в","г","д","дж","дз","е","ж","з","и","й","к","л","м","н","о","п","р","с","т","у","ф","х","ц","ч","ш",+ "і","ґ"]) v)+{-# INLINE strToIntG #-}++-- | Generalized variant of the 'soundGenF31G' with a possibility to specify sound quality using the 'String' argument. For more information,+-- please, refer to 'soxBasicParams'.+soundGenF32G :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> (Double -> OvertonesO) -> (Double, Double, Double) -> Int ->+ V.Vector Double -> String -> IO ()+soundGenF32G vf vd vi f (x, y, t0) j vdB ys = do+ let vD = helpF1 vf vd vi -- Vector of notes played simultaneously (e. g. just one, interval, accord etc.)+ vDz = V.mapMaybe id vD -- The previous one without Nothings and Justs+ vNotes = doubleVecFromVecOfDouble f t0 (V.map Just vDz) -- Vector of vectors of pairs (freq,ampl) -- notes and their absence (V.empty) with overtones+ ts = showFFloat (Just 4) (abs y) "" -- duration of the sound to be generated+ V.imapM_ (\i _ -> do+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ((if null ys then id else soxBasicParams ys) ((if V.null vdB + then id else (\wwws -> adjust_dbVol wwws (V.unsafeIndex vdB i))) ["-r22050", "-n", "test" ++ helpF0 i ++ ".wav", "synth",ts,+ "sine", showFFloat Nothing (V.unsafeIndex vDz i) "","vol", if compare y 0.0 == GT then "1.0" else "0"])) ""+ partialTest_k2G (V.unsafeIndex vNotes i) i ts vdB ys) vDz ++helpF0 :: Int -> String+helpF0 =+ getBFst' ("ZZ0",V.fromList . zip [0..] $ (map (:[]) "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ++ concatMap (\z -> map ((z:) . (:[])) "ABCDEFGHIJKLMNOPQRSTUVWXYZ")+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) ++helpF1 :: V.Vector (Double -> Double) -> V.Vector Double -> V.Vector Int -> V.Vector (Maybe Double)+helpF1 vf vd =+ V.map (\(f1,x,i2) ->+ case i2 of+ 0 -> Nothing+ _ -> Just $ f1 x) . V.zip3 vf vd++-- | Generates a 'V.Vector' of 'OvertonesO' that represents the sound. +doubleVecFromVecOfDouble :: (Double -> OvertonesO) -> Double -> V.Vector (Maybe Double) -> V.Vector OvertonesO+doubleVecFromVecOfDouble f t0 =+ V.map (\note1 -> if isNothing note1 then V.empty else V.filter (\(_,!z) -> compare (abs z) t0 == GT) . f . fromJust $ note1)
+ DobutokO/Sound/Functional/Split.hs view
@@ -0,0 +1,175 @@+-- |+-- Module : DobutokO.Sound.Functional.Split+-- 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.Functional.Split (+ -- * Splitting and concatenating OvertonesO+ splitO+ , splitO2+ , overConcat+ -- ** Generalization of the previous ones splitting functions+ , splitHelp1+ , splitHelp2+ , splitOG1+ , splitOG2+ , splitOG12+ , splitOG12S+ , splitOG22+ , splitOG22S+) where++import CaseBi (getBFst')+import Data.Char (isAsciiLower)+import Data.List (sortBy)+import qualified Data.Vector as V+import DobutokO.Sound.Functional.Basics+++-- | Splits (with addition of the new overtones) a given 'OvertonesO' into a number @n@ (specified by the first 'Int' argument) of 'OvertonesO' +-- (represented finally as a 'V.Vector' of them respectively) so that all except the first @n@ greatest by the absolute value of the amplitude +-- tuples of Doubles are considered overtones for the greatest by the absolute value one in the given 'OvertonesO' and all the next @n - 1@ +-- are treated as the greatest by the absolute value and each of them produces the similar by the @f :: Double -> OvertonesO@ function overtones.+-- +-- It is expected to obtain by such a conversion a splitted one sound into several simultaneous similar ones with different heights. +-- To provide a rich result, the given first argument must be strictly less than the length of the given 'OvertonesO' minus one.+splitO :: Int -> OvertonesO -> V.Vector OvertonesO+splitO n v0 + | compare (V.length v0) (n + 1) == GT = + let v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0+ (x0, y0) = V.unsafeIndex v1 0+ v2 = V.unsafeSlice 1 (n - 1) v1+ v31 = V.map (\t -> (fst t) / x0) v2+ v32 = V.map (\t -> (snd t) / y0) v2+ v3 = V.zip v31 v32+ f1Tup (t1, w2) = V.imap (\ i _ -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3+ in V.map f1Tup (V.unsafeSlice 0 n v1)+ | otherwise = V.singleton v0++-- | Splits (with addition of the new overtones) a given 'OvertonesO' into a number of 'OvertonesO' (represented finally as a 'V.Vector' of them repsectively) +-- so that it intermediately uses a special function before applying the \"similarization\" splitting function. Is a generalization of the 'splitO', +-- which can be considered a 'splitO2' with a first command line argument equals to 'id'.+-- +-- It is expected to obtain by such a conversion a splitted one sound into several simultaneous similar (less or more, depending on @h :: OvertonesO -> OvertonesO@) +-- ones with different heights. To provide a rich result, the given first argument must be strictly less than the length of the given 'OvertonesO' minus one.+splitO2 :: (OvertonesO -> OvertonesO) -> Int -> OvertonesO -> V.Vector OvertonesO+splitO2 h n v0+ | compare (V.length v0) (n + 1) == GT = + let v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0+ (x0, y0) = V.unsafeIndex v1 0+ v2 = V.unsafeSlice 1 (n - 1) v1+ v31 = V.map (\t -> (fst t) / x0) v2+ v32 = V.map (\t -> (snd t) / y0) v2+ v3 = V.zip v31 v32+ f1Tup (t1, w2) = V.imap (\ i _ -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3+ in V.map f1Tup (h . V.unsafeSlice 0 n $ v1)+ | otherwise = V.singleton v0++-- | Generalized variant of the 'splitO' with the different splitting variants depending on the first two ASCII lower case letters in the 'String' argument.+splitOG1 :: String -> Int -> OvertonesO -> V.Vector OvertonesO+splitOG1 xs n v0 + | compare (V.length v0) (n + 1) == GT = + let c1s = take 2 . filter isAsciiLower $ xs+ v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0+ (x0, y0) = V.unsafeIndex v1 0 in+ case c1s of+ "ab" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,n - 1,V.length v0 - n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0) + "ac" -> let (k1,k2,k3,k4) = (1,n - 1,n - 1,V.length v0 - n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0) + "ad" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,0,n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0) + _ -> let (k1,k2,k3,k4) = (1,n - 1,0,n) in splitHelp1 k1 k2 k3 k4 v1 (x0,y0) + | otherwise = V.singleton v0++-- | Auxiliary function that is used inside 'splitOG1'.+splitHelp1 :: Int -> Int -> Int -> Int -> OvertonesO -> (Double,Double) -> V.Vector OvertonesO+splitHelp1 x1 x2 x3 x4 v00 (y5,y6) = + let v2 = V.unsafeSlice x1 x2 v00+ v31 = V.map (\t -> (fst t) / y5) v2+ v32 = V.map (\t -> (snd t) / y6) v2+ v3 = V.zip v31 v32+ f1Tup (t1, w2) = V.imap (\ i _ -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3+ in V.map f1Tup (V.unsafeSlice x3 x4 v00)++-- | Auxiliary function that is used inside 'splitOG2'.+splitHelp2 :: (OvertonesO -> OvertonesO) -> Int -> Int -> Int -> Int -> OvertonesO -> (Double,Double) -> V.Vector OvertonesO+splitHelp2 h1 x1 x2 x3 x4 v00 (y5,y6) = + let v2 = V.unsafeSlice x1 x2 v00+ v31 = V.map (\t -> (fst t) / y5) v2+ v32 = V.map (\t -> (snd t) / y6) v2+ v3 = V.zip v31 v32+ f1Tup (t1, w2) = V.imap (\ i _ -> (fst (V.unsafeIndex v3 i) * t1, snd (V.unsafeIndex v3 i) * w2)) v3+ in V.map f1Tup (h1 . V.unsafeSlice x3 x4 $ v00) ++-- | Generalized variant of the 'splitO2' with the different splitting variants depending on the first two ASCII lower case letters in the 'String' argument.+splitOG2 :: (OvertonesO -> OvertonesO) -> String -> Int -> OvertonesO -> V.Vector OvertonesO+splitOG2 h xs n v0+ | compare (V.length v0) (n + 1) == GT = + let c1s = take 2 . filter isAsciiLower $ xs+ v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0+ (x0, y0) = V.unsafeIndex v1 0 in+ case c1s of+ "ab" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,n - 1,V.length v0 - n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) + "ac" -> let (k1,k2,k3,k4) = (1,n - 1,n - 1,V.length v0 - n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) + "ad" -> let (k1,k2,k3,k4) = (n - 1,V.length v0 - n,0,n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) + _ -> let (k1,k2,k3,k4) = (1,n - 1,0,n) in splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) + | otherwise = V.singleton v0 ++-- | Generalized variant of the 'splitOG1' with a possibility to specify a default value for splitting parameters as the first argument +-- @(Int,Int,Int,Int)@ and the sorted by the first element in the tuple (actually a 'String') in ascending order 'V.Vector' (the second one). +-- Each 'String' in the 'V.Vector' must be unique and consist of lowercase ASCII letters.+splitOG12 :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> String -> Int -> OvertonesO -> V.Vector OvertonesO+splitOG12 (x1,x2,x3,x4) vf xs n v0+ | compare (V.length v0) (n + 1) == GT && not (V.null vf) = + let c1s = filter isAsciiLower $ xs+ v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0+ (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) vf) c1s in + splitHelp1 k1 k2 k3 k4 v1 (x0,y0) + | otherwise = V.singleton v0 ++-- | Variant of the 'splitOG12' applied to the unsorted second argument. It sorts it internally. If you specify the already sorted second argument +-- then it is better to use 'splitOG12'. Each 'String' in the 'V.Vector' must be unique and consist of lowercase ASCII letters.+splitOG12S :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> String -> Int -> OvertonesO -> V.Vector OvertonesO+splitOG12S (x1,x2,x3,x4) vf xs n v0+ | compare (V.length v0) (n + 1) == GT && not (V.null vf) = + let c1s = filter isAsciiLower $ xs+ v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0+ v2 = V.fromList . sortBy (\(x1s,_) (x2s,_) -> compare x1s x2s) . V.toList $ vf+ (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) v2) c1s in + splitHelp1 k1 k2 k3 k4 v1 (x0,y0) + | otherwise = V.singleton v0 ++-- | Generalized variant of the 'splitOG2' with a possibility to specify a default value for splitting parameters as the first argument +-- @(Int,Int,Int,Int)@ and the sorted by the first element in the tuple (actually a 'String') in ascending order 'V.Vector' (the second one). +-- Each 'String' in the 'V.Vector' must be unique and consist of lowercase ASCII letters.+splitOG22 :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> (OvertonesO -> OvertonesO) -> String -> Int -> + OvertonesO -> V.Vector OvertonesO+splitOG22 (x1,x2,x3,x4) vf h xs n v0+ | compare (V.length v0) (n + 1) == GT && not (V.null vf) = + let c1s = filter isAsciiLower $ xs+ v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0+ (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) vf) c1s in + splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) + | otherwise = V.singleton v0 + +-- | Variant of the 'splitOG22' applied to the unsorted second argument. It sorts it internally. If you specify the already sorted second argument +-- then it is better to use 'splitOG22'. Each 'String' in the 'V.Vector' must be unique and consist of lowercase ASCII letters.+splitOG22S :: (Int,Int,Int,Int) -> V.Vector (String,Int -> OvertonesO -> (Int,Int,Int,Int)) -> (OvertonesO -> OvertonesO) -> String -> Int -> + OvertonesO -> V.Vector OvertonesO+splitOG22S (x1,x2,x3,x4) vf h xs n v0+ | compare (V.length v0) (n + 1) == GT && not (V.null vf) = + let c1s = filter isAsciiLower $ xs+ v1 = V.fromList . sortBy (\(x1,_) (x2,_) -> compare (abs x2) (abs x1)) . V.toList $ v0+ v2 = V.fromList . sortBy (\(x1s,_) (x2s,_) -> compare x1s x2s) . V.toList $ vf+ (x0, y0) = V.unsafeIndex v1 0 in let (k1,k2,k3,k4) = getBFst' ((x1,x2,x3,x4),V.map (\(ys,g) -> (ys,g n v1)) v2) c1s in + splitHelp2 h k1 k2 k3 k4 v1 (x0,y0) + | otherwise = V.singleton v0 ++-- | Concatenates a 'V.Vector' of 'OvertonesO' into a single 'OvertonesO'. Can be easily used with 'splitO'.+overConcat :: V.Vector OvertonesO -> OvertonesO+overConcat = V.concat . V.toList
DobutokO/Sound/IntermediateF.hs view
@@ -114,17 +114,15 @@ import Control.Exception (onException) import Control.Exception.FinalException (FinalException (NotRecorded,ExecutableNotProperlyInstalled),catchEnd) import Data.List (isPrefixOf,isSuffixOf,(\\),maximum,minimum)-import Data.Char (isDigit,isSpace) import qualified Data.Vector as V import System.Directory-import SoXBasics (playA,durationA,recA)+import SoXBasics (playA,durationA) import MMSyn7l import EndOfExe (showE) import System.Process (readProcessWithExitCode) 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)
+ DobutokO/Sound/Octaves.hs view
@@ -0,0 +1,63 @@+-- |+-- Module : DobutokO.Sound.Octaves+-- 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.Octaves (+ -- * Work with octaves+ octaveUp+ , octaveDown+ , liftInOctave+ , liftInOctaveV+) where++import Data.Maybe (fromJust)+import qualified Data.Vector as V+import DobutokO.Sound.Functional.Basics++-- | Returns an analogous note in the higher octave (its frequency in Hz).+octaveUp :: Double -> Double+octaveUp x = 2 * x+{-# INLINE octaveUp #-}++-- | Returns an analogous note in the lower octave (its frequency in Hz).+octaveDown :: Double -> Double+octaveDown x = x / 2+{-# INLINE octaveDown #-}++-- | Function lifts the given frequency to the given number of the octave (in American notation, from 0 to 8). This number is an 'Int' parameter.+-- The function also takes into account the lower pure quint for the closest note.+-- If it is not practical to determine the number, then the function returns 'Nothing'.+liftInOctave :: Int -> Double -> Maybe Double+liftInOctave n x+ | compare n 0 == LT || compare n 8 == GT = Nothing+ | compare (closestNote x) 24.4996 == GT =+ case compare (fromJust . whichOctave $ x) n of+ EQ -> Just (closestNote x)+ LT -> let z = logBase 2.0 (V.unsafeIndex notes (n * 12) / closestNote x)+ z1 = truncate z in+ if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001+ then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) octaveUp $ closestNote x)+ else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) octaveUp $ closestNote x)+ _ -> let z = logBase 2.0 (closestNote x / V.unsafeIndex notes (n * 12))+ z1 = truncate z in+ if abs (z - fromIntegral z1) > 0.999 || abs (z - fromIntegral z1) < 0.001+ then Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 2) octaveDown $ closestNote x)+ else Just (V.unsafeLast . V.iterateN (fromIntegral z1 + 1) octaveDown $ closestNote x)+ | otherwise = Nothing++-- | Function lifts the 'V.Vector' of 'Double' representing frequencies to the given octave with the 'Int' number. Better to use numbers in the range [1..8].+-- The function also takes into account the lower pure quint for the obtained note behaviour. If it is not practical to determine the octave, the resulting+-- frequency is omitted from the resulting 'V.Vector'.+liftInOctaveV :: Int -> V.Vector Double -> V.Vector Double+liftInOctaveV n = V.mapMaybe (liftInOctave n)++--------------------------------------------------------------------------------------------------------------------------------+
+ DobutokO/Sound/Overtones.hs view
@@ -0,0 +1,644 @@+-- |+-- Module : DobutokO.Sound.Overtones+-- 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.++{-# LANGUAGE BangPatterns #-}+{-# OPTIONS_GHC -threaded #-}++module DobutokO.Sound.Overtones (+ -- * Library and executable functions+ -- ** For the fixed timbre+ overSoXSynthN+ -- *** For the fixed timbre with different signs for harmonics coefficients+ , overTones2+ , overSoXSynth2+ , overSoXSynthN2+ , overSoXSynthN3+ -- *** Use additional parameters+ , overSoXSynthDN+ , overSoXSynth2DN+ -- *** Use a file for information+ , overSoXSynthNGen+ , overSoXSynthNGen2+ , overSoXSynthNGen3+ -- * Extended generation using enky functionality+ -- ** With somewhat fixed timbre+ , overSoXSynthNGenE+ , overSoXSynthNGen2E+ , overSoXSynthNGen3E+ -- * New 4G functions to work with Durations+ , overSoXSynthN4G+ , overSoXSynthN24G+ , overSoXSynthN34G+ , overSoXSynthNGenE4G+ , overSoXSynthNGen2E4G+ , overSoXSynthNGen3E4G+ -- ** 4G with speech-like composition+ , overSoXSynthN4GS+ , overSoXSynthN24GS+ , overSoXSynthN34GS+ , overSoXSynthNGenE4GS+ , overSoXSynthNGen2E4GS+ , overSoXSynthNGen3E4GS+ -- * New 5G functions to work also with Intervals+ , overSoXSynthN35G+ , overSoXSynthNGen3E5G+ -- ** 5G with obtained from the text arbitraty length Intervals+ , overSoXSynthN35GS+ , overSoXSynthNGen3E5GS+ -- * New 6G function to work also with Strengths+ , overSoXSynthNGen3E6G+ -- ** 6G with obtained from the text arbitrary length Strengths+ , overSoXSynthNGen3E6GS+ , overSoXSynthNGen3E6GSu+ -- * New generalized functions working with Params+ , overSoXSynthNGenEPar+ , overSoXSynthNGenE4GSPar+ , overSoXSynthNGenE4GPar+ , overSoXSynthNGen2EPar+ , overSoXSynthNGen2E4GSPar+ , overSoXSynthNGen2E4GPar+ , overSoXSynthNGen3EPar+ , overSoXSynthNGen3E4GSPar+ , overSoXSynthNGen3E4GPar+ , overSoXSynthNGen3E5GPar+ , overSoXSynthNGen3E5GSPar+ , overSoXSynthNGen3E6GPar+ , overSoXSynthNGen3E6GSPar+ , overSoXSynthNGen3E6GSuPar+) where++import Numeric (showFFloat)+import Data.List (isPrefixOf,sort)+import Data.Maybe (isNothing,fromJust,maybe)+import qualified Data.Vector as V+import System.Process+import EndOfExe (showE)+import System.Directory+import Melodics.Ukrainian (convertToProperUkrainian)+import DobutokO.Sound.Functional.Basics+import DobutokO.Sound.Functional.Params+import DobutokO.Sound.DIS5G6G++-- | For the given frequency of the note and a Ukrainian text it generates a 'V.Vector' of the tuples, each one of which contains+-- the harmonics' frequency and amplitude. The 'String' is used to produce the signs for harmonics coefficients.+overTones2 :: Double -> String -> OvertonesO+overTones2 note ts =+ V.takeWhile (\(!w,!z) -> compare w (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.filter (\(_, t4) -> t4 /= 0.0) .+ V.zip (V.generate 1024 (\i -> note * fromIntegral (i + 2))) $ (V.generate 1024 (\i -> fromIntegral (V.unsafeIndex (signsFromString 1024 ts)+ (i + 1)) / fromIntegral ((i + 1) * (i + 1))))++-- | Similar to 'overSoXSynth' except that takes not necessarily pure lower quint note as the second one, but the one specified by the 'String' parameter+-- as an argument to 'dNote'. If you begin the 'String' with space characters, or \"сь\", or \"ць\", or dash, or apostrophe, or soft sign, than there will+-- be no interval and the sound will be solely one with its 'OvertonesO'.+overSoXSynthDN :: Double -> String -> IO ()+overSoXSynthDN x = overSoXSynth2DN x 0.5++-- | Similar to 'overSoXSynthDN' except that the resulting duration is specified by the second 'Double' parameter in seconds. For 'overSoXSynthDN'+-- it is equal to 0.5.+overSoXSynth2DN :: Double -> Double -> String -> IO ()+overSoXSynth2DN x y zs+ | V.null . convertToProperUkrainian $ zs = overSoXSynth x+ | otherwise = do+ let note0 = closestNote x+ note1 = dNote (V.unsafeIndex (intervalsFromString zs) 0) note0+ v0 = overTones note0+ v1 = maybe V.empty overTones note1+ overSoXSynthHelp vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", showFFloat (Just 4) y "","sine", showFFloat (Just 4) noteN "",+ "vol", showFFloat (Just 4) amplN ""] "") vec+ overSoXSynthHelp2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", showFFloat (Just 4) y "","sine", showFFloat (Just 4) noteN "",+ "vol", showFFloat (Just 4) amplN ""] "") vec+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA.wav", "synth", showFFloat (Just 4) y "","sine",+ showFFloat (Just 4) note0 "", "vol","0.5"] ""+ if isNothing note1 then overSoXSynthHelp v0+ else do + _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB.wav", "synth", showFFloat (Just 4) y "","sine",+ showFFloat (Just 4) (fromJust note1) "", "vol","0.5"] ""+ overSoXSynthHelp v0+ overSoXSynthHelp2 v1+ mixTest++-- | For the given frequency it generates a musical sound with a timbre. The main component of the sound includes the lower pure quint,+-- which can be in the same octave or in the one with the number lower by one. Please, check before executing+-- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.+-- The 'String' argument is used to define signs of the harmonics coefficients for Overtones.+overSoXSynth2 :: Double -> String -> IO ()+overSoXSynth2 x tts = do+ let note0 = closestNote x+ note1 = pureQuintNote note0+ v0 = overTones2 note0 tts+ v1 = overTones2 note1 tts+ overSoXSynthHelp vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test0" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN "",+ "vol", showFFloat (Just 4) amplN ""] "") vec+ overSoXSynthHelp2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test1" ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN "",+ "vol", showFFloat (Just 4) amplN ""] "") vec+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test01.wav", "synth", "0.5","sine", showFFloat (Just 4) note0 "",+ "synth", "0.5","sine", "mix", showFFloat (Just 4) note1 "", "vol","0.5"] ""+ overSoXSynthHelp v0+ overSoXSynthHelp2 v1+ mixTest ++-- | Function to create a melody for the given arguments. 'String' is used to provide a rhythm. The main component of the sound includes the lower pure quint, which+-- can be in the same octave or in the one with the number lower by one. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude+-- for Overtones. If it is set to 1.0 the overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results+-- in their becoming more silent ones. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing+-- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.+overSoXSynthN :: Int -> Double -> Double -> String -> V.Vector Double -> IO ()+overSoXSynthN n ampL time3 zs = overSoXSynthN4G n ampL (str2DurationsDef n zs time3)++-- | Function to create a melody for the given arguments. 'Durations' is used to provide a rhythm. +overSoXSynthN4G :: Int -> Double -> Durations -> V.Vector Double -> IO ()+overSoXSynthN4G n ampL v2 vec0+ | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "+ | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT = + let zeroN = numVZeroesPre vec0+ v21 = V.filter (/=0.0) v2+ m = V.length v2 in V.imapM_ (\j x -> do + let note0 = closestNote x -- zs is obtained from the command line arguments+ note1 = pureQuintNote note0+ v0 = overTones note0+ v1 = overTones note1+ overSoXSynthHelpN vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec+ overSoXSynthHelpN2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec + soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++ prependZeroes zeroN "1" +++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "", "synth",+ showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", "mix", showFFloat (Just 4) note02 "", "vol",if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT + then "0.5" else "0"] ""+ _ <- soxSynthHelpMain note0 note1+ overSoXSynthHelpN v0+ overSoXSynthHelpN2 v1+ mixTest2 zeroN j) vec0+ | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in+ if abs ampL1 < 0.01 then overSoXSynthN4G n 0.01 v2 vec0+ else overSoXSynthN4G n ampL1 v2 vec0++-- | Variant of the 'overSoXSynthN4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition.+overSoXSynthN4GS :: Int -> Double -> Double -> String -> V.Vector Double -> IO ()+overSoXSynthN4GS n ampL time3 zs = overSoXSynthN4G n ampL (str2Durations zs time3)++-- | Function to create a melody for the given arguments. 'String' is used to provide a rhythm. The main component of the sound includes the lower pure quint, which+-- can be in the same octave or in the one with the number lower by one. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude+-- for Overtones. If it is set to 1.0 the overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results+-- in their becoming more silent ones. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing+-- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.+overSoXSynthN2 :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()+overSoXSynthN2 n ampL time3 zs = overSoXSynthN24G n ampL (str2DurationsDef n zs time3)+ +-- | Function to create a melody for the given arguments. 'Durations' is used to provide a rhythm. +overSoXSynthN24G :: Int -> Double -> Durations -> String -> V.Vector Double -> IO ()+overSoXSynthN24G n ampL v2 tts vec0+ | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "+ | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT = + let v21 = V.filter (/= 0.0) v2+ zeroN = numVZeroesPre vec0+ m = V.length v21 in V.imapM_ (\j x -> do + let note0 = closestNote x -- zs is obtained from the command line arguments+ note1 = pureQuintNote note0+ v0 = overTones2 note0 tts+ v1 = overTones2 note1 tts+ overSoXSynthHelpN vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine",showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec+ overSoXSynthHelpN2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec + soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++ prependZeroes zeroN "1" +++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "",+ "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", "mix", showFFloat (Just 4) note02 "", "vol",+ if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""+ _ <- soxSynthHelpMain note0 note1+ overSoXSynthHelpN v0+ overSoXSynthHelpN2 v1+ mixTest2 zeroN j) vec0+ | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in+ if abs ampL1 < 0.01 then overSoXSynthN24G n 0.01 v2 tts vec0+ else overSoXSynthN24G n ampL1 v2 tts vec0 ++-- | Variant of the 'overSoXSynthN24G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition.+overSoXSynthN24GS :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()+overSoXSynthN24GS n ampL time3 zs = overSoXSynthN24G n ampL (str2Durations zs time3)++-- | Function to create a melody for the given arguments. 'String' is used to provide a rhythm. The main component of the sound includes the lower pure quint, which+-- can be in the same octave or in the one with the number lower by one. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude+-- for Overtones. If it is set to 1.0 the overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results+-- in their becoming more silent ones. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing+-- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.+-- The third 'String' argument is used to define the intervals for the notes if any.+-- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of+-- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones.+-- The last one is experimental feature.+overSoXSynthN3 :: Int -> Double -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()+overSoXSynthN3 n ampL time3 dAmpl zs = overSoXSynthN34G n ampL dAmpl (str2DurationsDef n zs time3)++-- | Function to create a melody for the given arguments. 'Duraitons' is used to provide a rhythm. +overSoXSynthN34G :: Int -> Double -> Double -> Durations -> String -> String -> V.Vector Double -> IO ()+overSoXSynthN34G n ampL dAmpl v2 tts vs vec0+ | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "+ | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT = + let v21 = V.filter (/= 0.0) v2+ m = V.length v21+ zeroN = numVZeroesPre vec0+ v3 = intervalsFromString vs+ l = length vs in V.imapM_ (\j x -> do + let note0 = closestNote x -- zs is obtained from the command line arguments+ note1 = dNote (V.unsafeIndex v3 (j `rem` l)) note0+ v0 = overTones2 note0 tts+ v1 = if isNothing note1 then V.empty+ else overTones2 (fromJust note1) tts+ overSoXSynthHelpN vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine",showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec+ overSoXSynthHelpN2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl * amplN * ampL > 1.0 then 1.0+ else dAmpl * amplN * ampL) "" else "0"] "") vec + soxSynthHelpMain0 note01 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++ prependZeroes zeroN "1" ++ ".wav",+ "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "", "vol",+ if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""+ soxSynthHelpMain1 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB" +++ prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note02 "",+ "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / 2) "" else "0"] ""+ if isNothing note1 then do { _ <- soxSynthHelpMain0 note0+ ; overSoXSynthHelpN v0 }+ else do { _ <- soxSynthHelpMain0 note0+ ; _ <- soxSynthHelpMain1 (fromJust note1)+ ; overSoXSynthHelpN v0+ ; overSoXSynthHelpN2 v1}+ paths0 <- listDirectory "."+ let paths = sort . filter (isPrefixOf "test") $ paths0+ _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result0" ++ prependZeroes zeroN (show j) ++ ".wav","vol","0.3"]) ""+ mapM_ removeFile paths) vec0+ | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in+ if abs ampL1 < 0.01 then overSoXSynthN34G n 0.01 dAmpl v2 tts vs vec0+ else overSoXSynthN34G n ampL1 dAmpl v2 tts vs vec0++-- | Generalized variant of the 'overSoXSynthN34G' where you specify your own 'Intervals'. For more information, please, refer to 'intervalsFromStringG'.+overSoXSynthN35G :: Int -> Double -> Double -> Durations -> String -> Intervals -> V.Vector Double -> IO ()+overSoXSynthN35G n ampL dAmpl v2 tts v3 vec0+ | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "+ | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT = + let v21 = V.filter (/=0.0) v2+ m = V.length v21+ zeroN = numVZeroesPre vec0+ l = V.length v3 in V.imapM_ (\j x -> do + let note0 = closestNote x -- zs is obtained from the command line arguments+ note1 = dNote (V.unsafeIndex v3 (j `rem` l)) note0+ v0 = overTones2 note0 tts+ v1 = if isNothing note1 then V.empty+ else overTones2 (fromJust note1) tts+ overSoXSynthHelpN vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine",showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec+ overSoXSynthHelpN2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl * amplN * ampL > 1.0 then 1.0+ else dAmpl * amplN * ampL) "" else "0"] "") vec + soxSynthHelpMain0 note01 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" ++ prependZeroes zeroN "1" ++ ".wav",+ "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "", "vol",+ if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""+ soxSynthHelpMain1 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB" +++ prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note02 "",+ "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / 2) "" else "0"] ""+ if isNothing note1 then do { _ <- soxSynthHelpMain0 note0+ ; overSoXSynthHelpN v0 }+ else do { _ <- soxSynthHelpMain0 note0+ ; _ <- soxSynthHelpMain1 (fromJust note1)+ ; overSoXSynthHelpN v0+ ; overSoXSynthHelpN2 v1}+ paths0 <- listDirectory "."+ let paths = sort . filter (isPrefixOf "test") $ paths0+ _ <- readProcessWithExitCode (fromJust (showE "sox")) (["--combine", "mix"] ++ paths ++ ["result0" ++ prependZeroes zeroN (show j) ++ ".wav","vol","0.3"]) ""+ mapM_ removeFile paths) vec0+ | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in+ if abs ampL1 < 0.01 then overSoXSynthN35G n 0.01 dAmpl v2 tts v3 vec0+ else overSoXSynthN35G n ampL1 dAmpl v2 tts v3 vec0++-- | Variant of the 'overSoXSynthN34G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition.+overSoXSynthN34GS :: Int -> Double -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()+overSoXSynthN34GS n ampL time3 dAmpl zs = overSoXSynthN34G n ampL dAmpl (str2Durations zs time3)++-- | Variant of the 'overSoXSynthN34G' where intervals are obtained from the basic 'Intervals' with the length no more than 29 and a Ukrainian text +-- specified as the last 'String' argument so that you can produce 'Intervals' of the arbitrary length. For more information, please, refer to +-- 'intervalsFromStringG' and 'strToIntG'.+overSoXSynthN35GS :: Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> V.Vector Double -> IO ()+overSoXSynthN35GS n ampL time3 dAmpl zs tts v3 vs = overSoXSynthN35G n ampL dAmpl (str2Durations zs time3) tts (intervalsFromStringG v3 vs)++-- | Similar to 'overSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts+-- the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]). The first 'Double' argument from+-- the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the overTones amplitudes are just maximum ones,+-- otherwise they are multiplied by the parameter and this results in their becoming more silent ones.+-- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.+--+-- For better usage the 'FilePath' should be a filepath for the .wav file.+overSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> IO ()+overSoXSynthNGen file m = overSoXSynthNGenE file m 12+ +-- | Similar to 'overSoXSynthNGen', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'overSoXSynthNGen'. To obtain+-- its modifications, please, use 2, 3, 4, 6, or 9.+overSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> IO ()+overSoXSynthNGenE file m ku ampL time3 zs = do+ n <- duration1000 file+ nGenE4Gi n file m ku ampL (str2DurationsDef n zs time3)++-- | Generalized version of the 'overSoXSynthNGenE' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGenEPar :: FilePath -> Params -> Double -> Double -> String -> IO ()+overSoXSynthNGenEPar file params ampL time3 zs = do+ n <- duration1000 file+ nGenE4GiPar n file params ampL (str2DurationsDef n zs time3)++-- | Variant of the 'overSoXSynthNGenE4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition.+overSoXSynthNGenE4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> IO ()+overSoXSynthNGenE4GS file m ku ampL time3 zs = do+ n <- duration1000 file+ nGenE4Gi n file m ku ampL (str2Durations zs time3)++-- | Generalized version of the 'overSoXSynthNGenE4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGenE4GSPar :: FilePath -> Params -> Double -> Double -> String -> IO ()+overSoXSynthNGenE4GSPar file params ampL time3 zs = do+ n <- duration1000 file+ nGenE4GiPar n file params ampL (str2Durations zs time3) ++-- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.+nGenE4Gi :: Int -> FilePath -> Int -> Int -> Double -> Durations -> IO ()+nGenE4Gi n file m ku ampL v2 = do+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ overSoXSynthN4G n ampL v2 vecB+ endFromResult + +-- | Generalized version of the 'nGenE4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+nGenE4GiPar :: Int -> FilePath -> Params -> Double -> Durations -> IO ()+nGenE4GiPar n file params ampL v2 = do+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ overSoXSynthN4G n ampL v2 vecB+ endFromResult + +-- | 4G genaralized version of the 'overSoXSynthNGenE' where you provide your own 'Durations'.+overSoXSynthNGenE4G :: FilePath -> Int -> Int -> Double -> Durations -> IO ()+overSoXSynthNGenE4G file m ku ampL v2 = do+ n <- duration1000 file+ nGenE4Gi n file m ku ampL v2++-- | Generalized version of the 'overSoXSynthNGenE4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGenE4GPar :: FilePath -> Params -> Double -> Durations -> IO ()+overSoXSynthNGenE4GPar file params ampL v2 = do+ n <- duration1000 file+ nGenE4GiPar n file params ampL v2 ++-- | Similar to 'overSoXSynthN2', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts+-- the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]). The first 'Double' argument from+-- the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the overTones amplitudes are just maximum ones,+-- otherwise they are multiplied by the parameter and this results in their becoming more silent ones.+-- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.+-- +-- For better usage the 'FilePath' should be a filepath for the .wav file.+-- The second 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.+overSoXSynthNGen2 :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()+overSoXSynthNGen2 file m = overSoXSynthNGen2E file m 12+ +-- | Similar to 'overSoXSynthNGen2', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'overSoXSynthNGen2'. To obtain+-- its modifications, please, use 2, 3, 4, 6, or 9.+overSoXSynthNGen2E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()+overSoXSynthNGen2E file m ku ampL time3 zs tts = do+ n <- duration1000 file+ nGen2E4Gi n file m ku ampL (str2DurationsDef n zs time3) tts++-- | Generalized version of the 'overSoXSynthNGen2E' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGen2EPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()+overSoXSynthNGen2EPar file params ampL time3 zs tts = do+ n <- duration1000 file+ nGen2E4GiPar n file params ampL (str2DurationsDef n zs time3) tts ++-- | Variant of the 'overSoXSynthNGen2E4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition.+overSoXSynthNGen2E4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()+overSoXSynthNGen2E4GS file m ku ampL time3 zs tts = do+ n <- duration1000 file+ nGen2E4Gi n file m ku ampL (str2Durations zs time3) tts++-- | Generalized version of the 'overSoXSynthNGen2E4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGen2E4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()+overSoXSynthNGen2E4GSPar file params ampL time3 zs tts = do+ n <- duration1000 file+ nGen2E4GiPar n file params ampL (str2Durations zs time3) tts++-- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.+nGen2E4Gi :: Int -> FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()+nGen2E4Gi n file m ku ampL v2 tts = do+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ overSoXSynthN24G n ampL v2 tts vecB+ endFromResult ++-- | Generalized version of the 'nGen2E4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+nGen2E4GiPar :: Int -> FilePath -> Params -> Double -> Durations -> String -> IO ()+nGen2E4GiPar n file params ampL v2 tts = do+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ overSoXSynthN24G n ampL v2 tts vecB+ endFromResult + +-- | 4G genaralized version of the 'overSoXSynthNGen2E' where you provide your own 'Durations'.+overSoXSynthNGen2E4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()+overSoXSynthNGen2E4G file m ku ampL v2 tts = do+ n <- duration1000 file+ nGen2E4Gi n file m ku ampL v2 tts++-- | Generalized version of the 'overSoXSynthNGen2E4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGen2E4GPar :: FilePath -> Params -> Double -> Durations -> String -> IO ()+overSoXSynthNGen2E4GPar file params ampL v2 tts = do+ n <- duration1000 file+ nGen2E4GiPar n file params ampL v2 tts ++-- | Similar to 'overSoXSynthN2', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. Besides, the function lifts+-- the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]). The first 'Double' argument from+-- the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the overTones amplitudes are just maximum ones,+-- otherwise they are multiplied by the parameter and this results in their becoming more silent ones.+-- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.+-- +-- For better usage the 'FilePath' should be a filepath for the .wav file.+-- The second 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.+-- The third 'String' argument is used to define the intervals for the notes if any.+-- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of+-- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones.+-- The last one is experimental feature.+overSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()+overSoXSynthNGen3 file m = overSoXSynthNGen3E file m 12+ +-- | Similar to 'overSoXSynthNGen3', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'overSoXSynthNGen3'. To obtain+-- its modifications, please, use 2, 3, 4, 6, or 9.+overSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()+overSoXSynthNGen3E file m ku ampL time3 dAmpl zs tts vs = do+ n <- duration1000 file+ nGen3E4Gi n file m ku ampL dAmpl (str2DurationsDef n zs time3) tts vs++-- | Generalized version of the 'overSoXSynthNGen3E' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGen3EPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> IO ()+overSoXSynthNGen3EPar file params ampL time3 dAmpl zs tts vs = do+ n <- duration1000 file+ nGen3E4GiPar n file params ampL dAmpl (str2DurationsDef n zs time3) tts vs ++-- | Variant of the 'overSoXSynthNGen3E4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthNGen3E4GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> IO ()+overSoXSynthNGen3E4GS file m ku ampL time3 dAmpl zs tts vs = do+ n <- duration1000 file+ nGen3E4Gi n file m ku ampL dAmpl (str2Durations zs time3) tts vs ++-- | Generalized version of the 'overSoXSynthNGen3E4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGen3E4GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> IO ()+overSoXSynthNGen3E4GSPar file params ampL time3 dAmpl zs tts vs = do+ n <- duration1000 file+ nGen3E4GiPar n file params ampL dAmpl (str2Durations zs time3) tts vs ++-- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.+nGen3E4Gi :: Int -> FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> IO ()+nGen3E4Gi n file m ku ampL dAmpl v2 tts vs = do + vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ overSoXSynthN34G n ampL dAmpl v2 tts vs vecB+ endFromResult ++-- | Generalized version of the 'nGen3E4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+nGen3E4GiPar :: Int -> FilePath -> Params -> Double -> Double -> Durations -> String -> String -> IO ()+nGen3E4GiPar n file params ampL dAmpl v2 tts vs = do + vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ overSoXSynthN34G n ampL dAmpl v2 tts vs vecB+ endFromResult ++-- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.+nGen3E5Gi :: Int -> FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> IO ()+nGen3E5Gi n file m ku ampL dAmpl v2 tts v3 = do + vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ overSoXSynthN35G n ampL dAmpl v2 tts v3 vecB+ endFromResult + +-- | Generalized version of the 'nGen3E5Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+nGen3E5GiPar :: Int -> FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> IO ()+nGen3E5GiPar n file params ampL dAmpl v2 tts v3 = do + vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ overSoXSynthN35G n ampL dAmpl v2 tts v3 vecB+ endFromResult ++-- | 4G generalized function for 'overSoXSynthNGen3E' where you provide your own 'Durations'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthNGen3E4G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> IO ()+overSoXSynthNGen3E4G file m ku ampL dAmpl v2 tts vs = do+ n <- duration1000 file+ nGen3E4Gi n file m ku ampL dAmpl v2 tts vs++-- | Generalized version of the 'overSoXSynthNGen3E4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGen3E4GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> IO ()+overSoXSynthNGen3E4GPar file params ampL dAmpl v2 tts vs = do+ n <- duration1000 file+ nGen3E4GiPar n file params ampL dAmpl v2 tts vs ++-- | 5G generalized function for 'overSoXSynthNGen3E4G' where you provide your own 'Intervals'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthNGen3E5G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> IO ()+overSoXSynthNGen3E5G file m ku ampL dAmpl v2 tts v3 = do+ n <- duration1000 file+ nGen3E5Gi n file m ku ampL dAmpl v2 tts v3 ++-- | Generalized version of the 'overSoXSynthNGen3E5G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGen3E5GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> IO ()+overSoXSynthNGen3E5GPar file params ampL dAmpl v2 tts v3 = do+ n <- duration1000 file+ nGen3E5GiPar n file params ampL dAmpl v2 tts v3 ++-- | Variant of the 'overSoXSynthNGen3E5G' where 'Intervals' are obtained from the basic 'Intervals' with the length no more than 29 and a Ukrainian text +-- specified as the last 'String' argument so that you can produce 'Intervals' of the arbitrary length. For more information, please, refer to +-- 'intervalsFromStringG' and 'strToIntG'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthNGen3E5GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> IO ()+overSoXSynthNGen3E5GS file m ku ampL time3 dAmpl zs tts v3 vs = do+ n <- duration1000 file+ nGen3E5Gi n file m ku ampL dAmpl (str2Durations zs time3) tts (intervalsFromStringG v3 vs)++-- | Generalized version of the 'overSoXSynthNGen3E5GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGen3E5GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> Intervals -> String -> IO ()+overSoXSynthNGen3E5GSPar file params ampL time3 dAmpl zs tts v3 vs = do+ n <- duration1000 file+ nGen3E5GiPar n file params ampL dAmpl (str2Durations zs time3) tts (intervalsFromStringG v3 vs) + +-- | 6G generalized function for 'overSoXSynthNGen3E5G' where you provide your own 'Strengths'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthNGen3E6G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> Strengths -> Double -> IO ()+overSoXSynthNGen3E6G file m ku ampL dAmpl v2 tts v3 v6 limV = + overSoXSynthNGen3E5G file m ku ampL dAmpl v2 tts v3 >> apply6G2 v6 "221w" "result" limV >> endFromResult++-- | Generalized version of the 'overSoXSynthNGen3E6G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGen3E6GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> Strengths -> Double -> IO ()+overSoXSynthNGen3E6GPar file params ampL dAmpl v2 tts v3 v6 limV = + overSoXSynthNGen3E5GPar file params ampL dAmpl v2 tts v3 >> apply6G2 v6 "221w" "result" limV >> endFromResult ++-- | A variant of 'overSoXSynthNGen3E6G' where 'Strengths' are obtained from a Ukrainian text specified as the last 'String' argument. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthNGen3E6GS :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> Intervals -> String -> Double -> IO ()+overSoXSynthNGen3E6GS file m ku ampL dAmpl v2 tts v3 xxs limV = overSoXSynthNGen3E6G file m ku ampL dAmpl v2 tts v3 (str2Volume xxs) limV++-- | Generalized version of the 'overSoXSynthNGen3E6GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGen3E6GSPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> Intervals -> String -> Double -> IO ()+overSoXSynthNGen3E6GSPar file params ampL dAmpl v2 tts v3 xxs limV = overSoXSynthNGen3E6GPar file params ampL dAmpl v2 tts v3 (str2Volume xxs) limV++-- | A variant of 'overSoXSynthNGen3E6GS' where 'Strengths' and 'Durations' are obtained from the same Ukrainian text specified as +-- the last 'String' argument. The third 'Double' argument is an average duration of the sounds in seconds. +-- Note that 'Int' arguments are used by 'liftInEnku' in that order so it returns a 'Maybe' number (actually frequency) for +-- the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+overSoXSynthNGen3E6GSu :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> Intervals -> String -> Double -> IO ()+overSoXSynthNGen3E6GSu file m ku ampL dAmpl time3 tts v3 xxs = overSoXSynthNGen3E6G file m ku ampL dAmpl (str2Durations xxs time3) tts v3 (str2Volume xxs)++-- | Generalized version of the 'overSoXSynthNGen3E6GSu' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+overSoXSynthNGen3E6GSuPar :: FilePath -> Params -> Double -> Double -> Double -> String -> Intervals -> String -> Double -> IO ()+overSoXSynthNGen3E6GSuPar file params ampL dAmpl time3 tts v3 xxs = overSoXSynthNGen3E6GPar file params ampL dAmpl (str2Durations xxs time3) tts v3 (str2Volume xxs)
+ DobutokO/Sound/Process.hs view
@@ -0,0 +1,272 @@+-- |+-- Module : DobutokO.Sound.Process+-- 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.Process (+ -- * Basic functions for the executable+ recAndProcess+ , processD1+ , processD2+ , d3H+ , d4H+ , d5H+ , d7H+ , d8H+ , d9H+) where++import Data.List (isPrefixOf)+import CaseBi (getBFst')+import Numeric (showFFloat)+import Control.Exception (onException)+import Data.Maybe (fromJust)+import Data.Char (isDigit,isSpace)+import System.Process+import EndOfExe (showE)+import qualified Data.Vector as V (fromList)+import System.Directory+import SoXBasics+import Processing_mmsyn7ukr++-- | Function records and processes the sound data needed to generate the \"end.wav\" file in the 'dobutokO2' function. Please, check before executing+-- whether there is no \"x.wav\" file in the current directory, because it can be overwritten.+recAndProcess :: FilePath -> Int -> IO String+recAndProcess file =+ 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),(99,processD99),(999,processD99)])++processD_1 :: IO String+processD_1 = onException (do+ putStr "Please, specify two \'Int\' numbers (with intermediate space character between them): the first one is a number of different notes there will be "+ putStr "in the result, and the second one is a number of enky, to which you would like all the main components (not taking into account their "+ putStr "respective lower bases of the intervals if any will exist) should belong. "+ putStrLn "If you specify as the first one 2 (possibly the simplest case), then to the second one you can define a number in the range [3..53]. "+ putStrLn "If you specify as the first one 3, then to the second one you can define a number in the range [2..35]. "+ putStrLn "If you specify as the first one 4, then to the second one you can define a number in the range [2..26]. "+ putStrLn "If you specify as the first one 6, then to the second one you can define a number in the range [1..17]. "+ putStrLn "If you specify as the first one 9, then to the second one you can define a number in the range [1..11]. "+ enka0 <- getLine+ let enka1 = take 2 . words . filter (\x -> isDigit x || isSpace x) $ enka0+ enka2 = read (head . take 1 $ enka1)::Int+ enka3+ | enka2 == 2 = if compare ((read (take 2 . head . tail $ enka1)::Int) `rem` 53) 3 == LT then 28 else (read (take 2 . head . tail $ enka1)::Int)+ `rem` 53+ | enka2 == 3 = if compare ((read (take 2 . head . tail $ enka1)::Int) `rem` 35) 2 == LT then 19 else (read (take 2 . head . tail $ enka1)::Int)+ `rem` 35+ | enka2 == 4 = if compare ((read (take 2 . head . tail $ enka1)::Int) `rem` 26) 2 == LT then 14 else (read (take 2 . head . tail $ enka1)::Int)+ `rem` 26+ | enka2 == 6 = if compare ((read (take 2 . head . tail $ enka1)::Int) `rem` 17) 1 == LT then 9 else (read (take 2 . head . tail $ enka1)::Int)+ `rem` 17+ | enka2 == 9 = if compare ((read (take 2 . head . tail $ enka1)::Int) `rem` 11) 1 == LT then 6 else (read (take 2 . head . tail $ enka1)::Int)+ `rem` 11+ | otherwise = error "Not valid number in the second place. "+ return $ show enka2 ++ " " ++ show enka3 ) (do+ putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."+ putStrLn "_______________________________________________________________________"+ processD3)+{-# INLINE processD_1 #-}++processD0 :: FilePath -> IO String+processD0 file = onException (readProcessWithExitCode (fromJust (showE "sox")) [file, "x.wav", "-r22050", "channels", "1"] "" >> putStrLn "" >> return "") (do+ exist <- doesFileExist "x.wav"+ if exist then removeFile "x.wav"+ else putStr ""+ putStrLn ""+ putStr "The process was not successful may be because of the not valid data OR SoX cannot convert the given file to the .wav format. "+ putStrLn "Interrupt the program and start again with the valid file. "+ putStrLn "_______________________________________________________________________"+ processD0 file)+{-# INLINE processD0 #-}+ +processD1 :: IO String+processD1 = onException (do+ tempeRa 0+ putStrLn "Please, specify, how many seconds long sound data you would like to record."+ time <- getLine+ let time0 = read (filter (\t -> isDigit t || t == '.') time)::Double+ putStrLn "Please, wait for 0.5 second and produce the needed sound now."+ recA "x.wav" time0+ putStrLn ""+ return "") (do+ dir0 <- listDirectory "."+ let paths5 = filter (isPrefixOf "nx.") dir0+ paths6 = filter (== "x.wav") dir0+ paths = paths5 ++ paths6+ mapM_ removeFile paths+ putStrLn ""+ putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."+ putStrLn "_______________________________________________________________________"+ processD1)+{-# INLINE processD1 #-}++processD2 :: FilePath -> IO String+processD2 file = onException (do + exist3 <- doesFileExist file+ if exist3 then return ""+ else do+ putStr "Please, specify the control parameter for the SoX \"noisered\" effect in the range from 0.0 to 1.0. "+ putStrLn "The greater value causes more reduction with possibly removing some important sound data. The default value is 0.5 "+ putStrLn "To use the default value, you can simply press Enter."+ ctrlN <- getLine+ let addit = dropWhile (/= '.') . filter (\t -> isDigit t || t == '.') $ ctrlN+ noiseP = if null ctrlN then ""+ else tail addit+ controlNoiseReduction $ '0':noiseP + norm "_x.wav" + if "nx." `isPrefixOf` file + then putStr "" + else renameFile "8_x.wav" file + removeFile "x.wav" + removeFile "_x.wav" + dir <- listDirectory "." + let paths4 = filter (isPrefixOf "nx.") dir+ mapM_ removeFile paths4 + putStrLn "" + return "") (do+ putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."+ putStrLn "_______________________________________________________________________"+ processD2 file)+{-# INLINE processD2 #-}++processD3 :: IO String+processD3 = onException (do+ putStr "Please, specify the octave number, to which you would like all the main components (not taking into account their respective lower pure quints) "+ putStrLn "should belong. The number should be better in the range [1..8]"+ fmap d3H getLine) (do+ putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."+ putStrLn "_______________________________________________________________________"+ processD3)+{-# INLINE processD3 #-}++d3H :: String -> String+d3H xs = show $ (read (take 1 xs)::Int) `rem` 9+{-# INLINE d3H #-}++processD4 :: IO String+processD4 = onException (do+ putStr "Please, specify the amplitude for the generated overtones as an Int number in the range [0..99]. "+ putStrLn "The default one is 99"+ putStrLn "To use the default value, you can simply press Enter."+ fmap d4H getLine) (do+ putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."+ putStrLn "_______________________________________________________________________"+ processD4)+{-# INLINE processD4 #-}++d4H :: String -> String+d4H xs+ | null xs = "1.0"+ | otherwise = let amplOb = (read (take 2 . filter isDigit $ xs)::Int) `rem` 100 in+ case amplOb of+ 99 -> "1.0"+ _ -> if compare (amplOb `quot` 9) 1 == LT then "0.0" ++ show (amplOb + 1)+ else "0." ++ show (amplOb + 1)+{-# INLINE d4H #-}++processD5 :: IO String+processD5 = onException (do+ putStr "Please, specify the basic duration for the generated sounds as a Double number in the range [0.1..4.0]. "+ putStrLn "The default one is 0.5"+ putStrLn "To use the default value, you can simply press Enter."+ fmap d5H getLine) (do+ putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."+ putStrLn "_______________________________________________________________________"+ processD5)+{-# INLINE processD5 #-}++d5H :: String -> String+d5H xs+ | null xs = "0.5"+ | otherwise = let time1 = (read (filter (\z -> isDigit z || z == '.') xs)::Double) in+ if compare time1 0.1 /= LT && compare time1 4.0 /= GT then showFFloat (Just 4) time1 $ show 0+ else let mantissa = time1 - (fromIntegral . truncate $ time1)+ ceilP = (truncate time1::Int) `rem` 4 in+ if ceilP == 0 then "0." ++ showFFloat (Just 4) mantissa (show 0)+ else show ceilP ++ "." ++ showFFloat (Just 4) mantissa (show 0)+{-# INLINE d5H #-}++processD7 :: IO String+processD7 = onException (do+ putStrLn "Please, input the Ukrainian text that will be used to define signs for the harmonics coefficients to produce a special timbre for the notes: "+ fmap d7H getLine) (do+ putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."+ putStrLn "_______________________________________________________________________"+ processD7)+{-# INLINE processD7 #-}++d7H :: String -> String+d7H xs+ | null xs = "або"+ | otherwise = xs+{-# INLINE d7H #-}++processD8 :: IO String+processD8 = onException (do+ putStr "Please, specify in how many times the amplitude for the second lower note (if any) is greater than the amplitude for the main note. "+ putStrLn "The number is in the range [0.1..2.0]. The default one is 1.0"+ putStrLn "To use the default value, you can simply press Enter."+ fmap d8H getLine) (do+ putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."+ putStrLn "_______________________________________________________________________"+ processD8)+{-# INLINE processD8 #-}++d8H :: String -> String+d8H xs+ | null xs = "1.0"+ | otherwise = let dAmpl1 = (read (filter (\z -> isDigit z || z == '.') xs)::Double) in+ if compare dAmpl1 0.1 /= LT && compare dAmpl1 2.0 /= GT then showFFloat (Just 4) dAmpl1 $ show 0+ else let mantissa = dAmpl1 - (fromIntegral . truncate $ dAmpl1)+ ceilP = (truncate dAmpl1::Int) `rem` 2 in+ if ceilP == 0 then "0." ++ showFFloat (Just 4) mantissa (show 0)+ else show ceilP ++ "." ++ showFFloat (Just 4) mantissa (show 0)+{-# INLINE d8H #-}++processD9 :: IO String+processD9 = onException (do+ putStrLn "Please, input the Ukrainian text that will be used to define the intervals to be used to produce the lower note for the given main one. "+ putStrLn "The default one is \"й\". "+ putStrLn "To use the default value, you can simply press Enter."+ fmap d9H getLine) (do+ putStrLn "The process was not successful may be because of the not valid data. Please, specify the valid data as requested."+ putStrLn "_______________________________________________________________________"+ processD9)+{-# INLINE processD9 #-}++d9H :: String -> String+d9H xs+ | null xs = "й"+ | otherwise = xs+{-# INLINE d9H #-}++processD :: IO String+processD = onException (do+ putStrLn "Please, input the Ukrainian text that will be used to create a special timbre for the notes: "+ getLine) (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 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 indices 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 an "+ 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 the end of input (e. g. for Unices, it's probably Ctrl + D). "+ getContents) (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 #-}++---------------------------------------------------------------------------------------------- +
+ DobutokO/Sound/Uniq.hs view
@@ -0,0 +1,691 @@+-- |+-- Module : DobutokO.Sound.Uniq+-- 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.++{-# LANGUAGE BangPatterns #-}+{-# OPTIONS_GHC -threaded #-}++module DobutokO.Sound.Uniq (+ -- * Library and executable functions+ -- ** For the unique for the String structure timbre+ uniqOvertonesV+ , uniqOverSoXSynth+ , uniqOverSoXSynthN+ -- *** For the unique for the String structure timbre with different signs for harmonics coefficients+ , uniqOvertonesV2+ , uniqOverSoXSynth2+ , uniqOverSoXSynthN3+ , uniqOverSoXSynthN4+ -- *** Use a file for information+ , uniqOverSoXSynthNGen+ , uniqOverSoXSynthNGen3+ , uniqOverSoXSynthNGen4+ -- * Extended generation using enky functionality+ -- ** With usage of additional information in the Ukrainian text+ , uniqOverSoXSynthNGenE+ , uniqOverSoXSynthNGen3E+ , uniqOverSoXSynthNGen4E+ -- * New 4G functions to work with Durations+ , uniqOverSoXSynthN4G+ , uniqOverSoXSynthN34G+ , uniqOverSoXSynthN44G+ , uniqOverSoXSynthNGenE4G+ , uniqOverSoXSynthNGen3E4G+ , uniqOverSoXSynthNGen4E4G+ -- ** 4G with speech-like composition+ , uniqOverSoXSynthN4GS+ , uniqOverSoXSynthN34GS+ , uniqOverSoXSynthN44GS+ , uniqOverSoXSynthNGenE4GS+ , uniqOverSoXSynthNGen3E4GS+ , uniqOverSoXSynthNGen4E4GS+ -- * New 5G functions to work also with Intervals+ , uniqOverSoXSynthN45G+ , uniqOverSoXSynthNGen4E5G+ -- ** 5G with obtained from the text arbitraty length Intervals+ , uniqOverSoXSynthN45GS+ , uniqOverSoXSynthNGen4E5GS+ -- * New 6G function to work also with Strengths+ , uniqOverSoXSynthNGen4E6G+ -- ** 6G with obtained from the text arbitrary length Strengths+ , uniqOverSoXSynthN46GS+ , uniqOverSoXSynthN46GSu+ , uniqOverSoXSynthNGen4E6GS+ , uniqOverSoXSynthNGen4E6GSu+ -- ** With overtones obtained from the additional Ukrainian text+ , uniqOverSoXSynthNGenEPar+ , uniqOverSoXSynthNGenE4GSPar+ , uniqOverSoXSynthNGenE4GPar+ , uniqOverSoXSynthNGen3EPar+ , uniqOverSoXSynthNGen3E4GSPar+ , uniqOverSoXSynthNGen3E4GPar+ , uniqOverSoXSynthNGen4EPar+ , uniqOverSoXSynthNGen4E4GSPar+ , uniqOverSoXSynthNGen4E4GPar+ , uniqOverSoXSynthNGen4E5GPar+ , uniqOverSoXSynthNGen4E5GSPar+ , uniqOverSoXSynthNGen4E6GPar+ , uniqOverSoXSynthNGen4E6GSPar+ , uniqOverSoXSynthNGen4E6GSuPar+) where++import Numeric (showFFloat)+import Data.Maybe (isNothing,fromJust)+import qualified Data.Vector as V+import System.Process+import EndOfExe (showE)+import MMSyn7s+import DobutokO.Sound.Functional.Basics+import DobutokO.Sound.Functional.Params+import DobutokO.Sound.DIS5G6G++-- | For the given frequency of the note it generates a 'V.Vector' of the tuples, each one of which contains the harmonics' frequency and amplitude. For every given+-- 'String' structure of the uniqueness (see the documentation for @mmsyn7s@ package and its 'MMSyn7.Syllable' module) it produces the unique timbre.+uniqOvertonesV :: Double -> String -> OvertonesO+uniqOvertonesV note xs =+ let ys = uniquenessPeriods xs+ z = sum ys+ v = V.fromList . fmap (\y -> fromIntegral y / fromIntegral z) $ ys+ z2 = V.length v+ v2 = V.generate z2 (\i -> V.unsafeIndex v i / fromIntegral (i + 1)) in+ V.takeWhile (\(!u,!z) -> compare u (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.unsafeSlice 1 (z2 - 1) .+ V.zip (V.generate z2 (\i -> note * fromIntegral (i + 1))) $ v2++-- | For the given frequency of the note it generates a 'V.Vector' of the tuples, each one of which contains the harmonics' frequency and amplitude. For every given+-- first 'String' argument structure of the uniqueness (see the documentation for @mmsyn7s@ package and its 'MMSyn7.Syllable' module) it produces the unique timbre.+-- The second 'String' is used to produce the signs for harmonics coefficients.+uniqOvertonesV2 :: Double -> String -> String -> OvertonesO+uniqOvertonesV2 note xs ts = + let ys = uniquenessPeriods xs+ z = sum ys+ v = V.fromList . fmap (\y -> fromIntegral y / fromIntegral z) $ ys+ z2 = V.length v+ v2 = V.generate z2 (\i -> (V.unsafeIndex (V.map fromIntegral . signsFromString z2 $ ts) i) * V.unsafeIndex v i / fromIntegral (i + 1)) in+ V.takeWhile (\(!u,!z) -> compare u (V.unsafeIndex notes 107) /= GT && compare (abs z) 0.001 == GT) . V.filter (\(_, t4) -> t4 /= 0.0) .+ V.unsafeSlice 1 (z2 - 1) . V.zip (V.generate z2 (\i -> note * fromIntegral (i + 1))) $ v2+ +-- | For the given frequency and a Ukrainian text it generates a musical sound with the timbre obtained from the Ukrainian text (see the+-- documentation for @mmsyn7s@ package). The timbre for another given text usually differs, but can be the same. The last one is only+-- if the uniqueness structure and length are the same for both 'String'. Otherwise, they differs. This gives an opportunity to practically+-- and quickly synthesize differently sounding intervals. The main component of the sound includes the lower pure quint, which can be in+-- the same octave or in the one with the number lower by one. Please, check before executing +-- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.+uniqOverSoXSynth :: Double -> String -> IO ()+uniqOverSoXSynth x wws = do+ let note0 = closestNote x+ note1 = pureQuintNote note0+ v0 = uniqOvertonesV note0 wws+ v1 = uniqOvertonesV note1 wws+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test-.wav", "synth", "0.5","sine", showFFloat (Just 4) note0 "",+ "synth", "0.5","sine", "mix", showFFloat (Just 4) note1 "", "vol","0.5"] ""+ uniqOverSoXSynthHelp v0+ uniqOverSoXSynthHelp2 v1+ mixTest++uniqOverSoXSynthHelp1 :: String -> OvertonesO -> IO ()+uniqOverSoXSynthHelp1 xs = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", xs ++ show (i + 2) ++ ".wav", "synth", "0.5","sine", showFFloat (Just 4) noteN "", "vol", showFFloat (Just 4) amplN ""] "") ++uniqOverSoXSynthHelp :: OvertonesO -> IO ()+uniqOverSoXSynthHelp = uniqOverSoXSynthHelp1 "test0"++uniqOverSoXSynthHelp2 :: OvertonesO -> IO ()+uniqOverSoXSynthHelp2 = uniqOverSoXSynthHelp1 "test1"++-- | For the given frequency and a Ukrainian text it generates a musical sound with the timbre obtained from the Ukrainian text (see the+-- documentation for @mmsyn7s@ package). The timbre for another given text usually differs, but can be the same. The last one is only+-- if the uniqueness structure and length are the same for both 'String'. Otherwise, they differs. This gives an opportunity to practically+-- and quickly synthesize differently sounding intervals. The main component of the sound includes the lower pure quint, which can be in+-- the same octave or in the one with the number lower by one. Please, check before executing +-- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.+-- The second 'String' argument is used to define signs for the harmonics coefficients for Overtones.+uniqOverSoXSynth2 :: Double -> String -> String -> IO ()+uniqOverSoXSynth2 x wws tts = do+ let note0 = closestNote x+ note1 = pureQuintNote note0+ v0 = uniqOvertonesV2 note0 wws tts+ v1 = uniqOvertonesV2 note1 wws tts+ _ <- readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "test-.wav", "synth", "0.5","sine", showFFloat (Just 4) note0 "", "synth",+ "0.5","sine", "mix", showFFloat (Just 4) note1 "", "vol","0.5"] ""+ uniqOverSoXSynthHelp v0+ uniqOverSoXSynthHelp2 v1+ mixTest++-- | Function to create a melody for the given arguments. The first 'String' is used to provide a rhythm. The second one -- to provide a timbre.+-- The timbre for another given text usually differs, but can be the same. This gives an opportunity to practically and quickly+-- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones.+-- If it is set to 1.0 the overTones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in+-- their becoming more silent ones. The main component of the sound is in the given octave with a number given+-- by 'Int' parameter. Besides, another main component of the sound includes the lower pure quint, which can be in the same octave or in the one with+-- the number lower by one. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing+-- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.+uniqOverSoXSynthN :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN n ampL time3 zs = uniqOverSoXSynthN4G n ampL (str2DurationsDef n zs time3)++-- | Variant of the 'uniqOverSoXSynthN4G' function where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition.+uniqOverSoXSynthN4GS :: Int -> Double -> Double -> String -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN4GS n ampL time3 zs = uniqOverSoXSynthN4G n ampL (str2Durations zs time3)++-- | 4G generalized variant of the 'uniqOverSoXSynthN' where you specify your own 'Durations'.+uniqOverSoXSynthN4G :: Int -> Double -> Durations -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN4G n ampL v2 wws vec0+ | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "+ | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =+ let v21 = V.filter (/= 0.0) v2+ m = V.length v21+ zeroN = numVZeroesPre vec0 in V.imapM_ (\j x -> do + let note0 = closestNote x+ note1 = pureQuintNote note0+ v0 = uniqOvertonesV note0 wws+ v1 = uniqOvertonesV note1 wws+ uniqOverSoXSynthHelpN = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT + then showFFloat (Just 4) (amplN * ampL) "" else "0"] "")+ uniqOverSoXSynthHelpN2 = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT + then showFFloat (Just 4) (amplN * ampL) "" else "0"] "")+ soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" +++ prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "", "synth", showFFloat (Just 4) (V.unsafeIndex v2 (j `rem` m)) "","sine", "mix", showFFloat (Just 4) note02 "", "vol",+ if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""+ _ <- soxSynthHelpMain note0 note1+ uniqOverSoXSynthHelpN v0+ uniqOverSoXSynthHelpN2 v1+ mixTest2 zeroN j) vec0+ | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in+ if abs ampL1 < 0.01 then uniqOverSoXSynthN4G n 0.01 v2 wws vec0+ else uniqOverSoXSynthN4G n ampL1 v2 wws vec0++-- | Function to create a melody for the given arguments. The first 'String' is used to provide a rhythm. The second one -- to provide a timbre.+-- The timbre for another given text usually differs, but can be the same. This gives an opportunity to practically and quickly+-- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones.+-- If it is set to 1.0 the overTones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in+-- their becoming more silent ones. The main component of the sound is in the given octave with a number given+-- by 'Int' parameter. Besides, another main component of the sound includes the lower pure quint, which can be in the same octave or in the one with+-- the number lower by one. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing+-- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.+-- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.+uniqOverSoXSynthN3 :: Int -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN3 n ampL time3 zs = uniqOverSoXSynthN34G n ampL (str2DurationsDef n zs time3)++-- | Variant of the 'uniqOverSoXSynthN34G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition.+uniqOverSoXSynthN34GS :: Int -> Double -> Double -> String -> String -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN34GS n ampL time3 zs = uniqOverSoXSynthN34G n ampL (str2Durations zs time3)++-- | 4G generalized variant of the 'uniqOverSoXSynthN3' where you specify your own 'Durations'. +uniqOverSoXSynthN34G :: Int -> Double -> Durations -> String -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN34G n ampL v2 wws tts vec0+ | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "+ | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =+ let v21 = V.filter (/=0.0) v2+ m = V.length v2+ zeroN = numVZeroesPre vec0 in V.imapM_ (\j x -> do + let note0 = closestNote x -- zs ? vec0 -- are they related to the one object? No, they are obtained from different sources.+ note1 = pureQuintNote note0+ v0 = uniqOvertonesV2 note0 wws tts+ v1 = uniqOvertonesV2 note1 wws tts+ uniqOverSoXSynthHelpN vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec+ uniqOverSoXSynthHelpN2 vec = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") vec + soxSynthHelpMain note01 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" +++ prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "",+ "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", "mix", showFFloat (Just 4) note02 "", "vol",+ if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""+ _ <- soxSynthHelpMain note0 note1+ uniqOverSoXSynthHelpN v0+ uniqOverSoXSynthHelpN2 v1+ mixTest2 zeroN j) vec0+ | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in+ if abs ampL1 < 0.01 then uniqOverSoXSynthN34G n 0.01 v2 wws tts vec0+ else uniqOverSoXSynthN34G n ampL1 v2 wws tts vec0 ++-- | Function to create a melody for the given arguments. The first 'String' is used to provide a rhythm. The second one -- to provide a timbre.+-- The timbre for another given text usually differs, but can be the same. This gives an opportunity to practically and quickly+-- synthesize differently sounding intervals. The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones.+-- If it is set to 1.0 the overTones amplitudes are just maximum ones, otherwise they are multiplied by the parameter and this results in+-- their becoming more silent ones. The main component of the sound is in the given octave with a number given+-- by 'Int' parameter. Besides, another main component of the sound includes the lower pure quint, which can be in the same octave or in the one with+-- the number lower by one. The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). Please, check before executing+-- whether there is no \"x.wav\", \"test*\", \"result*\" files in the current directory, because they can be overwritten.+-- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.+-- The fourth 'String' argument is used to define the intervals for the notes if any.+-- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of+-- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones.+-- The last one is experimental feature.+uniqOverSoXSynthN4 :: Int -> Double -> Double -> Double -> String -> String -> String -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN4 n ampL time3 dAmpl zs = uniqOverSoXSynthN44G n ampL dAmpl (str2DurationsDef n zs time3)++-- | Variant of the 'uniqOverSoXSynthN44G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition.+uniqOverSoXSynthN44GS :: Int -> Double -> Double -> Double -> String -> String -> String -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN44GS n ampL time3 dAmpl zs = uniqOverSoXSynthN44G n ampL dAmpl (str2Durations zs time3)++-- | 4G generalized variant of the 'uniqOverSoXSynthN4' where you specify your own 'Durations'. +uniqOverSoXSynthN44G :: Int -> Double -> Double -> Durations -> String -> String -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN44G n ampL dAmpl v2 wws tts vs = uniqOverSoXSynthN45G n ampL dAmpl v2 wws tts (intervalsFromString vs)+ +-- | 5G generalized variant of the 'uniqOverSoXSynthN44G' where you specify your own 'Intervals'. +uniqOverSoXSynthN45G :: Int -> Double -> Double -> Durations -> String -> String -> Intervals -> V.Vector Double -> IO ()+uniqOverSoXSynthN45G n ampL dAmpl v2 wws tts v3 vec0+ | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "+ | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =+ let v21 = V.filter (/=0.0) v2+ m = V.length v2+ zeroN = numVZeroesPre vec0+ l = V.length v3 in V.imapM_ (\j x -> do + let note0 = closestNote x+ note1 = dNote (V.unsafeIndex v3 (j `rem` l)) note0+ v0 = uniqOvertonesV2 note0 wws tts+ v1 = if isNothing note1 then V.empty+ else uniqOvertonesV2 (fromJust note1) wws tts+ uniqOverSoXSynthHelpN = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine",showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") + uniqOverSoXSynthHelpN2 = V.imapM_ (\i (noteN, amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl * amplN * ampL > 1.0 then 1.0+ else dAmpl * amplN * ampL) "" else "0"] "") + soxSynthHelpMain0 note01 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" +++ prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "",+ "vol",if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""+ soxSynthHelpMain1 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB" +++ prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note02 "",+ "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / 2) "" else "0"] ""+ if isNothing note1 then do { _ <- soxSynthHelpMain0 note0+ ; uniqOverSoXSynthHelpN v0 }+ else do { _ <- soxSynthHelpMain0 note0+ ; _ <- soxSynthHelpMain1 (fromJust note1)+ ; uniqOverSoXSynthHelpN v0+ ; uniqOverSoXSynthHelpN2 v1}+ mixTest2 zeroN j) vec0+ | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in+ if abs ampL1 < 0.01 then uniqOverSoXSynthN45G n 0.01 dAmpl v2 wws tts v3 vec0+ else uniqOverSoXSynthN45G n ampL1 dAmpl v2 wws tts v3 vec0 ++-- | 6G generalized variant of the 'uniqOverSoXSynthN45G' where you specify your own 'Strengths' and a limit (as the last 'Double') when less volume level +-- sound files are treated as a silent ones and are not adjusted. +uniqOverSoXSynthN46G :: Int -> Double -> Double -> Durations -> String -> String -> Intervals -> V.Vector Double -> Strengths -> Double -> IO ()+uniqOverSoXSynthN46G n ampL dAmpl v2 wws tts v3 vec0 v6 limV+ | V.all (== 0.0) v2 = putStrLn "You provided no valid durations data! "+ | V.null v6 = putStrLn "You did not provide a volume adjustments vector! "+ | compare (abs ampL) 0.01 /= LT && compare (abs ampL) 1.0 /= GT =+ let v21 = V.filter (/=0.0) v2+ m = V.length v2+ zeroN = numVZeroesPre vec0+ l = V.length v3 in V.imapM_ (\j x -> do + let note0 = closestNote x+ note1 = dNote (V.unsafeIndex v3 (j `rem` l)) note0+ v0 = uniqOvertonesV2 note0 wws tts+ v1 = if isNothing note1 then V.empty+ else uniqOvertonesV2 (fromJust note1) wws tts+ uniqOverSoXSynthHelpN = V.imapM_ (\i (noteN, !amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "test" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine",showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (amplN * ampL) "" else "0"] "") + uniqOverSoXSynthHelpN2 = V.imapM_ (\i (noteN, amplN) -> readProcessWithExitCode (fromJust (showE "sox"))+ ["-r22050", "-n", "testQ" ++ prependZeroes zeroN (show (i + 2)) ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "",+ "sine", showFFloat (Just 4) noteN "", "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl * amplN * ampL > 1.0 then 1.0+ else dAmpl * amplN * ampL) "" else "0"] "") + soxSynthHelpMain0 note01 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testA" +++ prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note01 "",+ "vol",if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then "0.5" else "0"] ""+ soxSynthHelpMain1 note02 = readProcessWithExitCode (fromJust (showE "sox")) ["-r22050", "-n", "testB" +++ prependZeroes zeroN "1" ++ ".wav", "synth", showFFloat (Just 4) (abs (V.unsafeIndex v21 (j `rem` m))) "","sine", showFFloat (Just 4) note02 "",+ "vol", if compare (V.unsafeIndex v21 (j `rem` m)) 0.0 == GT then showFFloat (Just 4) (if dAmpl > 0.5 then 0.5 else dAmpl / 2) "" else "0"] ""+ if isNothing note1 then do { _ <- soxSynthHelpMain0 note0+ ; uniqOverSoXSynthHelpN v0 }+ else do { _ <- soxSynthHelpMain0 note0+ ; _ <- soxSynthHelpMain1 (fromJust note1)+ ; uniqOverSoXSynthHelpN v0+ ; uniqOverSoXSynthHelpN2 v1}+ mixTest2 zeroN j+ apply6GSilentFile ("result" ++ prependZeroes zeroN (show j) ++ ".wav") limV (V.unsafeIndex v6 (j `rem` V.length v6))) vec0+ | otherwise = let ampL1 = ampL - (fromIntegral . truncate $ ampL) in+ if abs ampL1 < 0.01 then uniqOverSoXSynthN46G n 0.01 dAmpl v2 wws tts v3 vec0 v6 limV+ else uniqOverSoXSynthN46G n ampL1 dAmpl v2 wws tts v3 vec0 v6 limV++-- | Variant of the 'uniqOverSoXSynthN45G' where 'Intervals' are obtained from the 'String' using 'intervalsFromStringG' function. Helps to create a speech-like +-- composition.+uniqOverSoXSynthN45GS :: Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> V.Vector Double -> IO ()+uniqOverSoXSynthN45GS n ampL time3 dAmpl zs wws tts v3 vs = uniqOverSoXSynthN45G n ampL dAmpl (str2Durations zs time3) wws tts (intervalsFromStringG v3 vs) ++-- | Variant of the 'uniqOverSoXSynthN46G' where 'Strengths' are obtained from the 'String' using 'str2Volume' function. Helps to create a speech-like +-- composition.+uniqOverSoXSynthN46GS :: Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> V.Vector Double -> String ->+ Double -> IO ()+uniqOverSoXSynthN46GS n ampL time3 dAmpl zs wws tts v3 vs vec0 xxs limV = uniqOverSoXSynthN46G n ampL dAmpl (str2Durations zs time3) wws tts + (intervalsFromStringG v3 vs) vec0 (str2Volume xxs) limV++-- | A variant of 'uniqOverSoXSynthN46GS' where 'Strengths' and 'Durations' are obtained from the same Ukrainian text specified as +-- the last 'String' argument. The second 'Double' argument is an average duration of the sounds in seconds. +-- Note that 'Int' arguments are used by 'liftInEnku' in that order so it returns a 'Maybe' number (actually frequency) for +-- the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthN46GSu :: Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> V.Vector Double -> String -> Double -> IO ()+uniqOverSoXSynthN46GSu n ampL time3 dAmpl wws tts v5 vs vec0 xxs limV = + uniqOverSoXSynthN46G n ampL dAmpl (str2Durations xxs time3) wws tts (intervalsFromStringG v5 vs) vec0 (str2Volume xxs) limV++-- | Similar to 'uniqOverSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. +-- Besides, the function lifts the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]).+-- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the+-- overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones.+-- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.+--+-- For better usage the 'FilePath' should be a filepath for the .wav file.+uniqOverSoXSynthNGen :: FilePath -> Int -> Double -> Double -> String -> String -> IO ()+uniqOverSoXSynthNGen file m = uniqOverSoXSynthNGenE file m 12++-- | Similar to 'uniqOverSoXSynthNGen', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOverSoXSynthNGen'. To obtain+-- its modifications, please, use 2, 3, 4, 6, or 9. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGenE :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()+uniqOverSoXSynthNGenE file m ku ampL time3 zs wws = do+ n <- duration1000 file+ unGenNE4Gi n file m ku ampL (str2DurationsDef n zs time3) wws++-- | Generalized version of the 'uniqOverSoXSynthNGenE' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGenEPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()+uniqOverSoXSynthNGenEPar file params ampL time3 zs wws = do+ n <- duration1000 file+ unGenNE4GiPar n file params ampL (str2DurationsDef n zs time3) wws ++-- | Variant of the 'uniqOverSoXSynthNGenE4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGenE4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> IO ()+uniqOverSoXSynthNGenE4GS file m ku ampL time3 zs wws = do+ n <- duration1000 file+ unGenNE4Gi n file m ku ampL (str2Durations zs time3) wws+ +-- | Generalized version of the 'uniqOverSoXSynthNGenE4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGenE4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> IO ()+uniqOverSoXSynthNGenE4GSPar file params ampL time3 zs wws = do+ n <- duration1000 file+ unGenNE4GiPar n file params ampL (str2Durations zs time3) wws ++-- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.+unGenNE4Gi :: Int -> FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()+unGenNE4Gi n file m ku ampL v2 wws = do+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ uniqOverSoXSynthN4G n ampL v2 wws vecB+ endFromResult++-- | Generalized version of the 'unGenNE4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+unGenNE4GiPar :: Int -> FilePath -> Params -> Double -> Durations -> String -> IO ()+unGenNE4GiPar n file params ampL v2 wws = do+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ uniqOverSoXSynthN4G n ampL v2 wws vecB+ endFromResult ++-- | 4G genaralized version of the 'uniqOverSoXSynthNGenE' where you provide your own 'Durations'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGenE4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> IO ()+uniqOverSoXSynthNGenE4G file m ku ampL v2 wws = do+ n <- duration1000 file+ unGenNE4Gi n file m ku ampL v2 wws++-- | Generalized version of the 'uniqOverSoXSynthNGenE4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGenE4GPar :: FilePath -> Params -> Double -> Durations -> String -> IO ()+uniqOverSoXSynthNGenE4GPar file params ampL v2 wws = do+ n <- duration1000 file+ unGenNE4GiPar n file params ampL v2 wws ++-- | Similar to 'uniqOverSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. +-- Besides, the function lifts the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]).+-- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the+-- overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones.+-- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.+--+-- For better usage the 'FilePath' should be a filepath for the .wav file.+-- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.+uniqOverSoXSynthNGen3 :: FilePath -> Int -> Double -> Double -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen3 file m = uniqOverSoXSynthNGen3E file m 12++-- | Similar to 'uniqOverSoXSynthNGen3', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOverSoXSynthNGen3'. To obtain+-- its modifications, please, use 2, 3, 4, 6, or 9. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGen3E :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen3E file m ku ampL time3 zs wws tts = do+ n <- duration1000 file+ unGenN3E4Gi n file m ku ampL (str2DurationsDef n zs time3) wws tts++-- | Generalized version of the 'uniqOverSoXSynthNGen3E' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGen3EPar :: FilePath -> Params -> Double -> Double -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen3EPar file params ampL time3 zs wws tts = do+ n <- duration1000 file+ unGenN3E4GiPar n file params ampL (str2DurationsDef n zs time3) wws tts ++-- | Variant of the 'uniqOverSoXSynthNGen3E4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGen3E4GS :: FilePath -> Int -> Int -> Double -> Double -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen3E4GS file m ku ampL time3 zs wws tts = do+ n <- duration1000 file+ unGenN3E4Gi n file m ku ampL (str2Durations zs time3) wws tts++-- | Generalized version of the 'uniqOverSoXSynthNGen3E4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGen3E4GSPar :: FilePath -> Params -> Double -> Double -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen3E4GSPar file params ampL time3 zs wws tts = do+ n <- duration1000 file+ unGenN3E4GiPar n file params ampL (str2Durations zs time3) wws tts++-- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.+unGenN3E4Gi :: Int -> FilePath -> Int -> Int -> Double -> Durations -> String -> String -> IO ()+unGenN3E4Gi n file m ku ampL v2 wws tts = do+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ uniqOverSoXSynthN34G n ampL v2 wws tts vecB+ endFromResult++-- | Generalized version of the 'unGenN3E4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+unGenN3E4GiPar :: Int -> FilePath -> Params -> Double -> Durations -> String -> String -> IO ()+unGenN3E4GiPar n file params ampL v2 wws tts = do+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ uniqOverSoXSynthN34G n ampL v2 wws tts vecB+ endFromResult ++-- | 4G genaralized version of the 'uniqOverSoXSynthNGen3E' where you provide your own 'Durations'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGen3E4G :: FilePath -> Int -> Int -> Double -> Durations -> String -> String -> IO ()+uniqOverSoXSynthNGen3E4G file m ku ampL v2 wws tts = do+ n <- duration1000 file+ unGenN3E4Gi n file m ku ampL v2 wws tts+ +-- | Generalized version of the 'uniqOverSoXSynthNGen3E4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGen3E4GPar :: FilePath -> Params -> Double -> Durations -> String -> String -> IO ()+uniqOverSoXSynthNGen3E4GPar file params ampL v2 wws tts = do+ n <- duration1000 file+ unGenN3E4GiPar n file params ampL v2 wws tts ++-- | Similar to 'uniqOverSoXSynthN', but uses a sound file to obtain the information analogous to 'V.Vector' in the latter one. +-- Besides, the function lifts the frequencies to the octave with the given by 'Int' parameter number (better to use from the range [1..8]).+-- The first 'Double' argument from the range [0.01..1.0] is used as a maximum amplitude for Overtones. If it is set to 1.0 the+-- overTones amplitudes are just the maximum ones, otherwise they are multiplied by the parameter and this results in their becoming more silent ones.+-- The second 'Double' argument is a basic sound duration. The default one is 0.5 (second). 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.+--+-- For better usage the 'FilePath' should be a filepath for the .wav file.+-- The third 'String' argument is used to define signs of the harmonics coefficients in the generated sounds.+-- The fourth 'String' argument is used to define the intervals for the notes if any.+-- The third 'Double' parameter basically is used to define in how many times the volume for the second lower note is less than the volume of+-- the main note. If it is rather great, it can signal that the volume for the second note overTones are greater than for the main note obetones.+-- The last one is an experimental feature.+uniqOverSoXSynthNGen4 :: FilePath -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen4 file m = uniqOverSoXSynthNGen4E file m 12++-- | Similar to 'uniqOverSoXSynthNGen4', but uses additional second 'Int' parameter. It defines, to which n-th elements set (see 'nkyT') belongs the obtained+-- higher notes in the intervals. If that parameter equals to 12, then the function is practically equivalent to 'uniqOverSoXSynthNGen4'. To obtain+-- its modifications, please, use 2, 3, 4, 6, or 9. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGen4E :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen4E file m ku ampL time3 dAmpl zs wws tts vs = do+ n <- duration1000 file+ unGenN4E4Gi n file m ku ampL dAmpl (str2DurationsDef n zs time3) wws tts vs++-- | Generalized version of the 'uniqOverSoXSynthNGen4E' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGen4EPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen4EPar file params ampL time3 dAmpl zs wws tts vs = do+ n <- duration1000 file+ unGenN4E4GiPar n file params ampL dAmpl (str2DurationsDef n zs time3) wws tts vs ++-- | Variant of the 'uniqOverSoXSynthNGen4E4G' where 'Durations' are obtained from the 'String' using 'str2Durations' function. Helps to create a speech-like +-- composition. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGen4E4GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen4E4GS file m ku ampL time3 dAmpl zs wws tts vs = do+ n <- duration1000 file+ unGenN4E4Gi n file m ku ampL dAmpl (str2Durations zs time3) wws tts vs++-- | Generalized version of the 'uniqOverSoXSynthNGen4E4GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGen4E4GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen4E4GSPar file params ampL time3 dAmpl zs wws tts vs = do+ n <- duration1000 file+ unGenN4E4GiPar n file params ampL dAmpl (str2Durations zs time3) wws tts vs ++-- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.+unGenN4E4Gi :: Int -> FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> String -> IO ()+unGenN4E4Gi n file m ku ampL dAmpl v2 wws tts vs = do+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ uniqOverSoXSynthN44G n ampL dAmpl v2 wws tts vs vecB+ endFromResult++-- | Generalized version of the 'unGenN4E4Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+unGenN4E4GiPar :: Int -> FilePath -> Params -> Double -> Double -> Durations -> String -> String -> String -> IO ()+unGenN4E4GiPar n file params ampL dAmpl v2 wws tts vs = do+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ uniqOverSoXSynthN44G n ampL dAmpl v2 wws tts vs vecB+ endFromResult ++-- | Note that the last two 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The third 'Int' parameter defines that @n@.+unGenN4E5Gi :: Int -> FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()+unGenN4E5Gi n file m ku ampL dAmpl v2 wws tts v3 = do+ vecA <- freqsFromFile file n+ let vecB = liftInEnkuV m ku . V.map fromIntegral . V.filter (/= (11440::Int)) $ vecA+ uniqOverSoXSynthN45G n ampL dAmpl v2 wws tts v3 vecB+ endFromResult++-- | Generalized version of the 'unGenN4E5Gi' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+unGenN4E5GiPar :: Int -> FilePath -> Params -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()+unGenN4E5GiPar n file params ampL dAmpl v2 wws tts v3 = do+ vecA <- freqsFromFile file n+ let vecB = liftInParamsV params . V.map fromIntegral $ vecA+ uniqOverSoXSynthN45G n ampL dAmpl v2 wws tts v3 vecB+ endFromResult + +-- | 4G genaralized version of the 'uniqOverSoXSynthNGen4E' where you provide your own 'Durations'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGen4E4G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen4E4G file m ku ampL dAmpl v2 wws tts vs = do+ n <- duration1000 file+ unGenN4E4Gi n file m ku ampL dAmpl v2 wws tts vs++-- | Generalized version of the 'uniqOverSoXSynthNGen4E4G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGen4E4GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> String -> IO ()+uniqOverSoXSynthNGen4E4GPar file params ampL dAmpl v2 wws tts vs = do+ n <- duration1000 file+ unGenN4E4GiPar n file params ampL dAmpl v2 wws tts vs++-- | 5G genaralized version of the 'uniqOverSoXSynthNGen4E' where you provide your own 'Durations' and 'Intervals'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGen4E5G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()+uniqOverSoXSynthNGen4E5G file m ku ampL dAmpl v2 wws tts v3 = do+ n <- duration1000 file+ unGenN4E5Gi n file m ku ampL dAmpl v2 wws tts v3++-- | Generalized version of the 'uniqOverSoXSynthNGen4E5G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGen4E5GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> Intervals -> IO ()+uniqOverSoXSynthNGen4E5GPar file params ampL dAmpl v2 wws tts v3 = do+ n <- duration1000 file+ unGenN4E5GiPar n file params ampL dAmpl v2 wws tts v3 ++-- | Variant of the 'uniqOverSoXSynthNGen4E5G' where 'Intervals' are obtained from the 'String' using 'intervalsFromStringG' function. Helps to create a speech-like +-- composition. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGen4E5GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> IO ()+uniqOverSoXSynthNGen4E5GS file m ku ampL time3 dAmpl zs wws tts v3 vs = do+ n <- duration1000 file+ unGenN4E5Gi n file m ku ampL dAmpl (str2Durations zs time3) wws tts (intervalsFromStringG v3 vs)++-- | Generalized version of the 'uniqOverSoXSynthNGen4E5GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGen4E5GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> IO ()+uniqOverSoXSynthNGen4E5GSPar file params ampL time3 dAmpl zs wws tts v3 vs = do+ n <- duration1000 file+ unGenN4E5GiPar n file params ampL dAmpl (str2Durations zs time3) wws tts (intervalsFromStringG v3 vs) ++-- | 6G generalized function for 'uniqOverSoXSynthNGen4E5G' where you provide your own 'Strengths'. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGen4E6G :: FilePath -> Int -> Int -> Double -> Double -> Durations -> String -> String -> Intervals -> Strengths -> Double -> IO ()+uniqOverSoXSynthNGen4E6G file m ku ampL dAmpl v2 wws tts v3 v6 limV = + uniqOverSoXSynthNGen4E5G file m ku ampL dAmpl v2 wws tts v3 >> apply6G2 v6 "221w" "result" limV >> endFromResult++-- | Generalized version of the 'uniqOverSoXSynthNGen4E6G' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGen4E6GPar :: FilePath -> Params -> Double -> Double -> Durations -> String -> String -> Intervals -> Strengths -> Double -> IO ()+uniqOverSoXSynthNGen4E6GPar file params ampL dAmpl v2 wws tts v3 v6 limV = + uniqOverSoXSynthNGen4E5GPar file params ampL dAmpl v2 wws tts v3 >> apply6G2 v6 "221w" "result" limV >> endFromResult ++-- | A variant of 'uniqOverSoXSynthNGen4E6G' where 'Strengths' are obtained from a Ukrainian text specified as the last 'String' argument. Note that 'Int' arguments are used by 'liftInEnku' in that order so it +-- returns a 'Maybe' number (actually frequency) for the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGen4E6GS :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> + String -> Double -> IO ()+uniqOverSoXSynthNGen4E6GS file m ku ampL time3 dAmpl zs wws tts v5 vs xxs limV = + uniqOverSoXSynthNGen4E6G file m ku ampL dAmpl (str2Durations zs time3) wws tts (intervalsFromStringG v5 vs) (str2Volume xxs) limV++-- | Generalized version of the 'uniqOverSoXSynthNGen4E6GS' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGen4E6GSPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> String -> Intervals -> String -> + String -> Double -> IO ()+uniqOverSoXSynthNGen4E6GSPar file params ampL time3 dAmpl zs wws tts v5 vs xxs limV = + uniqOverSoXSynthNGen4E6GPar file params ampL dAmpl (str2Durations zs time3) wws tts (intervalsFromStringG v5 vs) (str2Volume xxs) limV + +-- | A variant of 'uniqOverSoXSynthNGen4E6GS' where 'Strengths' and 'Durations' are obtained from the same Ukrainian text specified as +-- the last 'String' argument. The second 'Double' argument is an average duration of the sounds in seconds. +-- Note that 'Int' arguments are used by 'liftInEnku' in that order so it returns a 'Maybe' number (actually frequency) for +-- the n-th elements set of notes (see 'nkyT'). The second 'Int' parameter defines that @n@.+uniqOverSoXSynthNGen4E6GSu :: FilePath -> Int -> Int -> Double -> Double -> Double -> String -> String -> Intervals -> String -> String -> Double -> IO ()+uniqOverSoXSynthNGen4E6GSu file m ku ampL time3 dAmpl wws tts v5 vs xxs limV = + uniqOverSoXSynthNGen4E6G file m ku ampL dAmpl (str2Durations xxs time3) wws tts (intervalsFromStringG v5 vs) (str2Volume xxs) limV+ +-- | Generalized version of the 'uniqOverSoXSynthNGen4E6GSu' where instead of lifting with 'liftInEnkuV' 'liftInParamsV' is used. It allows e. g. to +-- use some tonality. For more information, please, refer to 'filterInParams'.+uniqOverSoXSynthNGen4E6GSuPar :: FilePath -> Params -> Double -> Double -> Double -> String -> String -> Intervals -> String -> String -> Double -> IO ()+uniqOverSoXSynthNGen4E6GSuPar file params ampL time3 dAmpl wws tts v5 vs xxs limV = + uniqOverSoXSynthNGen4E6GPar file params ampL dAmpl (str2Durations xxs time3) wws tts (intervalsFromStringG v5 vs) (str2Volume xxs) limV
README.markdown view
@@ -279,3 +279,10 @@ a special reencoding using lazy bytestrings. For more information, please, refer to DobutokO.Sound.Keyboard module. +Since 0.41.0.0 version the module structure is completely changed: there were added +new ones and rearranged the existing, module DobutokO.Sound splitted into three +different modules: DobutokO.Sound.Overtones, DobutokO.Sound.Uniq and +DobutokO.Sound.Octaves. This was done to simplify compilation and to produce more +logical and semantic structure. The most complicated functions from +DobutokO.Sound.Functional module are moved to a new package dobutokO3. Some code +improvements.
dobutokO2.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: dobutokO2-version: 0.40.0.0+version: 0.41.0.0 synopsis: Helps to create experimental music from a file (or its part) and a Ukrainian text. description: It can also generate 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, DobutokO.Sound.ParseList, DobutokO.Sound.Keyboard+ exposed-modules: Main, DobutokO.Sound.Overtones, DobutokO.Sound.Uniq, DobutokO.Sound.Functional, DobutokO.Sound.Process, DobutokO.Sound.Executable, DobutokO.Sound.IntermediateF, DobutokO.Sound.ParseList, DobutokO.Sound.Keyboard, DobutokO.Sound.Functional.Basics, DobutokO.Sound.Functional.Params, DobutokO.Sound.Functional.Split, DobutokO.Sound.DIS5G6G, DobutokO.Sound.Functional.Elements, DobutokO.Sound.Decibel, DobutokO.Sound.Extended, DobutokO.Sound.Octaves, DobutokO.Sound.FunctionF -- other-modules: -- other-extensions: build-depends: base >=4.7 && <4.15, bytestring >= 0.10.6 && <1, vector >=0.11 && <0.14, process >=1.4 && <1.9, mmsyn3 >=0.1.5 && <1, mmsyn7s >=0.6.7 && <1, directory >=1.2.7 && <1.7, mmsyn7ukr >=0.15.4 && <1, mmsyn2 >=0.1.8 && <1, mmsyn6ukr >=0.7.2 && <1, mmsyn7l >=0.5 && <1