From d6d5543d03ed1de093d1aaa89cca1f799768971c Mon Sep 17 00:00:00 2001 From: yemaozi88 <428968@gmail.com> Date: Mon, 7 Jan 2019 23:27:02 +0100 Subject: [PATCH] novoapi_functions is added to novo70 specific functions. --- .vs/acoustic_model/v15/.suo | Bin 78336 -> 83968 bytes acoustic_model/acoustic_model.pyproj | 5 +- acoustic_model/check_novoapi.py | 29 +--- ...nt_novo.py => novoapi_forced_alignment.py} | 6 + acoustic_model/novoapi_functions.py | 138 ++++++++++++++++++ 5 files changed, 150 insertions(+), 28 deletions(-) rename acoustic_model/{forced_alignment_novo.py => novoapi_forced_alignment.py} (93%) create mode 100644 acoustic_model/novoapi_functions.py diff --git a/.vs/acoustic_model/v15/.suo b/.vs/acoustic_model/v15/.suo index 88f58eb1a02007ca1a7b8925fd996cd673a84a9c..7f32711d9e4ad6d5867d970c56cca4af30ba1635 100644 GIT binary patch delta 3268 zcmd^>eN0nV6u^65Ux6xU%SQprM=2hQ>80XXoZq98PSy&>=vShGxOJOcd$QGAu*@53X z=bn4+dH3AD``&fjW{ZAF~}CSFNq z!Y)3P9Dq0Y=!PKl{)!o*QKuroNH+2~vJe?h9)|V;M2|dy%tcrqn?I9f-gXx1r@VF= z>cw6=7xfBcCGs?4M4l0eAWae@twWpTDBhE|KvIH@QrIo&m$qAuyzn_LM8>3rs131W z)c9hsp-g<)qBKNc4_l=;#0OzLQq&1ZDB_3AKr{#|oXPky%|_q52=mENs}Kbei3A{Q z0a)KG)Q=&o_;}Rwk@paP79Ng943dtdAR&knI{cKuY$y{odKMwfh5^3_o*7PQr8FO% z8Y(Q3FI!DFz5={bhp8KcD!sirD-ZusuMNU_pnc5Y*-eI=7%*jci4> zBXA`^=5kgCgPlTpA^9Gyauun?D0+D$W#fc%mFb~j8$1LXH_n9 z6S|0}xg6Cqw^q;^FG{F^qboVOj;E`+M^wHuzfQ_(JBVOCI|(h|XtB>jr%U(pG}8x2 z-dtgB%}p__0iwIrK(?*WI8Ay+c$)`Y$ zwGjf%$D#t*yNP%)LVaffeU*d5opEAx!qS_EU|aiIpzUhhRcu3{b4ABOLHE8+e8}BJ zz|p0K;;txAH&_L0a|@Zt9z^!a@fG!f=}eQ}Y^kxBtQCdjmgZ#U^uAnc0?X z-BDM!Gt(m_+N89M@~kASHa#sVOJg!6rDm0zw56$K=?gU(yUw#jzTQM&?pCO#8PJOZ z3g{8Zl!Y4qT800b!kVD3M+O^u5+L^ME#cCswH%C|okcvWz5EfZw!cX4$yM|Saw(_C zu?BuTof$brK;pA3LOv-14)iSk|I{BgsebPUg8q*UikCfGl3h~Vuj7>+K=kbK_dF%S zhMw63V!2>WKWPu8PqT-DC+=%Em)I&S=B>D6jqDc*d1%kX9(~@uDw2Jb#w5jEiUxbh z=x-2xwg&&8=xn?Y(lo2qOkqBP7kp*sD zLYS?hq_E0TT2`5#ys5&5zlf!}j0Mn}grp1P)+iB7m+Ls8Zs;X3$V-&?4i13s?lrK< zz5cIpzjZIDr?HM+~cCVQT+`SQB7Y!nbLgKgAB(D1*Bm!CnBU~*( zB->Ra$5!)*itGh4vc=advWRL#7T7%!Nwlt3If;g$L1U*vNmlWo?*Cf@eO$@mWOZlP zY;s%-jcs9_c%EqV`yiPVa8Ufs5_X8X0F8r*oh|X?lHc#H>e~uX=#GLTM>lqg$@@$qn1=$wumAiC~pV)~)g5hJ_(VZyTGhO52gZuo`Xl<$nf6^Dj^&e8ht G-roRg<9(w5 delta 2142 zcmb`Idu)?c6u|Gf{aV&ipnG+lt6kT1W5Ae&bqvPXi@|V?gb|s>i~*B}C_;r5VW4e@ zBr3X$9^Hr2@VE+rfeYgUCjNotp@|D~VDK+c7P9CVXl5MzK_d0srBkER@CUc~_1wp~ z_dLFHzc1LV5B4d|9vs|ev{@L_GsbkpgGeMof&nqLqdJ8fS+KWi^P#IyiGCj7+Zf*C zJNPBQM&0YiI)~I{Y%GEjpPWxU+Wu!NkB+@KRY^^pL!-xt%;;M?n3hI|e=bt3` z1W`sjMN|A((_lNktG{8id>+^8r$l7`D-n%>mq}|R8FH&^ zV`xr>Gh$w*CyuZaX+#Vm^^7E?UJ^+YF@f+9DTG`fNt%nsGHG%ymZX!g5)^U~%c71n zlumLy;U*p@CK8i~T*6Ew6ZE*5d~nlJn&~KcWI1-iIBHKDznT#FAB;zLPH4uKhVtiGJr%KYQOeX>R(k+_BRSRahRZ>Sv zxFy|_B?of9%;I`Nj-}OCh>e6iQO@DzbPsx6kK&k+xd9r{Zw|m#yi5NZ&_6C~J#3$~Uy5LCm3P@;zCK#3^hqLPcnTrA+?X|BeZ!K<2W;LsLVwd=*( zil|Ym7w2Lqr?2 zT0nYQ$PubDw2aNybjX|LV=!RRYId}NDB}3u2PcQe7vC%dH9Qw?blxb3G!RW(lq=$+ zsKe-b%cuGFHUqgW{anvQ$bw}}R?WJ9K!J9IgGcE?d`;P=LK>zOOEcyP!Lj-0Y_)j` z*zubh!&o0x$_DnL)WGov9oThv$qc$iqyOk6wvw%4tJw;d1|P9KEqJ6vhv83MSbxm%arhWusn>>%J6Wb%bk*a@T|L7CUtH8m&n@A& zDtsMVE{vBGIuk3$(sMo9XV>hY)n7Uav3q26(YBxDSncxAPMucL7UU0SVLBl6wMq7I(kof{vdwzbp|m7GJM2+^je#}l@kAIH32mV_x3k*{-NXK>H_h-| z=a2);xLL@AW3b Code - + Code Code + + Code + diff --git a/acoustic_model/check_novoapi.py b/acoustic_model/check_novoapi.py index cf6e7c6..3fd4601 100644 --- a/acoustic_model/check_novoapi.py +++ b/acoustic_model/check_novoapi.py @@ -19,35 +19,10 @@ import defaultfiles as default from forced_alignment import pyhtk, convert_phone_set import novoapi - +import novoapi_functions ## ======================= novo phoneset ====================== -translation_key = dict() - -#phonelist_novo70_ = pd.ExcelFile(default.phonelist_novo70_xlsx) -#df = pd.read_excel(phonelist_novo70_, 'list') -## *_simple includes columns which has only one phone in. -#for ipa, novo70 in zip(df['IPA_simple'], df['novo70_simple']): -# if not pd.isnull(ipa): -# print('{0}:{1}'.format(ipa, novo70)) -# translation_key[ipa] = novo70 -#phonelist_novo70 = np.unique(list(df['novo70_simple'])) - -phoneset_ipa = [] -phoneset_novo70 = [] -with open(default.novo70_phoneset, "rt", encoding="utf-8") as fin: - lines = fin.read() - lines = lines.split('\n') - for line in lines: - words = line.split('\t') - if len(words) > 1: - novo70 = words[0] - ipa = words[1] - phoneset_ipa.append(ipa) - phoneset_novo70.append(novo70) - translation_key[ipa] = novo70 -phoneset_ipa = np.unique(phoneset_ipa) -phoneset_novo70 = np.unique(phoneset_novo70) +phoneset_ipa, phoneset_novo70, translation_key = novoapi_functions.load_phonset() # As per Nederlandse phoneset_aki.xlsx recieved from David # [ɔː] oh / ohr diff --git a/acoustic_model/forced_alignment_novo.py b/acoustic_model/novoapi_forced_alignment.py similarity index 93% rename from acoustic_model/forced_alignment_novo.py rename to acoustic_model/novoapi_forced_alignment.py index 243f275..93b6a73 100644 --- a/acoustic_model/forced_alignment_novo.py +++ b/acoustic_model/novoapi_forced_alignment.py @@ -41,6 +41,7 @@ import argparse import json from novoapi.backend import session +import novoapi_functions # username / password cannot be passed as artuments... p = argparse.ArgumentParser() @@ -110,3 +111,8 @@ res = rec.setgrammar(grammar) #res = rec.recognize_wav("test/onetwothree.wav") res = rec.recognize_wav(wav_file) #print "Recognition result:", json.dumps(res.export(), indent=4) + +# list of the pronunciation for each words +word = 'pauw' +pronunciation_ipa = ['pau', 'pɑu'] +grammar = novoapi_functions.make_grammar(word, pronunciation_ipa) \ No newline at end of file diff --git a/acoustic_model/novoapi_functions.py b/acoustic_model/novoapi_functions.py new file mode 100644 index 0000000..0bdb324 --- /dev/null +++ b/acoustic_model/novoapi_functions.py @@ -0,0 +1,138 @@ +import numpy as np + +import defaultfiles as default + +def load_phonset(): + translation_key_ipa2novo70 = dict() + translation_key_novo702ipa = dict() + + #phonelist_novo70_ = pd.ExcelFile(default.phonelist_novo70_xlsx) + #df = pd.read_excel(phonelist_novo70_, 'list') + ## *_simple includes columns which has only one phone in. + #for ipa, novo70 in zip(df['IPA_simple'], df['novo70_simple']): + # if not pd.isnull(ipa): + # print('{0}:{1}'.format(ipa, novo70)) + # translation_key[ipa] = novo70 + #phonelist_novo70 = np.unique(list(df['novo70_simple'])) + + phoneset_ipa = [] + phoneset_novo70 = [] + with open(default.novo70_phoneset, "rt", encoding="utf-8") as fin: + lines = fin.read() + lines = lines.split('\n') + for line in lines: + words = line.split('\t') + if len(words) > 1: + novo70 = words[0] + ipa = words[1] + phoneset_ipa.append(ipa) + phoneset_novo70.append(novo70) + translation_key_ipa2novo70[ipa] = novo70 + translation_key_novo702ipa[novo70] = ipa + phoneset_ipa = np.unique(phoneset_ipa) + phoneset_novo70 = np.unique(phoneset_novo70) + + return phoneset_ipa, phoneset_novo70, translation_key_ipa2novo70, translation_key_novo702ipa + + +def multi_character_tokenize(line, multi_character_tokens): + """ + Tries to match one of the tokens in multi_character_tokens at each position of line, + starting at position 0, + if so tokenizes and eats that token. Otherwise tokenizes a single character. + + Copied from forced_alignment.convert_phone_set.py + """ + while line != '': + for token in multi_character_tokens: + if line.startswith(token) and len(token) > 0: + yield token + line = line[len(token):] + break + else: + yield line[:1] + line = line[1:] + + +def split_ipa(line): + """ + Split a line by IPA phones. + If nasalized sound (such as ɛ̃ː) is included, it will give error. + :param string line: one line written in IPA. + :return string lineSeperated: the line splitted in IPA phone. + """ + + multi_character_phones = [ + # IPAs in CGN. + u'ʌu', u'ɛi', u'œy', u'aː', u'eː', u'iː', u'oː', u'øː', u'ɛː', u'œː', u'ɔː', u'ɛ̃ː', u'ɑ̃ː', u'ɔ̃ː', u'œ̃', u'ɪː' + ] + + return [phone for phone in multi_character_tokenize(line.strip(), multi_character_phones)] + + +def split_novo70(line): + """ + Split a line by novo70 phones. + :param string line: one line written in novo70. + :return string lineSeperated: the line splitted by novo70 phones. + """ + _, phoneset_novo70, _, _ = load_phonset() + multi_character_phones = [p for p in phoneset_novo70 if len(p) > 1] + multi_character_phones = sorted(multi_character_phones, key=len, reverse=True) + + return ['sp' if phone == ' ' else phone + for phone in multi_character_tokenize(line.strip(), multi_character_phones)] + + +def novo702ipa(tokens): + pronunciation = [] + _, _, _, translation_key = load_phonset() + for phone in split_novo70(tokens): + pronunciation.append(translation_key.get(phone, phone)) + return ' '.join(pronunciation) + + +# numbering of novo70 should be checked. +def ipa2novo70(tokens): + pronunciation = [] + _, _, translation_key, _ = load_phonset() + for phone in split_ipa(tokens): + pronunciation.append(translation_key.get(phone, phone)) + return ' '.join(pronunciation) + + +def make_grammar(word, pronunciation_ipa): + """ + Args: + words + pronunciation_ipa: list of pronunciation variants. + """ + #word = 'pauw' + #pronunciation_ipa = ['pau', 'pɑu'] + + grammer_data_elements0_pronunciation = [] + for id, ipa in enumerate(pronunciation_ipa): + novo70 = novoapi_functions.ipa2novo70(ipa) + grammer_data_elements0_pronunciation.append({ + "phones": novo70.split(), + "id": id + }) + + grammar_data = { + "kind": 'sequence', + "elements": [{ + "kind": "word", + "pronunciation": grammer_data_elements0_pronunciation, + "label": word + }] + } + + grammar = { + "type": "confusion_network", + "version": "1.0", + "data": grammar_data, + "return_objects": ["grammar"], + "phoneset": "novo70" + } + + return grammar \ No newline at end of file