UNPKG

hama-js

Version:

G2P, phoneme-ASR, and P2G inference for Node, Bun, and browsers, powered by a self-contained WASM engine (no onnxruntime).

102 lines 3.43 kB
const S_BASE = 0xac00; const L_BASE = 0x1100; const V_BASE = 0x1161; const T_BASE = 0x11a7; const L_COUNT = 19; const V_COUNT = 21; const T_COUNT = 28; const N_COUNT = V_COUNT * T_COUNT; const S_COUNT = L_COUNT * N_COUNT; const FILLER_INITIAL = 0x110b; const isHangulSyllable = (code) => code >= S_BASE && code < S_BASE + S_COUNT; const WHITESPACE_REGEX = /\s/; export const splitTextToJamo = (text) => { const tokens = []; const mapping = []; let offset = 0; let charIndex = 0; while (offset < text.length) { const code = text.codePointAt(offset); const ch = String.fromCodePoint(code); const charLen = ch.length; offset += charLen; if (WHITESPACE_REGEX.test(ch)) { charIndex += 1; continue; } const normalizedPart = ch.toLocaleLowerCase("und"); let normalizedOffset = 0; while (normalizedOffset < normalizedPart.length) { const innerCode = normalizedPart.codePointAt(normalizedOffset); const innerChar = String.fromCodePoint(innerCode); normalizedOffset += innerChar.length; if (!isHangulSyllable(innerCode)) { tokens.push(innerChar); mapping.push(charIndex); continue; } const syllableIndex = innerCode - S_BASE; const l = Math.floor(syllableIndex / N_COUNT); const v = Math.floor((syllableIndex % N_COUNT) / T_COUNT); const t = syllableIndex % T_COUNT; tokens.push(String.fromCodePoint(L_BASE + l)); mapping.push(charIndex); tokens.push(String.fromCodePoint(V_BASE + v)); mapping.push(charIndex); if (t !== 0) { tokens.push(String.fromCodePoint(T_BASE + t)); mapping.push(charIndex); } } charIndex += 1; } return { tokens, originalIndices: mapping }; }; const composeSyllable = (initial, medial, final) => String.fromCodePoint(S_BASE + initial * N_COUNT + medial * T_COUNT + final); export const joinJamoTokens = (tokens) => { const result = []; let initial = null; let medial = null; let final = 0; const flush = () => { if (initial !== null && medial !== null) { result.push(composeSyllable(initial, medial, final)); } initial = null; medial = null; final = 0; }; tokens.forEach((token) => { const code = token.codePointAt(0); if (code >= L_BASE && code < L_BASE + L_COUNT) { if (initial !== null || medial !== null) { flush(); } initial = code - L_BASE; } else if (code >= V_BASE && code < V_BASE + V_COUNT) { if (initial === null) initial = FILLER_INITIAL - L_BASE; if (medial !== null) flush(); medial = code - V_BASE; } else if (code > T_BASE && code <= T_BASE + T_COUNT) { if (initial === null || medial === null) { flush(); result.push(token); } else { final = code - T_BASE; flush(); } } else { flush(); result.push(token); } }); flush(); return result.join(""); }; //# sourceMappingURL=jamo.js.map