mmsyn6ukr (empty) → 0.1.0.0
raw patch · 41 files changed
+424/−0 lines, 41 filesdep +basedep +bytestringdep +mmsyn2setup-changedbinary-added
Dependencies added: base, bytestring, mmsyn2, mmsyn5, process, vector
Files
- 0.wav binary
- 1.wav binary
- A.wav binary
- B.wav binary
- C.wav binary
- ChangeLog.md +5/−0
- D.wav binary
- E.wav binary
- F.wav binary
- G.wav binary
- H.wav binary
- I.wav binary
- J.wav binary
- K.wav binary
- L.wav binary
- LICENSE +20/−0
- M.wav binary
- Main.hs +39/−0
- Melodics/Ukrainian.hs +313/−0
- N.wav binary
- O.wav binary
- P.wav binary
- Q.wav binary
- R.wav binary
- README.md +16/−0
- S.wav binary
- Setup.hs +2/−0
- T.wav binary
- U.wav binary
- V.wav binary
- W.wav binary
- X.wav binary
- Y.wav binary
- Z.wav binary
- a.wav binary
- b.wav binary
- c.wav binary
- d.wav binary
- e.wav binary
- f.wav binary
- mmsyn6ukr.cabal +29/−0
binary file changed (absent → 2294 bytes)
binary file changed (absent → 6792 bytes)
binary file changed (absent → 6140 bytes)
binary file changed (absent → 2562 bytes)
binary file changed (absent → 4204 bytes)
@@ -0,0 +1,5 @@+# Revision history for mmsyn6ukr++## 0.1.0.0 -- 2019-11-23++* First version. Released on an unsuspecting world.
binary file changed (absent → 3432 bytes)
binary file changed (absent → 3222 bytes)
binary file changed (absent → 2190 bytes)
binary file changed (absent → 2496 bytes)
binary file changed (absent → 4172 bytes)
binary file changed (absent → 3158 bytes)
binary file changed (absent → 2506 bytes)
binary file changed (absent → 4452 bytes)
binary file changed (absent → 3232 bytes)
@@ -0,0 +1,20 @@+Copyright (c) 2019 OleksandrZhabenko++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
binary file changed (absent → 2070 bytes)
@@ -0,0 +1,39 @@+-- |+-- Module : Main+-- Copyright : (c) OleksandrZhabenko 2019+-- License : MIT+--+-- Maintainer : olexandr543@yahoo.com+--+-- A program that can be used as a musical instrument synthesizer or for Ukrainian speech synthesis +-- especially for poets, translators and writers. +--+++module Main where++--import Data.Maybe (isJust,fromJust)+import System.IO +import System.Environment+--import System.Process+--import EndOfExe+import Paths_mmsyn6ukr+import Melodics.Ukrainian++{-+-- Inspired by: https://mail.haskell.org/pipermail/beginners/2011-October/008649.html+-}++main :: IO ()+main = do+ args <- getArgs+ putStrLn "Please, specify the name of the resulting sound file! Please, do NOT use '}' character and space characters!"+ nameOfSoundFile <- getLine+ xs <- getContents+ let ys = take (nSymbols (let zs = take 1 args in if null zs then [] else head zs)) xs in do+ withBinaryFile (nameOfSoundFile ++ ".raw") AppendMode (appendS16LEFile (convertToProperUkrainian ys))+ putStr "You have a resulting file, which name begins with \"new.\" in a raw PCM format with bitrate 22050 Hz and 1 channel (mono) in the .dat format. "+ putStr "You can further process it by yourself manually, otherwise, please, install FFMpeg or LibAV executables in the directory mentioned in the variable PATH"+ putStrLn " and then run: "+ putStrLn "\"name_of_FFMpeg_or_LibAV_executable\" -f s16le -acodec pcm_s16le -ac 1 -ar 22050 -i \"name_Of_the_sound_file\" \"the_same_name_without_.dat_ending_and_with_.wav_ending\""+
@@ -0,0 +1,313 @@+-- |+-- Module : Melodics.Ukrainian+-- Copyright : (c) OleksandrZhabenko 2019+-- License : MIT+--+-- Maintainer : olexandr543@yahoo.com+--+-- A program that can be used as a musical instrument synthesizer or for Ukrainian speech synthesis +-- especially for poets, translators and writers. +--+++module Melodics.Ukrainian where++import Data.Char+import Data.List (groupBy)+import qualified Data.Vector as V+import qualified Data.ByteString.Lazy as B+import System.IO +import CaseBi+import Data.List.InnToOut.Basic+import Paths_mmsyn6ukr++{-+-- Inspired by: https://mail.haskell.org/pipermail/beginners/2011-October/008649.html+-}++data Triple = Z | O | T+ deriving (Eq,Ord,Show,Read)++takeData :: FilePath -> IO B.ByteString+takeData file = do+ data1 <- B.readFile file+ let dataN = B.drop 44 data1 in return dataN++appendS16LEFile :: V.Vector String -> Handle -> IO ()+appendS16LEFile xs hdl | not (V.null xs) = + do+ dataFileList <- mapM getDataFileName + ["0.wav", "1.wav", "A.wav", "B.wav", "C.wav", "D.wav", "E.wav", "F.wav", "G.wav", "H.wav", + "I.wav", "J.wav", "K.wav", "L.wav", "M.wav", "N.wav", "O.wav", "P.wav", "Q.wav", "R.wav", + "S.wav", "T.wav", "U.wav", "V.wav", "W.wav", "X.wav", "Y.wav", "Z.wav", "a.wav", "b.wav", "c.wav", + "d.wav", "e.wav", "f.wav"]+ dataList <- V.mapM takeData . V.fromList $! dataFileList+ V.mapM_ (\u -> + if V.all (\z -> B.length z > 0) dataList + then let rs = "new." ++ (tail . dropWhile (/= ' ') . takeWhile (/= '}') . show $ hdl) in + B.appendFile rs $ dataList V.! (getBFst' (0, V.fromList [("0", 0), ("1", 1), ("а", 2), ("б", 3), + ("в", 4), ("г", 5), ("д", 6), ("дж", 7), ("дз", 8), ("е", 9), ("ж", 10), ("з", 11), ("и", 12), + ("й", 13), ("к", 14), ("л", 15), ("м", 16), ("н", 17), ("о", 18), ("п", 19), ("р", 20), + ("с", 21), ("сь", 22), ("т", 23), ("у", 24), ("ф", 25), ("х", 26), ("ц", 27), ("ць", 28), ("ч", 29), + ("ш", 30), ("ь", 31), ("і", 32), ("ґ", 33)]) u)+ else error "Data sound file is not read!") xs+ | otherwise = return ()++convertToProperUkrainian :: String -> V.Vector String+convertToProperUkrainian ys = toVector . correctA . createTuplesByAnalysis . filterUkr $ ys++filterUkr :: String -> String +filterUkr xs = concatMap (\x -> if isUkrainian x then [toLower x] else if isSpace x || isControl x then [x] else []) xs++createTuplesByAnalysis :: String -> [(String, Triple)]+createTuplesByAnalysis x@(y:ys) | canChange [y] == O = ("1", Z):createTuplesByAnalysis ys+ | canChange [y] == T = applyChanges . initialA . groupBy isSimilar . changeJotted . wasFstConverted $ x+ | otherwise = ([y], Z):createTuplesByAnalysis ys+createTuplesByAnalysis _ = []++canChange :: String -> Triple+canChange ~(x:_) | isSpace x || isControl x = O+ | getBFst' (False, V.fromList $ zip ['\1075','\1076','\1079','\1078','\1082','\1087','\1089','\1090','\1092','\1093','\1094','\1095','\1096'] (repeat True)) x = T+ | otherwise = Z+ +isVoicedObstruent :: String -> Bool+isVoicedObstruent xs | not (null xs) = getBFst' (False, V.fromList $ zip ["\1073","\1075","\1076","\1076\1078","\1076\1079","\1078","\1079","\1169"] (repeat True)) xs+ | otherwise = False++initialA :: [String] -> [(String, Triple)]+initialA (t:ts) | null t = initialA ts+ | tu == O = ("_", Z):initialA (tail t:ts)+ | (tu == T) = + if getBFst' (False, V.fromList $ zip ["\1076","\1085","\1089","\1090","\1093","\1094"] (repeat True)) ht + then let (us,vs) = splitAt 2 t in + if getBFst' (False, V.fromList $ zip ["\1076\1078","\1076\1079","\1085\1090","\1089\1090","\1089\1100","\1090\1089","\1090\1100","\1093\1075","\1094\1100"] (repeat True)) us+ then (us, T):initialA (vs:ts)+ else (ht, T):initialA (tail t:ts)+ else case (getBFst' (False, V.fromList $ zip ["\1075","\1078","\1079","\1082","\1092","\1095","\1096"] (repeat True)) ht) of+ ~True -> (ht, T):initialA (tail t:ts)+ | otherwise = (ht, Z):initialA (tail t:ts)+ where ht = [head t]+ tu = canChange ht+initialA _ = []+ ++wasFstConverted :: String -> String+wasFstConverted = mapI mustBeConverted convertionFst++mustBeConverted :: Char -> Bool+mustBeConverted c = getBFst' (False, V.fromList $ zip "'\700\1097\1102\1103\1108\1111\8217" (repeat True)) c++convertionFst :: Char -> String+convertionFst u = getBFst' ([u], V.fromList $ zip "'\700\1097\1102\1103\1108\1111\8217" ["0","0","\1096\1095","\1081\1091","\1081\1072","\1081\1077","\1081\1110","0"]) u++isConsonant :: Char -> Bool+isConsonant = getBFst' (False, V.fromList $ zip "\1073\1074\1075\1076\1078\1079\1081\1082\1083\1084\1085\1087\1088\1089\1090\1092\1093\1094\1095\1096\1169" (repeat True))++changeJotted :: String -> String+changeJotted (x:y:z:zs) | (not (isNotVowel z)) && (y == '\1081') && (isConsonant x) = x:'\1100':z:changeJotted zs+ | isConsonant x && y == '\1110' = x:'\1100':y:changeJotted (z:zs)+ | otherwise = x:changeJotted (y:z:zs)+changeJotted xs = xs++isNotVowel :: Char -> Bool+isNotVowel = getBFst' (True, V.fromList $ zip "\1072\1077\1080\1086\1091\1102\1103\1108\1110\1111" (repeat False))++isSimilar :: Char -> Char -> Bool+isSimilar x y = isNotVowel x && isNotVowel y++applyChanges :: [(String, Triple)] -> [(String, Triple)]+applyChanges (z:t:zs) | snd z == T = + getBFst' ((fst z, Z), V.fromList . zip ["\1075","\1076","\1076\1079","\1078","\1079","\1082","\1085\1090",+ "\1087","\1089","\1089\1090","\1089\1100","\1090","\1090\1089","\1090\1100","\1092","\1093","\1093\1075","\1094","\1094\1100","\1095","\1096"] + $ [гT zs, дT zs, дзT zs, жT zs, зT zs, кT zs, + нтT zs, пT zs, сT zs, стT zs, сьT zs, тT zs, тсT zs, тьT zs, + фT zs, хT zs, хгT zs, цT zs, цьT zs, чT zs, шT zs]) (fst z):applyChanges (t:zs)+ | otherwise = z:applyChanges (t:zs)+applyChanges [(xs, _)] = [(xs, Z)]+applyChanges _ = []++(===) :: Eq a => a -> [a] -> Bool+(===) x ys = or . map (\y -> x == y) $ ys++-- in the further ??T functions the last (, T) means that it must be afterwards be separated with the soft sign into two tuples (1 additional function in the composition)+-- need further processing means that there should be additional checks and may be transformations. May be they can be omitted++isSoftDOrL :: [(String, Triple)] -> Bool+isSoftDOrL xs = getBFst' (False, V.fromList . zip ["\1073\1100","\1074\1100","\1076\1100","\1079\1100","\1083\1100",+ "\1084\1100","\1085\1100","\1087\1100","\1089\1100","\1090\1100","\1092\1100","\1094\1100"] $ (repeat True)) (takeFromFT_ 2 xs)++isSoftDen :: [(String, Triple)] -> Bool+isSoftDen xs = getBFst' (False, V.fromList . zip ["\1076\1100","\1079\1100","\1083\1100","\1085\1100","\1089\1100",+ "\1090\1100","\1094\1100"] $ (repeat True)) (takeFromFT_ 2 xs) || takeFromFT_ 3 xs == "\1076\1079\1100"++гT :: [(String, Triple)] -> (String, Triple)+гT (t:_) | head (fst t) == '\1082' || head (fst t) == '\1090' = ("\1093", Z)+ | otherwise = ("\1075", Z)+гT _ = ("г", Z)++дT :: [(String, Triple)] -> (String, Triple)+дT t1@(_:_) | takeFromFT_ 1 t1 === ["\1078","\1095","\1096"] = ("\1076\1078", Z) -- need further processing д дж+ | takeFromFT_ 2 t1 === ["\1089\1100","\1094\1100"] = ("\1076\1079\1100", T) -- need further processing д дзь+ | takeFromFT_ 1 t1 === ["\1079","\1089","\1094"] = ("\1076\1079", Z) -- need further processing д дз + | otherwise = ("\1076", Z)+дT _ = ("д", Z)++дзT :: [(String, Triple)] -> (String, Triple)+дзT t1@(_:_) | isSoftDOrL t1 = ("\1076\1079\1100", T)+ | otherwise = ("\1076\1079", Z)+дзT _ = ("дз", Z)++жT :: [(String, Triple)] -> (String, Triple)+жT t1@(_:_) | takeFromFT 2 t1 === ["\1089\1100","\1094\1100"] = ("\1079\1100", T)+ | otherwise = ("\1078", Z)+жT _ = ("ж", Z)++зT :: [(String, Triple)] -> (String, Triple)+зT t1@(_:_) | takeFromFT_ 1 t1 === ["\1078","\1095","\1096"] || takeFromFT_ 2 t1 == "\1076\1078" = ("\1078", Z)+ | isSoftDOrL t1 = ("\1079\1100", T)+ | takeFromFT 1 t1 === ["\1095","\1096"] = ("\1096", Z) -- need further processing з ш+ | takeFromFT 1 t1 === ["\1089","\1094"] || takeFromFT_ 1 t1 === ["\1082","\1087","\1090","\1092","\1093"] = ("\1089", Z) -- need further processing з с+ | otherwise = ("\1079", Z)+зT _ = ("з", Z)++кT :: [(String, Triple)] -> (String, Triple)+кT t1@(_:_) | isVoicedObstruent (takeFromFT_ 1 t1) || isVoicedObstruent (takeFromFT_ 2 t1) = ("\1169", Z)+ | otherwise = ("\1082", Z)+кT _ = ("к", Z)++нтT :: [(String, Triple)] -> (String, Triple)+нтT t1@(_:_) | takeFromFT 2 t1 == "\1089\1090" = ("\1085", Z)+ | takeFromFT 3 t1 == "\1089\1100\1082" = ("\1085\1100", T)+ | otherwise = ("\1085\1090", Z)+нтT _ = ("нт", T)++пT :: [(String, Triple)] -> (String, Triple)+пT t1@(_:_) | isVoicedObstruent (takeFromFT_ 1 t1) || isVoicedObstruent (takeFromFT_ 2 t1) = ("\1073", Z)+ | otherwise = ("\1087", Z)+пT _ = ("п", Z)++сT :: [(String, Triple)] -> (String, Triple)+сT t1@(_:_) | (isVoicedObstruent (takeFromFT_ 1 t1) && drop 1 (takeFromFT_ 2 t1) == "\1100") || + (isVoicedObstruent (takeFromFT_ 2 t1) && drop 2 (takeFromFT_ 3 t1) == "\1100") = ("\1079\1100", T)+ | isVoicedObstruent (takeFromFT_ 1 t1) || isVoicedObstruent (takeFromFT_ 2 t1) = ("\1073", Z)+ | isSoftDOrL t1 = ("\1089\1100", Z)+ | takeFromFT_ 1 t1 == "\1096" = ("\1096", Z)+ | otherwise = ("\1089", Z)+сT _ = ("с", Z)++стT :: [(String, Triple)] -> (String, Triple)+стT t1@(_:_) | isVoicedObstruent (takeFromFT_ 1 t1) || isVoicedObstruent (takeFromFT_ 2 t1) = ("\1079", Z)+ | takeFromFT_ 3 t1 == "\1089\1100\1082" || takeFromFT_ 2 t1 == "\1094\1100" = ("\1089\1100", Z)+ | takeFromFT_ 1 t1 === ["\1089","\1085"] = ("\1089", Z)+ | takeFromFT_ 1 t1 == "\1095" = ("\1096", Z)+ | otherwise = ("\1089\1090", T)+стT _ = ("ст", T)++сьT :: [(String, Triple)] -> (String, Triple)+сьT t1@(_:_) | isVoicedObstruent (takeFromFT_ 2 t1) || isVoicedObstruent (takeFromFT_ 1 t1) = ("\1079\1100", T)+ | otherwise = ("\1089\1100", Z)+сьT _ = ("сь", Z)++тT :: [(String, Triple)] -> (String, Triple)+тT t1@(_:_) | (isVoicedObstruent (takeFromFT_ 1 t1) && drop 1 (takeFromFT_ 2 t1) == "\1100") || + (isVoicedObstruent (takeFromFT_ 2 t1) && drop 2 (takeFromFT_ 3 t1) == "\1100") = ("\1076\1100", T)+ | isVoicedObstruent (takeFromFT_ 2 t1) || isVoicedObstruent (takeFromFT_ 1 t1) = ("\1076", Z)+ | takeFromFT_ 2 t1 == "\1094\1100" = ("\1094\1100", Z)+ | takeFromFT_ 1 t1 == "\1094" = ("\1094", Z)+ | isSoftDen t1 = ("\1090\1100", T)+ | takeFromFT_ 1 t1 === ["\1095","\1096"] = ("\1095", Z)+ | otherwise = ("\1090", Z)+тT _ = ("т", Z)++тсT :: [(String, Triple)] -> (String, Triple)+тсT _ = ("\1094", Z)+++тьT :: [(String, Triple)] -> (String, Triple)+тьT t1@(_:_) | isVoicedObstruent (takeFromFT_ 2 t1) || isVoicedObstruent (takeFromFT_ 1 t1) = ("\1076\1100", T)+ | takeFromFT_ 3 t1 == "\1089\1100\1072" = ("\1094\1100", Z)+ | otherwise = ("\1090\1100", T)+тьT _ = ("ть", T)++фT :: [(String, Triple)] -> (String, Triple)+фT t1@(_:_) | isVoicedObstruent (takeFromFT_ 2 t1) || isVoicedObstruent (takeFromFT_ 1 t1) = ("\1074", Z)+ | otherwise = ("\1092", Z)+фT _ = ("ф", Z)++хT :: [(String, Triple)] -> (String, Triple)+хT t1@(_:_) | isVoicedObstruent (takeFromFT_ 2 t1) || isVoicedObstruent (takeFromFT_ 1 t1) = ("\1075", Z)+ | otherwise = ("\1093", Z)+хT _ = ("х", Z)++хгT :: [(String, Triple)] -> (String, Triple)+хгT _ = ("\1075", Z)++цT :: [(String, Triple)] -> (String, Triple)+цT t1@(_:_) | (isVoicedObstruent (takeFromFT_ 1 t1) && drop 1 (takeFromFT_ 2 t1) == "\1100") || + (isVoicedObstruent (takeFromFT_ 2 t1) && drop 2 (takeFromFT_ 3 t1) == "\1100") = ("\1076\1079\1100", T)+ | isSoftDOrL t1 = ("\1094\1100", Z)+ | isVoicedObstruent (takeFromFT_ 2 t1) || isVoicedObstruent (takeFromFT_ 1 t1) = ("\1076\1079", Z)+ | otherwise = ("\1094", Z)+цT _ = ("ц", Z)++цьT :: [(String, Triple)] -> (String, Triple)+цьT t1@(_:_) | (isVoicedObstruent (takeFromFT_ 1 t1) && drop 1 (takeFromFT_ 2 t1) == "\1100") || + (isVoicedObstruent (takeFromFT_ 2 t1) && drop 2 (takeFromFT_ 3 t1) == "\1100") = ("\1076\1079\1100", T)+ | otherwise = ("\1094\1100", Z)+цьT _ = ("ць", Z)++чT :: [(String, Triple)] -> (String, Triple)+чT t1@(_:_) | takeFromFT_ 2 t1 === ["\1089\1100","\1094\110"] = ("\1094\1100", Z)+ | isVoicedObstruent (takeFromFT_ 2 t1) || isVoicedObstruent (takeFromFT_ 1 t1) = ("\1076\1078", Z)+ | otherwise = ("\1095", Z)+чT _ = ("ч", Z)++шT :: [(String, Triple)] -> (String, Triple)+шT t1@(_:_) | takeFromFT_ 2 t1 === ["\1089\1100","\1094\110"] = ("\1089\1100", Z)+ | isVoicedObstruent (takeFromFT_ 2 t1) || isVoicedObstruent (takeFromFT_ 1 t1) = ("\1078", Z)+ | otherwise = ("\1096", Z)+шT _ = ("ш", Z)++correctA :: [(String, Triple)] -> [(String, Triple)]+correctA = correctSomeW . separateSoftS++separateSoftS :: [(String, Triple)] -> [(String, Triple)]+separateSoftS xs = mapI (\x -> snd x == T) divideToParts xs++divideToParts :: (String, Triple) -> [(String, Triple)]+divideToParts (xs, _) = [(init xs, Z),([last xs], Z)]++correctSomeW :: [(String, Triple)] -> [(String, Triple)]+correctSomeW (x:y:z:xs) | fst x == "\1094\1100" && fst y == "\1089\1100" && fst z == "\1072" = x:("\1094\1100", Z):z:correctSomeW xs+ | fst x == "1" && fst y == "\1081" && fst z == "\1072" = + if takeFromFT 2 xs == "\1095\1085"+ then x:y:z:("\1096", Z):correctSomeW (tail xs)+ else x:correctSomeW (y:z:xs)+correctSomeW zs = zs ++takeFromFT :: Int -> [(String, Triple)] -> String+takeFromFT n ts | compare n 0 == GT = if null ts + then []+ else if compare k n /= LT + then take n ks+ else ks ++ takeFromFT (n - length ks) (tail ts)+ | otherwise = []+ where ks = fst (head ts)+ k = length ks++takeFromFT_ :: Int -> [(String, Triple)] -> String+takeFromFT_ n ts = takeFromFT n (map (\(xs, y) -> (filter (/='_') xs, y)) ts)+++toVector :: [(String, Triple)] -> V.Vector String+toVector ts = V.fromList . map fst $ ts++isUkrainian :: Char -> Bool+isUkrainian y | (y >= '\1040' && y <= '\1065') || (y >= '\1070' && y <= '\1097') = True+ | otherwise = getBFst' (False, V.fromList . map (\x -> (x, True)) $ "'\700\1028\1030\1031\1068\1100\1102\1103\1108\1110\1111\1168\1169\8217") y++nSymbols :: String -> Int+nSymbols xs | null xs = 31416::Int+ | otherwise = getBFst' (31416::Int, V.generate 10 (\n -> (n, (10^n + 1)::Int))) (let temp = read xs::Int in if temp <= 9 && temp >= 1+ then temp + else error "Please, specify a digit as a command line argument for the program!")
binary file changed (absent → 2868 bytes)
binary file changed (absent → 3456 bytes)
binary file changed (absent → 3318 bytes)
binary file changed (absent → 5166 bytes)
binary file changed (absent → 3212 bytes)
@@ -0,0 +1,16 @@+The program can be used as a special musical instrument +or a voicing for Ukrainian text. It is not +phonetically exact and proper, but it gives +an inspiration to listen to the Ukrainian sounds more attentively.+It can be used by writers (especially poets) to compose melodic+texts. It can be used simply for the experiments. There is an+opinion that Ukrainian is a very melodic language, so you can+even not knowing it get some impression and get acquainted with+this beautiful language. There are a lot of songs in it and the +program is intended to open some part of beauty of the language itself.++The phonetic and writing system material are from the source:++Solomija Buk, Ján Mačutek, Andrij Rovenchak. Some properties of +the Ukrainian writing system. Electronic resource. +<https://arxiv.org/ftp/arxiv/papers/0802/0802.4198.pdf>
binary file changed (absent → 2214 bytes)
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
binary file changed (absent → 3334 bytes)
binary file changed (absent → 3280 bytes)
binary file changed (absent → 4898 bytes)
binary file changed (absent → 4854 bytes)
binary file changed (absent → 2778 bytes)
binary file changed (absent → 3448 bytes)
binary file changed (absent → 2490 bytes)
binary file changed (absent → 3984 bytes)
binary file changed (absent → 2660 bytes)
binary file changed (absent → 2958 bytes)
binary file changed (absent → 1098 bytes)
binary file changed (absent → 4196 bytes)
binary file changed (absent → 2820 bytes)
@@ -0,0 +1,29 @@+-- Initial mmsyn6ukr.cabal generated by cabal init. For further+-- documentation, see http://haskell.org/cabal/users-guide/++name: mmsyn6ukr+version: 0.1.0.0+synopsis: Can be used as a musical instrument synthesizer or for Ukrainian language listening+description: A program that can be used as a musical instrument synthesizer or for Ukrainian speech synthesis especially for poets and writers++homepage: https://hackage.haskell.org/package/mmsyn6ukr+license: MIT+license-file: LICENSE+author: OleksandrZhabenko+maintainer: olexandr543@yahoo.com+copyright: (c) OleksandrZhabenko 2019+category: Language+build-type: Simple+extra-source-files: ChangeLog.md, README.md+data-files: 0.wav, 1.wav, A.wav, B.wav, C.wav, D.wav, E.wav, F.wav, G.wav, H.wav, I.wav, J.wav, K.wav, L.wav, M.wav, N.wav, O.wav, P.wav, Q.wav, R.wav, S.wav, T.wav, U.wav, V.wav, W.wav, X.wav, Y.wav, Z.wav, a.wav, b.wav, c.wav, d.wav, e.wav, f.wav++cabal-version: >=1.10++executable mmsyn6ukr+ main-is: Main.hs+ other-modules: Paths_mmsyn6ukr, Melodics.Ukrainian+ -- other-extensions:+ build-depends: base >=4.7 && <4.13, vector >=0.11 && <0.13, bytestring >=0.10 && <0.11, process >=1.4 && <1.7, mmsyn2 >=0.1.6.1 && <0.2, mmsyn5 >= 0.4 && < 1+ -- mmsyn3 >=0.1.3.0 && <0.2+ -- hs-source-dirs:+ default-language: Haskell2010