phonemize
Version:
Fast phonemizer with rule-based G2P prediction. Pure JavaScript implementation.
2 lines (1 loc) • 4.08 kB
JavaScript
var KO_DIGITS=[`영`,`일`,`이`,`삼`,`사`,`오`,`육`,`칠`,`팔`,`구`],KO_TEN=`십`,KO_HUNDRED=`백`,KO_THOUSAND=`천`,KO_TEN_THOUSAND=`만`,KO_HUNDRED_MILLION=`억`;function readSection(s){if(s===0)return``;var c=``,l=Math.floor(s/1e3),u=Math.floor(s%1e3/100),d=Math.floor(s%100/10),f=s%10;return l>0&&(c+=(l===1?``:KO_DIGITS[l])+KO_THOUSAND),u>0&&(c+=(u===1?``:KO_DIGITS[u])+KO_HUNDRED),d>0&&(c+=(d===1?``:KO_DIGITS[d])+KO_TEN),f>0&&(c+=KO_DIGITS[f]),c}function numberToWords(i){if(i===0)return KO_DIGITS[0];if(i<0)return`마이너스`+numberToWords(-i);var a=Math.floor(i/1e8),o=Math.floor(i%1e8/1e4),d=i%1e4,f=``;return a>0&&(f+=readSection(a)+KO_HUNDRED_MILLION),o>0&&(f+=readSection(o)+KO_TEN_THOUSAND),d>0&&(f+=readSection(d)),f}function digitByDigit(i){return i.split(``).map(function(i){return i>=`0`&&i<=`9`?KO_DIGITS[i.charCodeAt(0)-48]:i}).join(``)}function expandKoreanText(e){return e=e.replace(/(\d{4})년/g,function(e,i){return numberToWords(parseInt(i,10))+`년`}),e=e.replace(/₩\s*(\d+)/g,function(e,i){return numberToWords(parseInt(i,10))+`원`}),e=e.replace(/\$\s*(\d+(?:\.\d+)?)/g,function(e,i){var a=parseFloat(i);return numberToWords(Math.floor(a))+`달러`}),e=e.replace(/(\d+(?:\.\d+)?)%/g,function(e,i){var a=i.indexOf(`.`);return a===-1?numberToWords(parseInt(i,10))+`퍼센트`:numberToWords(parseInt(i.slice(0,a),10))+`점`+digitByDigit(i.slice(a+1))+`퍼센트`}),e=e.replace(/(\d+)\.(\d+)/g,function(e,i,a){return numberToWords(parseInt(i,10))+`점`+digitByDigit(a)}),e=e.replace(/\d+/g,function(e){return numberToWords(parseInt(e,10))}),e}var KOREAN_CONSONANTS={g:`k`,kk:`k͈`,k:`kʰ`,n:`n`,d:`t`,tt:`t͈`,t:`tʰ`,r:`ɾ`,l:`l`,m:`m`,b:`p`,pp:`p͈`,p:`pʰ`,s:`s`,ss:`s͈`,j:`tɕ`,jj:`tɕ͈`,ch:`tɕʰ`,h:`h`,ng:`ŋ`,"":``},KOREAN_VOWELS={a:`a`,ae:`ɛ`,ya:`ja`,yae:`jɛ`,eo:`ʌ`,e:`e`,yeo:`jʌ`,ye:`je`,o:`o`,wa:`wa`,wae:`wɛ`,oe:`we`,u:`u`,wo:`wʌ`,we:`we`,wi:`wi`,eu:`ɯ`,ui:`ɰi`,i:`i`},KOREAN_FINALS={g:`k̚`,k:`k̚`,kk:`k̚`,n:`n`,d:`t̚`,s:`t̚`,ss:`t̚`,t:`t̚`,j:`t̚`,ch:`t̚`,l:`l`,m:`m`,b:`p̚`,p:`p̚`,ng:`ŋ`},KoreanG2P=function(){function e(){this.id=`ko-g2p`,this.name=`Korean G2P Processor`,this.supportedLanguages=[`ko`]}return e.prototype.preProcess=function(e){return expandKoreanText(e)},e.prototype.predict=function(e,i,a){return this.processKorean(e)},e.prototype.addPronunciation=function(e,i){},e.prototype.decomposeRomajaSyllable=function(e){e=e.toLowerCase();for(var i=``,a=``,o=``,s=Object.keys(KOREAN_VOWELS).sort(function(e,i){return i.length-e.length}),c=0,l=s;c<l.length;c++){var u=l[c],d=e.indexOf(u);if(d!==-1){a=u,i=e.substring(0,d),o=e.substring(d+u.length);break}}return a?{initial:i,medial:a,final:o,original:e}:{initial:``,medial:e,final:``,original:e}},e.prototype.processKorean=function(e){var i=this,a,o,s,c,l=e.match(/[A-Z][a-z]*/g)||[];if(l.length===0)return e;for(var u=l.map(function(e){return i.decomposeRomajaSyllable(e)}),d=0;d<u.length-1;d++){var f=u[d],p=u[d+1];f.final&&!p.initial&&(p.initial=f.final,f.final=``)}for(var d=1;d<u.length;d++){var m=u[d-1],h=u[d];if(h.initial===`h`&&[`g`,`k`,`d`,`t`,`b`,`p`,`j`,`ch`].includes(m.final)){var g={g:`k`,k:`k`,d:`t`,t:`t`,b:`p`,p:`p`,j:`ch`,ch:`ch`};h.initial=g[m.final],m.final=``}else if(m.final===`h`&&[`g`,`d`,`b`,`j`].includes(h.initial)){var g={g:`k`,d:`t`,b:`p`,j:`ch`};h.initial=g[h.initial],m.final=``}if([`n`,`m`].includes(h.initial)&&[`g`,`k`,`d`,`t`,`b`,`p`,`s`,`ss`,`j`,`ch`].includes(m.final)){var _={g:`ng`,k:`ng`,d:`n`,t:`n`,s:`n`,ss:`n`,j:`n`,ch:`n`,b:`m`,p:`m`};m.final=_[m.final]}m.final===`n`&&h.initial===`l`?m.final=`l`:m.final===`l`&&h.initial===`n`&&(h.initial=`l`)}for(var v=``,d=0;d<u.length;d++){var y=u[d],b=(a=KOREAN_CONSONANTS[y.initial])??y.initial,x=(o=KOREAN_VOWELS[y.medial])??y.medial,S=(s=KOREAN_FINALS[y.final])??``;if(d>0&&[`k`,`t`,`p`,`tɕ`].includes(b)){var m=u[d-1],C=(c=KOREAN_FINALS[m.final])??``;if(KOREAN_VOWELS[m.medial]||[`n`,`m`,`ŋ`,`l`].includes(C)){var w={k:`ɡ`,t:`d`,p:`b`,tɕ:`dʑ`};b=w[b]}}if(d>0&&b===`l`){var m=u[d-1];m.final||(b=`ɾ`)}v+=b+x+S}return v},e}();export{KoreanG2P as default};