phonemize
Version:
Fast phonemizer with rule-based G2P prediction. Pure JavaScript implementation.
2 lines (1 loc) • 4.89 kB
JavaScript
var RU_ONES=[`ноль`,`один`,`два`,`три`,`четыре`,`пять`,`шесть`,`семь`,`восемь`,`девять`,`десять`,`одиннадцать`,`двенадцать`,`тринадцать`,`четырнадцать`,`пятнадцать`,`шестнадцать`,`семнадцать`,`восемнадцать`,`девятнадцать`],RU_TENS={20:`двадцать`,30:`тридцать`,40:`сорок`,50:`пятьдесят`,60:`шестьдесят`,70:`семьдесят`,80:`восемьдесят`,90:`девяносто`},RU_HUNDREDS={100:`сто`,200:`двести`,300:`триста`,400:`четыреста`,500:`пятьсот`,600:`шестьсот`,700:`семьсот`,800:`восемьсот`,900:`девятьсот`},THOUSAND_FORMS=[`тысяча`,`тысячи`,`тысяч`],MILLION_FORMS=[`миллион`,`миллиона`,`миллионов`],BILLION_FORMS=[`миллиард`,`миллиарда`,`миллиардов`],PERCENT_FORMS=[`процент`,`процента`,`процентов`],RUBLE_FORMS=[`рубль`,`рубля`,`рублей`],DOLLAR_FORMS=[`доллар`,`доллара`,`долларов`];function pluralForm(e,o){var s=e%100;if(s>=11&&s<=14)return o[2];var c=e%10;return c===1?o[0]:c>=2&&c<=4?o[1]:o[2]}function readUnder1000(c){if(c===0)return``;var l=[],u=Math.floor(c/100)*100;u>0&&l.push(RU_HUNDREDS[u]);var d=c%100;if(d>0)if(d<20)l.push(RU_ONES[d]);else{var f=Math.floor(d/10)*10,p=d%10;l.push(RU_TENS[f]),p>0&&l.push(RU_ONES[p])}return l.join(` `)}function readThousandsGroup(e){var o=readUnder1000(e);return o=o.replace(/(^| )один$/,`$1одна`),o=o.replace(/(^| )два$/,`$1две`),o}function numberToWords(o){if(o===0)return RU_ONES[0];if(o<0)return`минус `+numberToWords(-o);var s=Math.floor(o/1e9),d=Math.floor(o%1e9/1e6),f=Math.floor(o%1e6/1e3),p=o%1e3,v=[];return s>0&&v.push(readUnder1000(s),pluralForm(s,BILLION_FORMS)),d>0&&v.push(readUnder1000(d),pluralForm(d,MILLION_FORMS)),f>0&&v.push(readThousandsGroup(f),pluralForm(f,THOUSAND_FORMS)),p>0&&v.push(readUnder1000(p)),v.join(` `)}function readWithUnit(e,o){var s=parseInt(e,10);return numberToWords(s)+` `+pluralForm(s,o)}function expandRussianText(o){return o=o.replace(/(\d+)\s*(?:₽|руб\.)/g,function(e,o){return readWithUnit(o,RUBLE_FORMS)}),o=o.replace(/\$\s*(\d+)/g,function(e,o){return readWithUnit(o,DOLLAR_FORMS)}),o=o.replace(/(\d+)%/g,function(e,o){return readWithUnit(o,PERCENT_FORMS)}),o=o.replace(/(\d+)[.,](\d+)/g,function(o,s,c){var l=numberToWords(parseInt(s,10)),u=c.split(``).map(function(o){var s;return(s=RU_ONES[parseInt(o,10)])??o}).join(` `);return l+` точка `+u}),o=o.replace(/\d+/g,function(e){return numberToWords(parseInt(e,10))}),o}var RUSSIAN_TO_PHONEME={a:`a`,e:`e`,i:`i`,o:`o`,u:`u`,y:`ɨ`,b:`b`,v:`v`,g:`ɡ`,d:`d`,z:`z`,j:`j`,k:`k`,l:`l`,m:`m`,n:`n`,p:`p`,r:`r`,s:`s`,t:`t`,f:`f`,"'":`ʲ`,'"':``},DIGRAPHS=[[`shch`,`ɕː`],[`zh`,`ʐ`],[`kh`,`x`],[`ts`,`t͡s`],[`ch`,`t͡ɕ`],[`sh`,`ʂ`]],NON_PALATALIZING=new Set([`j`,`ʃ`,`ʒ`,`t͡s`,`ts`,`ɕː`,`ʂ`]),DEVOICE={b:`p`,d:`t`,ɡ:`k`,z:`s`,v:`f`,ʐ:`ʂ`},VOWELS_LATIN=new Set([`a`,`e`,`i`,`o`,`u`,`y`]),RussianG2P=function(){function e(){this.id=`ru-g2p`,this.name=`Russian G2P Processor`,this.supportedLanguages=[`ru`]}return e.prototype.preProcess=function(e){return expandRussianText(e)},e.prototype.predict=function(e,o,s){return this.processRussian(e)},e.prototype.processRussian=function(e){var o=this,s;if(e=e.toLowerCase(),/\s/.test(e))return e.split(/(\s+)/).map(function(e){return/^\s+$/.test(e)||e===``?e:o.processRussian(e)}).join(``);for(var c=[],l=0;l<e.length;){for(var u=null,d=0,f=DIGRAPHS;d<f.length;d++){var p=f[d],m=p[0],h=p[1];if(e.startsWith(m,l)){u={ipa:h,len:m.length};break}}if(u){c.push(u.ipa),l+=u.len;continue}if(e[l]===`y`&&l+1<e.length&&`aou`.includes(e[l+1])){var g=e[l+1],_=c[c.length-1];_&&!VOWELS_LATIN.has(_[0])&&!NON_PALATALIZING.has(_)&&_!==`j`?(c[c.length-1]=_+`ʲ`,c.push(g)):c.push(`j`,g),l+=2;continue}var v=e[l],y=(s=RUSSIAN_TO_PHONEME[v])??v;if(v===`e`||v===`i`){var _=c[c.length-1];_&&!VOWELS_LATIN.has(_[0])&&!NON_PALATALIZING.has(_)&&_!==`j`&&!_.endsWith(`ʲ`)&&(c[c.length-1]=_+`ʲ`)}c.push(y),l++}for(var b=c.length-1;b>=0;b--){var x=c[b];if(x){if(DEVOICE[x]){c[b]=DEVOICE[x];break}if(x!==`ʲ`&&(VOWELS_LATIN.has(x)||[`m`,`n`,`l`,`r`,`j`].includes(x)))break}}return this.applyStressAndReduction(c),c.join(``)},e.prototype.applyStressAndReduction=function(e){for(var o=new Set([`a`,`e`,`i`,`o`,`u`,`ɨ`]),s=[],c=0;c<e.length;c++)o.has(e[c])&&s.push(c);if(s.length!==0){for(var l=s.length===1?0:s.length-2,u=s[l],d=l>0?s[l-1]:-1,f=u;f>0&&!o.has(e[f-1]);)f--;for(var p=0;p<s.length;p++){var m=s[p];if(m!==u){var h=e[m];h===`o`||h===`a`?e[m]=m===d||p===0?`ɐ`:`ə`:h===`e`&&(e[m]=`ɪ`)}}e.splice(f,0,`ˈ`)}},e.prototype.addPronunciation=function(e,o){},e}();export{RussianG2P as default};