1
2
3
4
5
6
7
8 from collections import OrderedDict
9 from synthDriverHandler import SynthDriver, VoiceInfo, SynthSetting, LanguageInfo, StringParameterInfo
10 from ctypes import *
11 import os
12 import config
13 import nvwave
14 import re
15 from logHandler import log
16
17
18 abbreviationsLength = 4
19
20 isSpeaking = False
21 player = None
22 ProcessAudioCallback = WINFUNCTYPE(c_int, POINTER(c_char),POINTER(c_char),c_int)
23
24 @ProcessAudioCallback
25 -def processAudio(udata, buffer,length):
30
31 re_words = re.compile(r"\b(\w+)\b",re.U)
32 re_englishLetters = re.compile(r"\b([a-zA-Z])\b")
33 re_abbreviations = re.compile(ur"\b([bcdfghjklmnpqrstvwxzбвгджзклмнпрстфхцчшщ]{2,})\b",re.U)
34 re_capAbbreviations = re.compile(ur"([bcdfghjklmnpqrstvwxzбвгджзклмнпрстфхцчшщ]{3,})",re.U|re.I)
35 re_afterNumber = re.compile(r"(\d+)([^\.\:\-\/\!\?\d])")
36 re_omittedCharacters = re.compile(r"[\(\)\*_\"]+")
37 re_zeros = re.compile(r"\b\a?\.?(0+)")
38
39 ukrainianRules = {
40 re.compile(u"\\b(й)\\s",re.U|re.I): U"й",
41 re.compile(u"\\b(з)\\s",re.U|re.I): U"з",
42 re.compile(u"\\s(ж)\\b",re.U|re.I): U"ж",
43 re.compile(u"\\s(б)\\b",re.U|re.I): U"б",
44 re.compile(ur"'([яюєї])",re.I|re.U): u"ьй\\1",
45 re.compile(u"ц([ьіяюєї])",re.U|re.I): U"тс\\1"
46 }
47
48 englishLetters = {
49 'a': u"эй",
50 'b' : u"би",
51 'c': u"си",
52 'd': u"ди",
53 'e': u"и",
54 'f': u"эф",
55 'g': u"джи",
56 'h': u"эйчь",
57 'i': u"ай",
58 'j': u"джей",
59 'k': u"кэй",
60 'l': u"эль",
61 'm': u"эм",
62 'n': u"эн",
63 'o': u"оу",
64 'p': u"пи",
65 'q': u"къю",
66 'r': u"ар",
67 's': u"эс",
68 't': u"ти",
69 'u': u"ю",
70 'v': u"ви",
71 'w': u"да+блъю",
72 'x': u"экс",
73 'y': u"вай",
74 'z': u"зи"
75 }
76 russianLetters = {
77 u"б": u"бэ",
78 u"в": u"вэ",
79 u"к": u"ка",
80 u"с": u"эс",
81 u"ь": u"мя",
82 u"ъ": u"твё"
83 }
84
85 englishPronunciation= {
86 'x': u"кс",
87 'e': u"э",
88 'y': u"ы",
89 'j': u"дж"
90 }
91
92
93 ukrainianPronunciation = {
94 u"и": u"ы",
95 u"і": u"и",
96 u"ї": u"ййи",
97 u"е": u"э",
98 u"є": u"е",
99 u"ґ": u"г"
100 }
101 ukrainianPronunciationOrder = [u"и",u"і", u"ї", u"е", u"є", u"ґ"]
102
103 ukrainianLetters = {
104 u"й": u"йот",
105 u"ґ": u"Твэрдэ+ гэ",
106 u"и": u"ы",
107 u"і": u"и",
108 u"ї": u"ййи",
109 u"е": u"э",
110 u"є": u"е"
111 }
112 letters = {}
113 letters.update(englishLetters)
114 letters.update(russianLetters)
115 russianZeros=[u"ноль ",u"ноля",u"нолей"]
116 ukrainianZeros=[u"нуль ",u"нулі ",u"нулів "]
119 l = len(match.group(1))
120 if l == 1: return zeros[0]
121 text = " " + str(l) + " "
122 l = l%10
123 if l == 1: return text+ zeros[0]
124 elif l <5: return text+zeros[1]
125 else: return text+zeros[2]
126
128 loweredText = match.group(1).lower()
129 l = len(match.group(1))
130 if (match.group(1).isupper() and (l <= abbreviationsLength and l > 1) and re_capAbbreviations.match(match.group(1))) or re_abbreviations.match(loweredText):
131 expandedText = ""
132 for letter in loweredText:
133 expandedText += letters[letter] if letters.has_key(letter) else letter
134 if letter.isalpha(): expandedText+=" "
135 return expandedText
136 return loweredText
137
141
143 text = re_englishLetters.sub(subEnglishLetters, text)
144 for s in englishPronunciation:
145 text = text.replace(s, englishPronunciation[s])
146 return text
147
149 for rule in ukrainianRules:
150 text = rule.sub(ukrainianRules[rule],text)
151 for s in ukrainianPronunciationOrder:
152 text = text.replace(s, ukrainianPronunciation[s])
153
154 text = text.replace(s.upper(), ukrainianPronunciation[s])
155 return text
156
157 -def processText(text,language):
158 if len(text) == 1:
159 letter = text.lower()
160 if language == "uk" and ukrainianLetters.has_key(letter): return ukrainianLetters[letter]
161 elif letters.has_key(letter): return letters[letter]
162 else: return letter
163 text = re_omittedCharacters.sub(" ", text)
164 text = re_zeros.sub(lambda match: subZeros(match,russianZeros if language=="ru" else ukrainianZeros),text)
165 if language == "uk":
166 text = preprocessUkrainianText(text)
167 text = re_words.sub(expandAbbreviation,text)
168 text = preprocessEnglishText(text)
169 text = re_afterNumber.sub(r"\1-\2", text)
170 return text
171
173 name="newfon"
174 description = "Newfon"
175 supportedSettings=(
176 SynthDriver.VoiceSetting(),
177 SynthDriver.LanguageSetting(),
178 SynthDriver.RateSetting(),
179 SynthSetting("accel",_("&Acceleration")),
180 SynthDriver.PitchSetting(),
181 SynthDriver.InflectionSetting(10),
182 SynthDriver.VolumeSetting(),
183 )
184 _volume = 100
185 _language="ru"
186 _pitch = 50
187 _accel=0
188 _inflection=50
189 _rate=70
190 availableVoices = OrderedDict((str(index),VoiceInfo(str(index),name)) for index,name in enumerate([_("male 1"),_("female 1"),_("male 2"),_("female 2")]))
191 availableAccels=OrderedDict((str(x), StringParameterInfo(str(x),str(x))) for x in xrange(8))
192 pitchTable=[(90,130),(190,330),(60,120),(220,340)]
193 availableLanguages = OrderedDict((("ru",LanguageInfo("ru")), ("uk",LanguageInfo("uk"))))
194 newfon_lib = None
195 sdrvxpdbDll = None
196 dictDll = None
197
198 @classmethod
200 return os.path.isfile('synthDrivers/newfon_nvda.dll')
201
203 min,max=self.pitchTable[int(self.voice)]
204 i=max-min
205 i=int((i/50.0)*((inflection-50)/2))
206 min-=i
207 max+=i
208 i=int((pitch-50)/1.3)
209 min+=i
210 max+=i
211 return min,max
212
214 global player
215 player = nvwave.WavePlayer(channels=1, samplesPerSec=10000, bitsPerSample=8, outputDevice=config.conf["speech"]["outputDevice"])
216 self.hasDictLib = os.path.isfile('synthDrivers/dict.dll')
217 if self.hasDictLib:
218 self.sdrvxpdb_lib = windll.LoadLibrary(r"synthDrivers\sdrvxpdb.dll")
219 self.dict_lib = windll.LoadLibrary(r"synthDrivers\dict.dll")
220 self.newfon_lib = windll.LoadLibrary(r"synthDrivers\newfon_nvda.dll")
221 self.newfon_lib.speakText.argtypes = [c_char_p, c_int]
222 if not self.newfon_lib.initialize(): raise Exception
223 self.newfon_lib.set_callback(processAudio)
224 self.newfon_lib.set_dictionary(1)
225
236
237 - def speakText(self, text, index=None):
238 global isSpeaking
239 isSpeaking = True
240 text = processText(text, self._language)
241 if index is not None:
242 self.newfon_lib.speakText(text,index)
243 else:
244 self.newfon_lib.speakText(text,-1)
245
248
254
257
261
264
268
271
275
283
286
287 - def pause(self, switch):
290
293
295 self._language = language
296 if not self.hasDictLib: return
297 if language == "ru": self.newfon_lib.set_dictionary(1)
298 else: self.newfon_lib.set_dictionary(0)
299
303
306
310
313