/
SyllableJingju.py
148 lines (102 loc) · 5.5 KB
/
SyllableJingju.py
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
'''
Created on Oct 8, 2014
@author: joro
'''
import os
import sys
import sys
from numpy.ma.core import ceil
parentDir = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__) ), os.path.pardir))
pathHMMDuration = os.path.join(parentDir, 'AlignmentDuration')
if pathHMMDuration not in sys.path:
sys.path.append(pathHMMDuration)
from Phoneme import Phoneme
from Phonetizer import Phonetizer
from _SyllableBase import _SyllableBase
from ParametersAlgo import ParametersAlgo
import logging
logger = logging.getLogger(__name__)
class SyllableJingju(_SyllableBase):
''' syllables class for each chinse/jingju character in PINYIN
BUT not meant to be used alone, instead Syllable is a part of a Word class
'''
def __init__(self, text, noteNum):
_SyllableBase.__init__(self, text, noteNum)
# def get_Duration(self):
# return self.duration
self.durationPhonemes = None
def expandToPhonemes(self):
'''
one-to-one function: PINYIN characters to turkish METU.
as intermediate step mandarin phoneset are used.
'''
######################
### pinyin to mandarin phonemeSet
if not Phonetizer.phoneticDict:
sys.exit("Phonetizer.phonetic Dict not defined. do Phonetizer.initPhoneticDict at beginning of all code")
self.phonemes = []
# notes for instrument
if self.text == 'REST':
# TODO: replace with other model instead of silence
self.phonemes.append(Phoneme('sil'))
# TODO: does sp at end of sp make sence?
self.phonemes.append(Phoneme('sp'))
return
if self.text not in Phonetizer.phoneticDict:
sys.exit("unknown syllable {} Please add it to the dict".format(self.text))
mandarinPhonemes = Phonetizer.phoneticDict[self.text]
####################
#### mandarin to turkish METU
if not Phonetizer.lookupTable:
sys.exit("Phonetizer.lookupTable not defined. do Phonetizer.initlookupTable at beginning of all code")
phonemeIDs = []
for ph in mandarinPhonemes:
phonemeIDs = Phonetizer.grapheme2phonemeList(ph, phonemeIDs)
#### create Phonemes as field
for phonemeID in phonemeIDs:
self.phonemes.append(Phoneme(phonemeID))
if self.hasShortPauseAtEnd:
self.phonemes.append(Phoneme('sp'))
def calcPhonemeDurations(self):
'''
rule-based assignment of durations using Initial-Middle-final rules
all consonant durations set to CONSONANT_DURATION
'''
cofficinetTempo = 1
if self.phonemes is None:
self.expandToPhonemes()
if self.getNumPhonemes() == 0:
sys.exit("syllable with no phonemes!")
return
#copy to local var
consonant_duration = ParametersAlgo.CONSONANT_DURATION
# Workaraound: reduce consonant durationInMinUnit for syllables with very short note value.
while (self.getNumPhonemes() - 1) * consonant_duration >= self.durationInNumFrames:
logger.warn("Syllable {} has very short durationInMinUnit: {} . reducing the fixed durationInMinUnit of consonants".format(self.text, self.durationInMinUnit) )
consonant_duration /=2
#################
## assign durations
#############
initPhoneme = self.phonemes[0]
finalPhoneme = self.phonemes[-1]
#
if not initPhoneme.isVowel(): # initial is consonant
initPhoneme.durationInNumFrames = consonant_duration
if not finalPhoneme.isVowel(): # final is consonant
finalPhoneme.durationInNumFrames = consonant_duration
for currPhoneme in self.phonemes[1:-1]:
currPhoneme.durationInNumFrames = (self.durationInNumFrames - 2 * consonant_duration) / len(self.phonemes[1:-1])
else: # final is vowel
dur = (self.durationInNumFrames - float(consonant_duration) ) / len(self.phonemes[1:])
ceilDur = int(ceil(dur))
for currPhoneme in self.phonemes[1:-1]:
currPhoneme.durationInNumFrames = ceilDur
finalPhoneme.durationInNumFrames = self.durationInNumFrames - (len(self.phonemes[1:-1]) * ceilDur)
else: # initial is vowel
if not finalPhoneme.isVowel():
finalPhoneme.durationInNumFrames = consonant_duration
for currPhoneme in self.phonemes[:-1]:
currPhoneme.durationInNumFrames = (self.durationInNumFrames - consonant_duration) / len(self.phonemes[:-1])
else: # final is vowel
for currPhoneme in self.phonemes:
currPhoneme.durationInNumFrames = self.durationInNumFrames / len(self.phonemes)