diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..2ee8efc4d79b0be8eb94c54bb265518caf39089d --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2022, Yuan Gong +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index af34e0c7689c1498d10ba8624715021eb694d03b..68569ffc93548dd57ea4e2a1a6ef332aede801a5 100644 --- a/README.md +++ b/README.md @@ -1,144 +1,196 @@ --- tags: - speech -- whisper -- forced-alignment - pronunciation-assessment -- gopt +- streaming +- whisper +- charsiu +language: +- en license: other --- -# custom-gopt-252-eval - -This repository bundles the models needed for the local evaluation pipeline: - -`Whisper ASR -> Charsiu phone alignment -> Streaming GOPT pronunciation scoring` +# StreamPA + +Frozen StreamPA pronunciation-assessment inference: fine-tuned Whisper Base +N-best -> G2P / prefix-local Charsiu / PCN / prosody -> slot and utterance scores. +This is a downloadable, multi-component Python system, not a hosted endpoint +or a standard Transformers `AutoModel`/`pipeline` implementation. + +## Published identity + +* Experiment: `M_stress_scalar_gate_capacity64` (Ours-M), primary seed **1337**. +* Original checkpoint SHA256: + `870df8dbe3c787487f094e0c4d4ade6bed8fcc5d86b578c4edc57581e81023b4`. +* All original tensors are retained losslessly in `scorer/model.safetensors`. + Strict loading retains the historical inactive `utt_head`; the active + utterance path is the frozen `gru_visible` head. +* 64 hidden dimensions, three local-attention blocks, four heads, scalar + reliability gate, detached stress branch, 64-dimensional recurrent state. + Inputs: 40 phone columns including epsilon, 14 global prosody features, + 17 slot prosody features, and at most **72 PCN slots**. +* The included Whisper weights are the actual fine-tuned Base checkpoint, + SHA256 `8917c9612b44f73bb5ef2ffec48cf44a4ee0dfa5a94af25e9e6710b9fd66a17f`. + They must not be replaced with generic Whisper Base. Beam size 8, N-best 5, + maximum 128 decoded tokens; original hypothesis-score computation retained. +* The paper's four-seed aggregate (1337, 202601, 202602, 202603) is not the + performance of this single checkpoint. No unverified paper metric is copied + into this card. Interface tests do not establish assessment PCC. + +## Download and install + +Verified platform: **Python 3.10 on Ubuntu in local Windows WSL2, CPU FP32**. +Native Windows and GPU inference are not part of the verified platform. +Use a new Python 3.10 environment. The fixed release tag below is created only +after fresh Hub-download inference verification succeeds. -The current Streaming GOPT checkpoint is the v6 ASR-confidence version. It uses 47-dimensional phone-segment features: the previous Charsiu-derived acoustic features plus one ASR confidence feature. - -## Files - -- `streaming_gopt_best/best_audio_model.pth`: best validation Streaming GOPT checkpoint. -- `streaming_gopt_best/config.json`: model architecture and training arguments. -- `streaming_gopt_best/inference_assets.json`: normalization statistics and phone-id mapping used by the inference example. -- `streaming_gopt_best/result.csv`: per-epoch training and validation metrics. -- `streaming_gopt_best/test_metrics.json`: held-out test metrics for the selected checkpoint. -- `whisper_best_model/`: Whisper ASR model used by the pipeline. -- `charsiu_en_w2v2_tiny_fc_10ms/`: Charsiu frame-level phone alignment model. -- `examples/infer_one_audio.py`: one-audio inference example. - -## Download +```bash +python3.10 -m venv .venv-streampa +source .venv-streampa/bin/activate +python -m pip install huggingface_hub==0.36.0 +python -c "from huggingface_hub import snapshot_download; snapshot_download('faeea/StreamPA', revision='streampa-v1.0.0', local_dir='./StreamPA')" +cd StreamPA +python -m pip install --extra-index-url https://download.pytorch.org/whl/cpu -r requirements-lock.txt +python -m pip install --no-deps --no-build-isolation . +python scripts/setup_assets.py +python scripts/verify_bundle.py +``` -```python -from huggingface_hub import snapshot_download +The public bundle contains the scorer and fine-tuned Whisper weights. Setup +downloads Charsiu and G2P resources from official, **fixed revisions**, checks +their SHA256s, and installs them inside this bundle. There is no runtime +reference to a training checkout or private server. See `THIRD_PARTY_NOTICES.md` +for licenses and third-party weight terms. Internet is needed for initial +installation/setup, not for subsequent inference. No author token is required +for the public release or its official runtime resources. -snapshot_download( - repo_id="faeea/custom-gopt-252-eval", - repo_type="model", - local_dir="./hf_models/custom-gopt-252-eval", -) -``` +## One WAV and streaming CLI -Then set: +Input: your own English **mono 16,000-Hz WAV**, no transcript or labels. +The frontend supports at most 30 seconds per recording and 72 current PCN +slots; longer inputs return an explicit error/status, never hidden truncation. +Output files must not already exist. ```bash -export BUNDLE_DIR=$PWD/hf_models/custom-gopt-252-eval +python -m streampa.infer --audio /path/to/demo.wav --bundle-dir . --device cpu --output scores.json +python -m streampa.stream --audio /path/to/demo.wav --bundle-dir . --device cpu --output prefixes.jsonl ``` -## Code Dependencies +The single-file CLI returns all prefixes plus the EOF result. The streaming +CLI actually reads and appends waveform blocks, then signals EOF. Both run +the same causal implementation. CLI block size does not change the fixed +0.64-second schedule and 0.16-second lookahead. -This model bundle is not a standalone Transformers model. The inference script needs the model definitions from `custom-gopt` and the official Charsiu code. +For an appropriate CUDA installation, select one device externally and use +`--device cuda`. Do not use a broken/busy device. The inherited frontend uses +FP16 Whisper on CUDA, FP32 Charsiu/scorer; CPU is FP32 throughout. CUDA is +**untested in this release validation**, and changing precision can change ASR +decoding. The CPU lockfile deliberately selects CPU PyTorch. -```bash -git clone https://github.com/hf49w/custom-gopt.git -git clone https://github.com/lingjzhu/charsiu third_party/charsiu_repo -git -C third_party/charsiu_repo checkout 13a69f2a22ca0c0962b75cc693399b0ae23a12c9 -``` - -Install the project dependencies in the `custom-gopt` repository, then install the small extra NLTK assets used by Charsiu/G2P: +## Python sessions -```bash -pip install -r requirements.txt -python -m pip install nltk -python -m nltk.downloader cmudict averaged_perceptron_tagger averaged_perceptron_tagger_eng +```python +import soundfile as sf +from streampa import StreamPAPipeline + +pipeline = StreamPAPipeline('./StreamPA', device='cpu', threads=2) +session = pipeline.create_session() +with sf.SoundFile('demo.wav') as f: + assert f.samplerate == 16000 and f.channels == 1 + while True: + block = f.read(1600, dtype='float32') # 100 ms received audio + if len(block) == 0: + break + for result in session.append(block): + print(result['audio_end'], result['status'], result['scores']) +print(session.finish()) # process the exact EOF, including a short final block +session.reset() # required before a new recording in this session +assert session.current() is None ``` -## One-Audio Inference +The pipeline owns frozen models; sessions have separate audio and recurrent +state. Use sessions sequentially (concurrent GPU service scheduling is not +provided). `StreamPAPipeline.from_pretrained(repo_id, revision=...)` is also +implemented, but its downloaded directory must have `setup_assets.py` run +before loading; use the explicit local-bundle example for first setup. + +## JSON and state semantics + +* `commit_time`: scheduling boundary; `audio_end`: exact prefix waveform end + supplied to **every** frontend; `received_audio_end`: audio received by the + caller so far, which may be later when a block spans multiple boundaries. + A normal prefix is processed only after `commit_time + 0.16` is received. + EOF alone defines the final endpoint. No reference boundary is consulted. +* `slots`: raw independent phone-head and word-head predictions per current + PCN slot, ASR word assignment, slot time, validity and commitment masks. + Epsilon/gap slots are retained; `valid_phone=false` means their phone score + is not a localized phone assessment. `asr_word_id=-1` has no word assignment. +* `words`: mean **word-head** predictions over visible slots assigned to each + current ASR word. This is a presentation aggregation, not mean phone accuracy. + It is not the paper's offline reference-word-identity evaluation. ASR words + and scores may be revised at later prefixes, including committed words. +* `new_commit_mask`: the frozen legacy boundary-aware state-update rule. + Only newly committed word representations are consumed by the GRU. With + no new words the persistent state remains unchanged, but visible features + still enter the sentence head and may change current utterance scores. + This heuristic has **no formal exactly-once guarantee** for every possible + mixed predecessor merge. It is not silently replaced with a corrected rule. +* `scores.utterance_network_raw` retains native model outputs, including the + untrained completeness dimension for audit only. Displayed utterance scores + omit completeness. ASR confidence is not a probability of correct pronunciation. +* Historical target normalization divides all source scores by 5: native + word/utterance source scores span 0--10; phone source scores span 0--2. + Thus displayed 0--5 word/utterance = network output x 2.5, and phone = network + output x 12.5. Outputs are **not clipped**; out-of-range estimates remain + visible. Stress has a trained head but is not a calibrated correctness probability. +* `status != 'ok'` returns `scores=null`, never a false zero grade. Statuses + include empty/too-short/silent audio, no usable hypothesis, G2P/alignment/ + acoustic failures, nonfinite values and unsupported slot length. Failed + prefixes remain in the output; previously successful state is preserved. +* `stages` and `wall_time_sec` measure actual local computation, not capture + waiting or a universal real-time guarantee. Model loading is separate. + +## Offline operation and checks ```bash -python "$BUNDLE_DIR/examples/infer_one_audio.py" \ - --audio /path/to/demo.wav \ - --bundle-dir "$BUNDLE_DIR" \ - --repo-root /path/to/custom-gopt \ - --charsiu-src-dir /path/to/third_party/charsiu_repo \ - --device cuda \ - --output-json ./one_audio_score.json -``` - -Use `--device cpu` when CUDA is unavailable. - -The example accepts an English short utterance audio file. A mono 16 kHz WAV is preferred; other sample rates are resampled inside the script. - -## Output Meaning - -The Streaming GOPT model forward pass returns: - -- `u1`: utterance-level accuracy. -- `u2`: utterance-level completeness. -- `u3`: utterance-level fluency. -- `u4`: utterance-level prosodic score. -- `u5`: utterance-level total score. -- `p`: phone-level pronunciation score for each visible phone token. -- `w1`: word-level accuracy. -- `w2`: word-level stress. -- `w3`: word-level total score. -- `w4`: word-level ASR accuracy. - -The example script reports the user-facing utterance scores as: - -```json -{ - "utterance_scores": { - "accuracy": 8.4, - "completeness": 10.0, - "fluency": 8.3, - "prosodic": 7.9, - "total": 8.0 - }, - "overall_score": 8.0 -} +python scripts/setup_assets.py --offline +HF_HUB_OFFLINE=1 TRANSFORMERS_OFFLINE=1 python -m streampa.infer --audio /path/to/demo.wav --bundle-dir . --device cpu --output offline_scores.json +python -m pytest tests -q ``` -For `accuracy`, `completeness`, `fluency`, `prosodic`, and `total`, higher is better. These scores follow the SpeechOcean-style pronunciation scoring scale used during training. - -The word-level outputs have this meaning: - -- `word_accuracy`: pronunciation accuracy for the word. -- `word_stress`: stress score for the word. -- `word_total`: overall word score. -- `word_asr_accuracy`: whether the ASR-driven word matched the expected word. - -`word_asr_accuracy` is a 0/1-style score. In practice, it can be used as a word-read-correctly indicator: a value near `1` means the word was recognized/matched as read correctly, while a value near `0` means the word was not matched, not recognized correctly, or was not committed yet in the streaming prefix. - -中文提示:词级别的 `asr_accuracy` 评分可以当作“这个词是否读对”的辅助指标。它不替代发音分数本身,但很适合用来标记某个词在 ASR 视角下是否正确读出。 - -## Test Metrics - -Best checkpoint epoch: `11` - -Held-out test metrics: - -- `phone_test_mse`: `0.049197` -- `phone_test_pcc`: `0.397571` -- `utt_test_pcc`: `[0.651909, 0.012690, 0.724998, 0.733279, 0.681940]` -- `word_test_pcc`: `[0.404714, -0.003912, 0.412258, 0.417467]` - -The word PCC order is: - -`accuracy`, `stress`, `total`, `asr_accuracy` - -## Notes - -- The model was trained on SpeechOcean762-style English learner speech. -- The pipeline does not require a reference transcript at inference time; it first obtains a transcript from Whisper, aligns phones with Charsiu, then scores with Streaming GOPT. -- ASR errors can affect downstream word and phone alignment. Use `word_asr_accuracy` to identify words that the ASR-driven pipeline likely did or did not match correctly. +Keep the entire prepared bundle, including `charsiu/` and `assets/nltk_data/`. +Do not delete those setup-generated directories when preparing an offline copy. +For hash mismatch, stop and re-download the specified revision rather than +replacing a resource with another model. Missing G2P/tagger resources require +`setup_assets.py`; inference does not intentionally download them. Proxy +configuration may be needed during setup in restricted networks. Use a fresh +output filename for each command. Convert sample rate/channels before opening +a session; the inference entry point does not resample a hidden full recording. + +## Scope and limitations + +Inference accepts audio only. Training used human annotations and teacher +supervision. Historical evaluation data were selected by preprocessing filters +and predominantly contain read speech. Deployment removes the historical +reference-phone-count ratio filter and uses received-audio/EOF scheduling; +it does not claim to reproduce historical test membership or PCC on arbitrary +WAVs. The frozen dictionary is a corpus-derived pronunciation vocabulary, not +an utterance-specific reference transcript. Original PCN gap semantics, +alignment, normalization, repetition filtering and legacy commitment are retained. + +No claim of validated spontaneous/open-ended speech generalization, formal +exactly-once commitment, GRU-induced stability improvement, or end-to-end +real-time performance is made. Synthetic validation clips test computation +and interfaces, not pronunciation-assessment accuracy. See +`validation_summary.json` for actually completed and untested checks. + +Observed interface-test limitation: several short prefixes produce repeated +Whisper hypotheses and are explicitly unscorable. A synthetic "Good morning" +clip was unscorable at all three prefixes; three separately selected licensed +read-speech clips all produced valid EOF scores, with 9 valid prefixes out of +15 attempted. These failures were not hidden or repaired by changing decoding. +CPU frontend computation was much slower than the audio duration in these tests. + +The old v6 47-feature system remains historical only at +`faeea/StreamPA`, revision `legacy-v6-before-streampa`. It is not this checkpoint +and must not be mixed with these configurations or entry points. diff --git a/README_zh.md b/README_zh.md new file mode 100644 index 0000000000000000000000000000000000000000..fc3c98c9d5c5ff8b867ad887718f669a8b5ad336 --- /dev/null +++ b/README_zh.md @@ -0,0 +1,109 @@ +# StreamPA 使用说明 + +这是冻结的 Ours-M / `M_stress_scalar_gate_capacity64`,默认 seed 1337。 +它不是旧版 v6 的 47 维 Streaming GOPT。发布的是可下载运行的多组件系统, +不是 HF 网页在线推理服务,也不提供虚构的 Transformers `AutoModel` 接口。 + +原 checkpoint SHA256: +`870df8dbe3c787487f094e0c4d4ade6bed8fcc5d86b578c4edc57581e81023b4`。 +`model_manifest.json` 记录发布 tensor、配置、源文件和各组件身份。 +scorer 的全部原 tensor 保留为 safetensors,没有训练、微调、量化或修改值。 + +## 安装 + +实际验证环境是本机 Windows 的 Ubuntu WSL2,Python 3.10,CPU FP32。 +没有将服务器 Linux 测试写成 Windows 原生测试。Windows 原生和 CUDA 尚未验证。 +首次需要联网安装依赖和下载官方固定版本的 Charsiu、词典与 NLTK 资源。 + +```bash +python3.10 -m venv .venv-streampa +source .venv-streampa/bin/activate +python -m pip install huggingface_hub==0.36.0 +python -c "from huggingface_hub import snapshot_download; snapshot_download('faeea/StreamPA', revision='streampa-v1.0.0', local_dir='./StreamPA')" +cd StreamPA +python -m pip install --extra-index-url https://download.pytorch.org/whl/cpu -r requirements-lock.txt +python -m pip install --no-deps --no-build-isolation . +python scripts/setup_assets.py +python scripts/verify_bundle.py +``` + +Charsiu 权重未在本仓库重新分发,由 setup 从官方固定 revision 下载并验 hash。 +微调 Whisper Base 则已在包内,不能替换为通用预训练 Whisper。各组件并非同一 +许可证,详见 `THIRD_PARTY_NOTICES.md`。初始安装若需要网络代理,由用户环境设置, +包内不包含作者 token、代理密码或服务器路径。 + +## 最短完整推理 + +输入自己的英文、单声道、16 kHz WAV,不输入参考文本、音素数、GT 边界、分数或 teacher。 +输出文件必须不存在,以免覆盖旧结果。 + +```bash +python -m streampa.infer --audio /path/to/demo.wav --bundle-dir . --device cpu --output scores.json +python -m streampa.stream --audio /path/to/demo.wav --bundle-dir . --device cpu --output prefixes.jsonl +``` + +单音频命令返回全部 prefix 和 EOF 分数;流式命令逐块读取音频,经过相同的调度和计算。 +最大原始音频长度为 30 秒,最大当前 PCN 槽位数为 72。超限明确拒绝,不静默截断。 +实际运行路径:收到的 prefix 音频 -> 微调 Whisper N-best -> G2P、Charsiu、PCN、prosody +-> StreamPA。没有用预计算预测代替模型运行。 + +## 会话 API + +```python +from streampa import StreamPAPipeline +pipeline = StreamPAPipeline('./StreamPA', device='cpu', threads=2) +session = pipeline.create_session() +# block 是实际已收到的、16 kHz 单声道 float32 波形数组 +for result in session.append(block): + print(result) +print(session.current()) +print(session.finish()) # 调用方 EOF,处理最后不足一个 chunk 的音频 +session.reset() # 新录音前必须重置,清空音频、提交历史和 GRU state +``` + +完整可执行逐块示例:`python examples/session.py --bundle-dir . --audio demo.wav`。 +不同 session 的 state 独立;当前包不提供多线程服务调度,建议顺序调用。 + +## 如何读输出 + +- `commit_time` 每 0.64 秒推进,普通 prefix 等收到额外 0.16 秒 lookahead 才处理。 + `audio_end` 是每个前端实际得到的波形末端;`received_audio_end` 可能因整块到达而更晚, + 但前端不能读取更晚部分。EOF 由调用方决定,不从参考标注推导。 +- `slots` 保留原始独立 phone head 与 word head 输出、当前 ASR 词归属、时间、mask。 + epsilon/gap 槽位保留;`valid_phone=false` 时不能作为有效局部音素评分。 +- `words` 按当前 ASR word ID,平均该词可见槽位的 **word head** 输出用于显示。 + 不是平均 phone accuracy,不等同论文按 reference word ID 的共同单元评价。 +- GRU 只消费 `new_commit_mask` 对应的新词。没有任何新词时 persistent state 不变, + 但 visible 表示仍进入句级 head,所以句级分数仍可能变化。已提交词不代表其评分永远不变。 +- 保留冻结的 legacy commitment,包括复杂 mixed merge 下的已知限制。 + 不声称“每一个完成词均有形式化 exactly-once 保证”,没有偷偷换成 corrected 规则。 +- 原训练把源标签除以 5;词和句源尺度为 0--10、音素源尺度为 0--2。 + 显示成 0--5 时,词/句网络输出乘 2.5,音素网络输出乘 12.5。不裁剪超界估计。 + 原始网络输出同时保留。completeness 未参与训练,只在 raw 审计字段保留,不显示为可靠评分。 +- 非 `ok` 状态给 `scores=null`,包括空音频、静音、无可用假设、对齐失败、超限等。 + 不用零分代替失败,不静默删掉失败 prefix。ASR confidence 也不等于“读对的概率”。 + +## 离线和性能 + +```bash +python scripts/setup_assets.py --offline +HF_HUB_OFFLINE=1 TRANSFORMERS_OFFLINE=1 python -m streampa.infer --audio demo.wav --bundle-dir . --device cpu --output offline_scores.json +python -m pytest tests -q +``` + +离线复制时保留整个已准备好的 bundle,包括 setup 产生的 `charsiu/` 与 +`assets/nltk_data/`。依赖缺失先补 setup,不要用别的权重替换。 +`stages` 分开记录前端与 scorer 的计算时间;不把文件读取测试声称为包含真实采集等待的 +端到端实时实验。CUDA 分支保留原 Whisper FP16 行为,Charsiu/scorer FP32,但尚未验证。 + +## 论文与部署边界 + +发布 seed 1337 不等于论文四 seed 均值。接口测试音频不证明论文 PCC。 +训练使用人工监督和 teacher;历史评测样本经过预处理筛选,主要来自朗读数据。 +部署移除了历史参考音素长度比例筛选,并使用 audio/EOF 调度;这一差异已明确记录, +不声称任意 WAV 会复现历史样本集合和指标。词典只是通用词到音素的静态资源, +不按当前录音读取其标准文本。未验证自发开放回答泛化,不宣称 GRU/稳定性 loss 的 +直接稳定性机制已获得证明。 + +旧 v6 历史版本保留在 `faeea/StreamPA` 的 `legacy-v6-before-streampa` revision; +其权重、结构和调用方法不能与本包混用。实际已通过和未测试项目见 `validation_summary.json`。 diff --git a/SHA256SUMS b/SHA256SUMS new file mode 100644 index 0000000000000000000000000000000000000000..05fa213761a8bc62af7a1556eb6bc9198bdb5eb8 --- /dev/null +++ b/SHA256SUMS @@ -0,0 +1,41 @@ +d501f3b58c954ae35e9dac25422a1a4e1dc8a24be3de27c8feedfe383726e52c LICENSE +52d8113ecf4424695f4a967fcd8174693642659c3110cb044ab8458bc5d41ddc README.md +939a3e3859cc8edf2e4472b73b1068771cbfb8682e75631cdc0c0de95bb3ec4b README_zh.md +b10037f3f89563db6e3cea1d0872a7d8c6bf648798d13e643682bc95d40ac585 THIRD_PARTY_NOTICES.md +34d6a3fd820daf67d0f46d71c71bab83e2f4fe0a714e580098ce1b8981d19932 assets/phn_dict.json +3eae62ec67d23c40bd672a3e933ff68f20a5466286956c46cf5933d302a465a6 assets/prepared_resource_hashes.json +5d6f12bce4a61905d8fe2b78474bb9a6741f6165f40f390f6041d975a5dd06a2 assets/pronunciation_lexicon.json +5162cca670853595e2883504e55e74465f0921f643a43246b16b4ba3818389c7 assets/runtime_sources.json +3b74d2f27f7723852677f5acaa5a5fd1271129fc426e6f3cf29a0be41fdf9cb3 examples/session.py +77fd4710def9ec3c0f6225800e0235f15a425abd4a8b03559127fcd782612049 licenses/Apache-2.0.txt +a622a386b2acb06e150e16c26fb93ff6c09b3096eb1d84aa5b6436ac6c52f6bc licenses/Charsiu-MIT.txt +b40930bbcf80744c86c46a12bc9da056641d722716c378f5659b9e555ef833e1 licenses/G2P-Apache-2.0.txt +b5d65a59060e68c4ff940e1eddfa6f94b2d68fdf58ed7f4dd57721c997e35e9d licenses/Whisper-MIT.txt +daa6056f84581c2311acbeaf4d5aff7df5c4aacb4fa23a7f788876257ce43efe model_manifest.json +f4350f936a2483da11f024c60b36915c21852431904a72908a544884a7afcfa1 pyproject.toml +dafdbd306609bf108a4b7b44b3c29fa263fdf3ba157824d31a9bde9ba19659d9 requirements-lock.txt +d508e880fff94cfc882109a1acc5122ea4c442bdc055114780d5c17b8ae1d026 scorer/config.json +49c772a0428649c7f676913847d978d4139e4bcaea39acbe83ac834c819dd0a9 scorer/inference_assets.json +26b2f4a90b90e997ceb2eae9df2f09166a9173c1297c53ef26b4b843eb778583 scorer/model.safetensors +b0d43d81486bd7c5216a032a21b9b9521838dd4460cb10cd627e466f3b80d284 scripts/setup_assets.py +e7b8437efd1496d8717720a5c58776f3b30c0550ea11a4642a1e600ee9961a88 scripts/verify_bundle.py +375cbd9410f7bff742e7e49c0aaf8b9a6ba04e3a7e9a8869e115a5bfa8074282 streampa/__init__.py +742be32f8decb995a9deb75a2a9d841f69f4eebb0c8dedcc2d1f204b1244ddc3 streampa/charsiu_model.py +be2e7dd491614553fee0beba238cf6bf66a0f59f2c1ace6b9972151ac22daf74 streampa/frontend.py +70e3b07c3f8ec862c56b8c1e3c8df3ebc5afaba412a404bb7238484793b83ccf streampa/infer.py +40838175655baa4996aef7c20066b71c77406b1b811282f793c0c97b948b3058 streampa/pipeline.py +efdeb871324aa0bdacd0f6cf43e926ddbcec3103c77a7256bf617b656b9d0500 streampa/stream.py +3643ef2e07ff94dc7dc6e829b825680f73c9846d95a21f88189cb5ce6b0dab68 streampa/streaming_gopt.py +1794fa024a698babbdfca90dfc9091d0a7ec051215461870c9f0b597ccee16fd streampa/streaming_pcn_gopt.py +000ae55e222f6b246dd337a8b7eecda520e34308bd7bac4f7e6e90c47c6c6153 tests/test_runtime.py +0c3b548f54cbb8e54aea347bce2fc75f56368bf30b90bd2b42252eb4b5e1bd15 validation_summary.json +9715fd2243b6f06a5858b5e32950d2853f73dd5bc201aafcf76f5082a2d8acd1 whisper/added_tokens.json +8dfbe1b3c46fa95ddde6cff3c53ece3b09a050182b152c64da5d90fe7eb68ea1 whisper/config.json +7b226ee4c0ea765809d5adb7959e76ca53da1202ca5a67c956bf3221979d2d53 whisper/generation_config.json +2df2990a395e35e8dfbc7511e08c12d56018d8d04691e0133e5d63b21e154dc6 whisper/merges.txt +8917c9612b44f73bb5ef2ffec48cf44a4ee0dfa5a94af25e9e6710b9fd66a17f whisper/model.safetensors +bf1c507dc8724ca9cf9903640dacfb69dae2f00edee4f21ceba106a7392f26dd whisper/normalizer.json +994838f1fa6462c8b9b3c90edada831f11f3dd8b4664634e18f4694d005c9dbf whisper/preprocessor_config.json +e67ae3a0aaa99abcd9f187138e12db1f65c16a14761c50ef10eef2c174a7a691 whisper/special_tokens_map.json +21a4fc0483c14b87f4e0bbc177a9a357479bfa7c95aaf21ad53d71e9c5afafb9 whisper/tokenizer_config.json +50d6a919f0a0601d56a04eb583c780d18553aa388254ba3158eb6a00f13e2c1a whisper/vocab.json diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md new file mode 100644 index 0000000000000000000000000000000000000000..f8deeddfc3bc0d0250bbfbb544a6f9f494343bd8 --- /dev/null +++ b/THIRD_PARTY_NOTICES.md @@ -0,0 +1,43 @@ +# Third-party notices and redistribution scope + +This is a multi-component release, not a claim that every component shares one +license. The Hub card retains `license: other`; consult the component sources. + +* GOPT-derived scorer and preprocessing source retain the original project's + BSD-3-Clause notice (`LICENSE`, copyright Yuan Gong, 2022). The published + scorer is the publisher's frozen StreamPA checkpoint, not the original GOPT + model and not the legacy v6 release. No training data or optimizer is bundled. +* The publisher's fine-tuned Whisper Base weights and their actual tokenizer + and processor are included. OpenAI's Whisper project publishes code and + model weights under MIT (`licenses/Whisper-MIT.txt`); the Transformers Hub + [Whisper Base card](https://huggingface.co/openai/whisper-base) labels its + converted distribution Apache-2.0. Both upstream notices are retained. + The included fine-tune is not interchangeable with generic Whisper Base. +* Charsiu frame-classifier code is from `lingjzhu/charsiu` commit + `13a69f2a22ca0c0962b75cc693399b0ae23a12c9`, under its MIT notice + (`licenses/Charsiu-MIT.txt`). The Charsiu weight repository does not expose + sufficiently explicit weight-redistribution terms for this release to + assign it a license. Its weights/tokenizer are **not redistributed here**. + `scripts/setup_assets.py` retrieves their official fixed revisions listed + in `assets/runtime_sources.json`; users must check the upstream terms. +* The pronunciation lexicon contains only isolated normalized word-to-phone + entries required by the frozen frontend. It is derived from + [speechocean762](https://www.openslr.org/101/), released by Beijing + Speechocean and Microsoft under CC BY 4.0. It omits utterance IDs, ordered + transcripts, recordings, boundaries and human scores. The normalization + and deduplication are adaptations. Attribution: Zhang et al., + *speechocean762: An Open-Source Non-native English Speech Corpus For + Pronunciation Assessment* (2021), https://arxiv.org/abs/2104.01378 . + CC BY 4.0: https://creativecommons.org/licenses/by/4.0/ . +* g2p-en 2.1.0 is installed from its official package (Apache-2.0 notice in + `licenses/G2P-Apache-2.0.txt`). Its runtime uses NLTK CMUdict and English + POS tagger resources. They are fetched from a fixed `nltk/nltk_data` + revision, with individual SHA256s, rather than redistributed as corpus + archives here. Refer to their bundled notices and + https://github.com/nltk/nltk_data/blob/gh-pages/DATASET-LICENSES.md . +* PyTorch, Transformers, NumPy, librosa, SoundFile, NLTK and safetensors are + separately installed packages, each subject to its own upstream license. + +Synthetic verification audio stays outside the public bundle. This release +does not distribute private recordings, human assessment labels, experiment +predictions, proprietary corpus archives or third-party optimizer states. diff --git a/assets/phn_dict.json b/assets/phn_dict.json new file mode 100644 index 0000000000000000000000000000000000000000..93e6055ac10d8c07417b8d9579e80315ea19c73d --- /dev/null +++ b/assets/phn_dict.json @@ -0,0 +1,41 @@ +{ + "W": 0, + "IY": 1, + "K": 2, + "AO": 3, + "L": 4, + "IH": 5, + "T": 6, + "B": 7, + "EH": 8, + "R": 9, + "Z": 10, + "OW": 11, + "TH": 12, + "F": 13, + "AY": 14, + "V": 15, + "AH": 16, + "N": 17, + "UW": 18, + "S": 19, + "G": 20, + "AA": 21, + "M": 22, + "P": 23, + "NG": 24, + "HH": 25, + "EY": 26, + "SH": 27, + "AE": 28, + "D": 29, + "UH": 30, + "AW": 31, + "DH": 32, + "ER": 33, + "Y": 34, + "JH": 35, + "CH": 36, + "OY": 37, + "ZH": 38 +} diff --git a/assets/prepared_resource_hashes.json b/assets/prepared_resource_hashes.json new file mode 100644 index 0000000000000000000000000000000000000000..44ff7bd68d069b6ed895639305a405256d0089b0 --- /dev/null +++ b/assets/prepared_resource_hashes.json @@ -0,0 +1,102 @@ +{ + "g2p_en_version": "2.1.0", + "g2p_files": [ + { + "package_relative": "g2p_en/__init__.py", + "bytes": 21, + "sha256": "36ffae3e8f2cad9d285131c78963f690327f5046b5273dfecc52707659be949d" + }, + { + "package_relative": "g2p_en/checkpoint20.npz", + "bytes": 3342298, + "sha256": "b8af35e4596d8dd5836dfd3fe9b2ba4f97b9c311efe8879544cbcfcbd566d8c6" + }, + { + "package_relative": "g2p_en/expand.py", + "bytes": 2492, + "sha256": "b31f9f2173280f4479de1272d57540382d64496662ef127cf4d05af5a49d70db" + }, + { + "package_relative": "g2p_en/g2p.py", + "bytes": 7637, + "sha256": "fc2548b855e102f774506a6afe4f4bc88424229b69701ab6040aa16710ddff3a" + }, + { + "package_relative": "g2p_en/homographs.en", + "bytes": 18711, + "sha256": "0403edcc6aefe8945f8987be398279fd98bf6b767e54b741331d3bc99a307071" + } + ], + "prepared_resources": [ + { + "path": "charsiu/model/config.json", + "bytes": 1522, + "sha256": "49b4e164f0375c7b0eaab8cf4d9727a20f1060e73bf0d899e2442ae95f70cae4" + }, + { + "path": "charsiu/model/pytorch_model.bin", + "bytes": 93368972, + "sha256": "a5b59d8cc3c548382dbc38c48d537b0bb520b9a67d2fafef2afee7740f9ce0c7" + }, + { + "path": "charsiu/tokenizer/special_tokens_map.json", + "bytes": 85, + "sha256": "50eb73d51191696209d30d42d6ede50e57e7a542ca1db12df714b2c0aa3da8e2" + }, + { + "path": "charsiu/tokenizer/tokenizer_config.json", + "bytes": 180, + "sha256": "56e02b54de01a0ec4cc0c705ad3c303d7b73c83d61063a94b84cbf3a55da76a1" + }, + { + "path": "charsiu/tokenizer/vocab.json", + "bytes": 403, + "sha256": "781514e251e9615ea4a05bbf3760ffcf8ec2ebe67355f411177ea64b0602d897" + }, + { + "path": "assets/nltk_data/corpora/cmudict/README", + "bytes": 3808, + "sha256": "b0556be7a2b12bea6a667277b75864f802dd4854480657ce298c62e6897e766b" + }, + { + "path": "assets/nltk_data/corpora/cmudict/cmudict", + "bytes": 3820830, + "sha256": "cad209c39eb87677d64e93d97f8eed10b7e6f9bdd42de8e7ca8efc8e17d62e8a" + }, + { + "path": "assets/nltk_data/corpora/cmudict.zip", + "bytes": 896069, + "sha256": "d07cca47fd72ad32ea9d8ad1219f85301eeaf4568f8b6b73747506a71fb5afd6" + }, + { + "path": "assets/nltk_data/taggers/averaged_perceptron_tagger/averaged_perceptron_tagger.pickle", + "bytes": 6138625, + "sha256": "25a5a19c7ced7b2bac3831da5bc0afcc2c34e5dd01cd4f361bb799949a696238" + }, + { + "path": "assets/nltk_data/taggers/averaged_perceptron_tagger.zip", + "bytes": 2526731, + "sha256": "e1f13cf2532daadfd6f3bc481a49859f0b8ea6432ccdcd83e6a49a5f19008de9" + }, + { + "path": "assets/nltk_data/taggers/averaged_perceptron_tagger_eng/averaged_perceptron_tagger_eng.classes.json", + "bytes": 285, + "sha256": "d152ffa69d45b8357276341a3d592c6c025911d52ec0d9068d4f382560dd48b6" + }, + { + "path": "assets/nltk_data/taggers/averaged_perceptron_tagger_eng/averaged_perceptron_tagger_eng.tagdict.json", + "bytes": 25788, + "sha256": "4c713731cb06727736962bc8cd94ad919217a040e76691059af99bc0c2c9c246" + }, + { + "path": "assets/nltk_data/taggers/averaged_perceptron_tagger_eng/averaged_perceptron_tagger_eng.weights.json", + "bytes": 5677744, + "sha256": "789e8e35f6fac656d9b7eccea29ba4e8a137cbb5b525dd31f39e4291a9e80832" + }, + { + "path": "assets/nltk_data/taggers/averaged_perceptron_tagger_eng.zip", + "bytes": 1539115, + "sha256": "6025f530624335c67d6547d44757b357b4e79bae030a0383e9887a92c1718f0b" + } + ] +} diff --git a/assets/pronunciation_lexicon.json b/assets/pronunciation_lexicon.json new file mode 100644 index 0000000000000000000000000000000000000000..bbe429cfd6da49fce7c383582da04183c29cec93 --- /dev/null +++ b/assets/pronunciation_lexicon.json @@ -0,0 +1,17426 @@ +{ + "WE": [ + "W", + "IY" + ], + "CALL": [ + "K", + "AO", + "L" + ], + "IT": [ + "IH", + "T" + ], + "BEAR": [ + "B", + "EH", + "R" + ], + "ZERO": [ + "Z", + "IH", + "ER", + "OW" + ], + "THREE": [ + "TH", + "R", + "IY" + ], + "FIVE": [ + "F", + "AY", + "V" + ], + "ONE": [ + "W", + "AH", + "N" + ], + "TWO": [ + "T", + "UW" + ], + "SEVEN": [ + "S", + "EH", + "V", + "N" + ], + "ELEPHANTS": [ + "EH", + "L", + "IH", + "F", + "AH", + "N", + "T", + "S" + ], + "TAI": [ + "T", + "AY" + ], + "GOOSE": [ + "G", + "UW", + "S" + ], + "TOM": [ + "T", + "AA", + "M" + ], + "GIVES": [ + "G", + "IH", + "V", + "Z" + ], + "UP": [ + "AH", + "P" + ], + "BOXING": [ + "B", + "AA", + "K", + "S", + "IH", + "NG" + ], + "HE": [ + "HH", + "IY" + ], + "HATES": [ + "HH", + "EY", + "T", + "S" + ], + "SHOOTING": [ + "SH", + "UW", + "T", + "IH", + "NG" + ], + "MANDY": [ + "M", + "AE", + "N", + "D", + "IY" + ], + "HAS": [ + "HH", + "AE", + "Z" + ], + "A": [ + "AH" + ], + "BIG": [ + "B", + "IH", + "G" + ], + "ARM": [ + "AA", + "M" + ], + "LOOK": [ + "L", + "UH", + "K" + ], + "AT": [ + "AE", + "T" + ], + "ANN'S": [ + "AE", + "N", + "S" + ], + "PANTS": [ + "P", + "AE", + "N", + "T", + "S" + ], + "WHAT": [ + "W", + "AH", + "T" + ], + "ABOUT": [ + "AH", + "B", + "AW", + "T" + ], + "THE": [ + "DH", + "AH" + ], + "BUS": [ + "B", + "AH", + "S" + ], + "THEN": [ + "DH", + "EH", + "N" + ], + "WENT": [ + "W", + "EH", + "N", + "T" + ], + "TO": [ + "T", + "UW" + ], + "THEME": [ + "TH", + "IY", + "M" + ], + "PARK": [ + "P", + "AA", + "K" + ], + "LET'S": [ + "L", + "EH", + "T", + "S" + ], + "GO": [ + "G", + "OW" + ], + "RESTROOM": [ + "R", + "EH", + "S", + "T", + "R", + "UW", + "M" + ], + "MIKE": [ + "M", + "AY", + "K" + ], + "WALKS": [ + "W", + "AO", + "K", + "S" + ], + "COFFEE": [ + "K", + "AO", + "F", + "IY" + ], + "SO": [ + "S", + "OW" + ], + "MARY": [ + "M", + "AE", + "R", + "IH" + ], + "ON": [ + "AH", + "N" + ], + "STUDY": [ + "S", + "T", + "AH", + "D", + "IY" + ], + "KATE": [ + "K", + "EH", + "T" + ], + "GOT": [ + "G", + "AH", + "T" + ], + "TOMATO": [ + "T", + "AH", + "M", + "EY", + "T", + "OW" + ], + "TINA": [ + "T", + "IY", + "N", + "AH" + ], + "LOVES": [ + "L", + "AH", + "V", + "Z" + ], + "EGGPLANT": [ + "EH", + "G", + "P", + "L", + "AE", + "N", + "T" + ], + "DORA": [ + "D", + "AO", + "R", + "AH" + ], + "IS": [ + "IH", + "Z" + ], + "NOT": [ + "N", + "AH", + "T" + ], + "CLEANER": [ + "K", + "L", + "IY", + "N", + "ER" + ], + "MARK": [ + "M", + "AA", + "K" + ], + "LIVED": [ + "L", + "IH", + "V", + "D" + ], + "IN": [ + "IH", + "N" + ], + "NEW": [ + "N", + "Y", + "UW" + ], + "YORK": [ + "Y", + "AO", + "K" + ], + "BOB": [ + "B", + "AH", + "B" + ], + "LIVES": [ + "L", + "IH", + "V", + "Z" + ], + "CAIRO": [ + "K", + "AY", + "R", + "OW" + ], + "NOW": [ + "N", + "AW" + ], + "BYE": [ + "B", + "AY" + ], + "TREES": [ + "T", + "R", + "IY", + "Z" + ], + "LIKES": [ + "L", + "AY", + "K", + "S" + ], + "WHITE": [ + "W", + "AY", + "T" + ], + "ITS": [ + "IH", + "T", + "S" + ], + "NAME": [ + "N", + "EY", + "M" + ], + "SAY": [ + "S", + "EY" + ], + "BILLY": [ + "B", + "IH", + "L", + "IY" + ], + "AMERICA": [ + "AH", + "M", + "EH", + "R", + "IH", + "K", + "AH" + ], + "EIGHT": [ + "EY", + "T" + ], + "FOUR": [ + "F", + "AO" + ], + "NINE": [ + "N", + "AY", + "N" + ], + "SIX": [ + "S", + "IH", + "K", + "S" + ], + "LESS": [ + "L", + "EH", + "S" + ], + "MEAT": [ + "M", + "IY", + "T" + ], + "DOSE": [ + "D", + "OW", + "S" + ], + "LIKE": [ + "L", + "AY", + "K" + ], + "HAMBURGER": [ + "HH", + "AE", + "M", + "B", + "ER", + "G", + "AH" + ], + "ANNIE": [ + "AE", + "N", + "IH" + ], + "WANT": [ + "W", + "AA", + "N", + "T" + ], + "HAVE": [ + "HH", + "AE", + "V" + ], + "SOME": [ + "S", + "AH", + "M" + ], + "PRETTIES": [ + "P", + "R", + "IH", + "T", + "IY", + "S" + ], + "KATE'S": [ + "K", + "EH", + "IY", + "T", + "Z" + ], + "GREY": [ + "G", + "R", + "EY" + ], + "JOHN'S": [ + "JH", + "AH", + "N", + "S" + ], + "SWEATER": [ + "S", + "W", + "EH", + "T", + "ER" + ], + "TIM": [ + "T", + "IH", + "M" + ], + "BEAUTIFUL": [ + "B", + "Y", + "UW", + "T", + "IH", + "F", + "L" + ], + "TELL": [ + "T", + "EH", + "L" + ], + "JIM": [ + "JH", + "IH", + "M" + ], + "YOUR": [ + "Y", + "AO" + ], + "BLUE": [ + "B", + "L", + "UW" + ], + "SHORE": [ + "SH", + "AO", + "R" + ], + "WALKING": [ + "W", + "AO", + "K", + "IH", + "NG" + ], + "THEM": [ + "DH", + "EH", + "M" + ], + "LAYLA": [ + "L", + "EY", + "L", + "AA" + ], + "CAN": [ + "K", + "AE", + "N" + ], + "SEE": [ + "S", + "IY" + ], + "HOMETOWN": [ + "HH", + "OW", + "M", + "T", + "AW", + "N" + ], + "WASHROOM": [ + "W", + "AA", + "SH", + "R", + "UW", + "M" + ], + "ALL": [ + "AO", + "L" + ], + "WITH": [ + "W", + "IH", + "DH" + ], + "HIM": [ + "HH", + "IH", + "M" + ], + "GOOD": [ + "G", + "UH", + "D" + ], + "JOB": [ + "JH", + "AH", + "B" + ], + "JAYME": [ + "JH", + "EY", + "M", + "IY" + ], + "GOING": [ + "G", + "OW", + "IH", + "NG" + ], + "HEN": [ + "HH", + "EH", + "N" + ], + "COME": [ + "K", + "AH", + "M" + ], + "FROM": [ + "F", + "R", + "AH", + "M" + ], + "JAPAN": [ + "JH", + "AH", + "P", + "AE", + "N" + ], + "PHONE": [ + "F", + "OW", + "N" + ], + "PARTS": [ + "P", + "AA", + "T", + "S" + ], + "TICKETS": [ + "T", + "IH", + "K", + "IH", + "T", + "S" + ], + "ANN": [ + "AE", + "N" + ], + "ATE": [ + "EY", + "T" + ], + "LITTLE": [ + "L", + "IH", + "T", + "L" + ], + "DOG": [ + "D", + "AH", + "G" + ], + "DOES": [ + "D", + "AH", + "Z" + ], + "JAM": [ + "JH", + "AE", + "M" + ], + "LAMB": [ + "L", + "AE", + "M" + ], + "NOODLES": [ + "N", + "UW", + "D", + "L", + "Z" + ], + "OLD": [ + "OW", + "L", + "D" + ], + "NEEDS": [ + "N", + "IY", + "D", + "Z" + ], + "BOOTS": [ + "B", + "UW", + "T", + "S" + ], + "MOTOR": [ + "M", + "OW", + "T", + "ER" + ], + "CYCLE": [ + "S", + "AY", + "K", + "L" + ], + "LEFT": [ + "L", + "EH", + "F", + "T" + ], + "FRUIT": [ + "F", + "R", + "UW", + "T" + ], + "STAND": [ + "S", + "T", + "AE", + "N", + "D" + ], + "GYM": [ + "JH", + "IH", + "M" + ], + "WHEN": [ + "W", + "EH", + "N" + ], + "PET": [ + "P", + "EH", + "T" + ], + "SHOP": [ + "SH", + "AH", + "P" + ], + "ALICE": [ + "AE", + "L", + "IH", + "S" + ], + "VILLAGE": [ + "V", + "IH", + "L", + "IH", + "JH" + ], + "NO": [ + "N", + "OW" + ], + "THAT'S": [ + "DH", + "AE", + "T", + "S" + ], + "I'M": [ + "AY", + "M" + ], + "ACTOR": [ + "AE", + "K", + "T", + "ER" + ], + "LOVELY": [ + "L", + "AH", + "V", + "L", + "IY" + ], + "CLEAN": [ + "K", + "L", + "IY", + "N" + ], + "TEETH": [ + "T", + "IY", + "TH" + ], + "LOVE": [ + "L", + "AH", + "V" + ], + "BROWN": [ + "B", + "R", + "AW", + "N" + ], + "ANDY": [ + "AE", + "N", + "D", + "IH" + ], + "JOHN": [ + "JH", + "AH", + "N" + ], + "COW": [ + "K", + "AW" + ], + "TEDDY": [ + "T", + "EH", + "D", + "IH" + ], + "RACING": [ + "R", + "EY", + "S", + "IH", + "NG" + ], + "RED": [ + "R", + "EH", + "D" + ], + "JEANS": [ + "JH", + "IY", + "N", + "Z" + ], + "CLOTH": [ + "K", + "L", + "AH", + "TH" + ], + "T": [ + "T", + "IY" + ], + "SHIRT": [ + "SH", + "ER", + "T" + ], + "LILLY": [ + "L", + "IH", + "L", + "IY" + ], + "MUSIC": [ + "M", + "Y", + "UW", + "Z", + "IH", + "K" + ], + "ROOM": [ + "R", + "UW", + "M" + ], + "DO": [ + "D", + "UH" + ], + "YOU": [ + "Y", + "UW" + ], + "PEA": [ + "P", + "IY" + ], + "MUSHROOM": [ + "M", + "AH", + "SH", + "R", + "UH", + "M" + ], + "FOR": [ + "F", + "AO" + ], + "PARTY": [ + "P", + "AA", + "R", + "T", + "IY" + ], + "IT'S": [ + "IH", + "T", + "S" + ], + "JUST": [ + "JH", + "AH", + "S", + "T" + ], + "HARD": [ + "HH", + "AA", + "R", + "D" + ], + "PICTURE": [ + "P", + "IH", + "K", + "CH", + "ER" + ], + "SPEAK": [ + "S", + "P", + "IY", + "K" + ], + "OUT": [ + "AW", + "T" + ], + "FEEL": [ + "F", + "IY", + "L" + ], + "SHOULD": [ + "SH", + "UH", + "D" + ], + "I": [ + "AY" + ], + "COULD": [ + "K", + "UH", + "D" + ], + "BREAK": [ + "B", + "R", + "EY", + "K" + ], + "ALWAYS": [ + "AO", + "L", + "W", + "EY", + "Z" + ], + "NICE": [ + "N", + "AY", + "S" + ], + "UNFORTUNATELY": [ + "AH", + "N", + "F", + "AO", + "CH", + "AH", + "N", + "AH", + "T", + "L", + "IY" + ], + "ALLOW": [ + "AH", + "L", + "AW" + ], + "ALMOST": [ + "AO", + "L", + "M", + "OW", + "S", + "T" + ], + "TIME": [ + "T", + "AY", + "M" + ], + "HAIRCUT": [ + "HH", + "EH", + "R", + "K", + "AH", + "T" + ], + "BE": [ + "B", + "IY" + ], + "MORE": [ + "M", + "AO" + ], + "PRODUCTIVE": [ + "P", + "R", + "AH", + "D", + "AH", + "K", + "T", + "IH", + "V" + ], + "STARTING": [ + "S", + "T", + "AA", + "R", + "T", + "IH", + "NG" + ], + "BETTER": [ + "B", + "EH", + "T", + "ER" + ], + "THAN": [ + "DH", + "AE", + "N" + ], + "THIS": [ + "DH", + "IH", + "S" + ], + "KEEP": [ + "K", + "IY", + "P" + ], + "AMUSED": [ + "AH", + "M", + "Y", + "UW", + "Z", + "D" + ], + "BY": [ + "B", + "AY" + ], + "STUPIDITY": [ + "S", + "T", + "Y", + "UW", + "P", + "IH", + "D", + "AH", + "T", + "IY" + ], + "AFTER": [ + "AA", + "F", + "T", + "AH" + ], + "THAT": [ + "DH", + "AE", + "T" + ], + "READY": [ + "R", + "EH", + "D", + "IY" + ], + "THANK": [ + "TH", + "AE", + "NG", + "K" + ], + "SYMPATHY": [ + "S", + "IH", + "M", + "P", + "AH", + "TH", + "IY" + ], + "BECAUSE": [ + "B", + "IH", + "K", + "AH", + "Z" + ], + "COUNTS": [ + "K", + "AW", + "N", + "T", + "S" + ], + "OFF": [ + "AH", + "F" + ], + "CHAIN": [ + "CH", + "EY", + "N" + ], + "BET": [ + "B", + "EH", + "T" + ], + "NODDED": [ + "N", + "AH", + "D", + "IH", + "D" + ], + "HIS": [ + "HH", + "IH", + "Z" + ], + "HEAD": [ + "HH", + "EH", + "D" + ], + "AND": [ + "AE", + "N", + "D" + ], + "SMILED": [ + "S", + "M", + "AY", + "L", + "D" + ], + "BUT": [ + "B", + "AH", + "T" + ], + "ME": [ + "M", + "IY" + ], + "TRUTH": [ + "T", + "R", + "UW", + "TH" + ], + "FIRST": [ + "F", + "ER", + "S", + "T" + ], + "QUESTION": [ + "K", + "W", + "EH", + "S", + "CH", + "AH", + "N" + ], + "WAS": [ + "W", + "AH", + "Z" + ], + "AN": [ + "AE", + "N" + ], + "OBVIOUS": [ + "AH", + "B", + "V", + "IH", + "AH", + "S" + ], + "SHOCK": [ + "SH", + "AH", + "K" + ], + "TOO": [ + "T", + "UW" + ], + "MUCH": [ + "M", + "AH", + "CH" + ], + "KNOWS": [ + "N", + "OW", + "Z" + ], + "HE'S": [ + "HH", + "IY", + "Z" + ], + "GET": [ + "G", + "EH", + "T" + ], + "INTO": [ + "IH", + "N", + "T", + "UW" + ], + "FIGHT": [ + "F", + "AY", + "T" + ], + "ANYTHING": [ + "EH", + "N", + "IY", + "TH", + "IH", + "NG" + ], + "WHATEVER": [ + "W", + "AH", + "T", + "EH", + "V", + "ER" + ], + "LONG": [ + "L", + "AH", + "NG" + ], + "SHORT": [ + "SH", + "AO", + "T" + ], + "OF": [ + "AH", + "V" + ], + "FISH": [ + "F", + "IH", + "SH" + ], + "SHEEP": [ + "SH", + "IY", + "P" + ], + "LYNDA": [ + "L", + "IH", + "N", + "D", + "AH" + ], + "ELEPHANT": [ + "EH", + "L", + "IH", + "F", + "AH", + "N", + "T" + ], + "MY": [ + "M", + "AY" + ], + "DRAW": [ + "D", + "R", + "AO" + ], + "GOAT": [ + "G", + "OW", + "T" + ], + "BALT": [ + "B", + "AO", + "L", + "T" + ], + "BRO": [ + "B", + "R", + "OW" + ], + "JUMP": [ + "JH", + "AH", + "M", + "P" + ], + "HULK": [ + "HH", + "AH", + "L", + "K" + ], + "BREAD": [ + "B", + "R", + "EH", + "D" + ], + "LEG": [ + "L", + "EH", + "G" + ], + "HAND": [ + "HH", + "AE", + "N", + "D" + ], + "JEEP": [ + "JH", + "IY", + "P" + ], + "V": [ + "V", + "IY" + ], + "STRING": [ + "S", + "T", + "R", + "IH", + "NG" + ], + "BEAN": [ + "B", + "IY", + "N" + ], + "SHE": [ + "SH", + "IY" + ], + "WANTS": [ + "W", + "AH", + "N", + "T", + "S" + ], + "STUDENT": [ + "S", + "T", + "UW", + "D", + "N", + "T" + ], + "WILL": [ + "W", + "IH", + "L" + ], + "CAT": [ + "K", + "AE", + "T" + ], + "DOWN": [ + "D", + "AW", + "N" + ], + "FREED": [ + "F", + "R", + "IY", + "D" + ], + "ORANGE": [ + "AH", + "R", + "IH", + "N", + "JH" + ], + "PEACH": [ + "P", + "IY", + "CH" + ], + "TIGER": [ + "T", + "AY", + "G", + "ER" + ], + "MOUNTAINS": [ + "M", + "AW", + "N", + "T", + "AH", + "N", + "S" + ], + "SIR": [ + "S", + "ER" + ], + "PLANTING": [ + "P", + "L", + "AE", + "N", + "T", + "IH", + "NG" + ], + "GRAFF": [ + "G", + "R", + "AA", + "F" + ], + "SANDWICH": [ + "S", + "AE", + "N", + "W", + "IH", + "CH" + ], + "GIVE": [ + "G", + "IH", + "V" + ], + "BISCUIT": [ + "B", + "IH", + "S", + "K", + "IH", + "T" + ], + "CAKE": [ + "K", + "EY", + "K" + ], + "LIYA": [ + "L", + "IY", + "AH" + ], + "SAFE": [ + "S", + "EY", + "F" + ], + "TRAIN": [ + "T", + "R", + "EY", + "N" + ], + "TOILET": [ + "T", + "OY", + "L", + "AH", + "T" + ], + "ART": [ + "AA", + "T" + ], + "GREEN": [ + "G", + "R", + "IY", + "N" + ], + "CITY": [ + "S", + "IH", + "T", + "IY" + ], + "LONDON": [ + "L", + "AH", + "N", + "D", + "AH", + "N" + ], + "MEN": [ + "M", + "EH", + "N" + ], + "WHERE": [ + "W", + "EH", + "R" + ], + "DID": [ + "D", + "IH", + "D" + ], + "ONLY": [ + "OW", + "N", + "L", + "IY" + ], + "GARDEN": [ + "G", + "AA", + "D", + "N" + ], + "PORTER": [ + "P", + "OW", + "T", + "ER" + ], + "FOX": [ + "F", + "AH", + "K", + "S" + ], + "QUICK": [ + "K", + "W", + "IH", + "K" + ], + "PAST": [ + "P", + "AA", + "S", + "T" + ], + "PHOTO": [ + "F", + "OW", + "T", + "OW" + ], + "SHANGHAI": [ + "SH", + "AE", + "NG", + "HH", + "AY" + ], + "QUIRE": [ + "K", + "W", + "AY", + "AH" + ], + "TODAY": [ + "T", + "AH", + "D", + "EY" + ], + "ONCE": [ + "W", + "AH", + "N", + "S" + ], + "TOMORROW": [ + "T", + "AH", + "M", + "AH", + "R", + "OW" + ], + "KANGAROO": [ + "K", + "AE", + "NG", + "G", + "AH", + "R", + "UW" + ], + "COWS": [ + "K", + "AW", + "Z" + ], + "TRACE": [ + "T", + "R", + "EY", + "S" + ], + "PETER": [ + "P", + "IY", + "T", + "ER" + ], + "SKIN": [ + "S", + "K", + "IH", + "N" + ], + "BILLY'S": [ + "B", + "IH", + "L", + "IY", + "S" + ], + "FOOT": [ + "F", + "UH", + "T" + ], + "LINDA": [ + "L", + "IH", + "N", + "D", + "AH" + ], + "SUN": [ + "S", + "AH", + "N" + ], + "BOY": [ + "B", + "OY" + ], + "THIEF": [ + "TH", + "IY", + "F" + ], + "SANDY": [ + "S", + "AE", + "N", + "D", + "IY" + ], + "TURN": [ + "T", + "ER", + "N" + ], + "PAR": [ + "P", + "AA" + ], + "DRAWING": [ + "D", + "R", + "AO", + "IH", + "NG" + ], + "PASS": [ + "P", + "AA", + "S" + ], + "NILA": [ + "N", + "IY", + "L", + "AH" + ], + "NEWS": [ + "N", + "Y", + "UW", + "Z" + ], + "MUST": [ + "M", + "AH", + "S", + "T" + ], + "AM": [ + "AH", + "M" + ], + "GLASS": [ + "G", + "L", + "AA", + "S" + ], + "MONKEY": [ + "M", + "AH", + "NG", + "K", + "IY" + ], + "LUCY": [ + "L", + "UW", + "S", + "IY" + ], + "HORSE": [ + "HH", + "AO", + "S" + ], + "HOCK": [ + "HH", + "AH", + "K" + ], + "SONG": [ + "S", + "AH", + "NG" + ], + "MUTTON": [ + "M", + "AH", + "T", + "N" + ], + "DAVID'S": [ + "D", + "EH", + "V", + "IH", + "D", + "S" + ], + "TOES": [ + "T", + "OW", + "Z" + ], + "NEED": [ + "N", + "IY", + "D" + ], + "SHORTS": [ + "SH", + "AO", + "T", + "S" + ], + "JACK": [ + "JH", + "AE", + "K" + ], + "CUP": [ + "K", + "AH", + "P" + ], + "DORA'S": [ + "D", + "AO", + "R", + "AH", + "S" + ], + "CLOT": [ + "K", + "L", + "AH", + "T" + ], + "CAR": [ + "K", + "AA", + "R" + ], + "ARE": [ + "AA" + ], + "GOLD": [ + "G", + "OW", + "L", + "D" + ], + "TEACHER": [ + "T", + "IY", + "CH", + "ER" + ], + "NERVOUS": [ + "N", + "ER", + "V", + "AH", + "S" + ], + "ANYBODY": [ + "EH", + "N", + "IY", + "B", + "AH", + "D", + "IY" + ], + "BANK": [ + "B", + "AE", + "NG", + "K" + ], + "HERE": [ + "HH", + "IH", + "AH" + ], + "CHUCK": [ + "CH", + "AH", + "K" + ], + "LEAVE": [ + "L", + "IY", + "V" + ], + "WHO": [ + "HH", + "UW" + ], + "COUNT": [ + "K", + "AW", + "N", + "T" + ], + "BALL": [ + "B", + "AO", + "L" + ], + "MANGO": [ + "M", + "AE", + "NG", + "G", + "OW" + ], + "CUTE": [ + "K", + "Y", + "UW", + "T" + ], + "DEAR": [ + "D", + "IH", + "AH" + ], + "PIG": [ + "P", + "IH", + "G" + ], + "ZEBRA": [ + "Z", + "IY", + "B", + "R", + "AH" + ], + "SHOES": [ + "SH", + "UW", + "Z" + ], + "OLYMPIA": [ + "AH", + "UW", + "L", + "IY", + "M", + "P", + "IH", + "AH" + ], + "CINEMA": [ + "S", + "IH", + "N", + "AH", + "M", + "AH" + ], + "FRIDAY": [ + "F", + "R", + "AY", + "D", + "EY" + ], + "FANS": [ + "F", + "AE", + "N", + "Z" + ], + "RICE": [ + "R", + "AY", + "S" + ], + "LISA": [ + "L", + "IY", + "S", + "AH" + ], + "YET": [ + "Y", + "EH", + "T" + ], + "CLASSROOM": [ + "K", + "L", + "AA", + "S", + "R", + "UW", + "M" + ], + "BEDROOM": [ + "B", + "EH", + "D", + "R", + "UH", + "M" + ], + "DAD": [ + "D", + "AE", + "D" + ], + "GOES": [ + "G", + "OW", + "Z" + ], + "CARROT": [ + "K", + "AE", + "R", + "AH", + "T" + ], + "MOST": [ + "M", + "OW", + "S", + "T" + ], + "WELCOME": [ + "W", + "EH", + "L", + "K", + "AH", + "M" + ], + "WELL": [ + "W", + "EH", + "L" + ], + "MOTHER": [ + "M", + "AH", + "DH", + "ER" + ], + "WHAT'S": [ + "W", + "AH", + "T", + "S" + ], + "HER": [ + "HH", + "ER" + ], + "BORN": [ + "B", + "AO", + "N" + ], + "SINGER": [ + "S", + "IH", + "NG", + "ER" + ], + "COMING": [ + "K", + "AH", + "M", + "IH", + "NG" + ], + "AUSTRALIAN": [ + "AO", + "S", + "T", + "R", + "EY", + "L", + "IH", + "AH", + "N" + ], + "FRANCE": [ + "F", + "R", + "AE", + "N", + "S" + ], + "TENNIS": [ + "T", + "EH", + "N", + "IH", + "S" + ], + "KNOW": [ + "N", + "OW" + ], + "HOT": [ + "HH", + "AH", + "T" + ], + "COAT": [ + "K", + "OW", + "T" + ], + "PLANE": [ + "P", + "L", + "EY", + "N" + ], + "NEAR": [ + "N", + "IH", + "AH" + ], + "FARM": [ + "F", + "AA", + "M" + ], + "PEAR": [ + "P", + "EH", + "R" + ], + "EYE": [ + "AY" + ], + "LEMON": [ + "L", + "EH", + "M", + "AH", + "N" + ], + "RELATIVES": [ + "R", + "EH", + "L", + "AH", + "T", + "IH", + "V", + "Z" + ], + "N": [ + "EH", + "N" + ], + "U": [ + "Y", + "UW" + ], + "S": [ + "EH", + "S" + ], + "DRESSING": [ + "D", + "R", + "EH", + "S", + "IH", + "NG" + ], + "HOCKEY": [ + "HH", + "AH", + "K", + "IY" + ], + "P": [ + "P", + "IY" + ], + "GIRL": [ + "G", + "ER", + "L" + ], + "DINNER": [ + "D", + "IH", + "N", + "ER" + ], + "FAIRY": [ + "F", + "EH", + "R", + "IY" + ], + "TOLL": [ + "T", + "OW", + "L" + ], + "FULL": [ + "F", + "UH", + "L" + ], + "CHICKEN": [ + "CH", + "IH", + "K", + "IH", + "N" + ], + "TOM'S": [ + "T", + "AH", + "M", + "S" + ], + "SHOULDER": [ + "SH", + "OW", + "L", + "D", + "ER" + ], + "HAT": [ + "HH", + "AE", + "T" + ], + "GLOVES": [ + "G", + "L", + "AH", + "V", + "Z" + ], + "FARMER": [ + "F", + "AA", + "M", + "AH" + ], + "BILL": [ + "B", + "IH", + "L" + ], + "E": [ + "IY" + ], + "CLASS": [ + "K", + "L", + "AA", + "S" + ], + "SHALL": [ + "SH", + "AH", + "L" + ], + "HOME": [ + "HH", + "OW", + "M" + ], + "LAOS": [ + "L", + "AW", + "S" + ], + "CARDS": [ + "K", + "AA", + "D", + "Z" + ], + "BIRD": [ + "B", + "ER", + "D" + ], + "LISTEN": [ + "L", + "IH", + "S", + "N" + ], + "SURFING": [ + "S", + "ER", + "F", + "IH", + "NG" + ], + "RUNNING": [ + "R", + "AH", + "N", + "IH", + "NG" + ], + "HANDBALL": [ + "HH", + "AE", + "N", + "D", + "B", + "AO", + "L" + ], + "JACKET": [ + "JH", + "AE", + "K", + "IH", + "T" + ], + "SOCKS": [ + "S", + "AH", + "K", + "S" + ], + "VAN": [ + "V", + "AE", + "N" + ], + "PAINT": [ + "P", + "EY", + "N", + "T" + ], + "SUBWAY": [ + "S", + "AH", + "B", + "W", + "EY" + ], + "BOOKSTORE": [ + "B", + "UH", + "K", + "S", + "T", + "AO", + "R" + ], + "GEN": [ + "JH", + "EH", + "N" + ], + "AUSTRALIA": [ + "AH", + "S", + "T", + "R", + "EY", + "L", + "IH", + "AH" + ], + "CANADA": [ + "K", + "AE", + "N", + "AH", + "D", + "AH" + ], + "CHINA": [ + "CH", + "AY", + "N", + "AH" + ], + "BEEF": [ + "B", + "IY", + "F" + ], + "PLEASE": [ + "P", + "L", + "IY", + "Z" + ], + "CLOSE": [ + "K", + "L", + "OW", + "S" + ], + "SKIRT": [ + "S", + "K", + "ER", + "T" + ], + "MATCH": [ + "M", + "AE", + "CH" + ], + "DADDY": [ + "D", + "AE", + "D", + "IY" + ], + "SCIENCE": [ + "S", + "AY", + "AH", + "N", + "S" + ], + "SCHOOL": [ + "S", + "K", + "UW", + "L" + ], + "HOW": [ + "HH", + "AW" + ], + "HADI": [ + "HH", + "AA", + "D", + "IY" + ], + "FRIEND": [ + "F", + "R", + "EH", + "N", + "D" + ], + "JOURNEY": [ + "JH", + "ER", + "N", + "IY" + ], + "WHY": [ + "W", + "AY" + ], + "ASKED": [ + "AA", + "S", + "K", + "T" + ], + "STEP": [ + "S", + "T", + "EH", + "P" + ], + "MORNING": [ + "M", + "AO", + "N", + "IH", + "NG" + ], + "OVER": [ + "OW", + "V", + "ER" + ], + "MONTH": [ + "M", + "AH", + "N", + "TH" + ], + "WAR": [ + "W", + "AO" + ], + "FAR": [ + "F", + "AA" + ], + "EXACT": [ + "IH", + "G", + "Z", + "AE", + "K", + "T" + ], + "THESE": [ + "DH", + "IY", + "Z" + ], + "MATCHES": [ + "M", + "AE", + "CH", + "IH", + "Z" + ], + "GREAT": [ + "G", + "R", + "EY", + "T" + ], + "WORK": [ + "W", + "ER", + "K" + ], + "LIVING": [ + "L", + "IH", + "V", + "IH", + "NG" + ], + "EARLY": [ + "ER", + "L", + "IY" + ], + "NEVER": [ + "N", + "EH", + "V", + "ER" + ], + "WANTED": [ + "W", + "AA", + "N", + "T", + "IH", + "D" + ], + "COOL": [ + "K", + "UW", + "L" + ], + "REALLY": [ + "R", + "IH", + "AH", + "L", + "IY" + ], + "WASHING": [ + "W", + "AH", + "SH", + "IH", + "NG" + ], + "WATCH": [ + "W", + "AH", + "CH" + ], + "MANY": [ + "M", + "EH", + "N", + "IY" + ], + "SEA": [ + "S", + "IY" + ], + "JEALOUS": [ + "JH", + "EH", + "L", + "AH", + "S" + ], + "THING": [ + "TH", + "IH", + "NG" + ], + "GAME": [ + "G", + "EY", + "M" + ], + "TOP": [ + "T", + "AH", + "P" + ], + "CHARTS": [ + "CH", + "AA", + "T", + "S" + ], + "TALK": [ + "T", + "AO", + "K" + ], + "TONIGHT": [ + "T", + "AH", + "N", + "AY", + "T" + ], + "LAKE": [ + "L", + "EY", + "K" + ], + "WAITING": [ + "W", + "EY", + "T", + "IH", + "NG" + ], + "NEXT": [ + "N", + "EH", + "K", + "S", + "T" + ], + "SEASON": [ + "S", + "IY", + "Z", + "N" + ], + "MAN": [ + "M", + "AE", + "N" + ], + "BUCKET": [ + "B", + "AH", + "K", + "IH", + "T" + ], + "NERVOUSLY": [ + "N", + "ER", + "V", + "AH", + "S", + "L", + "IY" + ], + "WINGS": [ + "W", + "IH", + "NG", + "Z" + ], + "NIGHT": [ + "N", + "AY", + "T" + ], + "ROAD": [ + "R", + "OW", + "D" + ], + "PUT": [ + "P", + "UH", + "T" + ], + "ELBOWS": [ + "EH", + "L", + "B", + "OW", + "Z" + ], + "TABLE": [ + "T", + "EY", + "B", + "L" + ], + "YES": [ + "Y", + "EH", + "S" + ], + "SURE": [ + "SH", + "UH", + "AH" + ], + "VAGUE": [ + "V", + "EY", + "G" + ], + "THOUGHT": [ + "TH", + "AO", + "T" + ], + "DIVER": [ + "D", + "AY", + "V", + "ER" + ], + "FOOTBALL": [ + "F", + "UH", + "T", + "B", + "AO", + "L" + ], + "MIDDLE": [ + "M", + "IH", + "D", + "L" + ], + "RETURNS": [ + "R", + "IH", + "T", + "ER", + "N", + "S" + ], + "BOWING": [ + "B", + "OW", + "IH", + "NG" + ], + "PORK": [ + "P", + "AO", + "K" + ], + "HOUSE": [ + "HH", + "AW", + "S" + ], + "DAVID": [ + "D", + "EH", + "V", + "IH", + "D" + ], + "WALK": [ + "W", + "AO", + "K" + ], + "WASHED": [ + "W", + "AA", + "SH", + "T" + ], + "BUTTER": [ + "B", + "AH", + "T", + "ER" + ], + "OFFER": [ + "AO", + "F", + "ER" + ], + "BEST": [ + "B", + "EH", + "S", + "T" + ], + "PITS": [ + "P", + "IH", + "T", + "S" + ], + "LIGHTER": [ + "L", + "AY", + "T", + "AH" + ], + "THEY": [ + "DH", + "EY" + ], + "FIT": [ + "F", + "IH", + "T" + ], + "PIG'S": [ + "P", + "IH", + "G", + "S" + ], + "OFFICER": [ + "AH", + "F", + "IH", + "S", + "AH" + ], + "VERY": [ + "V", + "EH", + "R", + "IY" + ], + "PRETTY": [ + "P", + "R", + "IH", + "T", + "IY" + ], + "OUR": [ + "AW", + "ER" + ], + "WISH": [ + "W", + "IH", + "SH" + ], + "LIVE": [ + "L", + "IH", + "V" + ], + "THROUGH": [ + "TH", + "R", + "UW" + ], + "OTHERS": [ + "AH", + "DH", + "ER", + "Z" + ], + "SAME": [ + "S", + "EY", + "M" + ], + "AGAIN": [ + "AH", + "G", + "EH", + "N" + ], + "MADE": [ + "M", + "EY", + "D" + ], + "CLEAR": [ + "K", + "L", + "IH", + "AH" + ], + "STATEMENT": [ + "S", + "T", + "EY", + "T", + "M", + "AH", + "N", + "T" + ], + "THOSE": [ + "DH", + "OW", + "Z" + ], + "HAPPEN": [ + "HH", + "AE", + "P", + "AH", + "N" + ], + "ANYONE": [ + "EH", + "N", + "IY", + "W", + "AH", + "N" + ], + "SECOND": [ + "S", + "EH", + "K", + "AH", + "N", + "D" + ], + "SHOT": [ + "SH", + "AH", + "T" + ], + "CHOICE": [ + "CH", + "OY", + "S" + ], + "OPTIONS": [ + "AH", + "P", + "SH", + "N", + "Z" + ], + "MAKE": [ + "M", + "EY", + "K" + ], + "CAPTAINS": [ + "K", + "AE", + "P", + "T", + "IH", + "N", + "Z" + ], + "WORSE": [ + "W", + "ER", + "S" + ], + "FALL": [ + "F", + "AO", + "L" + ], + "EVERYDAY": [ + "EH", + "V", + "R", + "IY", + "D", + "EY" + ], + "FOREVER": [ + "F", + "ER", + "EH", + "V", + "AH" + ], + "BAD": [ + "B", + "AE", + "D" + ], + "DEAL": [ + "D", + "IY", + "L" + ], + "CHEATING": [ + "CH", + "IY", + "T", + "IH", + "NG" + ], + "CHILDISH": [ + "CH", + "AY", + "L", + "D", + "IH", + "SH" + ], + "SECRETARY": [ + "S", + "EH", + "K", + "R", + "AH", + "T", + "R", + "IY" + ], + "ENERGY": [ + "EH", + "N", + "ER", + "JH", + "IY" + ], + "WRONG": [ + "R", + "AH", + "NG" + ], + "IF": [ + "IH", + "F" + ], + "WAY": [ + "W", + "EY" + ], + "HEART": [ + "HH", + "AA", + "R", + "T" + ], + "LION": [ + "L", + "AY", + "AH", + "N" + ], + "ALREADY": [ + "AO", + "L", + "R", + "EH", + "D", + "IY" + ], + "DIRTY": [ + "D", + "ER", + "T", + "IY" + ], + "MIGHT": [ + "M", + "AY", + "T" + ], + "PUSH": [ + "P", + "UH", + "SH" + ], + "DEEPS": [ + "D", + "IY", + "P", + "S" + ], + "SHUT": [ + "SH", + "AH", + "T" + ], + "EYES": [ + "AY", + "Z" + ], + "BREATH": [ + "B", + "R", + "EH", + "TH" + ], + "THERE": [ + "DH", + "EH", + "R" + ], + "DOUBT": [ + "D", + "AW", + "T" + ], + "FORGIVE": [ + "F", + "AH", + "G", + "IH", + "V" + ], + "MYSELF": [ + "M", + "AY", + "S", + "EH", + "L", + "F" + ], + "EXPOSURE": [ + "IH", + "K", + "S", + "P", + "OW", + "ZH", + "AH" + ], + "LIGHT": [ + "L", + "AY", + "T" + ], + "RAIN": [ + "R", + "EY", + "N" + ], + "FALLING": [ + "F", + "AO", + "L", + "IH", + "NG" + ], + "WERE": [ + "W", + "ER" + ], + "ROLLING": [ + "R", + "OW", + "L", + "IH", + "NG" + ], + "AROUND": [ + "AH", + "R", + "AW", + "N", + "D" + ], + "FIELD": [ + "F", + "IY", + "L", + "D" + ], + "PLAY": [ + "P", + "L", + "EY" + ], + "FACE": [ + "F", + "EY", + "S" + ], + "EARTH": [ + "ER", + "TH" + ], + "MATTER": [ + "M", + "AE", + "T", + "ER" + ], + "US": [ + "AH", + "S" + ], + "COVER": [ + "K", + "AH", + "V", + "ER" + ], + "AFRAID": [ + "AH", + "F", + "R", + "EY", + "D" + ], + "INFORMED": [ + "IH", + "N", + "F", + "AO", + "R", + "M", + "D" + ], + "PEOPLE": [ + "P", + "IY", + "P", + "L" + ], + "ALONG": [ + "AH", + "L", + "AH", + "NG" + ], + "VOTE": [ + "V", + "OW", + "T" + ], + "PLUS": [ + "P", + "L", + "AH", + "S" + ], + "FUN": [ + "F", + "AH", + "N" + ], + "POINTING": [ + "P", + "OY", + "N", + "T", + "IH", + "NG" + ], + "SEEMS": [ + "S", + "IY", + "M", + "Z" + ], + "MOSTLY": [ + "M", + "OW", + "S", + "T", + "L", + "IY" + ], + "PHONES": [ + "F", + "OW", + "N", + "Z" + ], + "FEELING": [ + "F", + "IY", + "L", + "IH", + "NG" + ], + "STILL": [ + "S", + "T", + "IH", + "L" + ], + "COUPLE": [ + "K", + "AH", + "P", + "L" + ], + "WEEKS": [ + "W", + "IY", + "K", + "S" + ], + "FAN": [ + "F", + "AE", + "N" + ], + "STANDING": [ + "S", + "T", + "AE", + "N", + "D", + "IH", + "NG" + ], + "BOAT": [ + "B", + "OW", + "T" + ], + "BELOW": [ + "B", + "IH", + "L", + "OW" + ], + "RIVER": [ + "R", + "IH", + "V", + "ER" + ], + "BOOK": [ + "B", + "UH", + "K" + ], + "ENTERTAIN": [ + "EH", + "N", + "T", + "ER", + "T", + "EY", + "N" + ], + "AS": [ + "AE", + "Z" + ], + "INFORMS": [ + "IH", + "N", + "F", + "AO", + "M", + "Z" + ], + "EASY": [ + "IY", + "Z", + "IY" + ], + "ENTHUSIASTIC": [ + "IH", + "N", + "TH", + "Y", + "UW", + "Z", + "IY", + "AE", + "S", + "T", + "IH", + "K" + ], + "MOVE": [ + "M", + "UW", + "V" + ], + "PART": [ + "P", + "AA", + "T" + ], + "PLAN": [ + "P", + "L", + "AE", + "N" + ], + "INCREASE": [ + "IH", + "N", + "K", + "R", + "IY", + "S" + ], + "PROFITS": [ + "P", + "R", + "AA", + "F", + "IH", + "T", + "S" + ], + "REPORTS": [ + "R", + "IH", + "P", + "AO", + "T", + "S" + ], + "EXPECTED": [ + "IH", + "K", + "S", + "P", + "EH", + "K", + "T", + "IH", + "D" + ], + "END": [ + "EH", + "N", + "D" + ], + "YEAR": [ + "Y", + "IH", + "AH" + ], + "POSSIBLE": [ + "P", + "AH", + "S", + "AH", + "B", + "L" + ], + "MEET": [ + "M", + "IY", + "T" + ], + "DAY": [ + "D", + "EY" + ], + "LISTENING": [ + "L", + "IH", + "S", + "N", + "IH", + "NG" + ], + "RADIO": [ + "R", + "EY", + "D", + "IY", + "OW" + ], + "RIGHT": [ + "R", + "AY", + "T" + ], + "BELIEVE": [ + "B", + "IH", + "L", + "IY", + "V" + ], + "DREAMS": [ + "D", + "R", + "IY", + "M", + "Z" + ], + "CONTINUE": [ + "K", + "AH", + "N", + "T", + "IH", + "N", + "Y", + "UW" + ], + "HOPE": [ + "HH", + "OW", + "P" + ], + "TOUR": [ + "T", + "UH", + "AH" + ], + "BEAST": [ + "B", + "IY", + "S", + "T" + ], + "PACKAGE": [ + "P", + "AE", + "K", + "IH", + "JH" + ], + "BACK": [ + "B", + "AE", + "K" + ], + "RESOURCE": [ + "R", + "IH", + "S", + "AO", + "R", + "S" + ], + "STREET": [ + "S", + "T", + "R", + "IY", + "T" + ], + "ANSWER": [ + "AA", + "N", + "S", + "AH" + ], + "ALSO": [ + "AO", + "L", + "S", + "OW" + ], + "BEGINNING": [ + "B", + "IH", + "G", + "IH", + "N", + "IH", + "NG" + ], + "WOULD": [ + "W", + "UH", + "D" + ], + "IMPOSSIBLE": [ + "IH", + "M", + "P", + "AH", + "S", + "AH", + "B", + "L" + ], + "FLAT": [ + "F", + "L", + "AE", + "T" + ], + "TAKE": [ + "T", + "EY", + "K" + ], + "CHANCE": [ + "CH", + "AA", + "N", + "S" + ], + "EXPRESS": [ + "IH", + "K", + "S", + "P", + "R", + "EH", + "S" + ], + "PLAYING": [ + "P", + "L", + "EY", + "IH", + "NG" + ], + "FIND": [ + "F", + "AY", + "N", + "D" + ], + "TOUCH": [ + "T", + "AH", + "CH" + ], + "SHOW": [ + "SH", + "OW" + ], + "BRIGHT": [ + "B", + "R", + "AY", + "T" + ], + "HAPPENED": [ + "HH", + "AE", + "P", + "AH", + "N", + "D" + ], + "COLLEGE": [ + "K", + "AH", + "L", + "IH", + "JH" + ], + "SOMEONE": [ + "S", + "AH", + "M", + "W", + "AH", + "N" + ], + "HELP": [ + "HH", + "EH", + "L", + "P" + ], + "WITHOUT": [ + "W", + "IH", + "DH", + "AW", + "T" + ], + "HAVING": [ + "HH", + "AE", + "V", + "IH", + "NG" + ], + "THINK": [ + "TH", + "IH", + "NG", + "K" + ], + "REST": [ + "R", + "EH", + "S", + "T" + ], + "WAKE": [ + "W", + "EY", + "K" + ], + "INJURE": [ + "IH", + "N", + "JH", + "ER" + ], + "CERTAINLY": [ + "S", + "ER", + "T", + "N", + "L", + "IY" + ], + "WOLFS": [ + "W", + "UH", + "L", + "F", + "S" + ], + "QUITE": [ + "K", + "W", + "AY", + "T" + ], + "TOUGH": [ + "T", + "AH", + "F" + ], + "POSITION": [ + "P", + "AH", + "Z", + "IH", + "SH", + "N" + ], + "KIND": [ + "K", + "AY", + "N", + "D" + ], + "AMERICAN": [ + "AH", + "M", + "EH", + "R", + "IH", + "K", + "AH", + "N" + ], + "LEAD": [ + "L", + "IY", + "D" + ], + "AGAINST": [ + "AH", + "G", + "EY", + "N", + "S", + "T" + ], + "LAW": [ + "L", + "AO" + ], + "LOST": [ + "L", + "AH", + "S", + "T" + ], + "RUN": [ + "R", + "AH", + "N" + ], + "NOTHING": [ + "N", + "AH", + "TH", + "IH", + "NG" + ], + "BABY": [ + "B", + "EY", + "B", + "IY" + ], + "GUESSING": [ + "G", + "EH", + "S", + "IH", + "NG" + ], + "MONDAY": [ + "M", + "AH", + "N", + "D", + "EY" + ], + "NECK": [ + "N", + "EH", + "K" + ], + "WOODS": [ + "W", + "UH", + "D", + "Z" + ], + "WALL": [ + "W", + "AO", + "L" + ], + "DEPENDS": [ + "D", + "IH", + "P", + "EH", + "N", + "D", + "Z" + ], + "HEARTS": [ + "HH", + "AA", + "R", + "T", + "S" + ], + "SHAME": [ + "SH", + "EY", + "M" + ], + "LET": [ + "L", + "EH", + "T" + ], + "HOUR": [ + "AW", + "ER" + ], + "SLEEP": [ + "S", + "L", + "IY", + "P" + ], + "AWAY": [ + "AH", + "W", + "EY" + ], + "EVERYTHING": [ + "EH", + "V", + "R", + "IY", + "TH", + "IH", + "NG" + ], + "MIND": [ + "M", + "AY", + "N", + "D" + ], + "TEST": [ + "T", + "EH", + "S", + "T" + ], + "VIEW": [ + "V", + "Y", + "UW" + ], + "BEAT": [ + "B", + "IY", + "T" + ], + "FURTHER": [ + "F", + "ER", + "DH", + "ER" + ], + "SONGS": [ + "S", + "AO", + "NG", + "Z" + ], + "SPRING": [ + "S", + "P", + "R", + "IH", + "NG" + ], + "TRAINING": [ + "T", + "R", + "EY", + "N", + "IH", + "NG" + ], + "JAZZ": [ + "JH", + "AE", + "Z" + ], + "UNABLE": [ + "AH", + "N", + "EY", + "B", + "L" + ], + "FINAL": [ + "F", + "AY", + "N", + "L" + ], + "VICTIMS": [ + "V", + "IH", + "K", + "T", + "IH", + "M", + "S" + ], + "LISTED": [ + "L", + "IH", + "S", + "T", + "IH", + "D" + ], + "SERIOUS": [ + "S", + "IH", + "AH", + "R", + "IH", + "AH", + "S" + ], + "CONDITION": [ + "K", + "AH", + "N", + "D", + "IH", + "SH", + "N" + ], + "PLAYER": [ + "P", + "L", + "EH", + "IH", + "AH", + "R" + ], + "BUILDING": [ + "B", + "IH", + "L", + "D", + "IH", + "NG" + ], + "DIG": [ + "D", + "IH", + "G" + ], + "ALONE": [ + "AH", + "L", + "OW", + "N" + ], + "AGREE": [ + "AH", + "G", + "R", + "IY" + ], + "DISAGREE": [ + "D", + "IH", + "S", + "AH", + "G", + "R", + "IY" + ], + "ESPECIALLY": [ + "IH", + "S", + "P", + "EH", + "SH", + "AH", + "L", + "IY" + ], + "SESSION": [ + "S", + "EH", + "SH", + "N" + ], + "LUCKY": [ + "L", + "AH", + "K", + "IY" + ], + "SUCH": [ + "S", + "AH", + "CH" + ], + "PLACE": [ + "P", + "L", + "EY", + "S" + ], + "HANDS": [ + "HH", + "AE", + "N", + "D", + "Z", + "AA", + "N" + ], + "THINGS": [ + "TH", + "IH", + "NG", + "Z" + ], + "SOONER": [ + "S", + "UW", + "N", + "ER" + ], + "OH": [ + "OW" + ], + "RICH": [ + "R", + "IH", + "CH" + ], + "HEAR": [ + "HH", + "IH", + "AH" + ], + "SUFFICIENT": [ + "S", + "AH", + "F", + "IH", + "SH", + "N", + "T" + ], + "BEG": [ + "B", + "EH", + "G" + ], + "FACT": [ + "F", + "AE", + "K", + "T" + ], + "FILLED": [ + "F", + "IH", + "L", + "D" + ], + "SOMETHING": [ + "S", + "AH", + "M", + "TH", + "IH", + "NG" + ], + "YIELD": [ + "Y", + "IY", + "L", + "D" + ], + "ACCOUNT": [ + "AH", + "K", + "AW", + "N", + "T" + ], + "PIECE": [ + "P", + "IY", + "S" + ], + "INVEST": [ + "IH", + "N", + "V", + "EH", + "S", + "T" + ], + "FUTURE": [ + "F", + "Y", + "UW", + "CH", + "ER" + ], + "DEPENDENCE": [ + "D", + "IH", + "P", + "EH", + "N", + "D", + "AH", + "N", + "S" + ], + "IMPORTANCE": [ + "IH", + "M", + "P", + "AO", + "T", + "N", + "S" + ], + "CAPTAIN": [ + "K", + "AE", + "P", + "T", + "IH", + "N" + ], + "WIFE": [ + "W", + "AY", + "F" + ], + "LOSE": [ + "L", + "UW", + "Z" + ], + "PASSION": [ + "P", + "AE", + "SH", + "N" + ], + "WRAP": [ + "R", + "AE", + "P" + ], + "LOOKING": [ + "L", + "UH", + "K", + "IH", + "NG" + ], + "FORWARD": [ + "F", + "AO", + "W", + "AH", + "D" + ], + "BAG": [ + "B", + "AE", + "G" + ], + "IDEA": [ + "AY", + "D", + "IH", + "AH" + ], + "THINKING": [ + "TH", + "IH", + "NG", + "K", + "IH", + "NG" + ], + "FAMILY": [ + "F", + "AE", + "M", + "AH", + "L", + "IY" + ], + "FRIENDS": [ + "F", + "R", + "EH", + "N", + "D", + "Z" + ], + "BED": [ + "B", + "EH", + "D" + ], + "OPINION": [ + "AH", + "P", + "IH", + "N", + "Y", + "AH", + "N" + ], + "ACQUAINTANCE": [ + "AH", + "K", + "W", + "EY", + "N", + "T", + "AH", + "N", + "S" + ], + "STOP": [ + "S", + "T", + "AH", + "P" + ], + "MUSEUM": [ + "M", + "Y", + "UW", + "Z", + "IY", + "AH", + "M" + ], + "BATHE": [ + "B", + "EY", + "DH" + ], + "ALLOWED": [ + "AH", + "L", + "AW", + "D" + ], + "WRONGS": [ + "R", + "AH", + "NG", + "Z" + ], + "HITS": [ + "HH", + "IH", + "T", + "S" + ], + "INNINGS": [ + "IH", + "N", + "IH", + "NG", + "Z" + ], + "SET": [ + "S", + "EH", + "T" + ], + "DOCTOR": [ + "D", + "AH", + "K", + "T", + "AH" + ], + "FOLLOW": [ + "F", + "AH", + "L", + "OW" + ], + "BOSS": [ + "B", + "AH", + "S" + ], + "LOT": [ + "L", + "AH", + "T" + ], + "PAIN": [ + "P", + "EY", + "N" + ], + "GETTING": [ + "G", + "EH", + "T", + "IH", + "NG" + ], + "MOOD": [ + "M", + "UW", + "D" + ], + "ANY": [ + "EH", + "N", + "IY" + ], + "CONFIRMED": [ + "K", + "AH", + "N", + "F", + "ER", + "M", + "D" + ], + "BASED": [ + "B", + "EY", + "S", + "T" + ], + "COUSIN": [ + "K", + "AH", + "Z", + "N" + ], + "TRYING": [ + "T", + "R", + "AY", + "IH", + "NG" + ], + "IRON": [ + "AY", + "ER", + "N" + ], + "BANNER": [ + "B", + "AE", + "N", + "ER" + ], + "CONTROL": [ + "K", + "AH", + "N", + "T", + "R", + "OW", + "L" + ], + "SPENDING": [ + "S", + "P", + "EH", + "N", + "D", + "IH", + "NG" + ], + "DOING": [ + "D", + "UW", + "IH", + "NG" + ], + "DIFFERENCE": [ + "D", + "IH", + "F", + "R", + "AH", + "N", + "S" + ], + "HAD": [ + "HH", + "AE", + "D" + ], + "PRINTED": [ + "P", + "R", + "IH", + "N", + "T", + "IH", + "D" + ], + "PAPER": [ + "P", + "EY", + "P", + "ER" + ], + "DIFFICULT": [ + "D", + "IH", + "F", + "IH", + "K", + "AH", + "L", + "T" + ], + "YELL": [ + "Y", + "EH", + "L" + ], + "TRADE": [ + "T", + "R", + "EY", + "D" + ], + "BUY": [ + "B", + "AY" + ], + "OR": [ + "AO" + ], + "CULTURE": [ + "K", + "AH", + "L", + "CH", + "ER" + ], + "GAMES": [ + "G", + "EY", + "M", + "Z" + ], + "LOVED": [ + "L", + "AH", + "V", + "D" + ], + "MAYBE": [ + "M", + "EY", + "B", + "IY" + ], + "PROBLEM": [ + "P", + "R", + "AH", + "B", + "L", + "AH", + "M" + ], + "ABLE": [ + "EY", + "B", + "L" + ], + "START": [ + "S", + "T", + "AA", + "T" + ], + "OWN": [ + "OW", + "N" + ], + "PROJECTS": [ + "P", + "R", + "AH", + "JH", + "EH", + "K", + "T", + "S" + ], + "RETURNED": [ + "R", + "IH", + "T", + "ER", + "N", + "D" + ], + "DEMANDED": [ + "D", + "IH", + "M", + "AA", + "N", + "D" + ], + "EAT": [ + "IY", + "T" + ], + "UNCLE": [ + "AH", + "NG", + "K", + "L" + ], + "INDEED": [ + "IH", + "N", + "D", + "IY", + "D" + ], + "PROPER": [ + "P", + "R", + "AH", + "P", + "AH" + ], + "CAUGHT": [ + "K", + "AO", + "T" + ], + "BEFORE": [ + "B", + "IH", + "F", + "AO" + ], + "TREAT": [ + "T", + "R", + "IY", + "T" + ], + "FORMAL": [ + "F", + "AO", + "M", + "L" + ], + "CONFLICT": [ + "K", + "AH", + "N", + "F", + "L", + "IH", + "K", + "T" + ], + "BEHIND": [ + "B", + "IH", + "HH", + "AY", + "N", + "D" + ], + "YOUNG": [ + "Y", + "AH", + "NG" + ], + "SON": [ + "S", + "AH", + "N" + ], + "BLACK": [ + "B", + "L", + "AE", + "K" + ], + "TRUCK": [ + "T", + "R", + "AH", + "K" + ], + "STOPS": [ + "S", + "T", + "AH", + "P", + "S" + ], + "FRONT": [ + "F", + "R", + "AH", + "N", + "T" + ], + "MAKING": [ + "M", + "EY", + "K", + "IH", + "NG" + ], + "ALIVE": [ + "AH", + "L", + "AY", + "V" + ], + "ELECTION": [ + "IH", + "L", + "EH", + "K", + "SH", + "N" + ], + "TURNING": [ + "T", + "ER", + "N", + "IH", + "NG" + ], + "POINT": [ + "P", + "OY", + "N", + "T" + ], + "ARMY": [ + "AA", + "M", + "IY" + ], + "OKAY": [ + "OW", + "K", + "EY" + ], + "SWIM": [ + "S", + "W", + "IH", + "M" + ], + "ROUGH": [ + "R", + "AH", + "F" + ], + "STAR": [ + "S", + "T", + "AA" + ], + "CLOSED": [ + "K", + "L", + "OW", + "Z", + "D" + ], + "ATTACK": [ + "AH", + "T", + "AE", + "K" + ], + "OTHER": [ + "AH", + "DH", + "ER" + ], + "SIDE": [ + "S", + "AY", + "D" + ], + "WAIT": [ + "W", + "EY", + "T" + ], + "TILL": [ + "T", + "IH", + "L" + ], + "COMES": [ + "K", + "AH", + "M", + "Z" + ], + "SINGLE": [ + "S", + "IH", + "NG", + "G", + "L" + ], + "CAUSE": [ + "K", + "AO", + "Z" + ], + "DRIVE": [ + "D", + "R", + "AY", + "V" + ], + "WHOLE": [ + "HH", + "OW", + "L" + ], + "SCORE": [ + "S", + "K", + "AO" + ], + "THERE'S": [ + "DH", + "EH", + "R", + "Z" + ], + "WASTE": [ + "W", + "EY", + "S", + "T" + ], + "MAKES": [ + "M", + "EY", + "K", + "S" + ], + "SENSE": [ + "S", + "EH", + "N", + "S" + ], + "CONGRESS": [ + "K", + "AH", + "NG", + "G", + "R", + "EH", + "S" + ], + "DESIGNATION": [ + "D", + "EH", + "Z", + "IH", + "G", + "N", + "EY", + "SH", + "N" + ], + "PRIDE": [ + "P", + "R", + "AY", + "D" + ], + "COUNTRY": [ + "K", + "AH", + "N", + "T", + "R", + "IY" + ], + "SEEM": [ + "S", + "IY", + "M" + ], + "ORDER": [ + "AO", + "D", + "AH" + ], + "EFFECTIVELY": [ + "IH", + "F", + "EH", + "K", + "T", + "IH", + "V", + "L", + "IY" + ], + "ORGANIZE": [ + "AO", + "G", + "AH", + "N", + "AY", + "Z" + ], + "GOVERNMENT": [ + "G", + "AH", + "V", + "AH", + "N", + "M", + "AH", + "N", + "T" + ], + "REASON": [ + "R", + "IY", + "Z", + "N" + ], + "PARTICULAR": [ + "P", + "AH", + "T", + "IH", + "K", + "Y", + "AH", + "L", + "AH" + ], + "AMOUNT": [ + "AH", + "M", + "AW", + "N", + "T" + ], + "VIEWINGS": [ + "V", + "Y", + "UW", + "IH", + "NG", + "S" + ], + "HIT": [ + "HH", + "IH", + "T" + ], + "NAIL": [ + "N", + "EY", + "L" + ], + "AGO": [ + "AH", + "G", + "OW" + ], + "FUNNY": [ + "F", + "AH", + "N", + "IY" + ], + "SAD": [ + "S", + "AE", + "D" + ], + "EVERY": [ + "EH", + "V", + "R", + "IY" + ], + "MOMENT": [ + "M", + "OW", + "M", + "AH", + "N", + "T" + ], + "LOOKED": [ + "L", + "UH", + "K", + "T" + ], + "CARE": [ + "K", + "EH", + "R" + ], + "ENOUGH": [ + "IH", + "N", + "AH", + "F" + ], + "BITTER": [ + "B", + "IH", + "T", + "ER" + ], + "ALISA": [ + "AH", + "L", + "IY", + "S", + "AH" + ], + "SMELL": [ + "S", + "M", + "EH", + "L" + ], + "FRESH": [ + "F", + "R", + "EH", + "SH" + ], + "BUFF": [ + "B", + "AH", + "F" + ], + "TURKEY": [ + "T", + "ER", + "K", + "IY" + ], + "CARES": [ + "K", + "EH", + "R", + "Z" + ], + "FAT": [ + "F", + "AE", + "T" + ], + "COMPANY": [ + "K", + "AH", + "M", + "P", + "AH", + "N", + "IY" + ], + "HENNY": [ + "HH", + "EH", + "N", + "IY" + ], + "ARRIVE": [ + "AH", + "R", + "AY", + "V" + ], + "JANUARY": [ + "JH", + "AE", + "N", + "Y", + "UW", + "ER", + "IY" + ], + "SIXTH": [ + "S", + "IH", + "K", + "S", + "TH" + ], + "SHARK": [ + "SH", + "AA", + "K" + ], + "DONKEY": [ + "D", + "AH", + "NG", + "K", + "IY" + ], + "RAN": [ + "R", + "AE", + "N" + ], + "SQUID": [ + "S", + "K", + "W", + "IH", + "D" + ], + "KILLER": [ + "K", + "IH", + "L", + "ER" + ], + "EXPERT": [ + "EH", + "K", + "S", + "P", + "ER", + "T" + ], + "NEIL": [ + "N", + "IY", + "L" + ], + "JACK'S": [ + "JH", + "AE", + "K", + "S" + ], + "LAYLA'S": [ + "L", + "EY", + "L", + "AH", + "Z" + ], + "WALKED": [ + "W", + "AO", + "K", + "T" + ], + "POTATO": [ + "P", + "AH", + "T", + "EY", + "T", + "OW" + ], + "LOWEN": [ + "L", + "OW", + "AH", + "N" + ], + "MISS": [ + "M", + "IH", + "S" + ], + "SICK": [ + "S", + "IH", + "K" + ], + "TRIED": [ + "T", + "R", + "AY", + "D" + ], + "HEARING": [ + "HH", + "IH", + "AH", + "R", + "IH", + "NG" + ], + "GROUND": [ + "G", + "R", + "AW", + "N", + "D" + ], + "KID": [ + "K", + "IH", + "D" + ], + "ELSE": [ + "EH", + "L", + "S" + ], + "EXPERIENCE": [ + "IH", + "K", + "S", + "P", + "IH", + "AH", + "IH", + "AH", + "N", + "S" + ], + "PURPOSE": [ + "P", + "ER", + "P", + "AH", + "S" + ], + "BIT": [ + "B", + "IH", + "T" + ], + "WORD": [ + "W", + "ER", + "D" + ], + "O'CLOCK": [ + "AH", + "K", + "L", + "AH", + "K" + ], + "AFTERNOON": [ + "AA", + "F", + "T", + "AH", + "N", + "UW", + "N" + ], + "CHILD": [ + "CH", + "AY", + "L", + "D" + ], + "HARM": [ + "HH", + "AA", + "M" + ], + "PANDA": [ + "P", + "AE", + "N", + "D", + "AH" + ], + "BRITAIN": [ + "B", + "R", + "IH", + "T", + "N" + ], + "GERMAN": [ + "JH", + "ER", + "M", + "AH", + "N" + ], + "SMELLS": [ + "S", + "M", + "EH", + "L", + "Z" + ], + "TEA": [ + "T", + "IY" + ], + "HOSPITAL": [ + "HH", + "AH", + "S", + "P", + "IH", + "T", + "L" + ], + "GROW": [ + "G", + "R", + "OW" + ], + "LEEK": [ + "L", + "IY", + "K" + ], + "CHINESE": [ + "CH", + "AY", + "N", + "IY", + "Z" + ], + "CABBAGE": [ + "K", + "AE", + "B", + "IH", + "JH" + ], + "DRESS": [ + "D", + "R", + "EH", + "S" + ], + "DEER": [ + "D", + "IH", + "AH" + ], + "BETTY": [ + "B", + "EH", + "T", + "IY" + ], + "PEN": [ + "P", + "EH", + "N" + ], + "MANDY'S": [ + "M", + "AE", + "N", + "D", + "IY", + "S" + ], + "JIM'S": [ + "JH", + "IH", + "M", + "S" + ], + "MARY'S": [ + "M", + "AE", + "R", + "IH", + "S" + ], + "PLAYGROUND": [ + "P", + "L", + "EY", + "G", + "R", + "AW", + "N", + "D" + ], + "PUMPKIN": [ + "P", + "AH", + "M", + "P", + "K", + "IH", + "N" + ], + "REAL": [ + "R", + "IH", + "AH", + "L" + ], + "SALESPERSON": [ + "S", + "EY", + "L", + "Z", + "P", + "ER", + "S", + "N" + ], + "WE'RE": [ + "W", + "IH", + "AH" + ], + "HAPPY": [ + "HH", + "AE", + "P", + "IY" + ], + "CASEY": [ + "K", + "EY", + "S", + "IY" + ], + "GOLF": [ + "G", + "AH", + "L", + "F" + ], + "EGG": [ + "EH", + "G" + ], + "MOUTH": [ + "M", + "AW", + "TH" + ], + "BETTY'S": [ + "B", + "EH", + "T", + "IY", + "S" + ], + "SCARE": [ + "S", + "K", + "EH", + "R" + ], + "SHIP": [ + "SH", + "IH", + "P" + ], + "POT": [ + "P", + "AH", + "T" + ], + "TOWEL": [ + "T", + "AW", + "AH", + "L" + ], + "TRACK": [ + "T", + "R", + "AE", + "K" + ], + "PLANNED": [ + "P", + "L", + "AE", + "N", + "D" + ], + "UNITED": [ + "Y", + "UW", + "N", + "AY", + "T", + "IH", + "D" + ], + "STATES": [ + "S", + "T", + "EY", + "T", + "S" + ], + "PASTS": [ + "P", + "AA", + "S", + "T", + "S" + ], + "FAITH": [ + "F", + "EY", + "TH" + ], + "WORLD": [ + "W", + "ER", + "L", + "D" + ], + "PERIOD": [ + "P", + "IH", + "AH", + "R", + "IH", + "AH", + "D" + ], + "APRIL": [ + "EY", + "P", + "R", + "AH", + "L" + ], + "RESULTS": [ + "R", + "IH", + "Z", + "AH", + "L", + "T", + "S" + ], + "CALLED": [ + "K", + "AO", + "L", + "D" + ], + "WEEK": [ + "W", + "IY", + "K" + ], + "HUGE": [ + "HH", + "Y", + "UW", + "JH" + ], + "DEAD": [ + "D", + "EH", + "D" + ], + "REPEAT": [ + "R", + "IH", + "P", + "IY", + "T" + ], + "CALLS": [ + "K", + "AO", + "L", + "Z" + ], + "PUSHED": [ + "P", + "UH", + "SH", + "T" + ], + "PROFIT": [ + "P", + "R", + "AH", + "F", + "IH", + "T" + ], + "SPECIALISTS": [ + "S", + "P", + "EH", + "SH", + "AH", + "L", + "IH", + "S", + "T", + "S" + ], + "AMONG": [ + "AH", + "M", + "AH", + "NG" + ], + "RUSSIANS": [ + "R", + "AH", + "SH", + "N", + "Z" + ], + "SHE'S": [ + "SH", + "IY", + "Z" + ], + "WILD": [ + "W", + "AY", + "L", + "D" + ], + "FELLOWS": [ + "F", + "EH", + "L", + "OW", + "Z" + ], + "COURSE": [ + "K", + "AO", + "R", + "S" + ], + "PICKED": [ + "P", + "IH", + "K", + "T" + ], + "CONTRADICTION": [ + "K", + "AH", + "N", + "T", + "R", + "AH", + "D", + "IH", + "K", + "SH", + "N" + ], + "TERMS": [ + "T", + "ER", + "M", + "Z" + ], + "SUFFERED": [ + "S", + "AH", + "F", + "AH", + "D" + ], + "STROKES": [ + "S", + "T", + "R", + "OW", + "K", + "S" + ], + "FAILURE": [ + "F", + "EY", + "L", + "Y", + "ER" + ], + "HOWEVER": [ + "HH", + "AW", + "EH", + "V", + "ER" + ], + "FEAR": [ + "F", + "IH", + "AH" + ], + "BEING": [ + "B", + "IY", + "IH", + "NG" + ], + "ARRESTED": [ + "AH", + "R", + "EH", + "S", + "T", + "IH", + "D" + ], + "MONEY": [ + "M", + "AH", + "N", + "IY" + ], + "WIDE": [ + "W", + "AY", + "D" + ], + "TELLING": [ + "T", + "EH", + "L", + "IH", + "NG" + ], + "HIGH": [ + "HH", + "AY" + ], + "KITE": [ + "K", + "AY", + "T" + ], + "PASSED": [ + "P", + "AE", + "S", + "T" + ], + "HALF": [ + "HH", + "AA", + "F" + ], + "MILLION": [ + "M", + "IH", + "L", + "Y", + "AH", + "N" + ], + "VIEWS": [ + "V", + "Y", + "UW", + "Z" + ], + "MAINLY": [ + "M", + "EY", + "N", + "L", + "IY" + ], + "WORKING": [ + "W", + "ER", + "K", + "IH", + "NG" + ], + "BELLES": [ + "B", + "EH", + "L", + "Z" + ], + "CHEESE": [ + "CH", + "IY", + "Z" + ], + "BADLY": [ + "B", + "AE", + "D", + "L", + "IY" + ], + "THROW": [ + "TH", + "R", + "OW" + ], + "YOURSELF": [ + "Y", + "AO", + "S", + "EH", + "L", + "F" + ], + "KISS": [ + "K", + "IH", + "S" + ], + "TRAPPED": [ + "T", + "R", + "AE", + "P", + "T" + ], + "FATE": [ + "F", + "EY", + "T" + ], + "GOD": [ + "G", + "AH", + "D" + ], + "CANDIDATE": [ + "K", + "AE", + "N", + "D", + "IH", + "D", + "EY", + "T" + ], + "RESULT": [ + "R", + "IH", + "Z", + "AH", + "L", + "T" + ], + "MAJOR": [ + "M", + "EY", + "JH", + "AH" + ], + "REFORM": [ + "R", + "IH", + "F", + "AO", + "M" + ], + "EVEN": [ + "IY", + "V", + "N" + ], + "MARCH": [ + "M", + "AA", + "R", + "CH" + ], + "CAMERA": [ + "K", + "AE", + "M", + "R", + "AH" + ], + "BIRTHDAY": [ + "B", + "ER", + "TH", + "D", + "EY" + ], + "LUNCH": [ + "L", + "AH", + "N", + "CH" + ], + "WINNER": [ + "W", + "IH", + "N", + "AH" + ], + "BRAINS": [ + "B", + "R", + "EY", + "N", + "Z" + ], + "SEAT": [ + "S", + "IY", + "T" + ], + "SEEMED": [ + "S", + "IY", + "M", + "D" + ], + "SHAKE": [ + "SH", + "EY", + "K" + ], + "HIMSELF": [ + "HH", + "IH", + "M", + "S", + "EH", + "L", + "F" + ], + "TRUE": [ + "T", + "R", + "UW" + ], + "FLIGHT": [ + "F", + "L", + "AY", + "T" + ], + "RARELY": [ + "R", + "EH", + "R", + "L", + "IY" + ], + "CONSEQUENCE": [ + "K", + "AH", + "N", + "S", + "IH", + "K", + "W", + "AH", + "N", + "S" + ], + "TURNED": [ + "T", + "ER", + "N", + "D" + ], + "LIE": [ + "L", + "AY" + ], + "CONCERT": [ + "K", + "AA", + "N", + "S", + "ER", + "T" + ], + "SUPPOSED": [ + "S", + "AH", + "P", + "OW", + "Z", + "D" + ], + "EVENING": [ + "IY", + "V", + "N", + "IH", + "NG" + ], + "BAY": [ + "B", + "EY" + ], + "WIN": [ + "W", + "IH", + "N" + ], + "PARENTS": [ + "P", + "EH", + "R", + "AH", + "N", + "T", + "S" + ], + "ASK": [ + "AA", + "S", + "K" + ], + "SLOW": [ + "S", + "L", + "OW" + ], + "LIFE": [ + "L", + "AY", + "F" + ], + "HAPPENS": [ + "HH", + "AE", + "P", + "AH", + "N", + "Z" + ], + "BUSINESS": [ + "B", + "IH", + "Z", + "N", + "AH", + "S" + ], + "GOAL": [ + "G", + "OW", + "L" + ], + "ILL": [ + "IH", + "L" + ], + "APPLY": [ + "AH", + "P", + "L", + "AY" + ], + "MESSAGE": [ + "M", + "EH", + "S", + "IH", + "JH" + ], + "MEAN": [ + "M", + "IY", + "N" + ], + "QUARTER": [ + "K", + "W", + "AO", + "R", + "T", + "ER" + ], + "FINALS": [ + "F", + "AY", + "N", + "AH", + "L", + "Z" + ], + "ENJOY": [ + "IH", + "N", + "JH", + "OY" + ], + "DARLING": [ + "D", + "AA", + "R", + "L", + "IH", + "NG" + ], + "CUT": [ + "K", + "AH", + "T" + ], + "FRIENDLY": [ + "F", + "R", + "EH", + "N", + "D", + "L", + "IY" + ], + "SMALL": [ + "S", + "M", + "AO", + "L" + ], + "EFFECTIVE": [ + "IH", + "F", + "EH", + "K", + "T", + "IH", + "V" + ], + "WEEKEND": [ + "W", + "IY", + "K", + "EH", + "N", + "D" + ], + "PRACTICE": [ + "P", + "R", + "AE", + "K", + "T", + "IH", + "S" + ], + "SOUTH": [ + "S", + "AW", + "TH" + ], + "BATS": [ + "B", + "AE", + "T", + "S" + ], + "LUCK": [ + "L", + "AH", + "K" + ], + "EVERYONE": [ + "EH", + "V", + "R", + "IY", + "W", + "AH", + "N" + ], + "WONDERFUL": [ + "W", + "AH", + "N", + "D", + "AH", + "F", + "L" + ], + "KINGS": [ + "K", + "IH", + "NG", + "Z" + ], + "QUESTIONS": [ + "K", + "W", + "EH", + "S", + "CH", + "AH", + "N", + "Z" + ], + "ANSWERS": [ + "AA", + "N", + "S", + "AH", + "Z" + ], + "DIFFERENT": [ + "D", + "IH", + "F", + "R", + "AH", + "N", + "T" + ], + "SUBJECTS": [ + "S", + "AH", + "B", + "JH", + "EH", + "K", + "T", + "S" + ], + "DISCUSSION": [ + "D", + "IH", + "S", + "K", + "AH", + "SH", + "N" + ], + "BORED": [ + "B", + "AO", + "R", + "D" + ], + "ANGRY": [ + "AE", + "NG", + "G", + "R", + "IY" + ], + "USED": [ + "Y", + "UW", + "Z", + "D" + ], + "TALKING": [ + "T", + "AO", + "K", + "IH", + "NG" + ], + "WOMAN": [ + "W", + "UH", + "M", + "AH", + "N" + ], + "AUNT": [ + "AA", + "N", + "T" + ], + "PLANT": [ + "P", + "L", + "AA", + "N", + "T" + ], + "ICE": [ + "AY", + "S" + ], + "SKATING": [ + "S", + "K", + "EY", + "T", + "IH", + "NG" + ], + "HONEY": [ + "HH", + "AH", + "N", + "IY" + ], + "NACY'S": [ + "N", + "AA", + "S", + "IY", + "Z" + ], + "BITTY": [ + "B", + "IH", + "T", + "IY" + ], + "CHOOSE": [ + "CH", + "UW", + "Z" + ], + "EGYPT": [ + "IY", + "JH", + "IH", + "P", + "T" + ], + "READ": [ + "R", + "IY", + "D" + ], + "JUNE": [ + "JH", + "UW", + "N" + ], + "BUG": [ + "B", + "AH", + "G" + ], + "BASKETBALL": [ + "B", + "AA", + "S", + "K", + "IH", + "T", + "B", + "AO", + "L" + ], + "SAUSAGE": [ + "S", + "AH", + "S", + "IH", + "JH" + ], + "JAYME'S": [ + "JH", + "EY", + "M", + "IY", + "Z" + ], + "TOE": [ + "T", + "OW" + ], + "NEIL'S": [ + "N", + "IY", + "L", + "Z" + ], + "UNDERGROUND": [ + "AH", + "N", + "D", + "AH", + "G", + "R", + "AW", + "N", + "D" + ], + "TEACHER'S": [ + "T", + "IY", + "CH", + "AH", + "S" + ], + "OFFICE": [ + "AH", + "F", + "IH", + "S" + ], + "KITCHEN": [ + "K", + "IH", + "CH", + "IH", + "N" + ], + "STEEVEN": [ + "S", + "T", + "IY", + "V", + "AH", + "N" + ], + "WHALE": [ + "W", + "EY", + "L" + ], + "ANT": [ + "AE", + "N", + "T" + ], + "SNEAKERS": [ + "S", + "N", + "IY", + "K", + "AH", + "Z" + ], + "YACHT": [ + "Y", + "AA", + "T" + ], + "CUCUMBER": [ + "K", + "Y", + "UW", + "K", + "AH", + "M", + "B", + "ER" + ], + "CELERY": [ + "S", + "EH", + "L", + "ER", + "IY" + ], + "EDUCATION": [ + "EH", + "JH", + "UW", + "K", + "EY", + "SH", + "N" + ], + "VOLLEYBALL": [ + "V", + "AH", + "L", + "IY", + "B", + "AO", + "L" + ], + "SWIMMING": [ + "S", + "W", + "IH", + "M", + "IH", + "NG" + ], + "FRENCH": [ + "F", + "R", + "EH", + "N", + "CH" + ], + "FRIES": [ + "F", + "R", + "AY", + "Z" + ], + "SWEET": [ + "S", + "W", + "IY", + "T" + ], + "BOSSY": [ + "B", + "AH", + "S", + "IY" + ], + "SQUIRREL": [ + "S", + "K", + "W", + "ER", + "AH", + "L" + ], + "TOFU": [ + "T", + "OW", + "F", + "UW" + ], + "BOOT": [ + "B", + "UW", + "T" + ], + "CLEANING": [ + "K", + "L", + "IY", + "N", + "IH", + "NG" + ], + "NATURE": [ + "N", + "EY", + "CH", + "ER" + ], + "REPORTER": [ + "R", + "IH", + "P", + "AO", + "R", + "T", + "ER" + ], + "BASEBALL": [ + "B", + "EY", + "S", + "B", + "AO", + "L" + ], + "FATHER": [ + "F", + "AA", + "DH", + "ER" + ], + "VISIT": [ + "V", + "IH", + "Z", + "IH", + "T" + ], + "LATER": [ + "L", + "EY", + "T", + "ER" + ], + "APPROACHED": [ + "AH", + "P", + "R", + "OW", + "CH", + "T" + ], + "EXCHANGE": [ + "IH", + "K", + "S", + "CH", + "EY", + "N", + "JH" + ], + "SURGERY": [ + "S", + "ER", + "JH", + "ER", + "IY" + ], + "OPPORTUNITY": [ + "AH", + "P", + "AH", + "T", + "Y", + "UW", + "N", + "AH", + "T", + "IY" + ], + "CHANGE": [ + "CH", + "EY", + "N", + "JH" + ], + "COACH": [ + "K", + "OW", + "CH" + ], + "BOARD": [ + "B", + "AO", + "R", + "D" + ], + "SEVERAL": [ + "S", + "EH", + "V", + "R", + "AH", + "L" + ], + "DISCUSS": [ + "D", + "IH", + "S", + "K", + "AH", + "S" + ], + "LAST": [ + "L", + "AA", + "S", + "T" + ], + "ROD": [ + "R", + "AH", + "D" + ], + "STREAM": [ + "S", + "T", + "R", + "IY", + "M" + ], + "SMILE": [ + "S", + "M", + "AY", + "L" + ], + "TALKED": [ + "T", + "AO", + "K", + "T" + ], + "FAIR": [ + "F", + "EH", + "R" + ], + "FIRED": [ + "F", + "AY", + "R", + "D" + ], + "BATTLE": [ + "B", + "AE", + "T", + "L" + ], + "BIKE": [ + "B", + "AY", + "K" + ], + "MINDER": [ + "M", + "AY", + "N", + "D", + "ER" + ], + "SPARE": [ + "S", + "P", + "EH", + "R" + ], + "DUCK": [ + "D", + "AH", + "K" + ], + "STEVEN'S": [ + "S", + "T", + "IY", + "V", + "AH", + "N", + "S" + ], + "DATE": [ + "D", + "EY", + "T" + ], + "SUNS": [ + "S", + "AH", + "N", + "Z" + ], + "GLASSES": [ + "G", + "L", + "AA", + "S", + "IH", + "Z" + ], + "JOY'S": [ + "JH", + "OY", + "S" + ], + "SAND": [ + "S", + "AE", + "N", + "D" + ], + "WIT": [ + "W", + "IH", + "T" + ], + "JUMPED": [ + "JH", + "AH", + "M", + "P", + "T" + ], + "TOOLED": [ + "T", + "UW", + "L", + "D" + ], + "PANDAS": [ + "P", + "AE", + "N", + "D", + "AH", + "Z" + ], + "TOY": [ + "T", + "OY" + ], + "YOURS": [ + "Y", + "AO", + "R", + "Z" + ], + "BAN": [ + "B", + "AE", + "N" + ], + "PETS": [ + "P", + "EH", + "T", + "S" + ], + "NOTICE": [ + "N", + "OW", + "T", + "IH", + "S" + ], + "SYSTEM": [ + "S", + "IH", + "S", + "T", + "AH", + "M" + ], + "DOCTORS": [ + "D", + "AA", + "K", + "T", + "ER", + "Z" + ], + "DISCHARGE": [ + "D", + "IH", + "S", + "CH", + "AA", + "R", + "JH" + ], + "THEIR": [ + "DH", + "EH", + "R" + ], + "CHILD'S": [ + "CH", + "AY", + "L", + "D", + "Z" + ], + "DEATH": [ + "D", + "EH", + "TH" + ], + "VAIN": [ + "V", + "EY", + "N" + ], + "BACKWARDS": [ + "B", + "AE", + "K", + "W", + "ER", + "D", + "Z" + ], + "MIX": [ + "M", + "IH", + "K", + "S" + ], + "NORMAL": [ + "N", + "AO", + "M", + "L" + ], + "INTERESTING": [ + "IH", + "N", + "T", + "R", + "AH", + "S", + "T", + "IH", + "NG" + ], + "HANDLE": [ + "HH", + "AE", + "N", + "D", + "L" + ], + "REMAINS": [ + "R", + "IH", + "M", + "EY", + "N", + "Z" + ], + "STANDARD": [ + "S", + "T", + "AE", + "N", + "D", + "ER", + "D" + ], + "RULE": [ + "R", + "UW", + "L" + ], + "TERM": [ + "T", + "ER", + "M" + ], + "COMPARISON": [ + "K", + "AH", + "M", + "P", + "AE", + "R", + "IH", + "S", + "N" + ], + "GLANCE": [ + "G", + "L", + "AA", + "N", + "S" + ], + "DOOR": [ + "D", + "AO" + ], + "EXISTENCE": [ + "IH", + "G", + "Z", + "IH", + "S", + "T", + "AH", + "N", + "S" + ], + "LIGHTING": [ + "L", + "AY", + "T", + "IH", + "NG" + ], + "FIRE": [ + "F", + "AY", + "AH" + ], + "FOUND": [ + "F", + "AW", + "N", + "D" + ], + "LEAST": [ + "L", + "IY", + "S", + "T" + ], + "PROBABLY": [ + "P", + "R", + "AH", + "B", + "AH", + "B", + "L", + "IY" + ], + "SORRY": [ + "S", + "AH", + "R", + "IY" + ], + "COMPLICATED": [ + "K", + "AH", + "M", + "P", + "L", + "IH", + "K", + "EY", + "T", + "IH", + "D" + ], + "THANKS": [ + "TH", + "AE", + "NG", + "K", + "S" + ], + "JOY": [ + "JH", + "OY" + ], + "OWNERSHIP": [ + "OW", + "N", + "AH", + "SH", + "IH", + "P" + ], + "MADNESS": [ + "M", + "AE", + "D", + "N", + "AH", + "S" + ], + "PROGRAM": [ + "P", + "R", + "OW", + "G", + "R", + "AE", + "M" + ], + "GUN": [ + "G", + "AH", + "N" + ], + "BOTTOM": [ + "B", + "AH", + "T", + "AH", + "M" + ], + "LIST": [ + "L", + "IH", + "S", + "T" + ], + "HELPED": [ + "HH", + "EH", + "L", + "P", + "T" + ], + "TRAIL": [ + "T", + "R", + "EY", + "L" + ], + "THANKFUL": [ + "TH", + "AE", + "NG", + "K", + "F", + "L" + ], + "POINTS": [ + "P", + "OY", + "N", + "T", + "S" + ], + "REBELS": [ + "R", + "IH", + "B", + "EH", + "L", + "Z" + ], + "UPON": [ + "AH", + "P", + "AH", + "N" + ], + "LAND": [ + "L", + "AE", + "N", + "D" + ], + "PLANS": [ + "P", + "L", + "AE", + "N", + "Z" + ], + "MEMORIAL": [ + "M", + "AH", + "M", + "AO", + "R", + "IH", + "AH", + "L" + ], + "SERVICE": [ + "S", + "ER", + "V", + "IH", + "S" + ], + "NATURAL": [ + "N", + "AE", + "CH", + "R", + "AH", + "L" + ], + "TOGETHER": [ + "T", + "AH", + "G", + "EH", + "DH", + "ER" + ], + "DECIDE": [ + "D", + "IH", + "S", + "AY", + "D" + ], + "STATE": [ + "S", + "T", + "EY", + "T" + ], + "EUROPE": [ + "Y", + "UH", + "AH", + "AH", + "P" + ], + "ISSUE": [ + "IH", + "SH", + "UW" + ], + "HOPING": [ + "HH", + "OW", + "P", + "IH", + "NG" + ], + "GAIN": [ + "G", + "EY", + "N" + ], + "ASSIST": [ + "AH", + "S", + "IH", + "S", + "T" + ], + "STORY": [ + "S", + "T", + "AO", + "R", + "IY" + ], + "BATHROOM": [ + "B", + "AE", + "TH", + "R", + "UH", + "M" + ], + "ESCAPE": [ + "IH", + "S", + "K", + "EY", + "P" + ], + "TAPPED": [ + "T", + "AE", + "P", + "T" + ], + "STEAL": [ + "S", + "T", + "IY", + "L" + ], + "BRUSHES": [ + "B", + "R", + "AH", + "SH", + "IH", + "Z" + ], + "REMEMBER": [ + "R", + "IH", + "M", + "EH", + "M", + "B", + "ER" + ], + "DECISIONS": [ + "D", + "IH", + "S", + "IH", + "ZH", + "N", + "Z" + ], + "RELEASE": [ + "R", + "IH", + "L", + "IY", + "S" + ], + "TRUST": [ + "T", + "R", + "AH", + "S", + "T" + ], + "PLENTY": [ + "P", + "L", + "EH", + "N", + "T", + "IY" + ], + "OFTEN": [ + "AO", + "F", + "N" + ], + "UNTIL": [ + "AH", + "N", + "T", + "IH", + "L" + ], + "SIT": [ + "S", + "IH", + "T" + ], + "GLAD": [ + "G", + "L", + "AE", + "D" + ], + "WINDOWS": [ + "W", + "IH", + "N", + "D", + "OW", + "Z" + ], + "OPEN": [ + "OW", + "P", + "AH", + "N" + ], + "TRANSFORMERS": [ + "T", + "R", + "AE", + "N", + "S", + "F", + "AH", + "R", + "M", + "ER", + "Z" + ], + "MONTHS": [ + "M", + "AH", + "N", + "TH", + "S" + ], + "PREDICTION": [ + "P", + "R", + "IH", + "D", + "IH", + "K", + "SH", + "N" + ], + "SPECIAL": [ + "S", + "P", + "EH", + "SH", + "L" + ], + "RACE": [ + "R", + "EY", + "S" + ], + "MENTALLY": [ + "M", + "EH", + "N", + "T", + "AH", + "L", + "IY" + ], + "TRAVEL": [ + "T", + "R", + "AE", + "V", + "L" + ], + "SOMETIMES": [ + "S", + "AH", + "M", + "T", + "AY", + "M", + "Z" + ], + "DISGUSTING": [ + "D", + "IH", + "S", + "G", + "AH", + "S", + "T", + "IH", + "NG" + ], + "DRIVING": [ + "D", + "R", + "AY", + "V", + "IH", + "NG" + ], + "MOON": [ + "M", + "UW", + "N" + ], + "STYLE": [ + "S", + "T", + "AY", + "L" + ], + "MOVIE": [ + "M", + "UW", + "V", + "IY" + ], + "STARS": [ + "S", + "T", + "AA", + "Z" + ], + "EVERYBODY": [ + "EH", + "V", + "R", + "IY", + "B", + "AH", + "D", + "IY" + ], + "SCREEN": [ + "S", + "K", + "R", + "IY", + "N" + ], + "SOON": [ + "S", + "UW", + "N" + ], + "STEPPED": [ + "S", + "T", + "EH", + "P", + "T" + ], + "PASSAGE": [ + "P", + "AE", + "S", + "IH", + "JH" + ], + "HOPED": [ + "HH", + "OW", + "P", + "T" + ], + "CROSS": [ + "K", + "R", + "AH", + "S" + ], + "IMPROVE": [ + "IH", + "M", + "P", + "R", + "UW", + "V" + ], + "BOTH": [ + "B", + "OW", + "TH" + ], + "AREAS": [ + "EH", + "ER", + "IH", + "AH", + "Z" + ], + "STRESS": [ + "S", + "T", + "R", + "EH", + "S" + ], + "ROOT": [ + "R", + "UW", + "T" + ], + "DISEASE": [ + "D", + "IH", + "Z", + "IY", + "Z" + ], + "INTERESTED": [ + "IH", + "N", + "T", + "R", + "AH", + "S", + "T", + "IH", + "D" + ], + "OPTION": [ + "AH", + "P", + "SH", + "N" + ], + "SUCCESS": [ + "S", + "AH", + "K", + "S", + "EH", + "S" + ], + "PROCESS": [ + "P", + "R", + "OW", + "S", + "EH", + "S" + ], + "CONTENTS": [ + "K", + "AH", + "N", + "T", + "EH", + "N", + "T", + "S" + ], + "PIE": [ + "P", + "AY" + ], + "PILLAR": [ + "P", + "IH", + "L", + "AH" + ], + "FACTS": [ + "F", + "AE", + "K", + "T", + "S" + ], + "MENU": [ + "M", + "EH", + "N", + "Y", + "UW" + ], + "BRAVES": [ + "B", + "R", + "EY", + "V", + "Z" + ], + "UNLUCKY": [ + "AH", + "N", + "L", + "AH", + "K", + "IY" + ], + "TROUBLE": [ + "T", + "R", + "AH", + "B", + "L" + ], + "FINDING": [ + "F", + "AY", + "N", + "D", + "IH", + "NG" + ], + "SHIFTED": [ + "SH", + "IH", + "F", + "T", + "IH", + "D" + ], + "HENCE": [ + "HH", + "EH", + "N", + "S" + ], + "BRIEF": [ + "B", + "R", + "IY", + "F" + ], + "WINDOW": [ + "W", + "IH", + "N", + "D", + "OW" + ], + "ROLE": [ + "R", + "OW", + "L" + ], + "SITUATION": [ + "S", + "IH", + "CH", + "UW", + "EY", + "SH", + "N" + ], + "UNCOMFORTABLE": [ + "AH", + "N", + "K", + "AH", + "M", + "F", + "AH", + "T", + "AH", + "B", + "L" + ], + "TEARS": [ + "T", + "IH", + "AH", + "Z" + ], + "PRAISE": [ + "P", + "R", + "EY", + "Z" + ], + "RESPECT": [ + "R", + "IH", + "S", + "P", + "EH", + "K", + "T" + ], + "PRESIDENT": [ + "P", + "R", + "EH", + "Z", + "IH", + "D", + "AH", + "N", + "T" + ], + "FORGET": [ + "F", + "AH", + "G", + "EH", + "T" + ], + "CRITICISM": [ + "K", + "R", + "IH", + "T", + "IH", + "S", + "IH", + "Z", + "AH", + "M" + ], + "EVER": [ + "EH", + "V", + "ER" + ], + "WHICH": [ + "W", + "IH", + "CH" + ], + "STUPID": [ + "S", + "T", + "UW", + "P", + "IH", + "D" + ], + "MAJORITY": [ + "M", + "AH", + "JH", + "AH", + "R", + "AH", + "T", + "IY" + ], + "CITIZENS": [ + "S", + "IH", + "T", + "AH", + "Z", + "N", + "Z" + ], + "VOTED": [ + "V", + "OW", + "T", + "IH", + "D" + ], + "AWARDS": [ + "AH", + "W", + "AO", + "D", + "Z" + ], + "IMPORTANT": [ + "IH", + "M", + "P", + "AO", + "R", + "T", + "N", + "T" + ], + "VICTORY": [ + "V", + "IH", + "K", + "T", + "ER", + "IY" + ], + "DARK": [ + "D", + "AA", + "R", + "K" + ], + "CHAPTER": [ + "CH", + "AE", + "P", + "T", + "ER" + ], + "LAUGH": [ + "L", + "AA", + "F" + ], + "CORRESPONDENT": [ + "K", + "AH", + "R", + "AH", + "S", + "P", + "AH", + "N", + "D", + "AH", + "N", + "T" + ], + "LANA": [ + "L", + "AE", + "N", + "AH" + ], + "SANDALS": [ + "S", + "AE", + "N", + "D", + "L", + "Z" + ], + "TINA'S": [ + "T", + "IY", + "N", + "AH", + "S" + ], + "ELSA": [ + "EH", + "L", + "S", + "AH" + ], + "BRAVE": [ + "B", + "R", + "EY", + "V" + ], + "MOUNTAIN": [ + "M", + "AW", + "N", + "T", + "N" + ], + "CLIMBER": [ + "K", + "L", + "AY", + "M", + "AH" + ], + "SISTERS": [ + "S", + "IH", + "S", + "T", + "AH", + "Z" + ], + "USE": [ + "Y", + "UW", + "Z" + ], + "IDEAS": [ + "AY", + "D", + "IH", + "AH", + "S" + ], + "SIMPLE": [ + "S", + "IH", + "M", + "P", + "L" + ], + "KEY": [ + "K", + "IY" + ], + "RECORD": [ + "R", + "EH", + "K", + "AO", + "D" + ], + "ADOPTION": [ + "AH", + "D", + "AH", + "P", + "SH", + "N" + ], + "DELICIOUS": [ + "D", + "IH", + "L", + "IH", + "SH", + "AH", + "S" + ], + "TRY": [ + "T", + "R", + "AY" + ], + "ROUND": [ + "R", + "AW", + "N", + "D" + ], + "PERFECT": [ + "P", + "ER", + "F", + "IH", + "K", + "T" + ], + "BEACH": [ + "B", + "IY", + "CH" + ], + "TIGERS": [ + "T", + "AY", + "G", + "AH", + "Z" + ], + "BLOCKED": [ + "B", + "L", + "AH", + "K", + "T" + ], + "CHRISTIAN": [ + "K", + "R", + "IH", + "S", + "CH", + "AH", + "N" + ], + "JUDGE": [ + "JH", + "AH", + "JH" + ], + "I'D": [ + "AY", + "D" + ], + "PARTICIPATE": [ + "P", + "AA", + "T", + "IH", + "S", + "IH", + "P", + "EY", + "T" + ], + "UNHAPPY": [ + "AH", + "N", + "HH", + "AE", + "P", + "IY" + ], + "BOW": [ + "B", + "AW" + ], + "PUBLIC": [ + "P", + "AH", + "B", + "L", + "IH", + "K" + ], + "UPPER": [ + "AH", + "P", + "ER" + ], + "LIMIT": [ + "L", + "IH", + "M", + "IH", + "T" + ], + "PAY": [ + "P", + "EY" + ], + "ATTENTION": [ + "AH", + "T", + "EH", + "N", + "SH", + "N" + ], + "PRAYERS": [ + "P", + "R", + "EH", + "R", + "Z" + ], + "PARKING": [ + "P", + "AA", + "R", + "K", + "IH", + "NG" + ], + "PRAY": [ + "P", + "R", + "EY" + ], + "UTMOST": [ + "AH", + "T", + "M", + "OW", + "S", + "T" + ], + "WHO'S": [ + "HH", + "UW", + "Z" + ], + "PROUD": [ + "P", + "R", + "AW", + "D" + ], + "HUMAN": [ + "HH", + "Y", + "UW", + "M", + "AH", + "N" + ], + "STAY": [ + "S", + "T", + "EY" + ], + "UNUSUAL": [ + "AH", + "N", + "Y", + "UW", + "ZH", + "AH", + "L" + ], + "STRUCTURE": [ + "S", + "T", + "R", + "AH", + "K", + "CH", + "AH" + ], + "BOATS": [ + "B", + "OW", + "T", + "S" + ], + "ARMED": [ + "AA", + "R", + "M", + "D" + ], + "LIGHTLY": [ + "L", + "AY", + "T", + "L", + "IY" + ], + "KILL": [ + "K", + "IH", + "L" + ], + "TAKES": [ + "T", + "EY", + "K", + "S" + ], + "SATURDAY": [ + "S", + "AE", + "T", + "AH", + "D", + "EY" + ], + "WINNING": [ + "W", + "IH", + "N", + "IH", + "NG" + ], + "COLORS": [ + "K", + "AH", + "L", + "AH", + "Z" + ], + "BECOME": [ + "B", + "IH", + "K", + "AH", + "M" + ], + "FEARS": [ + "F", + "IH", + "AH", + "Z" + ], + "REMINDER": [ + "R", + "IH", + "M", + "AY", + "N", + "D", + "AH" + ], + "MARKET": [ + "M", + "AA", + "R", + "K", + "IH", + "T" + ], + "STRONG": [ + "S", + "T", + "R", + "AH", + "NG" + ], + "BOLD": [ + "B", + "OW", + "L", + "D" + ], + "NEITHER": [ + "N", + "AY", + "DH", + "AH" + ], + "LAUGHED": [ + "L", + "AA", + "F", + "T" + ], + "INSURANCE": [ + "IH", + "N", + "SH", + "UH", + "ER", + "AH", + "N", + "S" + ], + "CONSIDERATION": [ + "K", + "AH", + "N", + "S", + "IH", + "D", + "AH", + "R", + "EY", + "SH", + "N" + ], + "MOVING": [ + "M", + "UW", + "V", + "IH", + "NG" + ], + "DANGERS": [ + "D", + "EY", + "N", + "JH", + "ER", + "Z" + ], + "HANGING": [ + "HH", + "AE", + "NG", + "IH", + "NG" + ], + "PLACES": [ + "P", + "L", + "EY", + "S", + "IH", + "Z" + ], + "FINE": [ + "F", + "AY", + "N" + ], + "POP": [ + "P", + "AH", + "P" + ], + "USUAL": [ + "Y", + "UW", + "ZH", + "UW", + "AH", + "L" + ], + "SEEING": [ + "S", + "IY", + "IH", + "NG" + ], + "SPIRIT": [ + "S", + "P", + "IH", + "AH", + "IH", + "T" + ], + "HOLD": [ + "HH", + "OW", + "L", + "D" + ], + "STEADY": [ + "S", + "T", + "EH", + "D", + "IY" + ], + "ROCK": [ + "R", + "AH", + "K" + ], + "BEAMED": [ + "B", + "IY", + "M", + "D" + ], + "THOUGH": [ + "DH", + "OW" + ], + "EXTENSIVE": [ + "IH", + "K", + "S", + "T", + "EH", + "N", + "S", + "IH", + "V" + ], + "THOUSAND": [ + "TH", + "AW", + "Z", + "N", + "D" + ], + "YEARS": [ + "Y", + "IH", + "AH", + "R", + "Z" + ], + "HEAT": [ + "HH", + "IY", + "T" + ], + "RESPONSIBLE": [ + "R", + "IH", + "S", + "P", + "AH", + "N", + "S", + "AH", + "B", + "L" + ], + "TAG": [ + "T", + "AE", + "G" + ], + "FASHION": [ + "F", + "AE", + "SH", + "N" + ], + "TERRIBLE": [ + "T", + "EH", + "R", + "AH", + "B", + "L" + ], + "MAY": [ + "M", + "EY" + ], + "TIRED": [ + "T", + "AY", + "AH", + "D" + ], + "VIDEO": [ + "V", + "IH", + "D", + "IY", + "OW" + ], + "LOCATION": [ + "L", + "OW", + "K", + "EY", + "SH", + "N" + ], + "EQUAL": [ + "IY", + "K", + "W", + "AH", + "L" + ], + "KEEPING": [ + "K", + "IY", + "P", + "IH", + "NG" + ], + "POCKET": [ + "P", + "AH", + "K", + "IH", + "T" + ], + "WORKERS": [ + "W", + "ER", + "K", + "ER", + "Z" + ], + "SOMEBODY": [ + "S", + "AH", + "M", + "B", + "AH", + "D", + "IY" + ], + "RUNS": [ + "R", + "AH", + "N", + "Z" + ], + "TALENTED": [ + "T", + "AE", + "L", + "AH", + "N", + "T", + "IH", + "D" + ], + "SECONDARY": [ + "S", + "EH", + "K", + "AH", + "N", + "D", + "EH", + "R", + "IY" + ], + "BENEFIT": [ + "B", + "EH", + "N", + "IH", + "F", + "IH", + "T" + ], + "WATCHING": [ + "W", + "AH", + "CH", + "IH", + "NG" + ], + "FIRTH": [ + "F", + "ER", + "TH" + ], + "TROOPS": [ + "T", + "R", + "UW", + "P", + "S" + ], + "BURNED": [ + "B", + "ER", + "N", + "D" + ], + "ANIMAL": [ + "AE", + "N", + "IH", + "M", + "L" + ], + "KINGDOM": [ + "K", + "IH", + "NG", + "D", + "AH", + "M" + ], + "SUNDAY": [ + "S", + "AH", + "N", + "D", + "EY" + ], + "FICTION": [ + "F", + "IH", + "K", + "SH", + "N" + ], + "EDGE": [ + "EH", + "JH" + ], + "HERE'S": [ + "HH", + "IH", + "AH", + "Z" + ], + "TREATED": [ + "T", + "R", + "IY", + "T", + "IH", + "D" + ], + "EMERGENCY": [ + "IH", + "M", + "ER", + "JH", + "AH", + "N", + "S", + "IY" + ], + "STARTED": [ + "S", + "T", + "AA", + "T", + "IH", + "D" + ], + "APPROACH": [ + "AH", + "P", + "R", + "OW", + "CH" + ], + "ORGANIZATION": [ + "AO", + "G", + "AH", + "N", + "AY", + "Z", + "EY", + "SH", + "N" + ], + "MANAGER": [ + "M", + "AE", + "N", + "IH", + "JH", + "AH" + ], + "FINALE": [ + "F", + "IH", + "N", + "AE", + "L", + "IY" + ], + "SPECIFIC": [ + "S", + "P", + "AH", + "S", + "IH", + "F", + "IH", + "K" + ], + "SPEND": [ + "S", + "P", + "EH", + "N", + "D" + ], + "DEFEND": [ + "D", + "IH", + "F", + "EH", + "N", + "D" + ], + "SUCCESSFULLY": [ + "S", + "AH", + "K", + "S", + "EH", + "S", + "F", + "AH", + "L", + "IY" + ], + "MATE": [ + "M", + "EY", + "T" + ], + "PLANTS": [ + "P", + "L", + "AE", + "N", + "T", + "S" + ], + "SIZE": [ + "S", + "AY", + "Z" + ], + "FANCY": [ + "F", + "AE", + "N", + "S", + "IY" + ], + "SKETCH": [ + "S", + "K", + "EH", + "CH" + ], + "LARGE": [ + "L", + "AA", + "JH" + ], + "THUS": [ + "DH", + "AH", + "S" + ], + "THEREFORE": [ + "DH", + "EH", + "R", + "F", + "AO" + ], + "ANOTHER": [ + "AH", + "N", + "AH", + "DH", + "ER" + ], + "DRINK": [ + "D", + "R", + "IH", + "NG", + "K" + ], + "POST": [ + "P", + "OW", + "S", + "T" + ], + "REQUEST": [ + "R", + "IH", + "K", + "W", + "EH", + "S", + "T" + ], + "GUARD": [ + "G", + "AA", + "R", + "D" + ], + "HONEST": [ + "AH", + "N", + "IH", + "S", + "T" + ], + "BONE": [ + "B", + "OW", + "N" + ], + "LEARNING": [ + "L", + "ER", + "N", + "IH", + "NG" + ], + "EVENTS": [ + "IH", + "V", + "EH", + "N", + "T", + "S" + ], + "PRODUCE": [ + "P", + "R", + "AH", + "D", + "Y", + "UW", + "S" + ], + "ALCOHOL": [ + "AE", + "L", + "K", + "AH", + "HH", + "AH", + "L" + ], + "PUMPED": [ + "P", + "AH", + "M", + "P", + "T" + ], + "RETURN": [ + "R", + "IH", + "T", + "ER", + "N" + ], + "KING": [ + "K", + "IH", + "NG" + ], + "COMPLAIN": [ + "K", + "AH", + "M", + "P", + "L", + "EY", + "N" + ], + "SPIRITUAL": [ + "S", + "P", + "IH", + "AH", + "IH", + "CH", + "UW", + "AH", + "L" + ], + "FORMATION": [ + "F", + "AO", + "M", + "EY", + "SH", + "N" + ], + "MASTER": [ + "M", + "AE", + "S", + "T", + "ER" + ], + "BLESS": [ + "B", + "L", + "EH", + "S" + ], + "SUGAR": [ + "SH", + "UH", + "G", + "ER" + ], + "RAY": [ + "R", + "EY" + ], + "UNIVERSE": [ + "Y", + "UW", + "N", + "IH", + "V", + "ER", + "S" + ], + "TWENTY": [ + "T", + "W", + "EH", + "N", + "T", + "IY" + ], + "LEARNED": [ + "L", + "ER", + "N", + "IH", + "D" + ], + "LETTERS": [ + "L", + "EH", + "T", + "AH", + "Z" + ], + "SNOW": [ + "S", + "N", + "OW" + ], + "FORECAST": [ + "F", + "AO", + "K", + "AA", + "S", + "T" + ], + "CASE": [ + "K", + "EY", + "S" + ], + "NECESSARY": [ + "N", + "EH", + "S", + "AH", + "S", + "ER", + "IY" + ], + "DYNAMIC": [ + "D", + "AY", + "N", + "AE", + "M", + "IH", + "K" + ], + "HUMANE": [ + "HH", + "Y", + "UW", + "M", + "EY", + "N" + ], + "DEEP": [ + "D", + "IY", + "P" + ], + "TALENT": [ + "T", + "AE", + "L", + "AH", + "N", + "T" + ], + "EACH": [ + "IY", + "CH" + ], + "TEAM": [ + "T", + "IY", + "M" + ], + "STARTS": [ + "S", + "T", + "AA", + "R", + "T", + "S" + ], + "SAW": [ + "S", + "AO" + ], + "SOCCER": [ + "S", + "AH", + "K", + "AH" + ], + "LOOKS": [ + "L", + "UH", + "K", + "S" + ], + "WORTH": [ + "W", + "ER", + "TH" + ], + "FEELS": [ + "F", + "IY", + "L", + "Z" + ], + "GLORY": [ + "G", + "L", + "AO", + "R", + "IY" + ], + "MASKS": [ + "M", + "AA", + "S", + "K", + "S" + ], + "UNIFORM": [ + "Y", + "UW", + "N", + "IH", + "F", + "AO", + "M" + ], + "GUNS": [ + "G", + "AH", + "N", + "Z" + ], + "TOTALLY": [ + "T", + "OW", + "T", + "AH", + "L", + "IY" + ], + "SELL": [ + "S", + "EH", + "L" + ], + "SUPPORTED": [ + "S", + "AH", + "P", + "OW", + "R", + "T", + "IH", + "D" + ], + "SOPHISTICATE": [ + "S", + "AH", + "F", + "IH", + "S", + "T", + "IH", + "K", + "EY", + "T" + ], + "POSITIONING": [ + "P", + "AH", + "Z", + "IH", + "SH", + "AH", + "N", + "IH", + "NG" + ], + "DRAGONS": [ + "D", + "R", + "AE", + "G", + "AH", + "N", + "Z" + ], + "ECONOMY": [ + "IH", + "K", + "AH", + "N", + "AH", + "M", + "IY" + ], + "SOUND": [ + "S", + "AW", + "N", + "D" + ], + "SUPPER": [ + "S", + "AH", + "P", + "AH" + ], + "WEDNESDAY": [ + "W", + "EH", + "N", + "Z", + "D", + "EY" + ], + "DRILL": [ + "D", + "R", + "IH", + "L" + ], + "LOOP": [ + "L", + "UW", + "P" + ], + "FIRM": [ + "F", + "ER", + "M" + ], + "BROAD": [ + "B", + "R", + "AO", + "D" + ], + "SHOULDERS": [ + "SH", + "AH", + "UW", + "L", + "D", + "AH", + "Z" + ], + "LONGER": [ + "L", + "AH", + "NG", + "G", + "AH" + ], + "SPEAKING": [ + "S", + "P", + "IY", + "K", + "IH", + "NG" + ], + "TECHNICAL": [ + "T", + "EH", + "K", + "N", + "IH", + "K", + "L" + ], + "STUFF": [ + "S", + "T", + "AH", + "F" + ], + "BUSY": [ + "B", + "IH", + "Z", + "IY" + ], + "TEACHERS": [ + "T", + "IY", + "CH", + "ER", + "S" + ], + "PLASTIC": [ + "P", + "L", + "AE", + "S", + "T", + "IH", + "K" + ], + "SING": [ + "S", + "IH", + "NG" + ], + "COLOR": [ + "K", + "AH", + "L", + "ER" + ], + "SKY": [ + "S", + "K", + "AY" + ], + "STARED": [ + "S", + "T", + "EH", + "ER", + "D" + ], + "STUDENTS": [ + "S", + "T", + "Y", + "UH", + "D", + "N", + "T", + "S" + ], + "DRUNK": [ + "D", + "R", + "AH", + "NG", + "K" + ], + "LAP": [ + "L", + "AE", + "P" + ], + "WONDERING": [ + "W", + "AH", + "N", + "D", + "ER", + "IH", + "NG" + ], + "HI": [ + "HH", + "AY" + ], + "ANGEL": [ + "EY", + "N", + "JH", + "L" + ], + "HOPELESSNESS": [ + "HH", + "OW", + "P", + "L", + "AH", + "S", + "N", + "AH", + "S" + ], + "SIGH": [ + "S", + "AY" + ], + "SHARE": [ + "SH", + "EH", + "R" + ], + "SHADOW": [ + "SH", + "AE", + "D", + "OW" + ], + "ENDING": [ + "EH", + "N", + "D", + "IH", + "NG" + ], + "BLOCKS": [ + "B", + "L", + "AA", + "K", + "S" + ], + "CATCHES": [ + "K", + "AE", + "CH", + "IH", + "Z" + ], + "SIGNS": [ + "S", + "AY", + "N", + "Z" + ], + "NONE": [ + "N", + "AH", + "N" + ], + "COUNTED": [ + "K", + "AW", + "N", + "T", + "IH", + "D" + ], + "WEAKNESS": [ + "W", + "IY", + "K", + "N", + "AH", + "S" + ], + "MOVEMENTS": [ + "M", + "UW", + "V", + "M", + "AH", + "N", + "T", + "S" + ], + "FRIDGE": [ + "F", + "R", + "IH", + "JH" + ], + "WHILE": [ + "W", + "AY", + "L" + ], + "SCORED": [ + "S", + "K", + "AO", + "D" + ], + "GIFTS": [ + "G", + "IH", + "F", + "T", + "S" + ], + "HESITATE": [ + "HH", + "EH", + "Z", + "IH", + "T", + "EY", + "T" + ], + "POLICE": [ + "P", + "AH", + "L", + "IY", + "S" + ], + "OPENED": [ + "OW", + "P", + "AH", + "N" + ], + "DIFFICULTY": [ + "D", + "IH", + "F", + "IH", + "K", + "AH", + "L", + "T", + "IY" + ], + "MARKED": [ + "M", + "AA", + "K", + "T" + ], + "PROGRESS": [ + "P", + "R", + "OW", + "G", + "R", + "EH", + "S" + ], + "CHART": [ + "CH", + "AA", + "T" + ], + "PERHAPS": [ + "P", + "AH", + "HH", + "AE", + "P", + "S" + ], + "LATE": [ + "L", + "EY", + "T" + ], + "CHALLENGE": [ + "CH", + "AE", + "L", + "IH", + "N", + "JH" + ], + "SORT": [ + "S", + "AO", + "T" + ], + "COLLECTION": [ + "K", + "AH", + "L", + "EH", + "K", + "SH", + "N" + ], + "PROOF": [ + "P", + "R", + "UW", + "F" + ], + "VIA": [ + "V", + "AH", + "IH", + "AH" + ], + "CHOCOLATE": [ + "CH", + "AH", + "K", + "L", + "AH", + "T" + ], + "WEIGHT": [ + "W", + "EY", + "T" + ], + "ENEMY": [ + "EH", + "N", + "AH", + "M", + "IY" + ], + "PERFORMANCE": [ + "P", + "AH", + "F", + "AO", + "M", + "AH", + "N", + "S" + ], + "SOLUTION": [ + "S", + "AH", + "L", + "UW", + "SH", + "N" + ], + "PRAYER": [ + "P", + "R", + "EH", + "R" + ], + "SOURCE": [ + "S", + "AO", + "S" + ], + "STRENGTH": [ + "S", + "T", + "R", + "EH", + "NG", + "K", + "TH" + ], + "TEXT": [ + "T", + "EH", + "K", + "S", + "T" + ], + "SINGE": [ + "S", + "IH", + "N", + "JH" + ], + "VIOLENCE": [ + "V", + "AY", + "AH", + "L", + "AH", + "N", + "S" + ], + "RESORT": [ + "R", + "IH", + "Z", + "AO", + "T" + ], + "VIOLENT": [ + "V", + "AY", + "AH", + "L", + "AH", + "N", + "T" + ], + "GHOST": [ + "G", + "OW", + "S", + "T" + ], + "WISHED": [ + "W", + "IH", + "SH", + "T" + ], + "YEAH": [ + "Y", + "EH", + "R" + ], + "WARM": [ + "W", + "AO", + "M" + ], + "JOINING": [ + "JH", + "OY", + "N", + "IH", + "NG" + ], + "GUESS": [ + "G", + "EH", + "S" + ], + "CARS": [ + "K", + "AA", + "R", + "S" + ], + "HUNGRY": [ + "HH", + "AH", + "NG", + "G", + "R", + "IY" + ], + "CLOCK": [ + "K", + "L", + "AH", + "K" + ], + "POLICEMAN": [ + "P", + "AH", + "L", + "IY", + "S", + "M", + "AH", + "N" + ], + "DONE": [ + "D", + "AH", + "N" + ], + "DOCTOR'S": [ + "D", + "AA", + "K", + "T", + "ER", + "S" + ], + "FEET": [ + "F", + "IY", + "T" + ], + "WRITES": [ + "R", + "AY", + "T", + "S" + ], + "WRITE": [ + "R", + "AY", + "T" + ], + "PRISON": [ + "P", + "R", + "IH", + "Z", + "N" + ], + "AUTHORITIES": [ + "AO", + "TH", + "AH", + "R", + "IH", + "T", + "IH", + "Z" + ], + "CLAIMS": [ + "K", + "L", + "EY", + "M", + "Z" + ], + "KILLINGS": [ + "K", + "IH", + "L", + "IH", + "NG", + "Z" + ], + "CRIME": [ + "K", + "R", + "AY", + "M" + ], + "ANGER": [ + "AE", + "NG", + "G", + "ER" + ], + "APPEAL": [ + "AH", + "P", + "IY", + "L" + ], + "IMMEDIATELY": [ + "IH", + "M", + "IY", + "D", + "IH", + "AH", + "T", + "L", + "IY" + ], + "HURT": [ + "HH", + "ER", + "T" + ], + "CANCER": [ + "K", + "AE", + "N", + "S", + "ER" + ], + "DREAM": [ + "D", + "R", + "IY", + "M" + ], + "BASKET": [ + "B", + "AA", + "S", + "K", + "IH", + "T" + ], + "SORTS": [ + "S", + "AO", + "R", + "T", + "S" + ], + "DUMB": [ + "D", + "AH", + "M" + ], + "UNDERSTAND": [ + "AH", + "N", + "D", + "AH", + "S", + "T", + "AE", + "N", + "D" + ], + "AFFECTS": [ + "AH", + "F", + "EH", + "K", + "T", + "S" + ], + "FLOOR": [ + "F", + "L", + "AO" + ], + "SPITE": [ + "S", + "P", + "AY", + "T" + ], + "ACT": [ + "AE", + "K", + "T" + ], + "UNDERTAKE": [ + "AH", + "N", + "D", + "AH", + "T", + "EY", + "K" + ], + "LETTER": [ + "L", + "EH", + "T", + "ER" + ], + "LOCK": [ + "L", + "AH", + "K" + ], + "WANTING": [ + "W", + "AA", + "N", + "T", + "IH", + "NG" + ], + "SEEN": [ + "S", + "IY", + "N" + ], + "LIKED": [ + "L", + "AY", + "K", + "T" + ], + "NOR": [ + "N", + "AO" + ], + "NUMBER": [ + "N", + "AH", + "M", + "B", + "ER" + ], + "TEAR": [ + "T", + "EH", + "R" + ], + "DRINKING": [ + "D", + "R", + "IH", + "NG", + "K", + "IH", + "NG" + ], + "BEGIN": [ + "B", + "IH", + "G", + "IH", + "N" + ], + "BOOKS": [ + "B", + "UH", + "K", + "S" + ], + "WASH": [ + "W", + "AH", + "SH" + ], + "BREAKFAST": [ + "B", + "R", + "EH", + "K", + "F", + "AH", + "S", + "T" + ], + "WAKING": [ + "W", + "EY", + "K", + "IH", + "NG" + ], + "HAIR": [ + "HH", + "EH", + "R" + ], + "WATER": [ + "W", + "AO", + "T", + "ER" + ], + "POOR": [ + "P", + "UH", + "AH" + ], + "TRAINS": [ + "T", + "R", + "EY", + "N", + "Z" + ], + "HELLO": [ + "HH", + "AH", + "L", + "OW" + ], + "GUESSED": [ + "G", + "EH", + "S", + "T" + ], + "HOLIDAY": [ + "HH", + "AH", + "L", + "AH", + "D", + "EY" + ], + "TEN": [ + "T", + "EH", + "N" + ], + "TWELVE": [ + "T", + "W", + "EH", + "L", + "V" + ], + "SURELY": [ + "SH", + "UH", + "AH", + "L", + "IY" + ], + "FOURS": [ + "F", + "AO", + "Z" + ], + "SISTER": [ + "S", + "IH", + "S", + "T", + "ER" + ], + "TRIES": [ + "T", + "R", + "AY", + "Z" + ], + "DAYS": [ + "D", + "EY", + "Z" + ], + "GUESSES": [ + "G", + "EH", + "S", + "IH", + "Z" + ], + "TIE": [ + "T", + "AY" + ], + "WITCHES": [ + "W", + "IH", + "CH", + "IH", + "Z" + ], + "BANANAS": [ + "B", + "AH", + "N", + "AA", + "N", + "AH", + "Z" + ], + "ROW": [ + "R", + "OW" + ], + "BRILLIANT": [ + "B", + "R", + "IH", + "L", + "IH", + "AH", + "N", + "T" + ], + "CIVIL": [ + "S", + "IH", + "V", + "L" + ], + "SUIT": [ + "S", + "Y", + "UW", + "T" + ], + "COUNTY": [ + "K", + "AW", + "N", + "T", + "IY" + ], + "POSSIBILITY": [ + "P", + "AH", + "S", + "AH", + "B", + "IH", + "L", + "AH", + "T", + "IY" + ], + "PRIVILEGE": [ + "P", + "R", + "IH", + "V", + "AH", + "L", + "IH", + "JH" + ], + "SECURITY": [ + "S", + "IH", + "K", + "Y", + "UH", + "AH", + "AH", + "T", + "IY" + ], + "HOTEL": [ + "HH", + "OW", + "T", + "EH", + "L" + ], + "TIGHT": [ + "T", + "AY", + "T" + ], + "ALTHOUGH": [ + "AO", + "L", + "DH", + "OW" + ], + "LACK": [ + "L", + "AE", + "K" + ], + "ABILITY": [ + "AH", + "B", + "IH", + "L", + "AH", + "T", + "IY" + ], + "GRASP": [ + "G", + "R", + "AA", + "S", + "P" + ], + "CONCEPT": [ + "K", + "AH", + "N", + "S", + "EH", + "P", + "T" + ], + "JAIL": [ + "JH", + "EY", + "L" + ], + "STORE": [ + "S", + "T", + "AO", + "R" + ], + "LOSS": [ + "L", + "AH", + "S" + ], + "GRATEFUL": [ + "G", + "R", + "EY", + "T", + "F", + "L" + ], + "SURPRISE": [ + "S", + "AH", + "P", + "R", + "AY", + "Z" + ], + "HOURS": [ + "AH", + "UW", + "AH", + "Z" + ], + "TALE": [ + "T", + "EY", + "L" + ], + "WON'T": [ + "W", + "OW", + "N", + "T" + ], + "BILLS": [ + "B", + "IH", + "L", + "Z" + ], + "FOLLOWED": [ + "F", + "AH", + "L", + "OW", + "D" + ], + "CAN'T": [ + "K", + "AE", + "N", + "T" + ], + "PARTED": [ + "P", + "AA", + "T", + "IH", + "D" + ], + "AH": [ + "AA" + ], + "THEMSELVES": [ + "DH", + "AH", + "M", + "S", + "EH", + "L", + "V", + "Z" + ], + "SHAKING": [ + "SH", + "EY", + "K", + "IH", + "NG" + ], + "FEELINGS": [ + "F", + "IY", + "L", + "IY", + "NG", + "S" + ], + "TRAVELERS": [ + "T", + "R", + "AE", + "V", + "AH", + "L", + "AH", + "Z" + ], + "CLOTHES": [ + "K", + "L", + "OW", + "Z" + ], + "READS": [ + "R", + "IY", + "D", + "Z" + ], + "NEWSPAPERS": [ + "N", + "Y", + "UW", + "Z", + "P", + "EY", + "P", + "AH", + "Z" + ], + "I'LL": [ + "AY", + "L" + ], + "YOU'RE": [ + "Y", + "UH", + "AH" + ], + "DAUGHTERS": [ + "D", + "AH", + "T", + "ER", + "Z" + ], + "GROUNDS": [ + "G", + "R", + "AW", + "N", + "D", + "Z" + ], + "DAUGHTER": [ + "D", + "AO", + "T", + "AH" + ], + "WEST": [ + "W", + "EH", + "S", + "T" + ], + "CANNOT": [ + "K", + "AE", + "N", + "AH", + "T" + ], + "COUSINS": [ + "K", + "AH", + "Z", + "N", + "Z" + ], + "DON'T": [ + "D", + "OW", + "N", + "T" + ], + "CAPITAL": [ + "K", + "AE", + "P", + "IH", + "T", + "L" + ], + "CARRY": [ + "K", + "AE", + "R", + "IY" + ], + "PRESENT": [ + "P", + "R", + "EH", + "Z", + "N", + "T" + ], + "COLD": [ + "K", + "OW", + "L", + "D" + ], + "WORDS": [ + "W", + "ER", + "D", + "Z" + ], + "SAYS": [ + "S", + "EH", + "Z" + ], + "MEETING": [ + "M", + "IY", + "T", + "IH", + "NG" + ], + "FINISHED": [ + "F", + "IH", + "N", + "IH", + "SH", + "T" + ], + "NEEDED": [ + "N", + "IY", + "D", + "IH", + "D" + ], + "ONES": [ + "W", + "AH", + "N", + "Z" + ], + "TEACH": [ + "T", + "IY", + "CH" + ], + "FOURTEEN": [ + "F", + "AO", + "R", + "T", + "IY", + "N" + ], + "FIFTEEN": [ + "F", + "IH", + "F", + "T", + "IY", + "N" + ], + "EIGHTEEN": [ + "EY", + "T", + "IY", + "N" + ], + "BROKEN": [ + "B", + "R", + "OW", + "K", + "AH", + "N" + ], + "ENTERED": [ + "EH", + "N", + "T", + "AH", + "D" + ], + "VOICE": [ + "V", + "OY", + "S" + ], + "CAME": [ + "K", + "EY", + "M" + ], + "ABOVE": [ + "AH", + "B", + "AH", + "V" + ], + "MEANS": [ + "M", + "IY", + "N", + "Z" + ], + "SAID": [ + "S", + "EH", + "D" + ], + "GOODBYE": [ + "G", + "UH", + "D", + "B", + "AY" + ], + "WOMEN": [ + "W", + "IH", + "M", + "IH", + "N" + ], + "VISITED": [ + "V", + "IH", + "Z", + "IH", + "T", + "IH", + "D" + ], + "TABLES": [ + "T", + "EY", + "B", + "L", + "Z" + ], + "BEGAN": [ + "B", + "IH", + "G", + "AE", + "N" + ], + "TOOK": [ + "T", + "UH", + "K" + ], + "LEST": [ + "L", + "EH", + "S", + "T" + ], + "SHOE": [ + "SH", + "UW" + ], + "STOPPED": [ + "S", + "T", + "AH", + "P", + "T" + ], + "BOYS": [ + "B", + "OY", + "Z" + ], + "LIBRARY": [ + "L", + "AY", + "B", + "R", + "ER", + "IY" + ], + "KIT": [ + "K", + "IH", + "T" + ], + "SPORT": [ + "S", + "P", + "AO", + "T" + ], + "WONDER": [ + "W", + "AH", + "N", + "D", + "ER" + ], + "HISTORY": [ + "HH", + "IH", + "S", + "T", + "R", + "IY" + ], + "NURSE": [ + "N", + "ER", + "S" + ], + "CHILDREN": [ + "CH", + "IH", + "L", + "D", + "R", + "AH", + "N" + ], + "PRESENTLY": [ + "P", + "R", + "EH", + "Z", + "N", + "T", + "L", + "IY" + ], + "STOPED": [ + "S", + "T", + "OW", + "P", + "T" + ], + "FAMILIES": [ + "F", + "AE", + "M", + "IH", + "L", + "IH", + "Z" + ], + "CAMPED": [ + "K", + "AE", + "M", + "P", + "T" + ], + "CRY": [ + "K", + "R", + "AY" + ], + "STAMPS": [ + "S", + "T", + "AE", + "M", + "P", + "S" + ], + "TRIP": [ + "T", + "R", + "IH", + "P" + ], + "KNOWING": [ + "N", + "OW", + "IH", + "NG" + ], + "LIVELY": [ + "L", + "AY", + "V", + "L", + "IY" + ], + "BOX": [ + "B", + "AH", + "K", + "S" + ], + "STAGE": [ + "S", + "T", + "EY", + "JH" + ], + "FISHES": [ + "F", + "IH", + "SH", + "IH", + "Z" + ], + "JUMPPED": [ + "JH", + "AH", + "M", + "P", + "T" + ], + "EXAMPLE": [ + "IH", + "G", + "Z", + "AE", + "M", + "P", + "L" + ], + "MINUTE": [ + "M", + "IH", + "N", + "IH", + "T" + ], + "LARGER": [ + "L", + "AA", + "R", + "JH", + "ER" + ], + "TREE": [ + "T", + "R", + "IY" + ], + "FLYING": [ + "F", + "L", + "AY", + "IH", + "NG" + ], + "RIDE": [ + "R", + "AY", + "D" + ], + "CAPS": [ + "K", + "AE", + "P", + "S" + ], + "MEANING": [ + "M", + "IY", + "N", + "IH", + "NG" + ], + "SILK": [ + "S", + "IH", + "L", + "K" + ], + "HELD": [ + "HH", + "EH", + "L", + "D" + ], + "CROSSED": [ + "K", + "R", + "AH", + "S", + "T" + ], + "STOOD": [ + "S", + "T", + "UH", + "D" + ], + "CLIMBED": [ + "K", + "L", + "AY", + "M", + "D" + ], + "LADDER": [ + "L", + "AE", + "D", + "AH" + ], + "KIDS": [ + "K", + "IH", + "D", + "Z" + ], + "DOGS": [ + "D", + "AO", + "G", + "Z" + ], + "USUALLY": [ + "Y", + "UW", + "ZH", + "AH", + "L", + "IY" + ], + "COMMUNITY": [ + "K", + "AH", + "M", + "Y", + "UW", + "N", + "AH", + "T", + "IY" + ], + "FOLLOWS": [ + "F", + "AH", + "L", + "OW", + "Z" + ], + "SPORTS": [ + "S", + "P", + "AO", + "T", + "S" + ], + "GENERAL": [ + "JH", + "EH", + "N", + "R", + "AH", + "L" + ], + "SUCCESSFUL": [ + "S", + "AH", + "K", + "S", + "EH", + "S", + "F", + "L" + ], + "COMPETITION": [ + "K", + "AA", + "M", + "P", + "AH", + "T", + "IH", + "SH", + "N" + ], + "INDUSTRY": [ + "IH", + "N", + "D", + "AH", + "S", + "T", + "R", + "IY" + ], + "ANXIOUSLY": [ + "AE", + "NG", + "K", + "SH", + "AH", + "S", + "L", + "IY" + ], + "BRING": [ + "B", + "R", + "IH", + "NG" + ], + "FRIENDSHIP": [ + "F", + "R", + "EH", + "N", + "D", + "SH", + "IH", + "P" + ], + "ALARM": [ + "AH", + "L", + "AA", + "M" + ], + "WORRYING": [ + "W", + "AH", + "R", + "IY", + "IH", + "NG" + ], + "SAVED": [ + "S", + "EY", + "V", + "D" + ], + "APPEAR": [ + "AH", + "P", + "IH", + "AH" + ], + "BEEN": [ + "B", + "IH", + "N" + ], + "SPENDS": [ + "S", + "P", + "EH", + "N", + "D" + ], + "RUSHING": [ + "R", + "AH", + "SH", + "IH", + "NG" + ], + "BETWEEN": [ + "B", + "IH", + "T", + "W", + "IY", + "N" + ], + "SIXTEEN": [ + "S", + "IH", + "K", + "S", + "T", + "IY", + "N" + ], + "SEVENTEEN": [ + "S", + "EH", + "V", + "N", + "T", + "IY", + "N" + ], + "PERSON": [ + "P", + "ER", + "S", + "N" + ], + "HUNT": [ + "HH", + "AH", + "N", + "T" + ], + "TOWN": [ + "T", + "AW", + "N" + ], + "ALTOGETHER": [ + "AO", + "L", + "T", + "AH", + "G", + "EH", + "DH", + "AH" + ], + "STRANGE": [ + "S", + "T", + "R", + "EY", + "N", + "JH" + ], + "NATIONALLY": [ + "N", + "AE", + "SH", + "N", + "AH", + "L", + "IY" + ], + "TREND": [ + "T", + "R", + "EH", + "N", + "D" + ], + "UPWARD": [ + "AH", + "P", + "W", + "ER", + "D" + ], + "WORRY": [ + "W", + "ER", + "IY" + ], + "DOCK": [ + "D", + "AH", + "K" + ], + "HONOR": [ + "AA", + "N", + "ER" + ], + "CHECK": [ + "CH", + "EH", + "K" + ], + "BLAMES": [ + "B", + "L", + "EY", + "M" + ], + "LOVING": [ + "L", + "AH", + "V", + "IH", + "NG" + ], + "MINE": [ + "M", + "AY", + "N" + ], + "STICK": [ + "S", + "T", + "IH", + "K" + ], + "CHEERS": [ + "CH", + "IH", + "AH", + "Z" + ], + "GROUP": [ + "G", + "R", + "UW", + "P" + ], + "DIVISION": [ + "D", + "IH", + "V", + "IH", + "ZH", + "N" + ], + "MOVES": [ + "M", + "UW", + "V", + "Z" + ], + "DANGER": [ + "D", + "EY", + "N", + "JH", + "ER" + ], + "BLANK": [ + "B", + "L", + "AE", + "NG", + "K" + ], + "BEATING": [ + "B", + "IY", + "T", + "IH", + "NG" + ], + "DESCRIBE": [ + "D", + "IH", + "S", + "K", + "R", + "AY", + "B" + ], + "OUTSIDE": [ + "AW", + "T", + "S", + "AY", + "D" + ], + "TENT": [ + "T", + "EH", + "N", + "T" + ], + "ROMANTIC": [ + "R", + "OW", + "M", + "AE", + "N", + "T", + "IH", + "K" + ], + "STORED": [ + "S", + "T", + "AO", + "D" + ], + "APPEARED": [ + "AH", + "P", + "IH", + "AH", + "D" + ], + "LONELY": [ + "L", + "OW", + "N", + "L", + "IY" + ], + "QUIET": [ + "K", + "W", + "AY", + "AH", + "T" + ], + "SALES": [ + "S", + "EY", + "L", + "Z" + ], + "CRYING": [ + "K", + "R", + "AY", + "IH", + "NG" + ], + "THIRD": [ + "TH", + "ER", + "D" + ], + "BLOW": [ + "B", + "L", + "OW" + ], + "KILLED": [ + "K", + "IH", + "L", + "D" + ], + "HALL": [ + "HH", + "AO", + "L" + ], + "DREAMING": [ + "D", + "R", + "IY", + "M", + "IH", + "NG" + ], + "SHOUTED": [ + "SH", + "AW", + "T", + "IH", + "D" + ], + "FEW": [ + "F", + "Y", + "UW" + ], + "CREATURE": [ + "K", + "R", + "IY", + "CH", + "ER" + ], + "JOIN": [ + "JH", + "OY", + "N" + ], + "STAFF": [ + "S", + "T", + "AA", + "F" + ], + "DIE": [ + "D", + "AY" + ], + "EXPECT": [ + "IH", + "K", + "S", + "P", + "EH", + "K", + "T" + ], + "PARTNER": [ + "P", + "AA", + "T", + "N", + "AH" + ], + "SECRET": [ + "S", + "IY", + "K", + "R", + "AH", + "T" + ], + "HERS": [ + "HH", + "ER", + "Z" + ], + "CONSIDER": [ + "K", + "AH", + "N", + "S", + "IH", + "D", + "ER" + ], + "ANYWAY": [ + "EH", + "N", + "IY", + "W", + "EY" + ], + "SIGHT": [ + "S", + "AY", + "T" + ], + "REMAINED": [ + "R", + "IH", + "M", + "EY", + "N", + "D" + ], + "TWICE": [ + "T", + "W", + "AY", + "S" + ], + "PRODUCT": [ + "P", + "R", + "AH", + "D", + "AH", + "K", + "T" + ], + "SEATED": [ + "S", + "IY", + "T", + "IH", + "D" + ], + "CHURCH": [ + "CH", + "ER", + "CH" + ], + "SUGGESTED": [ + "S", + "AH", + "JH", + "EH", + "S", + "T", + "IH", + "D" + ], + "ITSELF": [ + "IH", + "T", + "S", + "EH", + "L", + "F" + ], + "REACH": [ + "R", + "IY", + "CH" + ], + "ACCIDENT": [ + "AE", + "K", + "S", + "IH", + "D", + "AH", + "N", + "T" + ], + "MARRY": [ + "M", + "AE", + "R", + "IY" + ], + "PITY": [ + "P", + "IH", + "T", + "IY" + ], + "PRICE": [ + "P", + "R", + "AY", + "S" + ], + "PLEASANT": [ + "P", + "L", + "EH", + "Z", + "N", + "T" + ], + "EXERCISE": [ + "EH", + "K", + "S", + "ER", + "S", + "AY", + "Z" + ], + "APPOINTMENT": [ + "AH", + "P", + "OY", + "N", + "T", + "M", + "AH", + "N", + "T" + ], + "BUILD": [ + "B", + "IH", + "L", + "D" + ], + "RELATIONSHIP": [ + "R", + "IH", + "L", + "EY", + "SH", + "N", + "SH", + "IH", + "P" + ], + "SPOT": [ + "S", + "P", + "AH", + "T" + ], + "THINKS": [ + "TH", + "IH", + "NG", + "K", + "S" + ], + "ANXIOUS": [ + "AE", + "NG", + "K", + "SH", + "AH", + "S" + ], + "PULLED": [ + "P", + "UH", + "L", + "D" + ], + "QUICKLY": [ + "K", + "W", + "IH", + "K", + "L", + "IY" + ], + "MANNER": [ + "M", + "AE", + "N", + "AH" + ], + "POINTED": [ + "P", + "OY", + "N", + "T", + "IH", + "D" + ], + "KINDNESS": [ + "K", + "AY", + "N", + "D", + "N", + "AH", + "S" + ], + "ADVICE": [ + "AH", + "D", + "V", + "AY", + "S" + ], + "CHEERED": [ + "CH", + "IH", + "AH", + "D" + ], + "SHELL": [ + "SH", + "EH", + "L" + ], + "BROTHER": [ + "B", + "R", + "AH", + "DH", + "AH" + ], + "REACHED": [ + "R", + "IY", + "CH", + "T" + ], + "AIRS": [ + "EH", + "R", + "Z" + ], + "PAINFUL": [ + "P", + "EY", + "N", + "F", + "L" + ], + "HELL": [ + "HH", + "EH", + "L" + ], + "CURIOUS": [ + "K", + "Y", + "UH", + "AH", + "IH", + "AH", + "S" + ], + "POWER": [ + "P", + "AW", + "AH" + ], + "ACCEPT": [ + "AH", + "K", + "S", + "EH", + "P", + "T" + ], + "PROVE": [ + "P", + "R", + "UW", + "V" + ], + "RUBBED": [ + "R", + "AH", + "B", + "D" + ], + "SLOWLY": [ + "S", + "L", + "OW", + "L", + "IY" + ], + "GAINED": [ + "G", + "EY", + "N", + "D" + ], + "JOBS": [ + "JH", + "OW", + "B", + "S" + ], + "AWFUL": [ + "AO", + "F", + "L" + ], + "DREADFUL": [ + "D", + "R", + "EH", + "D", + "F", + "L" + ], + "GUARDS": [ + "G", + "AA", + "R", + "D", + "Z" + ], + "PAUSE": [ + "P", + "AO", + "Z" + ], + "PLOTTING": [ + "P", + "L", + "AH", + "T", + "IH", + "NG" + ], + "ENGLISHMAN": [ + "IH", + "NG", + "G", + "L", + "IH", + "SH", + "M", + "AH", + "N" + ], + "APART": [ + "AH", + "P", + "AA", + "T" + ], + "MURDERER": [ + "M", + "ER", + "D", + "ER", + "ER" + ], + "BARELY": [ + "B", + "EH", + "R", + "L", + "IY" + ], + "COMPLETELY": [ + "K", + "AH", + "M", + "P", + "L", + "IY", + "T", + "L", + "IY" + ], + "PUTTING": [ + "P", + "UH", + "T", + "IH", + "NG" + ], + "BARGAIN": [ + "B", + "AA", + "G", + "AH", + "N" + ], + "WATCHED": [ + "W", + "AH", + "CH", + "T" + ], + "ABSENT": [ + "AE", + "B", + "S", + "AH", + "N", + "T" + ], + "ACCEPTED": [ + "AH", + "K", + "S", + "EH", + "P", + "T", + "IH", + "D" + ], + "PAPERS": [ + "P", + "EH", + "P", + "ER", + "Z" + ], + "JAPANESE": [ + "JH", + "AE", + "P", + "AH", + "N", + "IY", + "Z" + ], + "SOUNDED": [ + "S", + "AW", + "N", + "D", + "IH", + "D" + ], + "ADMITTED": [ + "AH", + "D", + "M", + "IH", + "T", + "IH", + "D" + ], + "SUBURBS": [ + "S", + "AH", + "B", + "ER", + "B", + "S" + ], + "ATTRACTED": [ + "AH", + "T", + "R", + "AE", + "K", + "T", + "IH", + "D" + ], + "REALITY": [ + "R", + "IY", + "AE", + "L", + "AH", + "T", + "IY" + ], + "SEND": [ + "S", + "EH", + "N", + "D" + ], + "SILENCE": [ + "S", + "AY", + "L", + "AH", + "N", + "S" + ], + "AFFAIR": [ + "AH", + "F", + "EH", + "R" + ], + "LITERATURE": [ + "L", + "IH", + "T", + "R", + "AH", + "CH", + "ER" + ], + "ACTUALLY": [ + "AE", + "K", + "CH", + "UW", + "AH", + "L", + "IY" + ], + "CARRIAGE": [ + "K", + "AE", + "R", + "IH", + "JH" + ], + "DROPPED": [ + "D", + "R", + "AH", + "P", + "T" + ], + "CONVENTION": [ + "K", + "AH", + "N", + "V", + "EH", + "N", + "SH", + "N" + ], + "DEFEAT": [ + "D", + "IH", + "F", + "IY", + "T" + ], + "INDIFFERENT": [ + "IH", + "N", + "D", + "IH", + "F", + "R", + "AH", + "N", + "T" + ], + "UNEASY": [ + "AH", + "N", + "IY", + "Z", + "IY" + ], + "REMIND": [ + "R", + "IH", + "M", + "AY", + "N", + "D" + ], + "PRESENTED": [ + "P", + "R", + "IH", + "Z", + "EH", + "N", + "T", + "IH", + "D" + ], + "ROSE": [ + "R", + "OW", + "Z" + ], + "RANKS": [ + "R", + "AE", + "NG", + "K", + "S" + ], + "BREAKING": [ + "B", + "R", + "EY", + "K", + "IH", + "NG" + ], + "GRACED": [ + "G", + "R", + "EY", + "S" + ], + "MACHINE": [ + "M", + "AH", + "SH", + "IY", + "N" + ], + "AWAKE": [ + "AH", + "W", + "EY", + "K" + ], + "SEATS": [ + "S", + "IY", + "T", + "S" + ], + "SUDDENLY": [ + "S", + "AH", + "D", + "AH", + "N", + "L", + "IY" + ], + "WAVED": [ + "W", + "EY", + "V", + "D" + ], + "DEBTS": [ + "D", + "EH", + "T", + "S" + ], + "RESTORE": [ + "R", + "IH", + "S", + "T", + "AO", + "R" + ], + "SHIFT": [ + "SH", + "IH", + "F", + "T" + ], + "IMPRESSIVELY": [ + "IH", + "M", + "P", + "R", + "EH", + "S", + "IH", + "V", + "L", + "IY" + ], + "NEARLY": [ + "N", + "IH", + "AH", + "L", + "IY" + ], + "SHARP": [ + "SH", + "AA", + "P" + ], + "BURSTS": [ + "B", + "ER", + "S", + "T", + "S" + ], + "SATISFIED": [ + "S", + "AE", + "T", + "IH", + "S", + "F", + "AY", + "D" + ], + "EXCEEDINGLY": [ + "IH", + "K", + "S", + "IY", + "D", + "IH", + "NG", + "L", + "IY" + ], + "USEFUL": [ + "Y", + "UW", + "S", + "F", + "L" + ], + "COOKED": [ + "K", + "UH", + "K", + "T" + ], + "CRUEL": [ + "K", + "R", + "UW", + "AH", + "L" + ], + "FLOWER": [ + "F", + "L", + "AW", + "AH" + ], + "FOOL": [ + "F", + "UW", + "L" + ], + "FINALLY": [ + "F", + "AY", + "N", + "AH", + "L", + "IY" + ], + "FACED": [ + "F", + "EY", + "S", + "T" + ], + "INSTALL": [ + "IH", + "N", + "S", + "T", + "AO", + "L" + ], + "OURSELVES": [ + "AW", + "ER", + "S", + "EH", + "L", + "V", + "Z" + ], + "PEACEFUL": [ + "P", + "IY", + "S", + "F", + "L" + ], + "DELICATE": [ + "D", + "EH", + "L", + "IH", + "K", + "AH", + "T" + ], + "SOLDIER": [ + "S", + "OW", + "L", + "JH", + "ER" + ], + "SPACE": [ + "S", + "P", + "EY", + "S" + ], + "FURIOUSLY": [ + "F", + "Y", + "UH", + "ER", + "IH", + "AH", + "S", + "L", + "IY" + ], + "GIRLS": [ + "G", + "ER", + "L", + "Z" + ], + "HELPING": [ + "HH", + "EH", + "L", + "P", + "IH", + "NG" + ], + "REMOVAL": [ + "R", + "IH", + "M", + "UW", + "V", + "L" + ], + "LESSENING": [ + "L", + "EH", + "S", + "N", + "IH", + "NG" + ], + "EITHER": [ + "AY", + "DH", + "AH" + ], + "SILLY": [ + "S", + "IH", + "L", + "IY" + ], + "SIDES": [ + "S", + "AY", + "D", + "Z" + ], + "EATING": [ + "IY", + "T", + "IH", + "NG" + ], + "GIVING": [ + "G", + "IH", + "V", + "IH", + "NG" + ], + "WIDENING": [ + "W", + "AY", + "D", + "N", + "IH", + "NG" + ], + "GAP": [ + "G", + "AE", + "P" + ], + "DRIFTED": [ + "D", + "R", + "IH", + "F", + "T", + "IH", + "D" + ], + "SUNSET": [ + "S", + "AH", + "N", + "S", + "EH", + "T" + ], + "RISE": [ + "R", + "AY", + "Z" + ], + "HAZARDED": [ + "HH", + "AE", + "Z", + "ER", + "D" + ], + "BULLETS": [ + "B", + "UH", + "L", + "IH", + "T", + "S" + ], + "MAD": [ + "M", + "AE", + "D" + ], + "SINCE": [ + "S", + "IH", + "N", + "S" + ], + "AUTOMOBILE": [ + "AO", + "T", + "AH", + "M", + "AH", + "B", + "IY", + "L" + ], + "REMARK": [ + "R", + "IH", + "M", + "AA", + "R", + "K" + ], + "LIPS": [ + "L", + "IH", + "P", + "S" + ], + "ACQUAINTED": [ + "AH", + "K", + "W", + "EY", + "N", + "T", + "IH", + "D" + ], + "ATTACKED": [ + "AH", + "T", + "AE", + "K", + "T" + ], + "SIMILAR": [ + "S", + "IH", + "M", + "AH", + "L", + "AH" + ], + "WISHING": [ + "W", + "IH", + "SH", + "IH", + "NG" + ], + "REIGNS": [ + "R", + "EY", + "N", + "Z" + ], + "RESTAURANT": [ + "R", + "EH", + "S", + "T", + "R", + "AH", + "N", + "T" + ], + "SHOWED": [ + "SH", + "OW", + "D" + ], + "OCCURRED": [ + "AH", + "K", + "ER", + "R", + "D" + ], + "WHISPERED": [ + "W", + "IH", + "S", + "P", + "AH", + "D" + ], + "CLEARLY": [ + "K", + "L", + "IH", + "AH", + "L", + "IY" + ], + "SITTING": [ + "S", + "IH", + "T", + "IH", + "NG" + ], + "THIN": [ + "TH", + "IH", + "N" + ], + "FINGERS": [ + "F", + "IH", + "NG", + "G", + "AH", + "S" + ], + "GRIPPING": [ + "G", + "R", + "IH", + "P", + "IH", + "NG" + ], + "IMAGINE": [ + "IH", + "M", + "AE", + "JH", + "IH", + "N" + ], + "TIMES": [ + "T", + "AY", + "M", + "Z" + ], + "DIRT": [ + "D", + "ER", + "T" + ], + "FAST": [ + "F", + "AE", + "S", + "T" + ], + "MISSED": [ + "M", + "IH", + "S", + "T" + ], + "ENDS": [ + "EH", + "N", + "D", + "Z" + ], + "SALAD": [ + "S", + "AE", + "L", + "AH", + "D" + ], + "TIME'S": [ + "T", + "AY", + "M", + "Z" + ], + "BOB'S": [ + "B", + "AH", + "B", + "S" + ], + "MAP": [ + "M", + "AE", + "P" + ], + "YUMMY": [ + "Y", + "AH", + "M", + "IY" + ], + "TEDDY'S": [ + "T", + "EH", + "D", + "IH", + "S" + ], + "STIR": [ + "S", + "T", + "ER" + ], + "BEN": [ + "B", + "EH", + "N" + ], + "DANCE": [ + "D", + "AA", + "N", + "S" + ], + "EXCITING": [ + "IH", + "K", + "S", + "AY", + "T", + "IH", + "NG" + ], + "RABBIT": [ + "R", + "AE", + "B", + "IH", + "T" + ], + "YELLOW": [ + "Y", + "EH", + "L", + "OW" + ], + "OWNED": [ + "OW", + "N", + "D" + ], + "CLAUS": [ + "K", + "L", + "AH", + "UW", + "S" + ], + "LANTERN": [ + "L", + "AE", + "N", + "T", + "AH", + "N" + ], + "LYNDA'S": [ + "L", + "IH", + "N", + "D", + "AH", + "S" + ], + "SHIRTS": [ + "SH", + "ER", + "T", + "S" + ], + "HOMES": [ + "HH", + "OW", + "M", + "Z" + ], + "GRAPE": [ + "G", + "R", + "EY", + "P" + ], + "SEX": [ + "S", + "EH", + "K", + "S" + ], + "LEE": [ + "L", + "IY" + ], + "EAR": [ + "IH", + "AH" + ], + "CAP": [ + "K", + "AE", + "P" + ], + "PURPLE": [ + "P", + "ER", + "P", + "L" + ], + "ROWING": [ + "R", + "OW", + "IH", + "NG" + ], + "CAFE": [ + "K", + "AE", + "F", + "EY" + ], + "DRIVER": [ + "D", + "R", + "AY", + "V", + "ER" + ], + "LONGAN": [ + "L", + "AH", + "NG", + "G", + "AH", + "N" + ], + "JULY": [ + "JH", + "UW", + "L", + "AY" + ], + "NOVEMBER": [ + "N", + "OW", + "V", + "EH", + "M", + "B", + "ER" + ], + "HOMEWORK": [ + "HH", + "OW", + "M", + "W", + "ER", + "K" + ], + "YAM": [ + "Y", + "AE", + "M" + ], + "TOKYO": [ + "T", + "OW", + "K", + "Y", + "OW" + ], + "FORTUNATE": [ + "F", + "AO", + "R", + "CH", + "AH", + "N", + "AH", + "T" + ], + "TRAFFIC": [ + "T", + "R", + "AE", + "F", + "IH", + "K" + ], + "CAREER": [ + "K", + "AH", + "R", + "IH", + "AH" + ], + "PRESSURE": [ + "P", + "R", + "EH", + "SH", + "AH" + ], + "AGE": [ + "EY", + "JH" + ], + "CAREFUL": [ + "K", + "EH", + "R", + "F", + "L" + ], + "PROVIDE": [ + "P", + "R", + "AH", + "V", + "AY", + "D" + ], + "PICK": [ + "P", + "IH", + "K" + ], + "EFFORT": [ + "EH", + "F", + "ER", + "T" + ], + "LITERALLY": [ + "L", + "IH", + "T", + "ER", + "AH", + "L", + "IY" + ], + "EASILY": [ + "IY", + "Z", + "AH", + "L", + "IY" + ], + "INTERVIEW": [ + "IH", + "N", + "T", + "AH", + "V", + "Y", + "UW" + ], + "CURIOUSLY": [ + "K", + "Y", + "UH", + "AH", + "IH", + "AH", + "S", + "L", + "IY" + ], + "CLOUD": [ + "K", + "L", + "AW", + "D" + ], + "STEVEN": [ + "S", + "T", + "IY", + "V", + "N" + ], + "SOAP": [ + "S", + "OW", + "P" + ], + "REVENGE": [ + "R", + "IH", + "V", + "EH", + "N", + "JH" + ], + "CUPS": [ + "K", + "AH", + "P", + "S" + ], + "PRINTERS": [ + "P", + "R", + "IY", + "N", + "T", + "ER", + "Z" + ], + "CUB": [ + "K", + "AH", + "B" + ], + "RESEARCHERS": [ + "R", + "IH", + "S", + "ER", + "CH", + "AH", + "Z" + ], + "RATED": [ + "R", + "EY", + "T", + "IH", + "D" + ], + "ACCEPTABLE": [ + "AH", + "K", + "S", + "EH", + "P", + "T", + "AH", + "B", + "L" + ], + "SOCIETY": [ + "S", + "AH", + "S", + "AY", + "AH", + "T", + "IY" + ], + "DUE": [ + "D", + "Y", + "UW" + ], + "WOUNDED": [ + "W", + "UW", + "N", + "D", + "IH", + "D" + ], + "LOOSE": [ + "L", + "UW", + "S" + ], + "VACATION": [ + "V", + "EY", + "K", + "EY", + "SH", + "N" + ], + "COMPUTER": [ + "K", + "AH", + "M", + "P", + "Y", + "UW", + "T", + "ER" + ], + "OPINIONS": [ + "AH", + "P", + "IH", + "N", + "Y", + "AH", + "N", + "Z" + ], + "ASHAMED": [ + "AH", + "SH", + "EY", + "M", + "D" + ], + "SOUL": [ + "S", + "OW", + "L" + ], + "WATCHES": [ + "W", + "AH", + "CH", + "IH", + "Z" + ], + "TELEVISION": [ + "T", + "EH", + "L", + "IH", + "V", + "IH", + "ZH", + "N" + ], + "GENUINE": [ + "JH", + "EH", + "N", + "Y", + "UW", + "IH", + "N" + ], + "HANDED": [ + "HH", + "AE", + "N", + "D", + "IH", + "D" + ], + "HOOK": [ + "HH", + "UH", + "K" + ], + "STREETS": [ + "S", + "T", + "R", + "IY", + "T", + "S" + ], + "RELATIVELY": [ + "R", + "EH", + "L", + "AH", + "T", + "IH", + "V", + "L", + "IY" + ], + "CALM": [ + "K", + "AA", + "M" + ], + "CONTEST": [ + "K", + "AH", + "N", + "T", + "EH", + "S", + "T" + ], + "COURT": [ + "K", + "AO", + "T" + ], + "LANGUAGE": [ + "L", + "AE", + "NG", + "G", + "W", + "IH", + "JH" + ], + "PLAYERS": [ + "P", + "L", + "EH", + "ER", + "Z" + ], + "PERSONALITY": [ + "P", + "ER", + "S", + "AH", + "N", + "AE", + "L", + "AH", + "T", + "IY" + ], + "TASTE": [ + "T", + "EY", + "S", + "T" + ], + "CONTROLLED": [ + "K", + "AH", + "N", + "T", + "R", + "OW", + "L", + "D" + ], + "PROPERTY": [ + "P", + "R", + "AH", + "P", + "AH", + "T", + "IY" + ], + "RISK": [ + "R", + "IH", + "S", + "K" + ], + "LEADERS": [ + "L", + "IY", + "D", + "ER", + "S" + ], + "WEAR": [ + "W", + "EH", + "R" + ], + "ELECTRONIC": [ + "IH", + "L", + "EH", + "K", + "T", + "R", + "AH", + "N", + "IH", + "K" + ], + "MONITOR": [ + "M", + "AH", + "N", + "IH", + "T", + "AH" + ], + "OVEN": [ + "AH", + "V", + "N" + ], + "CREATE": [ + "K", + "R", + "IY", + "EY", + "T" + ], + "PEACE": [ + "P", + "IY", + "S" + ], + "ENTIRE": [ + "IH", + "N", + "T", + "AY", + "AH" + ], + "SPOONS": [ + "S", + "P", + "UW", + "N", + "S" + ], + "PREVENTION": [ + "P", + "R", + "IH", + "V", + "EH", + "N", + "SH", + "N" + ], + "BODY": [ + "B", + "AH", + "D", + "IY" + ], + "HIGHLY": [ + "HH", + "AY", + "L", + "IY" + ], + "LEGALLY": [ + "L", + "IY", + "G", + "AH", + "L", + "IY" + ], + "AD": [ + "AE", + "D" + ], + "INNER": [ + "IH", + "N", + "AH" + ], + "WEAK": [ + "W", + "IY", + "K" + ], + "SITE": [ + "S", + "AY", + "T" + ], + "NOWADAYS": [ + "N", + "AW", + "AH", + "D", + "EY", + "Z" + ], + "SUFFER": [ + "S", + "AH", + "F", + "AH" + ], + "RATE": [ + "R", + "EY", + "T" + ], + "DISAPPOINTED": [ + "D", + "IH", + "S", + "AH", + "P", + "OY", + "N", + "T", + "IH", + "D" + ], + "PRINCIPLE": [ + "P", + "R", + "IH", + "N", + "S", + "AH", + "P", + "L" + ], + "RULES": [ + "R", + "UW", + "L", + "Z" + ], + "MAGICAL": [ + "M", + "AE", + "JH", + "IH", + "K", + "L" + ], + "CONDITIONS": [ + "K", + "AH", + "N", + "D", + "IH", + "SH", + "N", + "Z" + ], + "REPUBLICANS": [ + "R", + "IH", + "P", + "AH", + "B", + "L", + "IH", + "K", + "AH", + "N", + "Z" + ], + "MEASURE": [ + "M", + "EH", + "ZH", + "ER" + ], + "DESIRE": [ + "D", + "IH", + "Z", + "AY", + "ER" + ], + "DEFINE": [ + "D", + "IH", + "F", + "AY", + "N" + ], + "DURING": [ + "D", + "UH", + "AH", + "IH", + "NG" + ], + "MISSING": [ + "M", + "IH", + "S", + "IH", + "NG" + ], + "GOD'S": [ + "G", + "AH", + "D", + "Z" + ], + "SOUNDS": [ + "S", + "AW", + "N", + "D", + "Z" + ], + "HOLDING": [ + "HH", + "OW", + "L", + "D", + "IH", + "NG" + ], + "CUTS": [ + "K", + "AH", + "T", + "S" + ], + "TRIAL": [ + "T", + "R", + "AY", + "AH", + "L" + ], + "FORTH": [ + "F", + "AO", + "R", + "TH" + ], + "CONFIDENCE": [ + "K", + "AH", + "N", + "F", + "IH", + "D", + "AH", + "N", + "S" + ], + "MAGIC": [ + "M", + "AE", + "JH", + "IH", + "K" + ], + "ADS": [ + "AE", + "D", + "Z" + ], + "INSIDE": [ + "IH", + "N", + "S", + "AY", + "D" + ], + "PERFECTLY": [ + "P", + "ER", + "F", + "IH", + "K", + "T", + "L", + "IY" + ], + "DECISION": [ + "D", + "IH", + "S", + "IH", + "ZH", + "N" + ], + "GENTLE": [ + "JH", + "EH", + "N", + "T", + "L" + ], + "KNOCK": [ + "N", + "AH", + "K" + ], + "STRIKING": [ + "S", + "T", + "R", + "AY", + "K", + "IH", + "NG" + ], + "CONTRIBUTE": [ + "K", + "AH", + "N", + "T", + "R", + "IH", + "B", + "Y", + "UW", + "T" + ], + "CAMPAIGN": [ + "K", + "AE", + "M", + "P", + "EY", + "N" + ], + "MASTERS": [ + "M", + "AE", + "S", + "T", + "ER", + "Z" + ], + "LASTS": [ + "L", + "AE", + "S", + "T", + "S" + ], + "LEARN": [ + "L", + "ER", + "N" + ], + "IGNORE": [ + "IH", + "G", + "N", + "AO", + "R" + ], + "JOKE": [ + "JH", + "OW", + "K" + ], + "INTEREST": [ + "IH", + "N", + "T", + "R", + "AH", + "S", + "T" + ], + "SUMMER": [ + "S", + "AH", + "M", + "ER" + ], + "SHARING": [ + "SH", + "EH", + "R", + "IH", + "NG" + ], + "PIECES": [ + "P", + "IY", + "S", + "IH", + "Z" + ], + "CHARGE": [ + "CH", + "AA", + "JH" + ], + "MURDER": [ + "M", + "ER", + "D", + "AH" + ], + "PASSIVE": [ + "P", + "AE", + "S", + "IH", + "V" + ], + "RESIGNED": [ + "R", + "IH", + "Z", + "AY", + "N", + "D" + ], + "FOOD": [ + "F", + "UW", + "D" + ], + "PEARL": [ + "P", + "ER", + "L" + ], + "RELIES": [ + "R", + "IH", + "L", + "AY", + "Z" + ], + "TAXI": [ + "T", + "AE", + "K", + "S", + "IY" + ], + "CORN": [ + "K", + "AO", + "N" + ], + "TONY": [ + "T", + "OW", + "N", + "IY" + ], + "DESKS": [ + "D", + "EH", + "S", + "K", + "S" + ], + "CHAIRS": [ + "CH", + "EH", + "R", + "Z" + ], + "EAGLE": [ + "IY", + "G", + "L" + ], + "JAR": [ + "JH", + "AA" + ], + "BENNY": [ + "B", + "EH", + "N", + "IY" + ], + "GOATS": [ + "G", + "OW", + "T", + "S" + ], + "ELLS": [ + "EH", + "L", + "Z" + ], + "NOSE": [ + "N", + "OW", + "Z" + ], + "ASSURE": [ + "AH", + "SH", + "UH", + "AH" + ], + "OUGHT": [ + "AO", + "T" + ], + "CHRISTMAS": [ + "K", + "R", + "IH", + "S", + "M", + "AH", + "S" + ], + "GROWING": [ + "G", + "R", + "OW", + "IH", + "NG" + ], + "CREATIVE": [ + "K", + "R", + "IY", + "EY", + "T", + "IH", + "V" + ], + "KNOWN": [ + "N", + "OW", + "N" + ], + "PROTECTION": [ + "P", + "R", + "AH", + "T", + "EH", + "K", + "SH", + "N" + ], + "SERIOUSLY": [ + "S", + "IH", + "AH", + "R", + "IH", + "AH", + "S", + "L", + "IY" + ], + "WIND": [ + "W", + "IH", + "N", + "D" + ], + "REMINDING": [ + "R", + "IH", + "M", + "AY", + "N", + "D", + "IH", + "NG" + ], + "FIXED": [ + "F", + "IH", + "K", + "S", + "T" + ], + "PATIENT": [ + "P", + "EY", + "SH", + "N", + "T" + ], + "SUCKS": [ + "S", + "AH", + "K", + "S" + ], + "ARMS": [ + "AA", + "M", + "Z" + ], + "FINANCIAL": [ + "F", + "AY", + "N", + "AE", + "N", + "SH", + "L" + ], + "STANDPOINT": [ + "S", + "T", + "AE", + "N", + "D", + "P", + "OY", + "N", + "T" + ], + "DANGEROUS": [ + "D", + "EY", + "N", + "JH", + "ER", + "AH", + "S" + ], + "COOPERATE": [ + "K", + "OW", + "AH", + "P", + "ER", + "EY", + "T" + ], + "PLACED": [ + "P", + "L", + "EY", + "S", + "T" + ], + "UNDER": [ + "AH", + "N", + "D", + "ER" + ], + "ARREST": [ + "AH", + "R", + "EH", + "S", + "T" + ], + "LATEST": [ + "L", + "EY", + "T", + "IH", + "S", + "T" + ], + "ADDITION": [ + "AH", + "D", + "IH", + "SH", + "N" + ], + "TAKING": [ + "T", + "EY", + "K", + "IH", + "NG" + ], + "CRAZY": [ + "K", + "R", + "EY", + "Z", + "IY" + ], + "POETRY": [ + "P", + "OW", + "UH", + "AH", + "T", + "R", + "IY" + ], + "BLACKNESS": [ + "B", + "L", + "AE", + "K", + "N", + "AH", + "S" + ], + "AFTERWARDS": [ + "AA", + "F", + "T", + "AH", + "W", + "AH", + "D", + "Z" + ], + "TRICK": [ + "T", + "R", + "IH", + "K" + ], + "DESK": [ + "D", + "EH", + "S", + "K" + ], + "SHELF": [ + "SH", + "EH", + "L", + "F" + ], + "REMOVE": [ + "R", + "IH", + "M", + "UW", + "V" + ], + "STAT": [ + "S", + "T", + "AE", + "T" + ], + "BLESSING": [ + "B", + "L", + "EH", + "S", + "IH", + "NG" + ], + "FORK": [ + "F", + "AO", + "K" + ], + "ATTEND": [ + "AH", + "T", + "EH", + "N", + "D" + ], + "WOOD": [ + "W", + "UH", + "D" + ], + "ADMIT": [ + "AH", + "D", + "M", + "IH", + "T" + ], + "COMMENTS": [ + "K", + "AH", + "M", + "EH", + "N", + "T", + "S" + ], + "COPY": [ + "K", + "AH", + "P", + "IY" + ], + "GRIPS": [ + "G", + "R", + "IH", + "P", + "S" + ], + "SPONSORS": [ + "S", + "P", + "AA", + "N", + "S", + "ER", + "S" + ], + "IMPACT": [ + "IH", + "M", + "P", + "AE", + "K", + "T" + ], + "DEED": [ + "D", + "IY", + "D" + ], + "AWARDED": [ + "AH", + "W", + "AO", + "D", + "IH", + "D" + ], + "WINTER": [ + "W", + "IH", + "N", + "T", + "AH" + ], + "ACTS": [ + "AE", + "K", + "T", + "S" + ], + "DRAMA": [ + "D", + "R", + "AA", + "M", + "AH" + ], + "SIGN": [ + "S", + "AY", + "N" + ], + "DESPAIR": [ + "D", + "IH", + "S", + "P", + "EH", + "R" + ], + "AIR": [ + "EH", + "R" + ], + "UNDERSTANDING": [ + "AH", + "N", + "D", + "ER", + "S", + "T", + "AE", + "N", + "D", + "IH", + "NG" + ], + "HELPS": [ + "HH", + "EH", + "L", + "P", + "S" + ], + "GYMNASTICS": [ + "JH", + "IH", + "M", + "N", + "AE", + "S", + "T", + "IH", + "K", + "S" + ], + "LUCY'S": [ + "L", + "UW", + "S", + "IH", + "S" + ], + "SEAK": [ + "S", + "IY", + "K" + ], + "HANDY": [ + "HH", + "AE", + "N", + "D", + "IY" + ], + "CATHY": [ + "K", + "AE", + "TH", + "IY" + ], + "FREEZE": [ + "F", + "R", + "IY", + "Z" + ], + "WUSS": [ + "W", + "UH", + "S" + ], + "COTTON": [ + "K", + "AH", + "T", + "N" + ], + "CROW": [ + "K", + "R", + "OW" + ], + "THOUGHTS": [ + "TH", + "AO", + "T", + "S" + ], + "STRUGGLE": [ + "S", + "T", + "R", + "AH", + "G", + "L" + ], + "AIM": [ + "EY", + "M" + ], + "BLAME": [ + "B", + "L", + "EY", + "M" + ], + "PUZZLE": [ + "P", + "AH", + "Z", + "L" + ], + "MENTION": [ + "M", + "EH", + "N", + "SH", + "N" + ], + "PROJECT": [ + "P", + "R", + "AH", + "JH", + "EH", + "K", + "T" + ], + "OVERALL": [ + "OW", + "V", + "ER", + "AO", + "L" + ], + "MOUSE": [ + "M", + "AW", + "S" + ], + "LISTENS": [ + "L", + "IH", + "S", + "N", + "Z" + ], + "PENCIL": [ + "P", + "EH", + "N", + "S", + "L" + ], + "DANIEL": [ + "D", + "AE", + "N", + "Y", + "AH", + "L" + ], + "MILKING": [ + "M", + "IH", + "L", + "K", + "IH", + "NG" + ], + "BIRDBATH": [ + "B", + "ER", + "D", + "B", + "AA", + "TH" + ], + "ACHIEVE": [ + "AH", + "CH", + "IY", + "V" + ], + "CONCERNED": [ + "K", + "AH", + "N", + "S", + "ER", + "N", + "D" + ], + "ORGANIZED": [ + "AO", + "G", + "AH", + "N", + "AY", + "Z", + "D" + ], + "FREEDOM": [ + "F", + "R", + "IY", + "D", + "AH", + "M" + ], + "CELEBRATE": [ + "S", + "EH", + "L", + "IH", + "B", + "R", + "EY", + "T" + ], + "HOST": [ + "HH", + "OW", + "S", + "T" + ], + "REASONS": [ + "R", + "IY", + "Z", + "N", + "Z" + ], + "GAY": [ + "G", + "EY" + ], + "ZOO": [ + "Z", + "UW" + ], + "TOBOGGAN": [ + "T", + "AH", + "B", + "AH", + "G", + "AH", + "N" + ], + "PIGS": [ + "P", + "IH", + "G", + "Z" + ], + "MISSION": [ + "M", + "IH", + "SH", + "N" + ], + "FIX": [ + "F", + "IH", + "K", + "S" + ], + "SUMMARY": [ + "S", + "AH", + "M", + "ER", + "IY" + ], + "PROVISIONS": [ + "P", + "R", + "AH", + "V", + "IH", + "ZH", + "N", + "Z" + ], + "COACHES": [ + "K", + "OW", + "CH", + "IH", + "Z" + ], + "MARRIED": [ + "M", + "AE", + "R", + "IY", + "D" + ], + "BLESSINGS": [ + "B", + "L", + "EH", + "S", + "IH", + "NG", + "Z" + ], + "LIFE'S": [ + "L", + "AY", + "F", + "S" + ], + "DARKNESS": [ + "D", + "AA", + "K", + "N", + "AH", + "S" + ], + "TEAMS": [ + "T", + "IY", + "M", + "Z" + ], + "REMAIN": [ + "R", + "IH", + "M", + "EY", + "N" + ], + "COMFORTABLE": [ + "K", + "AH", + "M", + "F", + "AH", + "T", + "AH", + "B", + "L" + ], + "CHARITY": [ + "CH", + "AE", + "R", + "AH", + "T", + "IY" + ], + "THREW": [ + "TH", + "R", + "UW" + ], + "LINE": [ + "L", + "AY", + "N" + ], + "TIRES": [ + "T", + "AY", + "AH", + "Z" + ], + "KILLING'S": [ + "K", + "IH", + "L", + "IH", + "NG", + "S" + ], + "SUSPECTS": [ + "S", + "AH", + "S", + "P", + "EH", + "K", + "T", + "S" + ], + "ACROSS": [ + "AH", + "K", + "R", + "AH", + "S" + ], + "RESPONDED": [ + "R", + "IH", + "S", + "P", + "AH", + "N", + "D", + "IH", + "D" + ], + "GAS": [ + "G", + "AE", + "S" + ], + "SEPTEMBER": [ + "S", + "EH", + "P", + "T", + "EH", + "M", + "B", + "ER" + ], + "SMOKING": [ + "S", + "M", + "OW", + "K", + "IH", + "NG" + ], + "SNOWING": [ + "S", + "N", + "OW", + "IH", + "NG" + ], + "LINK": [ + "L", + "IH", + "NG", + "K" + ], + "REGISTER": [ + "R", + "EH", + "JH", + "IH", + "S", + "T", + "ER" + ], + "STORM": [ + "S", + "T", + "AO", + "M" + ], + "MISTAKE": [ + "M", + "IH", + "S", + "T", + "EY", + "K" + ], + "HAPPINESS": [ + "HH", + "AE", + "P", + "IY", + "N", + "AH", + "S" + ], + "WORST": [ + "W", + "ER", + "S", + "T" + ], + "CREATED": [ + "K", + "R", + "IY", + "EY", + "T", + "IH", + "D" + ], + "PEOPLES": [ + "P", + "IY", + "P", + "L", + "Z" + ], + "CONSCIOUS": [ + "K", + "AH", + "N", + "SH", + "AH", + "S" + ], + "HELPFUL": [ + "HH", + "EH", + "L", + "P", + "F", + "L" + ], + "SAINTS": [ + "S", + "EY", + "N", + "T", + "S" + ], + "BLAMING": [ + "B", + "L", + "EY", + "M", + "IH", + "NG" + ], + "LOTS": [ + "L", + "AH", + "T", + "S" + ], + "TOUCHED": [ + "T", + "AH", + "CH", + "T" + ], + "FLY": [ + "F", + "L", + "AY" + ], + "STAKE": [ + "S", + "T", + "EY", + "K" + ], + "OTHERWISE": [ + "AH", + "DH", + "AH", + "W", + "AY", + "Z" + ], + "PARADISE": [ + "P", + "AE", + "R", + "AH", + "D", + "AY", + "S" + ], + "CORNER": [ + "K", + "AO", + "R", + "N", + "ER" + ], + "ROLL": [ + "R", + "OW", + "L" + ], + "COST": [ + "K", + "AH", + "S", + "T" + ], + "GRAVE": [ + "G", + "R", + "EY", + "V" + ], + "SOUP": [ + "S", + "UW", + "P" + ], + "SNAKES": [ + "S", + "N", + "EY", + "K", + "S" + ], + "DRIFTING": [ + "D", + "R", + "IH", + "F", + "T", + "IH", + "NG" + ], + "AHEAD": [ + "AH", + "HH", + "EH", + "D" + ], + "HEIGHT": [ + "HH", + "AY", + "T" + ], + "FREE": [ + "F", + "R", + "IY" + ], + "INSTEAD": [ + "IH", + "N", + "S", + "T", + "EH", + "D" + ], + "TYPE": [ + "T", + "AY", + "P" + ], + "EXECUTE": [ + "EH", + "K", + "S", + "IH", + "K", + "Y", + "UW", + "T" + ], + "YESTERDAY": [ + "Y", + "EH", + "S", + "T", + "AH", + "D", + "EY" + ], + "BENEFITS": [ + "B", + "EH", + "N", + "IH", + "F", + "IH", + "T", + "S" + ], + "TRULY": [ + "T", + "R", + "UW", + "L", + "IY" + ], + "SALARY": [ + "S", + "AE", + "L", + "ER", + "IY" + ], + "ADD": [ + "AE", + "D" + ], + "BIRDS": [ + "B", + "ER", + "D", + "Z" + ], + "COURTING": [ + "K", + "AO", + "R", + "T", + "IH", + "NG" + ], + "SENDING": [ + "S", + "EH", + "N", + "D", + "IH", + "NG" + ], + "BIND": [ + "B", + "AY", + "N", + "D" + ], + "TANK": [ + "T", + "AE", + "NG", + "K" + ], + "MEAL": [ + "M", + "IY", + "L" + ], + "FIGHTING": [ + "F", + "AY", + "T", + "IH", + "NG" + ], + "PATTERN": [ + "P", + "AE", + "T", + "N" + ], + "HARDLY": [ + "HH", + "AA", + "R", + "D", + "L", + "IY" + ], + "SELFISH": [ + "S", + "EH", + "L", + "F", + "IH", + "SH" + ], + "RID": [ + "R", + "IH", + "D" + ], + "SPOTS": [ + "S", + "P", + "AH", + "T", + "S" + ], + "BLAZE": [ + "B", + "L", + "EY", + "Z" + ], + "SUNSHINE": [ + "S", + "AH", + "N", + "SH", + "AY", + "N" + ], + "BOMBINGS": [ + "B", + "AH", + "M", + "IH", + "NG", + "S" + ], + "ARGUMENT": [ + "AA", + "G", + "Y", + "UW", + "M", + "AH", + "N", + "T" + ], + "TARGETING": [ + "T", + "AA", + "G", + "IH", + "T", + "IH", + "NG" + ], + "WEAPONS": [ + "W", + "EH", + "P", + "AH", + "N", + "Z" + ], + "BUD": [ + "B", + "AH", + "D" + ], + "NIGHTS": [ + "N", + "AY", + "T", + "S" + ], + "CONFERENCE": [ + "K", + "AH", + "N", + "F", + "ER", + "AH", + "N", + "S" + ], + "SERIES": [ + "S", + "IH", + "AH", + "IY", + "Z" + ], + "MALL": [ + "M", + "AO", + "L" + ], + "FOURTH": [ + "F", + "AO", + "TH" + ], + "ELEVEN": [ + "IH", + "L", + "EH", + "V", + "N" + ], + "EARS": [ + "IH", + "AH", + "Z" + ], + "MERRY": [ + "M", + "EH", + "R", + "IY" + ], + "FORTY": [ + "F", + "AO", + "T", + "IY" + ], + "CHAIR": [ + "CH", + "EH", + "R" + ], + "SUBJECT": [ + "S", + "AH", + "B", + "JH", + "EH", + "K", + "T" + ], + "DIS": [ + "D", + "IH", + "S" + ], + "OLDER": [ + "OW", + "L", + "D", + "ER" + ], + "SERE": [ + "S", + "IH", + "AH" + ], + "PARTIES": [ + "P", + "AA", + "T", + "IY", + "Z" + ], + "LOVERS": [ + "L", + "AH", + "V", + "AH", + "Z" + ], + "BELL": [ + "B", + "EH", + "L" + ], + "TOLD": [ + "T", + "OW", + "L", + "D" + ], + "WILLING": [ + "W", + "IH", + "L", + "IH", + "NG" + ], + "MODERN": [ + "M", + "AH", + "D", + "N" + ], + "WORRIED": [ + "W", + "AH", + "R", + "IY", + "D" + ], + "PERSONALLY": [ + "P", + "ER", + "S", + "AH", + "N", + "AH", + "L", + "IY" + ], + "HANDSOME": [ + "HH", + "AE", + "N", + "S", + "AH", + "M" + ], + "WHETHER": [ + "W", + "EH", + "DH", + "AH" + ], + "SPEAKS": [ + "S", + "P", + "IY", + "K", + "S" + ], + "NATIONS": [ + "N", + "EY", + "SH", + "N", + "Z" + ], + "WARS": [ + "W", + "AH", + "R", + "Z" + ], + "PREPARE": [ + "P", + "R", + "IH", + "P", + "EH", + "R" + ], + "PATH": [ + "P", + "AA", + "TH" + ], + "ANSWERED": [ + "AA", + "N", + "S", + "AH", + "D" + ], + "REPORT": [ + "R", + "IH", + "P", + "AO", + "T" + ], + "CENSE": [ + "S", + "EH", + "N", + "S" + ], + "DIFFERENTLY": [ + "D", + "IH", + "F", + "R", + "AH", + "N", + "T", + "L", + "IY" + ], + "FIFTY": [ + "F", + "IH", + "F", + "T", + "IY" + ], + "LESSON": [ + "L", + "EH", + "S", + "N" + ], + "BELONGED": [ + "B", + "IH", + "L", + "AH", + "NG", + "D" + ], + "GREATLY": [ + "G", + "R", + "EY", + "T", + "L", + "IY" + ], + "EXPLAIN": [ + "IH", + "K", + "S", + "P", + "L", + "EY", + "N" + ], + "PLEASURE": [ + "P", + "L", + "EH", + "ZH", + "ER" + ], + "MOMENTS": [ + "M", + "OW", + "M", + "AH", + "N", + "T", + "S" + ], + "STONE": [ + "S", + "T", + "OW", + "N" + ], + "FOLLOWING": [ + "F", + "AH", + "L", + "OW", + "IH", + "NG" + ], + "FINGER": [ + "F", + "IH", + "NG", + "G", + "ER" + ], + "KNOCKED": [ + "N", + "AA", + "K", + "T" + ], + "POPULAR": [ + "P", + "AH", + "P", + "Y", + "AH", + "L", + "AH" + ], + "PLATFORM": [ + "P", + "L", + "AE", + "T", + "F", + "AO", + "M" + ], + "PLAIN": [ + "P", + "L", + "EY", + "N" + ], + "MESSED": [ + "M", + "EH", + "S", + "T" + ], + "INTIMATE": [ + "IH", + "N", + "T", + "IH", + "M", + "AH", + "T" + ], + "CONFESSION": [ + "K", + "AH", + "N", + "F", + "EH", + "SH", + "N" + ], + "EVIL": [ + "IY", + "V", + "IH", + "L" + ], + "KNOB": [ + "N", + "AH", + "B" + ], + "INTERPRET": [ + "IH", + "N", + "T", + "ER", + "P", + "R", + "AH", + "T" + ], + "VISIBLE": [ + "V", + "IH", + "Z", + "AH", + "B", + "L" + ], + "EMPTY": [ + "EH", + "M", + "P", + "T", + "IY" + ], + "RECEIVER": [ + "R", + "IH", + "S", + "IY", + "V", + "AH" + ], + "TURNS": [ + "T", + "ER", + "N", + "Z" + ], + "WRITING": [ + "R", + "AY", + "T", + "IH", + "NG" + ], + "VEILED": [ + "V", + "EY", + "L", + "D" + ], + "RESERVE": [ + "R", + "IH", + "Z", + "ER", + "V" + ], + "SILVER": [ + "S", + "IH", + "L", + "V", + "ER" + ], + "PUPIL": [ + "P", + "Y", + "UW", + "P", + "L" + ], + "BORING": [ + "B", + "AO", + "R", + "IH", + "NG" + ], + "MARCHING": [ + "M", + "AA", + "R", + "CH", + "IH", + "NG" + ], + "FLASHED": [ + "F", + "L", + "AE", + "SH", + "T" + ], + "AUTHOR": [ + "AO", + "TH", + "ER" + ], + "NOTE": [ + "N", + "OW", + "T" + ], + "HEADS": [ + "HH", + "EH", + "D", + "Z" + ], + "FARTHER": [ + "F", + "AA", + "R", + "DH", + "ER" + ], + "EXPLANATION": [ + "EH", + "K", + "S", + "P", + "L", + "AH", + "N", + "EY", + "SH", + "N" + ], + "JEWEL": [ + "JH", + "UW", + "AH", + "L" + ], + "FLAG": [ + "F", + "L", + "AE", + "G" + ], + "IMMENSE": [ + "IH", + "M", + "EH", + "N", + "S" + ], + "DATING": [ + "D", + "EY", + "T", + "IH", + "NG" + ], + "SHRUGGED": [ + "SH", + "R", + "AH", + "G" + ], + "EXTREMELY": [ + "IH", + "K", + "S", + "T", + "R", + "IY", + "M", + "L", + "IY" + ], + "EXPLAINED": [ + "IH", + "K", + "S", + "P", + "L", + "EY", + "N", + "D" + ], + "KINGDOMS": [ + "K", + "IH", + "NG", + "D", + "AH", + "M", + "Z" + ], + "AREA": [ + "EH", + "ER", + "IH", + "AH" + ], + "MEMBERS": [ + "M", + "EH", + "M", + "B", + "AH", + "Z" + ], + "FATHER'S": [ + "F", + "AA", + "DH", + "AH", + "S" + ], + "TENSE": [ + "T", + "EH", + "N", + "S" + ], + "FORGETTING": [ + "F", + "ER", + "G", + "EH", + "T", + "IH", + "NG" + ], + "TOOTH": [ + "T", + "UW", + "TH" + ], + "SUNGLASSES": [ + "S", + "AH", + "N", + "G", + "L", + "AA", + "S", + "IH", + "Z" + ], + "CUMBER": [ + "K", + "AH", + "M", + "B", + "AH" + ], + "BANGKOK": [ + "B", + "AE", + "NG", + "K", + "AA", + "K" + ], + "BOBBY": [ + "B", + "AH", + "B", + "IY" + ], + "SEEK": [ + "S", + "IY", + "K" + ], + "BLACKS": [ + "B", + "L", + "AE", + "K", + "S" + ], + "STOCK": [ + "S", + "T", + "AH", + "K" + ], + "JACKIE": [ + "JH", + "AE", + "K", + "IY" + ], + "PARROT": [ + "P", + "AE", + "R", + "AH", + "T" + ], + "RAINCOAT": [ + "R", + "EY", + "N", + "K", + "OW", + "T" + ], + "BERLIN": [ + "B", + "ER", + "L", + "IH", + "N" + ], + "PLUM": [ + "P", + "L", + "AH", + "M" + ], + "GERMANY": [ + "JH", + "ER", + "M", + "AH", + "N", + "IY" + ], + "DRESSES": [ + "D", + "R", + "EH", + "S", + "IH", + "Z" + ], + "SCIENTIST": [ + "S", + "AY", + "AH", + "N", + "T", + "IH", + "S", + "T" + ], + "NUT": [ + "N", + "AH", + "T" + ], + "FLU": [ + "F", + "L", + "UW" + ], + "DUCKS": [ + "D", + "AH", + "K", + "S" + ], + "TURKEYS": [ + "T", + "ER", + "R", + "K", + "IY", + "Z" + ], + "TUESDAY": [ + "T", + "Y", + "UW", + "Z", + "D", + "EY" + ], + "CANBERRA": [ + "K", + "AE", + "N", + "B", + "ER", + "AH" + ], + "WOLF": [ + "W", + "UH", + "L", + "F" + ], + "SCARF": [ + "S", + "K", + "AA", + "R", + "F" + ], + "BALLON": [ + "B", + "AA", + "L", + "UH", + "NG" + ], + "CLIMBING": [ + "K", + "L", + "AY", + "M", + "IH", + "NG" + ], + "SYDNEY": [ + "S", + "IH", + "D", + "N", + "IY" + ], + "PAINTS": [ + "P", + "EY", + "N", + "T", + "S" + ], + "SCREAMING": [ + "S", + "K", + "R", + "IY", + "M", + "IH", + "NG" + ], + "SHOUTING": [ + "SH", + "AW", + "T", + "IH", + "NG" + ], + "BELIEF": [ + "B", + "IH", + "L", + "IY", + "F" + ], + "MILITARY": [ + "M", + "IH", + "L", + "AH", + "T", + "EH", + "R", + "IY" + ], + "FINISH": [ + "F", + "IH", + "N", + "IH", + "SH" + ], + "LAY": [ + "L", + "EY" + ], + "OFFICIAL": [ + "AH", + "F", + "IH", + "SH", + "L" + ], + "SURGEON": [ + "S", + "ER", + "JH", + "AH", + "N" + ], + "SUFFERERS": [ + "S", + "AH", + "F", + "ER", + "AH" + ], + "ERROR": [ + "EH", + "R", + "AH" + ], + "FACTOR": [ + "F", + "AE", + "K", + "T", + "ER" + ], + "PHYSICAL": [ + "F", + "IH", + "Z", + "IH", + "K", + "L" + ], + "RANK": [ + "R", + "AE", + "NG", + "K" + ], + "BOTTLE": [ + "B", + "AH", + "T", + "L" + ], + "ASH": [ + "AE", + "SH" + ], + "STRAIGHT": [ + "S", + "T", + "R", + "EY", + "T" + ], + "MOTIONED": [ + "M", + "OW", + "SH", + "N" + ], + "YARD": [ + "Y", + "AA", + "D" + ], + "TREASURE": [ + "T", + "R", + "EH", + "ZH", + "AH" + ], + "UPSET": [ + "AH", + "P", + "S", + "EH", + "T" + ], + "PUBLISHED": [ + "P", + "AH", + "B", + "L", + "IH", + "SH", + "T" + ], + "DETAILS": [ + "D", + "IH", + "T", + "EY", + "L", + "Z" + ], + "PREVIOUSLY": [ + "P", + "R", + "IY", + "V", + "IH", + "AH", + "S", + "L", + "IY" + ], + "LEADING": [ + "L", + "IY", + "D", + "IH", + "NG" + ], + "TRADITIONS": [ + "T", + "R", + "AH", + "D", + "IH", + "SH", + "N", + "Z" + ], + "TASK": [ + "T", + "AE", + "S", + "K" + ], + "SUPPORTING": [ + "S", + "AH", + "P", + "AO", + "T", + "IH", + "NG" + ], + "POUNDS": [ + "P", + "AW", + "N", + "D", + "Z" + ], + "STEAK": [ + "S", + "T", + "EY", + "K" + ], + "TIM'S": [ + "T", + "IH", + "M", + "S" + ], + "DV": [ + "D", + "IY", + "V", + "IY" + ], + "GARLIC": [ + "G", + "AA", + "L", + "IH", + "K" + ], + "TIMMY": [ + "T", + "IY", + "M", + "IY" + ], + "LOCKING": [ + "L", + "AH", + "K", + "IH", + "NG" + ], + "LILLY'S": [ + "L", + "IH", + "L", + "IY", + "S" + ], + "CARD": [ + "K", + "AA", + "D" + ], + "CONCERN": [ + "K", + "AH", + "N", + "S", + "ER", + "N" + ], + "MARKETING": [ + "M", + "AA", + "K", + "IH", + "T", + "IH", + "NG" + ], + "CREW": [ + "K", + "R", + "UW" + ], + "LATELY": [ + "L", + "EY", + "T", + "L", + "IY" + ], + "CELLS": [ + "S", + "EH", + "L", + "Z" + ], + "LIGHT'S": [ + "L", + "AY", + "T", + "S" + ], + "DESIGN": [ + "D", + "IH", + "Z", + "AY", + "N" + ], + "SPIRITED": [ + "S", + "P", + "IH", + "AH", + "IH", + "T", + "IH", + "D" + ], + "MASTERPIECE": [ + "M", + "AA", + "S", + "T", + "AH", + "P", + "IY", + "S" + ], + "KIDDING": [ + "K", + "IH", + "D", + "IH", + "NG" + ], + "OWNER": [ + "OW", + "N", + "AH" + ], + "LINES": [ + "L", + "AY", + "N", + "Z" + ], + "REWARD": [ + "R", + "IH", + "W", + "AO", + "R", + "D" + ], + "EXCITED": [ + "IH", + "K", + "S", + "AY", + "T", + "IH", + "D" + ], + "THANKED": [ + "TH", + "AE", + "NG", + "K", + "T" + ], + "COSTLY": [ + "K", + "AH", + "S", + "T", + "L", + "IY" + ], + "PREVAIL": [ + "P", + "R", + "IH", + "V", + "EY", + "L" + ], + "LEGAL": [ + "L", + "IY", + "G", + "L" + ], + "DRAMATIC": [ + "D", + "R", + "AH", + "M", + "AE", + "T", + "IH", + "K" + ], + "ORIGINAL": [ + "AH", + "R", + "IH", + "JH", + "AH", + "N", + "L" + ], + "DEPEND": [ + "D", + "IH", + "P", + "EH", + "N", + "D" + ], + "TAP": [ + "T", + "AE", + "P" + ], + "EXPLOSION": [ + "IH", + "K", + "S", + "P", + "L", + "OW", + "ZH", + "N" + ], + "MORALE": [ + "M", + "AH", + "R", + "AE", + "L" + ], + "OFFERED": [ + "AH", + "F", + "AH", + "D" + ], + "SALUTE": [ + "S", + "AH", + "L", + "UW", + "T" + ], + "INTEND": [ + "IH", + "N", + "T", + "EH", + "N", + "D" + ], + "CRITICAL": [ + "K", + "R", + "IH", + "T", + "IH", + "K", + "L" + ], + "CLEVER": [ + "K", + "L", + "EH", + "V", + "AH" + ], + "INTERESTS": [ + "IH", + "N", + "T", + "R", + "AH", + "S", + "T", + "S" + ], + "CURE": [ + "K", + "Y", + "UH", + "AH" + ], + "WAKES": [ + "W", + "EY", + "K", + "S" + ], + "BIKING": [ + "B", + "AY", + "K", + "IH", + "NG" + ], + "PETER'S": [ + "P", + "IY", + "T", + "ER", + "S" + ], + "MIKE'S": [ + "M", + "AY", + "K", + "S" + ], + "SHINY": [ + "SH", + "AY", + "N", + "IY" + ], + "HEY": [ + "HH", + "EY" + ], + "ENGLISH": [ + "IH", + "NG", + "G", + "L", + "IH", + "SH" + ], + "FAMOUS": [ + "F", + "EY", + "M", + "AH", + "S" + ], + "GRANDMA": [ + "G", + "R", + "AE", + "N", + "M", + "AA" + ], + "O": [ + "OW" + ], + "BROTHER'S": [ + "B", + "R", + "AH", + "DH", + "ER", + "S" + ], + "SMOKE": [ + "S", + "M", + "OW", + "K" + ], + "FAULTED": [ + "F", + "AO", + "L", + "T", + "IH", + "D" + ], + "DEFENDANTS": [ + "D", + "IH", + "F", + "EH", + "N", + "D", + "AH", + "N", + "T", + "S" + ], + "MIRROR": [ + "M", + "IH", + "AH", + "AH" + ], + "FLOAT": [ + "F", + "L", + "OW", + "T" + ], + "HATE": [ + "HH", + "EY", + "T" + ], + "RUGBY": [ + "R", + "AH", + "G", + "B", + "IY" + ], + "OCTOBER": [ + "AH", + "K", + "T", + "OW", + "B", + "AH" + ], + "LOWEN'S": [ + "L", + "OW", + "AH", + "N", + "Z" + ], + "PANT": [ + "P", + "AE", + "N", + "T" + ], + "WETTER": [ + "W", + "EH", + "T", + "ER" + ], + "GARS": [ + "G", + "AA", + "R", + "S" + ], + "RAW": [ + "R", + "AO" + ], + "TAX": [ + "T", + "AE", + "K", + "S" + ], + "SUPER": [ + "S", + "UW", + "P", + "ER" + ], + "SNACKED": [ + "S", + "N", + "AE", + "K" + ], + "PENT": [ + "P", + "EH", + "N", + "T" + ], + "GRIFT": [ + "G", + "R", + "IH", + "F", + "T" + ], + "CHARM": [ + "CH", + "AA", + "M" + ], + "VANS": [ + "V", + "AE", + "N", + "Z" + ], + "KEYED": [ + "K", + "IY", + "D" + ], + "FLOWERS": [ + "F", + "L", + "AW", + "ER", + "Z" + ], + "NOSES": [ + "N", + "OW", + "Z", + "IH", + "Z" + ], + "MINIMUM": [ + "M", + "IH", + "N", + "IH", + "M", + "AH", + "M" + ], + "SPEAKER": [ + "S", + "P", + "IY", + "K", + "ER" + ], + "ABROAD": [ + "AH", + "B", + "R", + "AO", + "D" + ], + "EDITOR": [ + "EH", + "D", + "IH", + "T", + "ER" + ], + "POWERFUL": [ + "P", + "AW", + "AH", + "F", + "L" + ], + "RECOVER": [ + "R", + "IH", + "K", + "AH", + "V", + "ER" + ], + "REVOLUTION": [ + "R", + "EH", + "V", + "AH", + "L", + "UW", + "SH", + "N" + ], + "CHILL": [ + "CH", + "IH", + "L" + ], + "FIGURE": [ + "F", + "IH", + "G", + "AH" + ], + "BRITISH": [ + "B", + "R", + "IH", + "T", + "IH", + "SH" + ], + "PREMIERE": [ + "P", + "R", + "EH", + "M", + "IY", + "EH", + "R" + ], + "CATCH": [ + "K", + "AE", + "CH" + ], + "JETS": [ + "JH", + "EH", + "T", + "S" + ], + "APOLOGIZE": [ + "AH", + "P", + "AH", + "L", + "AH", + "JH", + "AY", + "Z" + ], + "EXTRA": [ + "EH", + "K", + "S", + "T", + "R", + "AH" + ], + "STATUE": [ + "S", + "T", + "AE", + "CH", + "UW" + ], + "SOCIAL": [ + "S", + "OW", + "SH", + "L" + ], + "SNOWSTORM": [ + "S", + "N", + "OW", + "S", + "T", + "AO", + "M" + ], + "REPLACE": [ + "R", + "IH", + "P", + "L", + "EY", + "S" + ], + "SETTING": [ + "S", + "EH", + "T", + "IH", + "NG" + ], + "MOTIVE": [ + "M", + "OW", + "T", + "IH", + "V" + ], + "IMMEDIATE": [ + "IH", + "M", + "IY", + "D", + "IH", + "AH", + "T" + ], + "COMMENT": [ + "K", + "AH", + "M", + "EH", + "N", + "T" + ], + "ATTEMPTING": [ + "AH", + "T", + "EH", + "M", + "P", + "T" + ], + "THURSDAY": [ + "TH", + "ER", + "Z", + "D", + "EY" + ], + "YEAR'S": [ + "Y", + "IH", + "AH", + "R", + "S" + ], + "DEBATE": [ + "D", + "IH", + "B", + "EY", + "T" + ], + "FORM": [ + "F", + "AO", + "M" + ], + "SELFISHNESS": [ + "S", + "EH", + "L", + "F", + "IH", + "SH", + "N", + "AH", + "S" + ], + "SHAPE": [ + "SH", + "EY", + "P" + ], + "PRECIOUS": [ + "P", + "R", + "EH", + "SH", + "AH", + "S" + ], + "PARCEL": [ + "P", + "AA", + "S", + "L" + ], + "MANAGEMENT": [ + "M", + "AE", + "N", + "IH", + "JH", + "M", + "AH", + "N", + "T" + ], + "STRIKES": [ + "S", + "T", + "R", + "AY", + "K", + "S" + ], + "AFRICA": [ + "AE", + "F", + "R", + "IH", + "K", + "AH" + ], + "GLIMPSE": [ + "G", + "L", + "IH", + "M", + "P", + "S" + ], + "MIRACLE": [ + "M", + "IH", + "AH", + "AH", + "K", + "L" + ], + "PROFESSOR": [ + "P", + "R", + "AH", + "F", + "EH", + "S", + "ER" + ], + "SHEETS": [ + "SH", + "IY", + "T", + "S" + ], + "DOUBTS": [ + "D", + "AW", + "T", + "S" + ], + "HATS": [ + "HH", + "AE", + "T", + "S" + ], + "BUTTONS": [ + "B", + "AH", + "T", + "N", + "Z" + ], + "BALLOONS": [ + "B", + "AH", + "L", + "UW", + "N", + "Z" + ], + "INTERNATIONAL": [ + "IH", + "N", + "T", + "ER", + "N", + "AE", + "SH", + "N", + "AH", + "L" + ], + "REPORTED": [ + "R", + "IH", + "P", + "AO", + "T", + "IH", + "D" + ], + "GUARDED": [ + "G", + "AA", + "R", + "D", + "IH", + "D" + ], + "DEADLY": [ + "D", + "EH", + "D", + "L", + "IY" + ], + "MEANWHILE": [ + "M", + "IY", + "N", + "W", + "AY", + "L" + ], + "ROAST": [ + "R", + "OW", + "S", + "T" + ], + "NUCLEAR": [ + "N", + "Y", + "UW", + "K", + "L", + "IH", + "AH" + ], + "PROTEST": [ + "P", + "R", + "OW", + "T", + "EH", + "S", + "T" + ], + "PITCH": [ + "P", + "IH", + "CH" + ], + "RIDICULOUS": [ + "R", + "IH", + "D", + "IH", + "K", + "Y", + "AH", + "L", + "AH", + "S" + ], + "PHOTOGRAPHERS": [ + "F", + "AH", + "T", + "AA", + "G", + "R", + "AH", + "F", + "ER", + "S" + ], + "EARTHQUAKE": [ + "ER", + "TH", + "K", + "W", + "EY", + "K" + ], + "OPENING": [ + "OW", + "P", + "AH", + "N", + "IH", + "NG" + ], + "DISMISSED": [ + "D", + "IH", + "S", + "M", + "IH", + "S", + "T" + ], + "AFFECTIES": [ + "AH", + "F", + "EH", + "K", + "T", + "IY", + "Z" + ], + "CONCLUSION": [ + "K", + "AH", + "N", + "K", + "L", + "UW", + "ZH", + "N" + ], + "OIL": [ + "OY", + "L" + ], + "PRICES": [ + "P", + "R", + "AY", + "S", + "IY", + "Z" + ], + "SHARPLY": [ + "SH", + "AA", + "P", + "L", + "IY" + ], + "LEAGUE": [ + "L", + "IY", + "G" + ], + "THREAD": [ + "TH", + "R", + "EH", + "D" + ], + "ATTENDANT": [ + "AH", + "T", + "EH", + "N", + "D", + "AH", + "N", + "T" + ], + "MEMORY": [ + "M", + "EH", + "M", + "ER", + "IY" + ], + "FATHERS": [ + "F", + "AA", + "DH", + "ER", + "Z" + ], + "TRANSFERRED": [ + "T", + "R", + "AE", + "N", + "S", + "F", + "ER", + "D" + ], + "WAD": [ + "W", + "AH", + "D" + ], + "GOODS": [ + "G", + "UH", + "D", + "Z" + ], + "COLDS": [ + "K", + "OW", + "L", + "D", + "Z" + ], + "WORKS": [ + "W", + "ER", + "K", + "S" + ], + "SEVENTH": [ + "S", + "EH", + "V", + "N", + "TH" + ], + "CARED": [ + "K", + "EH", + "R", + "D" + ], + "KNIFE": [ + "N", + "AY", + "F" + ], + "DATES": [ + "D", + "EY", + "T", + "S" + ], + "WINDY": [ + "W", + "IH", + "N", + "D", + "IY" + ], + "RAINY": [ + "R", + "EY", + "N", + "IY" + ], + "ELL": [ + "EH", + "L" + ], + "TAME": [ + "T", + "EY", + "M" + ], + "FAILING": [ + "F", + "EY", + "L", + "IH", + "NG" + ], + "HILL": [ + "HH", + "IH", + "L" + ], + "CLOUDS": [ + "K", + "L", + "AW", + "D", + "Z" + ], + "STORIES": [ + "S", + "T", + "AO", + "R", + "IH", + "Z" + ], + "RIGHTED": [ + "R", + "AY", + "T" + ], + "FASTER": [ + "F", + "AH", + "S", + "T", + "AH" + ], + "WET": [ + "W", + "EH", + "T" + ], + "TIRE": [ + "T", + "AY", + "AH", + "R" + ], + "PAIR": [ + "P", + "EH", + "R" + ], + "MARCHED": [ + "M", + "AA", + "CH" + ], + "PANS": [ + "P", + "AE", + "N", + "Z" + ], + "MEETINGS": [ + "M", + "IY", + "T", + "IY", + "NG", + "Z" + ], + "FUR": [ + "F", + "ER" + ], + "LADY": [ + "L", + "EY", + "D", + "IY" + ], + "LIKENESS": [ + "L", + "AY", + "K", + "N", + "AH", + "S" + ], + "ASKING": [ + "AA", + "S", + "K", + "IH", + "NG" + ], + "PLAYS": [ + "P", + "L", + "EY", + "Z" + ], + "EARLIER": [ + "ER", + "L", + "IH", + "AH" + ], + "OFTENER": [ + "AH", + "F", + "N", + "ER" + ], + "PALACE": [ + "P", + "AE", + "L", + "AH", + "S" + ], + "WROTE": [ + "R", + "OW", + "T" + ], + "WONDERS": [ + "W", + "AH", + "N", + "D", + "ER" + ], + "GAVE": [ + "G", + "EY", + "V" + ], + "MILK": [ + "M", + "IH", + "L", + "K" + ], + "MR": [ + "M", + "IH", + "S", + "T", + "ER" + ], + "WRIGHT": [ + "R", + "AY", + "T" + ], + "ASKS": [ + "AA", + "S", + "K", + "S" + ], + "PUSHING": [ + "P", + "UH", + "SH", + "IH", + "NG" + ], + "FACES": [ + "F", + "EY", + "S", + "IH", + "Z" + ], + "DREAMED": [ + "D", + "R", + "IY", + "M", + "D" + ], + "WISHES": [ + "W", + "IH", + "SH", + "IH", + "Z" + ], + "ROADS": [ + "R", + "OW", + "D", + "Z" + ], + "QUIRT": [ + "K", + "W", + "ER", + "T" + ], + "PROMISE": [ + "P", + "R", + "AH", + "M", + "IH", + "S" + ], + "TEMPLE": [ + "T", + "EH", + "M", + "P", + "L" + ], + "STAIRS": [ + "S", + "T", + "EH", + "R", + "Z" + ], + "RATHER": [ + "R", + "AE", + "DH", + "ER" + ], + "COULDN'T": [ + "K", + "UH", + "D", + "N", + "T" + ], + "SEEMING": [ + "S", + "IY", + "M", + "IH", + "NG" + ], + "RING": [ + "R", + "IH", + "NG" + ], + "LAZY": [ + "L", + "EY", + "Z", + "IY" + ], + "TENTH": [ + "T", + "EH", + "N", + "TH" + ], + "MEDICINE": [ + "M", + "EH", + "D", + "IH", + "S", + "N" + ], + "HIDE": [ + "HH", + "AY", + "D" + ], + "EXCEPTION": [ + "IH", + "K", + "S", + "EH", + "P", + "SH", + "N" + ], + "SUPPORT": [ + "S", + "AH", + "P", + "AO", + "R", + "T" + ], + "CARELESS": [ + "K", + "EH", + "R", + "L", + "AH", + "S" + ], + "AMERICA'S": [ + "AH", + "M", + "EH", + "R", + "IH", + "K", + "AH", + "S" + ], + "NAMES": [ + "N", + "EY", + "M", + "Z" + ], + "REMAINING": [ + "R", + "IH", + "M", + "EY", + "N", + "IH", + "NG" + ], + "BURNING": [ + "B", + "ER", + "N", + "IH", + "NG" + ], + "SENDS": [ + "S", + "EH", + "N", + "D", + "Z" + ], + "SUCCEED": [ + "S", + "AH", + "K", + "S", + "IY", + "D" + ], + "UNLESS": [ + "AH", + "N", + "L", + "EH", + "S" + ], + "FOOLS": [ + "F", + "UW", + "L", + "Z" + ], + "NOISE": [ + "N", + "OY", + "Z" + ], + "COVERED": [ + "K", + "AH", + "V", + "ER", + "D" + ], + "FURNITURE": [ + "F", + "ER", + "N", + "IH", + "CH", + "ER" + ], + "ORDERS": [ + "AH", + "R", + "D", + "ER", + "S" + ], + "LIFTED": [ + "L", + "IH", + "F", + "T", + "IH", + "D" + ], + "KISSED": [ + "K", + "IH", + "S", + "T" + ], + "PRIZE": [ + "P", + "R", + "AY", + "Z" + ], + "REGARD": [ + "R", + "IH", + "G", + "AA", + "R", + "D" + ], + "BEAUTY": [ + "B", + "Y", + "UW", + "T", + "IY" + ], + "SWING": [ + "S", + "W", + "IH", + "NG" + ], + "ROPE": [ + "R", + "OW", + "P" + ], + "SPEECH": [ + "S", + "P", + "IY", + "CH" + ], + "HERSELF": [ + "HH", + "ER", + "S", + "EH", + "L", + "F" + ], + "PREPARATION": [ + "P", + "R", + "EH", + "P", + "AH", + "R", + "EY", + "SH", + "N" + ], + "ACTING": [ + "AE", + "K", + "T", + "IH", + "NG" + ], + "CERTAIN": [ + "S", + "ER", + "T", + "N" + ], + "GENTLEMAN": [ + "JH", + "EH", + "N", + "T", + "L", + "M", + "AH", + "N" + ], + "JEST": [ + "JH", + "EH", + "S", + "T" + ], + "INSTANCE": [ + "IH", + "N", + "S", + "T", + "AH", + "N", + "S" + ], + "CHICKENS": [ + "CH", + "IH", + "K", + "IH", + "N", + "Z" + ], + "LEGS": [ + "L", + "EH", + "G", + "Z" + ], + "EVENT": [ + "IH", + "V", + "EH", + "N", + "T" + ], + "SITS": [ + "S", + "IH", + "T", + "S" + ], + "SINK": [ + "S", + "IH", + "NG", + "K" + ], + "AGREEMENT": [ + "AH", + "G", + "R", + "IY", + "M", + "AH", + "N", + "T" + ], + "LIFT": [ + "L", + "IH", + "F", + "T" + ], + "DRESSED": [ + "D", + "R", + "EH", + "S", + "T" + ], + "DOWNSTAIRS": [ + "D", + "AW", + "N", + "S", + "T", + "EH", + "R", + "Z" + ], + "SIGNED": [ + "S", + "AY", + "N", + "D" + ], + "DIRECTION": [ + "D", + "AH", + "R", + "EH", + "K", + "SH", + "N" + ], + "SPARED": [ + "S", + "P", + "EH", + "R", + "D" + ], + "GETS": [ + "G", + "EH", + "T", + "S" + ], + "CONSIDERATIONS": [ + "K", + "AH", + "N", + "S", + "IH", + "D", + "AH", + "R", + "EY", + "SH", + "N", + "Z" + ], + "GUILTY": [ + "G", + "IH", + "L", + "T", + "IY" + ], + "WEIGH": [ + "W", + "EY" + ], + "OFFERS": [ + "AO", + "F", + "ER", + "Z" + ], + "BOWED": [ + "B", + "OW", + "D" + ], + "DUTY": [ + "D", + "Y", + "UW", + "T", + "IY" + ], + "ADVERTISEMENT": [ + "AH", + "D", + "V", + "ER", + "T", + "IH", + "S", + "M", + "AH", + "N", + "T" + ], + "STERN": [ + "S", + "T", + "ER", + "N" + ], + "STARING": [ + "S", + "T", + "EH", + "R", + "IH", + "NG" + ], + "COOK": [ + "K", + "UH", + "K" + ], + "SOMEWHERE": [ + "S", + "AH", + "M", + "W", + "EH", + "R" + ], + "CONFUSION": [ + "K", + "AH", + "N", + "F", + "Y", + "UW", + "ZH", + "N" + ], + "SUPPOSE": [ + "S", + "AH", + "P", + "OW", + "Z" + ], + "WORKMAN": [ + "W", + "ER", + "K", + "M", + "AH", + "N" + ], + "PATTED": [ + "P", + "AE", + "T", + "IH", + "D" + ], + "HIDING": [ + "HH", + "AY", + "D", + "IH", + "NG" + ], + "WAVE": [ + "W", + "EY", + "V" + ] +} diff --git a/assets/runtime_sources.json b/assets/runtime_sources.json new file mode 100644 index 0000000000000000000000000000000000000000..04550501f4397717453d62230bf7350a92122086 --- /dev/null +++ b/assets/runtime_sources.json @@ -0,0 +1,74 @@ +{ + "schema": 1, + "sources": [ + { + "kind": "hub", + "repo_id": "charsiu/en_w2v2_tiny_fc_10ms", + "revision": "8272e6ec07582696d212c2b15bdd271c92ae64ee", + "filename": "config.json", + "destination": "charsiu/model/config.json", + "sha256": "49b4e164f0375c7b0eaab8cf4d9727a20f1060e73bf0d899e2442ae95f70cae4", + "bytes": 1522 + }, + { + "kind": "hub", + "repo_id": "charsiu/en_w2v2_tiny_fc_10ms", + "revision": "8272e6ec07582696d212c2b15bdd271c92ae64ee", + "filename": "pytorch_model.bin", + "destination": "charsiu/model/pytorch_model.bin", + "sha256": "a5b59d8cc3c548382dbc38c48d537b0bb520b9a67d2fafef2afee7740f9ce0c7", + "bytes": 93368972 + }, + { + "kind": "hub", + "repo_id": "charsiu/tokenizer_en_cmu", + "revision": "10507401aedf5e0aba164128535b49225ff95260", + "filename": "vocab.json", + "destination": "charsiu/tokenizer/vocab.json", + "sha256": "781514e251e9615ea4a05bbf3760ffcf8ec2ebe67355f411177ea64b0602d897", + "bytes": 403 + }, + { + "kind": "hub", + "repo_id": "charsiu/tokenizer_en_cmu", + "revision": "10507401aedf5e0aba164128535b49225ff95260", + "filename": "tokenizer_config.json", + "destination": "charsiu/tokenizer/tokenizer_config.json", + "sha256": "56e02b54de01a0ec4cc0c705ad3c303d7b73c83d61063a94b84cbf3a55da76a1", + "bytes": 180 + }, + { + "kind": "hub", + "repo_id": "charsiu/tokenizer_en_cmu", + "revision": "10507401aedf5e0aba164128535b49225ff95260", + "filename": "special_tokens_map.json", + "destination": "charsiu/tokenizer/special_tokens_map.json", + "sha256": "50eb73d51191696209d30d42d6ede50e57e7a542ca1db12df714b2c0aa3da8e2", + "bytes": 85 + }, + { + "kind": "zip", + "url": "https://raw.githubusercontent.com/nltk/nltk_data/550b6625bcef1f2abff2ff770a5a0d272c9c6b2a/packages/corpora/cmudict.zip", + "destination": "assets/nltk_data/corpora/cmudict.zip", + "extract_to": "assets/nltk_data/corpora", + "sha256": "d07cca47fd72ad32ea9d8ad1219f85301eeaf4568f8b6b73747506a71fb5afd6", + "bytes": 896069 + }, + { + "kind": "zip", + "url": "https://raw.githubusercontent.com/nltk/nltk_data/550b6625bcef1f2abff2ff770a5a0d272c9c6b2a/packages/taggers/averaged_perceptron_tagger.zip", + "destination": "assets/nltk_data/taggers/averaged_perceptron_tagger.zip", + "extract_to": "assets/nltk_data/taggers", + "sha256": "e1f13cf2532daadfd6f3bc481a49859f0b8ea6432ccdcd83e6a49a5f19008de9", + "bytes": 2526731 + }, + { + "kind": "zip", + "url": "https://raw.githubusercontent.com/nltk/nltk_data/550b6625bcef1f2abff2ff770a5a0d272c9c6b2a/packages/taggers/averaged_perceptron_tagger_eng.zip", + "destination": "assets/nltk_data/taggers/averaged_perceptron_tagger_eng.zip", + "extract_to": "assets/nltk_data/taggers", + "sha256": "6025f530624335c67d6547d44757b357b4e79bae030a0383e9887a92c1718f0b", + "bytes": 1539115 + } + ] +} diff --git a/bundle_manifest.json b/bundle_manifest.json deleted file mode 100644 index a1598f78ff7cb8d275c6d7621bfd3d1a9b64b4f2..0000000000000000000000000000000000000000 --- a/bundle_manifest.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "repo_id": "faeea/custom-gopt-252-eval", - "description": "Bundle of the v6 ASR-confidence Streaming GOPT checkpoint plus the Whisper and Charsiu models required by the local evaluation pipeline.", - "artifacts": [ - { - "path": "streaming_gopt_best/best_audio_model.pth", - "type": "streaming_gopt_weights", - "purpose": "Pronunciation scoring model selected by validation phone MSE." - }, - { - "path": "streaming_gopt_best/config.json", - "type": "streaming_gopt_config", - "purpose": "Network shape and training arguments used to restore the v6 ASR-confidence model." - }, - { - "path": "streaming_gopt_best/result.csv", - "type": "training_metrics", - "purpose": "Per-epoch train/validation metrics." - }, - { - "path": "streaming_gopt_best/test_metrics.json", - "type": "test_metrics", - "purpose": "Held-out test metrics for the best validation checkpoint." - }, - { - "path": "streaming_gopt_best/inference_assets.json", - "type": "inference_metadata", - "purpose": "Normalization stats, feature dimension, and phone-id mapping required for one-audio local inference." - }, - { - "path": "whisper_best_model", - "type": "transformers_whisper_model", - "purpose": "ASR model used to build ASR-driven GOPT chunks." - }, - { - "path": "charsiu_en_w2v2_tiny_fc_10ms", - "type": "charsiu_aligner_model", - "purpose": "Frame-level phone alignment model used by preprocessing and inference." - }, - { - "path": "examples/infer_one_audio.py", - "type": "example_script", - "purpose": "Minimal one-audio local inference script that prints utterance-level scores." - }, - { - "path": "examples/eval_streaming_gopt_test.py", - "type": "example_script", - "purpose": "Minimal evaluation script for val/test split using the bundled best GOPT checkpoint." - } - ], - "model_outputs": { - "utterance": [ - "accuracy", - "completeness", - "fluency", - "prosodic", - "total" - ], - "phone": [ - "phone pronunciation score" - ], - "word": [ - "accuracy", - "stress", - "total", - "asr_accuracy" - ], - "word_asr_accuracy_note": "The word-level ASR accuracy score can be used as an auxiliary indicator of whether the word was read correctly." - }, - "best_validation_summary": { - "selection_metric": "phone_val_mse", - "best_epoch": 11, - "phone_val_mse": 0.04760764539241791, - "phone_val_pcc": 0.34831968338670993, - "utt_val_pcc_total": 0.661865583803676, - "word_val_pcc_total": 0.3418123225833971, - "word_val_pcc_asr_accuracy": 0.3633849619530143 - }, - "test_summary": { - "phone_test_mse": 0.04919730871915817, - "phone_test_pcc": 0.3975705055993251, - "utt_test_pcc": [ - 0.651909193610124, - 0.012690043750859805, - 0.7249977587357453, - 0.7332794084754206, - 0.681940037784353 - ], - "word_test_pcc": [ - 0.4047142491023989, - -0.0039119825110344765, - 0.4122583381095728, - 0.41746734262039764 - ], - "word_score_names": [ - "accuracy", - "stress", - "total", - "asr_accuracy" - ] - }, - "code_dependencies": { - "custom_gopt_repo": "https://github.com/hf49w/custom-gopt.git", - "charsiu_repo": "https://github.com/lingjzhu/charsiu", - "charsiu_repo_commit": "13a69f2a22ca0c0962b75cc693399b0ae23a12c9" - } -} diff --git a/charsiu_en_w2v2_tiny_fc_10ms/config.json b/charsiu_en_w2v2_tiny_fc_10ms/config.json deleted file mode 100644 index d375873e325eb6e006317647778391ebe9aea4f1..0000000000000000000000000000000000000000 --- a/charsiu_en_w2v2_tiny_fc_10ms/config.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "activation_dropout": 0.1, - "apply_spec_augment": true, - "architectures": [ - "Wav2Vec2ForFrameClassification" - ], - "attention_dropout": 0.1, - "bos_token_id": 1, - "codevector_dim": 256, - "contrastive_logits_temperature": 0.1, - "conv_bias": false, - "conv_dim": [ - 512, - 512, - 512, - 512, - 512, - 512, - 512 - ], - "conv_kernel": [ - 10, - 3, - 3, - 3, - 3, - 2, - 2 - ], - "conv_stride": [ - 5, - 2, - 2, - 2, - 2, - 2, - 1 - ], - "ctc_loss_reduction": "sum", - "ctc_zero_infinity": false, - "diversity_loss_weight": 0.1, - "do_stable_layer_norm": false, - "eos_token_id": 2, - "feat_extract_activation": "gelu", - "feat_extract_norm": "group", - "feat_proj_dropout": 0.1, - "feat_quantizer_dropout": 0.0, - "final_dropout": 0.1, - "gradient_checkpointing": false, - "hidden_act": "gelu", - "hidden_dropout": 0.1, - "hidden_size": 384, - "initializer_range": 0.02, - "intermediate_size": 3072, - "layer_norm_eps": 1e-05, - "layerdrop": 0.1, - "mask_feature_length": 10, - "mask_feature_prob": 0.0, - "mask_time_length": 10, - "mask_time_prob": 0.05, - "model_type": "wav2vec2", - "num_attention_heads": 6, - "num_codevector_groups": 2, - "num_codevectors_per_group": 320, - "num_conv_pos_embedding_groups": 16, - "num_conv_pos_embeddings": 128, - "num_feat_extract_layers": 7, - "num_hidden_layers": 6, - "num_negatives": 100, - "pad_token_id": 0, - "proj_codevector_dim": 256, - "torch_dtype": "float32", - "transformers_version": "4.9.0", - "vocab_size": 42 -} diff --git a/charsiu_en_w2v2_tiny_fc_10ms/preprocessor_config.json b/charsiu_en_w2v2_tiny_fc_10ms/preprocessor_config.json deleted file mode 100644 index a05a475a6970fb263cfb3279b401dd38eff88ba4..0000000000000000000000000000000000000000 --- a/charsiu_en_w2v2_tiny_fc_10ms/preprocessor_config.json +++ /dev/null @@ -1 +0,0 @@ -Entry not found \ No newline at end of file diff --git a/charsiu_en_w2v2_tiny_fc_10ms/pytorch_model.bin b/charsiu_en_w2v2_tiny_fc_10ms/pytorch_model.bin deleted file mode 100644 index cfe97daee519720d726e7c138504eaf0d1026e2d..0000000000000000000000000000000000000000 --- a/charsiu_en_w2v2_tiny_fc_10ms/pytorch_model.bin +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a5b59d8cc3c548382dbc38c48d537b0bb520b9a67d2fafef2afee7740f9ce0c7 -size 93368972 diff --git a/examples/eval_streaming_gopt_test.py b/examples/eval_streaming_gopt_test.py deleted file mode 100644 index b4419ad19b0471941023a9e79323df08722081c9..0000000000000000000000000000000000000000 --- a/examples/eval_streaming_gopt_test.py +++ /dev/null @@ -1,119 +0,0 @@ -import argparse -import json -import sys -from pathlib import Path - -import torch - - -def get_args(): - parser = argparse.ArgumentParser( - description="Evaluate the bundled Streaming GOPT checkpoint on a prepared val/test split." - ) - parser.add_argument("--data-dir", type=Path, required=True, help="Directory containing *_chunks.npz and metadata.json.") - parser.add_argument("--model-dir", type=Path, required=True, help="Directory containing best_audio_model.pth and config.json.") - parser.add_argument("--repo-src", type=Path, required=True, help="Path to custom-gopt/src.") - parser.add_argument("--split", type=str, default="test", choices=["val", "test", "train"]) - parser.add_argument("--device", type=str, default=None, help="cuda / cuda:0 / cpu. Defaults to cuda if available.") - parser.add_argument("--output-json", type=Path, default=None) - parser.add_argument("--main-context-tokens", type=int, default=None, help="Override evaluation main context tokens.") - parser.add_argument("--right-context-tokens", type=int, default=None, help="Override evaluation right context tokens.") - return parser.parse_args() - - -def load_summary(data_dir, model_dir, repo_src, split, device_name, main_context_tokens=None, right_context_tokens=None): - sys.path.insert(0, str(repo_src)) - - from models import StreamingGOPT, StreamingGOPTNoPhn - from train_streaming_charsiu import StreamingChunkDataset, load_model_state, make_loader, validate - - metadata = json.loads((data_dir / "metadata.json").read_text(encoding="utf-8")) - cfg = json.loads((model_dir / "config.json").read_text(encoding="utf-8")) - args_dict = cfg["args"] - - class Args: - pass - - args = Args() - for key, value in args_dict.items(): - setattr(args, key, value) - - args.main_context_token_choices = args_dict.get("main_context_token_choices") or [ - int(item.strip()) for item in str(args_dict["main_context_tokens"]).split(",") if item.strip() - ] - args.right_context_token_choices = args_dict.get("right_context_token_choices") or [ - int(item.strip()) for item in str(args_dict["right_context_tokens"]).split(",") if item.strip() - ] - - device = torch.device(device_name or ("cuda" if torch.cuda.is_available() else "cpu")) - if getattr(args, "tf32", False) and device.type == "cuda": - if hasattr(torch, "set_float32_matmul_precision"): - torch.set_float32_matmul_precision("high") - torch.backends.cuda.matmul.allow_tf32 = True - torch.backends.cudnn.allow_tf32 = True - - dataset = StreamingChunkDataset(split, data_dir, metadata, final_only=(split != "train")) - loader = make_loader(dataset, len(dataset), False, int(getattr(args, "num_workers", 0))) - - model_cls = StreamingGOPT if args_dict["model"] == "streaming_gopt" else StreamingGOPTNoPhn - model = model_cls( - embed_dim=int(args_dict["embed_dim"]), - num_heads=int(args_dict["heads"]), - depth=int(args_dict["depth"]), - input_dim=int(cfg["input_dim"]), - seq_len=int(cfg["seq_len"]), - phn_num=int(cfg["phn_num"]), - ) - - state = torch.load(model_dir / "best_audio_model.pth", map_location=device) - load_model_state(model, state) - model = model.to(device) - model.eval() - - eval_main_context = int(main_context_tokens if main_context_tokens is not None else max(args.main_context_token_choices)) - eval_right_context = int(right_context_tokens if right_context_tokens is not None else max(args.right_context_token_choices)) - - mse, corr, utt_mse, utt_corr, word_mse, word_corr = validate( - model, - loader, - args, - -1, - device, - eval_main_context, - eval_right_context, - ) - - return { - "split": split, - "device": str(device), - "main_context_tokens": eval_main_context, - "right_context_tokens": eval_right_context, - "phone_mse": float(mse), - "phone_pcc": float(corr), - "utt_mse": [float(x) for x in utt_mse], - "utt_pcc": [float(x) for x in utt_corr], - "word_mse": [float(x) for x in word_mse], - "word_pcc": [float(x) for x in word_corr], - } - - -def main(): - args = get_args() - summary = load_summary( - data_dir=args.data_dir, - model_dir=args.model_dir, - repo_src=args.repo_src, - split=args.split, - device_name=args.device, - main_context_tokens=args.main_context_tokens, - right_context_tokens=args.right_context_tokens, - ) - payload = json.dumps(summary, ensure_ascii=False, indent=2) - print(payload) - if args.output_json is not None: - args.output_json.parent.mkdir(parents=True, exist_ok=True) - args.output_json.write_text(payload, encoding="utf-8") - - -if __name__ == "__main__": - main() diff --git a/examples/infer_one_audio.py b/examples/infer_one_audio.py deleted file mode 100644 index aae843df5afe9ae9b844a1cf527301c56113907e..0000000000000000000000000000000000000000 --- a/examples/infer_one_audio.py +++ /dev/null @@ -1,395 +0,0 @@ -import argparse -import json -import sys -import warnings -from pathlib import Path - -import numpy as np -import torch - - -SCORE_NAMES = ["accuracy", "completeness", "fluency", "prosodic", "total"] - - -def get_args(): - parser = argparse.ArgumentParser( - description="Run one-audio inference with the bundled Whisper + Charsiu + Streaming GOPT pipeline." - ) - parser.add_argument("--audio", type=Path, required=True, help="Path to one wav audio file.") - parser.add_argument("--bundle-dir", type=Path, default=Path(__file__).resolve().parents[1]) - parser.add_argument("--repo-root", type=Path, required=True, help="Path to the cloned custom-gopt repository root.") - parser.add_argument("--charsiu-src-dir", type=Path, required=True, help="Path to the official Charsiu repo root or its src directory.") - parser.add_argument("--device", type=str, default=None, help="cuda / cuda:0 / cpu. Defaults to cuda if available.") - parser.add_argument("--output-json", type=Path, default=None) - parser.add_argument("--main-context-tokens", type=int, default=None) - parser.add_argument("--right-context-tokens", type=int, default=None) - return parser.parse_args() - - -def add_repo_paths(repo_root): - repo_src = repo_root / "src" - prep_src = repo_src / "prep_data" - for path in [repo_src, prep_src]: - path_str = str(path) - if path_str not in sys.path: - sys.path.insert(0, path_str) - - -def load_asr_pipeline(whisper_model_dir, device): - from transformers import pipeline - from transformers.utils import logging as hf_logging - - hf_logging.set_verbosity_error() - - if str(device).startswith("cuda"): - pipe_device = int(str(device).split(":", 1)[1]) if ":" in str(device) else 0 - torch_dtype = torch.float16 - else: - pipe_device = -1 - torch_dtype = torch.float32 - - pipe = pipeline( - "automatic-speech-recognition", - model=str(whisper_model_dir), - tokenizer=str(whisper_model_dir), - feature_extractor=str(whisper_model_dir), - framework="pt", - device=pipe_device, - dtype=torch_dtype, - ) - if hasattr(pipe.model, "generation_config"): - pipe.model.generation_config.use_cache = False - kwargs = { - "return_timestamps": "word", - "generate_kwargs": { - "language": "english", - "task": "transcribe", - "max_new_tokens": 128, - "use_cache": False, - }, - } - return pipe, kwargs - - -def load_audio_for_asr(audio_path, sample_rate): - import librosa - import soundfile as sf - - audio, sr = sf.read(str(audio_path)) - if audio.ndim > 1: - audio = audio.mean(axis=1) - audio = np.asarray(audio, dtype=np.float32) - if sr != sample_rate: - audio = librosa.resample(audio, orig_sr=sr, target_sr=sample_rate) - sr = sample_rate - return audio, sr - - -def transcribe_audio(asr_pipe, pipe_kwargs, audio_path, sample_rate, normalize_word): - audio, sr = load_audio_for_asr(audio_path, sample_rate) - result = asr_pipe({"raw": audio, "sampling_rate": sr}, **pipe_kwargs) - transcript = (result.get("text") or "").strip() - words = [] - for chunk in result.get("chunks", []): - text = normalize_word(chunk.get("text", "")) - timestamp = chunk.get("timestamp") or (None, None) - if not text or timestamp[0] is None or timestamp[1] is None: - continue - words.append( - { - "text": text, - "start": float(timestamp[0]), - "end": float(timestamp[1]), - } - ) - return transcript, words - - -def load_model(model_dir, repo_root, device): - add_repo_paths(repo_root) - from models import StreamingGOPT, StreamingGOPTNoPhn - - cfg = json.loads((model_dir / "config.json").read_text(encoding="utf-8")) - model_args = cfg["args"] - model_cls = StreamingGOPT if model_args["model"] == "streaming_gopt" else StreamingGOPTNoPhn - model = model_cls( - embed_dim=int(model_args["embed_dim"]), - num_heads=int(model_args["heads"]), - depth=int(model_args["depth"]), - input_dim=int(cfg["input_dim"]), - seq_len=int(cfg["seq_len"]), - phn_num=int(cfg["phn_num"]), - ) - state = torch.load(model_dir / "best_audio_model.pth", map_location=device) - incompatible = model.load_state_dict(state, strict=False) - allowed_missing = { - "mlp_head_word4.0.weight", - "mlp_head_word4.0.bias", - "mlp_head_word4.1.weight", - "mlp_head_word4.1.bias", - } - unexpected = set(incompatible.unexpected_keys) - missing = set(incompatible.missing_keys) - if unexpected: - raise RuntimeError(f"Unexpected checkpoint keys: {sorted(unexpected)}") - disallowed_missing = missing - allowed_missing - if disallowed_missing: - raise RuntimeError(f"Missing required checkpoint keys: {sorted(disallowed_missing)}") - model = model.to(device) - model.eval() - return model, cfg - - -def build_phone_segments( - audio_path, - transcript, - repo_root, - charsiu_src_dir, - charsiu_model_dir, - sample_rate, - device, - phn_dict, - expected_feat_dim, -): - add_repo_paths(repo_root) - for module_name in ["Charsiu", "models", "utils", "processors"]: - sys.modules.pop(module_name, None) - from build_charsiu_seq_data import ( - audio_logits, - build_model_phone_map, - build_silence_keep_mask, - import_official_charsiu_forced_align, - load_official_charsiu_aligner, - normalize_phone, - segment_feature, - ) - - charsiu = load_official_charsiu_aligner( - model_name=str(charsiu_model_dir), - device=str(device), - sample_rate=sample_rate, - sil_threshold=4, - lang="en", - charsiu_src_dir=str(charsiu_src_dir), - ) - phone_to_frame_id, _, _ = build_model_phone_map(charsiu) - phone_groups, words = charsiu.charsiu_processor.get_phones_and_words(transcript) - if not phone_groups: - raise ValueError("ASR transcript cannot be converted into phones.") - - flat_records = [] - for word_id, phones in enumerate(phone_groups): - word_text = str(words[word_id]).lower() if word_id < len(words) else f"word_{word_id}" - for phone in phones: - norm_phone = normalize_phone(phone) - if not norm_phone or norm_phone == "SIL": - continue - if norm_phone not in phone_to_frame_id: - raise ValueError(f"Phone not found in Charsiu frame-classifier vocab: {norm_phone}") - if norm_phone not in phn_dict: - raise ValueError(f"Phone not found in GOPT phone vocab: {norm_phone}") - flat_records.append( - { - "phone": norm_phone, - "word_id": int(word_id), - "word_text": word_text, - } - ) - - if not flat_records: - raise ValueError("No valid phones remained after transcript normalization.") - - phone_ids = charsiu.charsiu_processor.get_phone_ids(phone_groups) - target_phone_ids = list(phone_ids[1:-1]) - if len(target_phone_ids) != len(flat_records): - raise ValueError( - f"Phone count mismatch after G2P: target_phone_ids={len(target_phone_ids)} flat_records={len(flat_records)}" - ) - - probs, audio_duration = audio_logits( - audio_path=str(audio_path), - processor=charsiu.charsiu_processor, - model=charsiu.aligner, - sample_rate=sample_rate, - device=device, - ) - keep_mask = build_silence_keep_mask(charsiu, probs) - kept_indices = np.flatnonzero(keep_mask) - kept_probs = probs[keep_mask] - if kept_probs.shape[0] < len(target_phone_ids): - raise ValueError( - f"Not enough non-silence frames for the recognized phones: frames={kept_probs.shape[0]} phones={len(target_phone_ids)}" - ) - - forced_align = import_official_charsiu_forced_align(str(charsiu_src_dir)) - aligned_phone_ids = np.asarray(forced_align(kept_probs, target_phone_ids), dtype=np.int32) - frame_step = float(audio_duration) / max(len(probs), 1) - - segments = [] - for phone_idx, record in enumerate(flat_records): - token_frames = np.flatnonzero(aligned_phone_ids == phone_idx) - if token_frames.size == 0: - raise ValueError(f"Empty aligned segment for phone index {phone_idx} ({record['phone']}).") - - segment_probs = kept_probs[token_frames] - target_id = int(phone_to_frame_id[record["phone"]]) - base_feature = segment_feature(segment_probs, target_id, frame_step).astype(np.float32) - expected_base_dim = int(expected_feat_dim) - 1 - expected_phone_prob_dim = expected_base_dim - 4 - current_phone_prob_dim = int(base_feature.shape[0]) - 4 - if current_phone_prob_dim == expected_phone_prob_dim + 1: - # Current local Charsiu exports an extra [PAD] probability channel at the end. - # The released GOPT checkpoint was trained without that channel. - base_feature = np.concatenate([base_feature[:expected_phone_prob_dim], base_feature[-4:]], axis=0) - elif current_phone_prob_dim != expected_phone_prob_dim: - raise ValueError( - f"Unexpected phone probability dimension: current={current_phone_prob_dim} expected={expected_phone_prob_dim}" - ) - feature = np.concatenate([base_feature, np.array([0.0], dtype=np.float32)], axis=0) - - start_frame = int(kept_indices[token_frames[0]]) - end_frame = int(kept_indices[token_frames[-1]]) + 1 - start_time = float(start_frame * frame_step) - end_time = float(min(audio_duration, end_frame * frame_step)) - - segments.append( - { - "phone": record["phone"], - "phone_id": int(phn_dict[record["phone"]]), - "word_id": int(record["word_id"]), - "word_text": record["word_text"], - "start_time": start_time, - "end_time": end_time, - "feature": feature, - } - ) - return segments - - -def prepare_model_inputs(segments, seq_len, feat_dim, norm_mean, norm_std, device): - if len(segments) > seq_len: - raise ValueError(f"Phone sequence too long for this model: {len(segments)} > seq_len({seq_len})") - - feat = np.zeros((seq_len, feat_dim), dtype=np.float32) - phn = np.full((seq_len,), -1, dtype=np.int64) - for idx, segment in enumerate(segments): - if int(segment["feature"].shape[-1]) != feat_dim: - raise ValueError( - f"Feature dimension mismatch at segment {idx}: got {segment['feature'].shape[-1]}, expected {feat_dim}" - ) - feat[idx] = segment["feature"] - phn[idx] = int(segment["phone_id"]) - - valid = phn >= 0 - feat[valid] = (feat[valid] - float(norm_mean)) / float(norm_std) - x = torch.from_numpy(feat).unsqueeze(0).to(device) - p = torch.from_numpy(phn).unsqueeze(0).to(device) - return x, p - - -def predict_scores(model, x, p, main_context_tokens, right_context_tokens): - with torch.no_grad(): - u1, u2, u3, u4, u5, _, _, _, _, _ = model( - x, - p, - main_context_tokens=int(main_context_tokens), - right_context_tokens=int(right_context_tokens), - ) - values = torch.cat([u1, u2, u3, u4, u5], dim=1).squeeze(0).cpu().numpy() * 5.0 - values = np.clip(values, 0.0, 10.0) - return {name: float(value) for name, value in zip(SCORE_NAMES, values.tolist())} - - -def build_output(audio_path, transcript, asr_words, scores, segments, device, bundle_dir): - return { - "status": "ok", - "audio_path": str(audio_path.resolve()).replace("\\", "/"), - "bundle_dir": str(bundle_dir.resolve()).replace("\\", "/"), - "device": str(device), - "transcript": transcript, - "utterance_scores": scores, - "overall_score": float(scores["total"]), - "num_phone_segments": int(len(segments)), - "num_asr_words": int(len(asr_words)), - "recognized_words": [str(word["text"]).lower() for word in asr_words], - } - - -def main(): - warnings.filterwarnings("ignore", message=".*return_token_timestamps.*") - args = get_args() - bundle_dir = args.bundle_dir.resolve() - repo_root = args.repo_root.resolve() - charsiu_src_dir = args.charsiu_src_dir.resolve() - device = torch.device(args.device or ("cuda" if torch.cuda.is_available() else "cpu")) - - if not args.audio.exists(): - raise FileNotFoundError(f"Audio file not found: {args.audio}") - - model_dir = bundle_dir / "streaming_gopt_best" - whisper_model_dir = bundle_dir / "whisper_best_model" - charsiu_model_dir = bundle_dir / "charsiu_en_w2v2_tiny_fc_10ms" - inference_assets_path = model_dir / "inference_assets.json" - - inference_assets = json.loads(inference_assets_path.read_text(encoding="utf-8")) - sample_rate = int(inference_assets["sample_rate"]) - norm_mean = float(inference_assets["train_norm_mean"]) - norm_std = float(inference_assets["train_norm_std"]) - phn_dict = {str(key): int(value) for key, value in inference_assets["phn_dict"].items()} - - model, cfg = load_model(model_dir, repo_root, device) - add_repo_paths(repo_root) - from build_charsiu_seq_data import normalize_word - - asr_pipe, asr_kwargs = load_asr_pipeline(whisper_model_dir, device) - transcript, asr_words = transcribe_audio(asr_pipe, asr_kwargs, args.audio, sample_rate, normalize_word) - if not transcript: - raise ValueError("Whisper produced an empty transcript.") - - segments = build_phone_segments( - audio_path=args.audio, - transcript=transcript, - repo_root=repo_root, - charsiu_src_dir=charsiu_src_dir, - charsiu_model_dir=charsiu_model_dir, - sample_rate=sample_rate, - device=device, - phn_dict=phn_dict, - expected_feat_dim=int(cfg["input_dim"]), - ) - - seq_len = int(cfg["seq_len"]) - feat_dim = int(cfg["input_dim"]) - x, p = prepare_model_inputs( - segments=segments, - seq_len=seq_len, - feat_dim=feat_dim, - norm_mean=norm_mean, - norm_std=norm_std, - device=device, - ) - - model_args = cfg["args"] - main_context_choices = model_args.get("main_context_token_choices") or [ - int(item.strip()) for item in str(model_args["main_context_tokens"]).split(",") if item.strip() - ] - right_context_choices = model_args.get("right_context_token_choices") or [ - int(item.strip()) for item in str(model_args["right_context_tokens"]).split(",") if item.strip() - ] - - main_context_tokens = int(args.main_context_tokens if args.main_context_tokens is not None else max(main_context_choices)) - right_context_tokens = int( - args.right_context_tokens if args.right_context_tokens is not None else max(right_context_choices) - ) - scores = predict_scores(model, x, p, main_context_tokens, right_context_tokens) - payload = build_output(args.audio, transcript, asr_words, scores, segments, device, bundle_dir) - - result_json = json.dumps(payload, ensure_ascii=False, indent=2) - print(result_json) - if args.output_json is not None: - args.output_json.parent.mkdir(parents=True, exist_ok=True) - args.output_json.write_text(result_json, encoding="utf-8") - - -if __name__ == "__main__": - main() diff --git a/examples/sa1_infer_output.json b/examples/sa1_infer_output.json deleted file mode 100644 index ddaf0f4f9b8ccdacbf494b146bf7e8731c06a052..0000000000000000000000000000000000000000 --- a/examples/sa1_infer_output.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "status": "ok", - "audio_path": "D:/研究生/模型/charsiu/charsiu_repo/local/SA1.WAV", - "bundle_dir": "D:/研究生/智能体/gopt_charsiu/hf_bundle/custom-gopt-252-eval", - "device": "cpu", - "transcript": "She had your dark suit in greasy wash water all year.", - "utterance_scores": { - "accuracy": 5.0, - "completeness": 5.0, - "fluency": 5.0, - "prosodic": 5.0, - "total": 5.0 - }, - "overall_score": 5.0, - "num_phone_segments": 34, - "num_asr_words": 11, - "recognized_words": [ - "she", - "had", - "your", - "dark", - "suit", - "in", - "greasy", - "wash", - "water", - "all", - "year" - ] -} \ No newline at end of file diff --git a/examples/session.py b/examples/session.py new file mode 100644 index 0000000000000000000000000000000000000000..c2da43d88dd3d38671af647fdf9751aacda2704d --- /dev/null +++ b/examples/session.py @@ -0,0 +1,21 @@ +"""Live-style local example. Input: your own mono 16 kHz English WAV.""" +import argparse +import json +import soundfile as sf +from streampa import StreamPAPipeline + +p=argparse.ArgumentParser() +p.add_argument('--bundle-dir',required=True); p.add_argument('--audio',required=True) +p.add_argument('--device',default='cpu') +a=p.parse_args() +pipeline=StreamPAPipeline(a.bundle_dir,device=a.device) +session=pipeline.create_session() +with sf.SoundFile(a.audio) as audio: + if audio.samplerate!=16000 or audio.channels!=1: raise ValueError('Expected mono 16-kHz WAV') + while True: + block=audio.read(1600,dtype='float32') + if not len(block): break + for result in session.append(block): print(json.dumps(result)) +print(json.dumps(session.finish())) +session.reset() +assert session.current() is None and session.state is None diff --git a/licenses/Apache-2.0.txt b/licenses/Apache-2.0.txt new file mode 100644 index 0000000000000000000000000000000000000000..68b7d66c97d66c58de883ed0c451af2b3183e6f3 --- /dev/null +++ b/licenses/Apache-2.0.txt @@ -0,0 +1,203 @@ +Copyright 2018- The Hugging Face team. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/licenses/Charsiu-MIT.txt b/licenses/Charsiu-MIT.txt new file mode 100644 index 0000000000000000000000000000000000000000..b8bea73a24af5b0b32f3114c6b1ab5da42216fd6 --- /dev/null +++ b/licenses/Charsiu-MIT.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 jzhu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/licenses/G2P-Apache-2.0.txt b/licenses/G2P-Apache-2.0.txt new file mode 100644 index 0000000000000000000000000000000000000000..8dada3edaf50dbc082c9a125058f25def75e625a --- /dev/null +++ b/licenses/G2P-Apache-2.0.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/licenses/Whisper-MIT.txt b/licenses/Whisper-MIT.txt new file mode 100644 index 0000000000000000000000000000000000000000..d25552598bb9c5400612159ed4bab92ce12a5ce5 --- /dev/null +++ b/licenses/Whisper-MIT.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 OpenAI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/model_manifest.json b/model_manifest.json new file mode 100644 index 0000000000000000000000000000000000000000..3dd5568e48ae7e790e6aabc405fa7190717c35a0 --- /dev/null +++ b/model_manifest.json @@ -0,0 +1,46 @@ +{ + "model_name": "StreamPA", + "experiment_id": "M_stress_scalar_gate_capacity64", + "primary_seed": 1337, + "original_checkpoint_sha256": "870df8dbe3c787487f094e0c4d4ade6bed8fcc5d86b578c4edc57581e81023b4", + "scorer_sha256": "26b2f4a90b90e997ceb2eae9df2f09166a9173c1297c53ef26b4b843eb778583", + "config_sha256": "d508e880fff94cfc882109a1acc5122ea4c442bdc055114780d5c17b8ae1d026", + "parameter_count": 142258, + "official_paper_seeds": [ + 1337, + 202601, + 202602, + 202603 + ], + "source_model_class": "PCNStreamingScorer", + "charsiu_mode": "prefix_recompute", + "commit_rule": "legacy", + "source_config_sha256": "0aca7850b95ad2d522992493b6eabfb5810be9b7802c5557c355047a090602ab", + "data_manifest_sha256": "ce3c021836de4e8241bfc61f196dbda502b06da160080e70e0de76accbc6214c", + "source_files": { + "augment_slot_prosody_pcn.py": "e6ace1b6f909fd911f7a163b12363e9d33ef60fd46f25af4e2499e4c4097db2f", + "benchmark_ours_m_efficiency.py": "d7263131d9c84b398669b50e609d14fa3925c31d6f1d89d134cbca3e5dffb9e3", + "build_charsiu_seq_data.py": "2535957cce06f1816b7520ea1ffc1a35dd3815bda11a0e335cbcbb3c8f92ff2e", + "build_streaming_asr_gopt_data.py": "3bab451431f3386f293bd49760252d558e93ae92e706971a05394fe898a7fe39", + "build_streaming_charsiu_data.py": "3d6963e702d792b1967a24af8add08eaf812f30f02798589d60c50708f30822c", + "build_streaming_pcn_gopt_data.py": "4444775df9e88586247ed6233ff8fadb9a099dae36dd98271e8dd2dc7c6da43f", + "infer_streaming_pcn.py": "e005fd5612f0286f026641958f2259ed2774811ac0a7f00f05b329758de3c1d1", + "streaming_gopt.py": "3643ef2e07ff94dc7dc6e829b825680f73c9846d95a21f88189cb5ce6b0dab68", + "streaming_pcn_gopt.py": "1794fa024a698babbdfca90dfc9091d0a7ec051215461870c9f0b597ccee16fd", + "train_streaming_pcn.py": "8779d624c563e84acaa42e4b812835e672b385e7b3b03b20a5aa3a0afce22df6" + }, + "deployment_changes": [ + "caller EOF determines final time", + "reference phone-ratio filter removed", + "explicit overlength and invalid-prefix statuses", + "ASR-word presentation aggregation; raw slot outputs preserved" + ], + "score_scaling": { + "word_network_to_0_10": 5, + "utterance_network_to_0_10": 5, + "phone_network_to_0_2": 5, + "word_network_to_0_5": 2.5, + "utterance_network_to_0_5": 2.5, + "phone_network_to_0_5": 12.5 + } +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..dbd2bbb566b167d979a9b37740569c39ed002eb8 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,13 @@ +[build-system] +requires = ["setuptools>=68", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "streampa" +version = "1.0.0" +description = "Frozen StreamPA streaming pronunciation-assessment inference" +requires-python = ">=3.10,<3.11" +dependencies = ["torch==2.5.1", "transformers==4.46.3", "huggingface-hub==0.36.0", "safetensors==0.6.2", "numpy==1.26.4", "librosa==0.11.0", "soundfile==0.13.1", "g2p-en==2.1.0", "nltk==3.9.1"] + +[tool.setuptools.packages.find] +include = ["streampa*"] diff --git a/requirements-lock.txt b/requirements-lock.txt new file mode 100644 index 0000000000000000000000000000000000000000..deeb15d0c7c45d39cf709e54b66b3a6b16a144b3 --- /dev/null +++ b/requirements-lock.txt @@ -0,0 +1,58 @@ +# Verified Python 3.10 / Linux CPU environment. +# Install with --extra-index-url https://download.pytorch.org/whl/cpu +audioread==3.1.0 +certifi==2026.7.22 +cffi==2.1.1 +charset-normalizer==3.5.1 +click==8.5.0 +cloudpickle==3.1.2 +decorator==5.3.1 +Distance==0.1.3 +exceptiongroup==1.3.1 +filelock==3.32.6 +fsspec==2026.7.0 +g2p-en==2.1.0 +hf-xet==1.6.0 +huggingface-hub==0.36.0 +idna==3.19 +inflect==7.5.0 +iniconfig==2.3.0 +Jinja2==3.1.6 +joblib==1.6.0 +lazy-loader==0.5 +librosa==0.11.0 +llvmlite==0.49.0 +MarkupSafe==3.0.3 +more-itertools==11.1.0 +mpmath==1.3.0 +msgpack==1.2.2 +networkx==3.4.2 +nltk==3.9.1 +numba==0.67.0 +numpy==1.26.4 +packaging==26.3 +platformdirs==4.11.8 +pluggy==1.6.0 +pooch==1.9.0 +pycparser==3.0 +Pygments==2.21.0 +pytest==8.4.2 +PyYAML==6.0.3 +regex==2026.9.10 +requests==2.34.2 +safetensors==0.6.2 +scikit-learn==1.7.2 +scipy==1.15.3 +setuptools==79.0.1 +soundfile==0.13.1 +soxr==1.1.0 +sympy==1.13.1 +threadpoolctl==3.6.0 +tokenizers==0.20.3 +tomli==2.4.1 +torch==2.5.1+cpu +tqdm==4.70.0 +transformers==4.46.3 +typeguard==4.6.0 +typing_extensions==4.16.0 +urllib3==2.7.0 diff --git a/scorer/config.json b/scorer/config.json new file mode 100644 index 0000000000000000000000000000000000000000..da392e1c78052fc5edbba94fe498beaacc84af7f --- /dev/null +++ b/scorer/config.json @@ -0,0 +1,180 @@ +{ + "metadata_schema": "streaming_pcn_gopt_v2_stateful", + "pcn_type": "nbest_derived_phone_confusion_network", + "phone_dim": 40, + "seq_len": 72, + "prosody_dim": 14, + "prosody_norm_mean": [ + 3.9681200981140137, + 204.3585205078125, + 24.05475616455078, + -0.20867417752742767, + 0.12271453440189362, + -4.253726005554199, + 1.724206805229187, + 0.004727904684841633, + 0.20122256875038147, + 10.172670364379883, + 0.3134472370147705, + 1.937715768814087, + 5.8537139892578125, + 17295600.0 + ], + "prosody_norm_std": [ + 2.0985183715820312, + 55.536617279052734, + 13.517866134643555, + 0.4277317225933075, + 0.06661950051784515, + 0.6672922372817993, + 0.378594309091568, + 0.009153330698609352, + 0.0010623399866744876, + 11.080301284790039, + 0.1449834257364273, + 0.9631871581077576, + 2.870692014694214, + 205320480.0 + ], + "slot_prosody_dim": 17, + "slot_prosody": [ + "slot_duration", + "slot_log_energy_mean", + "slot_log_energy_std", + "slot_log_energy_max", + "slot_f0_mean", + "slot_f0_std", + "slot_f0_max", + "slot_voiced_ratio", + "slot_position_in_word", + "word_phone_count", + "energy_relative_to_word_mean", + "duration_relative_to_word_mean", + "f0_relative_to_word_mean", + "is_vowel", + "lexical_stress_0", + "lexical_stress_1", + "lexical_stress_2" + ], + "slot_prosody_norm_mean": [ + 0.039656512439250946, + -0.9386982917785645, + 0.12416643649339676, + -0.7695538997650146, + 49.076961517333984, + 1.3523738384246826, + 51.32339096069336, + 0.18721239268779755, + 0.13828140497207642, + 1.0300568342208862, + 4.231509587171445e-10, + 0.28040772676467896, + -2.2446879910376083e-08, + 0.11200845241546631, + 0.0, + 0.0, + 0.0 + ], + "slot_prosody_norm_std": [ + 0.11444349586963654, + 1.6153852939605713, + 0.31157857179641724, + 1.3436129093170166, + 92.65617370605469, + 4.188445568084717, + 97.01981353759766, + 0.3661966025829315, + 0.31229057908058167, + 1.9228776693344116, + 0.3923450708389282, + 0.5529012084007263, + 27.52008056640625, + 0.31510770320892334, + 0.0, + 0.0, + 0.0 + ], + "utt_pooling_head": "gru_visible", + "fusion_mode": "scalar_gate", + "stress_branch": "detached", + "stress_grad_scale": 0.2, + "uses_state_projection": false, + "args": { + "lr": 0.001, + "n_epochs": 80, + "batch_size": 12, + "num_workers": 4, + "embed_dim": 64, + "depth": 3, + "heads": 4, + "gru_dim": 64, + "main_context_tokens": 16, + "tbptt_steps": 0, + "loss_w_phone": 1.0, + "loss_w_word": 1.0, + "loss_w_utt": 1.0, + "loss_w_asr": 0.5, + "loss_w_uncertainty": 0.2, + "loss_w_confidence": 0.2, + "loss_w_abstention": 0.2, + "loss_w_calibration": 0.1, + "loss_w_teacher_score": 0.8, + "loss_w_prefix_kd": 1.0, + "loss_w_rank": 0.2, + "loss_w_oracle_phone": 0.3, + "loss_w_oracle_word": 1.0, + "loss_w_oracle_utt_prefix": 0.2, + "loss_w_oracle_utt_final": 0.3, + "loss_w_stress_pearson": 0.2, + "loss_w_oracle_stress_pearson": 0.3, + "loss_w_teacher_stress_pearson": 0.1, + "loss_w_stress_rank": 0.1, + "loss_w_oracle_stress_rank": 0.1, + "loss_w_phone_stability": 0.01, + "loss_w_word_stability": 0.01, + "loss_w_utt_stability": 0.01, + "loss_w_commit_consistency": 0.0, + "loss_w_state_projection": 0.0, + "utt_dim_weights": [ + 1.0, + 0.0, + 1.0, + 1.0, + 1.0 + ], + "word_dim_weights": [ + 1.0, + 3.0, + 1.0 + ], + "teacher_word_dim_weights": [ + 1.0, + 2.0, + 1.0 + ], + "oracle_word_dim_weights": [ + 1.0, + 5.0, + 1.0 + ], + "soft_label_policy": "original", + "relaxed_min_gt_posterior": 0.05, + "relaxed_acoustic_scale": 0.3, + "relaxed_min_weight": 0.05, + "relaxed_max_weight": 0.5, + "utt_pooling_head": "gru_visible", + "fusion_mode": "scalar_gate", + "rank_margin": 0.02, + "stress_rank_margin": 0.02, + "stress_rank_max_items": 512, + "stress_loss_mask": "vowel", + "stress_voiced_threshold": 0.3, + "stress_branch": "detached", + "stress_grad_scale": 0.2, + "grad_clip_norm": 1.0, + "compile": false, + "tf32": true, + "seed": 1337 + }, + "preserve_unused_legacy_utt_head": true +} diff --git a/scorer/inference_assets.json b/scorer/inference_assets.json new file mode 100644 index 0000000000000000000000000000000000000000..8f58d0de7598dc5b08770c9e0a054a1289415227 --- /dev/null +++ b/scorer/inference_assets.json @@ -0,0 +1,50 @@ +{ + "sample_rate": 16000, + "chunk_sec": 0.64, + "right_context_sec": 0.16, + "nbest": 5, + "beam_size": 8, + "max_new_tokens": 128, + "no_repeat_ngram_size": 0, + "language": "english", + "min_sil_frames": 4, + "commit_rule": "legacy", + "max_audio_sec": 30, + "filter": { + "max_new_tokens": 128, + "no_repeat_ngram_size": 0, + "strict_repeat_word_trigger": 64, + "strict_repeat_phone_trigger": 100, + "repeat_ngram_min_repeats": 4, + "repeat_max_ngram_size": 12, + "repeat_ngram_coverage": 0.6, + "repeat_token_ratio": 0.5, + "length_policy": "word_count and absolute phone_count only enable strict repetition checks; non-repetitive long hypotheses are retained", + "hard_rejection_policy": "reference-independent repeated hypotheses only; G2P or alignment failures return explicit invalid status" + }, + "historical_reference_ratio_filter_disabled": true, + "lexical_stress_features": "zero as frozen builder", + "native_target_divisor": 5, + "score_scaling": { + "word_network_to_0_10": 5, + "utterance_network_to_0_10": 5, + "phone_network_to_0_2": 5, + "word_network_to_0_5": 2.5, + "utterance_network_to_0_5": 2.5, + "phone_network_to_0_5": 12.5 + }, + "clip_scores": false, + "historical_filter_metadata": { + "max_new_tokens": 128, + "no_repeat_ngram_size": 0, + "strict_repeat_word_trigger": 64, + "strict_repeat_phone_trigger": 100, + "max_phone_ratio": 3.0, + "repeat_ngram_min_repeats": 4, + "repeat_max_ngram_size": 12, + "repeat_ngram_coverage": 0.6, + "repeat_token_ratio": 0.5, + "length_policy": "word_count and absolute phone_count only enable strict repetition checks; non-repetitive long hypotheses are retained", + "hard_rejection_policy": "drop individual N-best hypotheses with detected repetition or ASR/reference phone ratio above max_phone_ratio; drop chunk only if all hypotheses are filtered" + } +} diff --git a/scorer/model.safetensors b/scorer/model.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..155008ffa5e6890ace31b83a88130c058bf274fe --- /dev/null +++ b/scorer/model.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26b2f4a90b90e997ceb2eae9df2f09166a9173c1297c53ef26b4b843eb778583 +size 578264 diff --git a/scripts/setup_assets.py b/scripts/setup_assets.py new file mode 100644 index 0000000000000000000000000000000000000000..24e9c98b3bcf13b776647c86d3a25ffb62197a3a --- /dev/null +++ b/scripts/setup_assets.py @@ -0,0 +1,74 @@ +"""Fetch fixed official third-party assets; validate hashes; no model execution.""" +import argparse +import hashlib +import importlib.metadata +import json +from pathlib import Path +import urllib.request +import zipfile +from huggingface_hub import hf_hub_download + +def sha(path): + h=hashlib.sha256() + with Path(path).open('rb') as f: + for chunk in iter(lambda:f.read(1048576),b''): h.update(chunk) + return h.hexdigest() + +def setup(bundle, offline=False): + bundle=Path(bundle).resolve() + spec=json.loads((bundle/'assets/runtime_sources.json').read_text()) + checks=[] + for row in spec['sources']: + dest=bundle/row['destination'] + dest.parent.mkdir(parents=True,exist_ok=True) + if not dest.exists(): + if offline: raise FileNotFoundError(f'Offline asset missing: {row["destination"]}') + if row['kind']=='hub': + source=Path(hf_hub_download(row['repo_id'],row['filename'],revision=row['revision'],token=False)) + assert sha(source)==row['sha256'], row['destination'] + dest.write_bytes(source.read_bytes()) + else: + with urllib.request.urlopen(row['url'],timeout=120) as response: + content=response.read() + if hashlib.sha256(content).hexdigest()!=row['sha256']: + raise RuntimeError(f'Asset checksum failed: {row["destination"]}') + dest.write_bytes(content) + if sha(dest)!=row['sha256']: + raise RuntimeError(f'Asset checksum failed, not overwriting: {row["destination"]}') + if row['kind']=='zip': + target=(bundle/row['extract_to']).resolve() + with zipfile.ZipFile(dest) as archive: + for member in archive.infolist(): + path=(target/member.filename).resolve() + if target!=path and target not in path.parents: + raise RuntimeError('Unsafe resource archive path') + if not member.is_dir(): + content=archive.read(member) + if path.exists(): + if path.read_bytes()!=content: + raise RuntimeError(f'Installed resource differs: {path.name}') + else: + path.parent.mkdir(parents=True,exist_ok=True) + path.write_bytes(content) + checks.append(dict(path=row['destination'],sha256=row['sha256'],status='PASS')) + inventory=json.loads((bundle/'assets/prepared_resource_hashes.json').read_text()) + dist=importlib.metadata.distribution('g2p-en') + if dist.version!=inventory['g2p_en_version']: raise RuntimeError('G2P package version differs') + for row in inventory['g2p_files']: + path=Path(dist.locate_file(row['package_relative'])) + if not path.is_file() or sha(path)!=row['sha256']: + raise RuntimeError(f'G2P resource differs: {row["package_relative"]}') + checks.append(dict(path=row['package_relative'],sha256=row['sha256'],status='PASS')) + for row in inventory['prepared_resources']: + path=bundle/row['path'] + if not path.is_file() or sha(path)!=row['sha256']: + raise RuntimeError(f'Prepared resource differs: {row["path"]}') + print(json.dumps(dict(offline=offline,checks=checks),indent=2)) + return checks + +if __name__=='__main__': + p=argparse.ArgumentParser() + p.add_argument('--bundle-dir',type=Path,default=Path(__file__).resolve().parents[1]) + p.add_argument('--offline',action='store_true') + a=p.parse_args() + setup(a.bundle_dir,a.offline) diff --git a/scripts/verify_bundle.py b/scripts/verify_bundle.py new file mode 100644 index 0000000000000000000000000000000000000000..b121a526e0f3213cd9e5d732bd13a665e6cd539e --- /dev/null +++ b/scripts/verify_bundle.py @@ -0,0 +1,21 @@ +"""Verify every published entity against the release SHA256SUMS.""" +import argparse +import hashlib +from pathlib import Path + +def verify(root): + root=Path(root).resolve(); count=0 + for row in (root/'SHA256SUMS').read_text().splitlines(): + digest,name=row.split(' ',1); path=(root/name).resolve() + if root not in path.parents: raise ValueError('Invalid manifest path') + h=hashlib.sha256() + with path.open('rb') as f: + for block in iter(lambda:f.read(1048576),b''): h.update(block) + if h.hexdigest()!=digest: raise RuntimeError(f'Checksum mismatch: {name}') + count+=1 + print(f'PASS: {count} published files verified') + return count + +if __name__=='__main__': + p=argparse.ArgumentParser(); p.add_argument('--bundle-dir',default=Path(__file__).resolve().parents[1]) + verify(p.parse_args().bundle_dir) diff --git a/streaming_gopt_best/best_audio_model.pth b/streaming_gopt_best/best_audio_model.pth deleted file mode 100644 index 079cd2cffe188099b725e4b472edfcf7259dacb7..0000000000000000000000000000000000000000 --- a/streaming_gopt_best/best_audio_model.pth +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d3ab226af75d1dfd7dd71cbcf512a9441aa1200ba2079d34470f81159cd6b977 -size 190932 diff --git a/streaming_gopt_best/config.json b/streaming_gopt_best/config.json deleted file mode 100644 index fa77166495b9a3d52d4a62bee43da476497d84af..0000000000000000000000000000000000000000 --- a/streaming_gopt_best/config.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "data_dir": "/DATA_2/guest/custom-gopt/data/streaming_asr_gopt_v6_asrconf", - "input_dim": 47, - "phn_num": 40, - "seq_len": 692, - "args": { - "data_dir": "/DATA_2/guest/custom-gopt/data/streaming_asr_gopt_v6_asrconf", - "exp_dir": "/DATA_2/guest/custom-gopt/exp/streaming-asr-gopt-v6-asrconf", - "lr": 0.001, - "n_epochs": 100, - "depth": 3, - "heads": 1, - "batch_size": 64, - "embed_dim": 24, - "loss_w_phn": 1.0, - "loss_w_word": 1.0, - "loss_w_word_asr": 1.0, - "loss_w_utt": 1.0, - "model": "streaming_gopt", - "noise": 0.0, - "num_workers": 4, - "device": "cuda", - "main_context_tokens": "4,8,12,16", - "right_context_tokens": "0,1,2,4", - "compile": false, - "tf32": false, - "seed": 1337, - "resume": false, - "main_context_token_choices": [ - 4, - 8, - 12, - 16 - ], - "right_context_token_choices": [ - 0, - 1, - 2, - 4 - ] - } -} \ No newline at end of file diff --git a/streaming_gopt_best/inference_assets.json b/streaming_gopt_best/inference_assets.json deleted file mode 100644 index 6938595507dabc0b61b793bd505114ceb838d2bf..0000000000000000000000000000000000000000 --- a/streaming_gopt_best/inference_assets.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "sample_rate": 16000, - "train_norm_mean": 0.0722440779209137, - "train_norm_std": 0.25949764251708984, - "feat_dim": 47, - "phn_num": 40, - "phn_dict": { - "W": 0, - "IY": 1, - "K": 2, - "AO": 3, - "L": 4, - "IH": 5, - "T": 6, - "B": 7, - "EH": 8, - "R": 9, - "Z": 10, - "OW": 11, - "TH": 12, - "F": 13, - "AY": 14, - "V": 15, - "AH": 16, - "N": 17, - "UW": 18, - "S": 19, - "G": 20, - "AA": 21, - "M": 22, - "P": 23, - "NG": 24, - "HH": 25, - "EY": 26, - "SH": 27, - "AE": 28, - "D": 29, - "UH": 30, - "AW": 31, - "DH": 32, - "ER": 33, - "Y": 34, - "JH": 35, - "CH": 36, - "OY": 37, - "ZH": 38 - } -} diff --git a/streaming_gopt_best/result.csv b/streaming_gopt_best/result.csv deleted file mode 100644 index 8331a0c06cd0ec53e11d70fa73f1b7fce652c0b2..0000000000000000000000000000000000000000 --- a/streaming_gopt_best/result.csv +++ /dev/null @@ -1,101 +0,0 @@ -epoch,phone_train_mse,phone_train_pcc,phone_val_mse,phone_val_pcc,learning rate,utt_train_mse_accuracy,utt_train_mse_completeness,utt_train_mse_fluency,utt_train_mse_prosodic,utt_train_mse_total,utt_train_pcc_accuracy,utt_train_pcc_completeness,utt_train_pcc_fluency,utt_train_pcc_prosodic,utt_train_pcc_total,utt_val_mse_accuracy,utt_val_mse_completeness,utt_val_mse_fluency,utt_val_mse_prosodic,utt_val_mse_total,utt_val_pcc_accuracy,utt_val_pcc_completeness,utt_val_pcc_fluency,utt_val_pcc_prosodic,utt_val_pcc_total,word_train_pcc_accuracy,word_train_pcc_stress,word_train_pcc_total,word_train_pcc_asr_accuracy,word_val_pcc_accuracy,word_val_pcc_stress,word_val_pcc_total,word_val_pcc_asr_accuracy -0.000000000000000000e+00,1.079137027263641357e-01,2.776732289780305396e-01,5.458179116249084473e-02,2.056475016002890233e-01,1.000000000000000021e-03,1.017732769250869751e-01,1.537960255518555641e-03,8.632741868495941162e-02,7.209369540214538574e-02,9.389597922563552856e-02,5.060659645574577814e-01,1.744086679858893388e-02,5.009421071735626896e-01,4.932015166782500182e-01,5.813221164796392726e-01,8.561448007822036743e-02,1.139749772846698761e-03,6.641924381256103516e-02,7.153119891881942749e-02,7.674410939216613770e-02,4.032423467488363000e-01,-1.592214327453594924e-02,3.815769695007495410e-01,3.394003035876998475e-01,5.042478848682950821e-01,2.077918562638139122e-01,-8.336524674171885696e-02,2.191634810191739335e-01,1.596240049224992019e-01,1.359882526136001468e-01,-4.588009800221485440e-02,1.449690180410702356e-01,1.804069662785112715e-01 -1.000000000000000000e+00,1.041820421814918518e-01,3.706449166264469408e-01,6.219116970896720886e-02,2.582953758852352122e-01,1.000000000000000021e-03,7.506916671991348267e-02,3.650750964879989624e-03,6.011062115430831909e-02,5.140639096498489380e-02,6.998758018016815186e-02,6.370056414927510735e-01,1.298882550120022128e-01,6.780273015672545478e-01,6.862977747573038023e-01,6.796541662922360727e-01,8.756997436285018921e-02,3.653137944638729095e-03,7.288870215415954590e-02,6.140800565481185913e-02,8.417460322380065918e-02,5.261388264911209811e-01,2.443657795377397399e-02,5.871761168081823801e-01,5.965706019434455776e-01,5.679167708900907385e-01,3.640398602379311677e-01,-4.233877629281119354e-02,3.880548763609277252e-01,2.728305487899807535e-01,2.182483660645393453e-01,-3.853244682653233361e-02,2.504640631625094094e-01,3.203802817658301660e-01 -2.000000000000000000e+00,9.281047433614730835e-02,4.388932832189844646e-01,5.085919052362442017e-02,2.917910224071572634e-01,1.000000000000000021e-03,6.204526871442794800e-02,3.228217363357543945e-03,4.249990358948707581e-02,4.041586443781852722e-02,5.738137662410736084e-02,7.214929956115374576e-01,8.182538551806139981e-02,7.771532765174712365e-01,7.594808830575937586e-01,7.377560843879427122e-01,6.918659806251525879e-02,3.128336509689688683e-03,4.416642710566520691e-02,4.611694440245628357e-02,6.303169578313827515e-02,5.695003532178497530e-01,-5.067768569970219732e-03,6.471075033146025390e-01,6.484407925864426048e-01,5.987705131988432239e-01,4.295590856406035218e-01,4.127377961734719075e-02,4.581967800386524403e-01,3.538432132168152222e-01,2.500769892836061659e-01,-1.171821163103803007e-02,2.867814875505260153e-01,3.951812826603934847e-01 -3.000000000000000000e+00,8.795424550771713257e-02,4.852790553580234034e-01,5.026153847575187683e-02,3.126730051242129216e-01,1.000000000000000021e-03,5.290393158793449402e-02,1.651985454373061657e-03,3.355559706687927246e-02,3.485541418194770813e-02,4.882648214697837830e-02,7.594843870921196283e-01,6.719378746568728522e-02,8.178115626685859008e-01,8.000001848572846352e-01,7.757036692980765480e-01,6.167699769139289856e-02,1.421156455762684345e-03,4.079946875572204590e-02,4.082865267992019653e-02,5.512074753642082214e-02,6.063115601065953708e-01,-1.548446743561882055e-02,7.083793729119221005e-01,6.996366675591403350e-01,6.376530729514864326e-01,4.858310069896916716e-01,6.929232988970045193e-02,5.100691439367808222e-01,3.846799513993024444e-01,2.785472851702357477e-01,-3.475561394853065884e-03,3.115620678538462696e-01,4.184954436680822232e-01 -4.000000000000000000e+00,8.721461892127990723e-02,5.109648368379621219e-01,6.383151561021804810e-02,3.174473789177553185e-01,1.000000000000000021e-03,4.725972935557365417e-02,1.288253813982009888e-03,3.230554983019828796e-02,3.321465849876403809e-02,4.065737873315811157e-02,7.754567118380922830e-01,6.929346740417351158e-02,8.312628993336449446e-01,8.169172738551149227e-01,7.957848608365545306e-01,6.013352796435356140e-02,9.462164598517119884e-04,3.752611950039863586e-02,3.895737975835800171e-02,5.430128425359725952e-02,6.190762454692686489e-01,1.694164467552703758e-03,7.283609325777327115e-01,7.194678905436201477e-01,6.520788335982493633e-01,5.206589800308554228e-01,1.233108496997321890e-01,5.402275814379471353e-01,3.854360042662868802e-01,2.983254935808805075e-01,2.548658286062590109e-02,3.280349747585073472e-01,4.151764133724160089e-01 -5.000000000000000000e+00,8.810387551784515381e-02,5.233755684010888976e-01,6.833378225564956665e-02,3.205610361957397236e-01,1.000000000000000021e-03,4.402649030089378357e-02,1.182442763820290565e-03,3.257671743631362915e-02,2.821853384375572205e-02,3.860916569828987122e-02,7.844561945868420150e-01,8.341824281097018345e-02,8.422572964788933580e-01,8.295394734322586450e-01,8.070802518044921658e-01,6.067190691828727722e-02,7.594404160045087337e-04,4.596406221389770508e-02,3.856667503714561462e-02,5.295049399137496948e-02,6.282226133800322687e-01,1.692926155089146192e-02,7.419398580744197558e-01,7.319690681809026822e-01,6.642837027774701752e-01,5.339778616486737794e-01,1.488257401530594937e-01,5.520129563203034495e-01,3.729090532051128615e-01,3.039651271249513842e-01,4.959261266514947142e-02,3.319566011496995483e-01,4.006294076261598947e-01 -6.000000000000000000e+00,8.414012193679809570e-02,5.381291814772770632e-01,6.494909524917602539e-02,3.196504956671062936e-01,1.000000000000000021e-03,4.297406971454620361e-02,1.028442755341529846e-03,2.753048017621040344e-02,2.733003720641136169e-02,3.911860659718513489e-02,7.904577456767357679e-01,8.890016920034679582e-02,8.449343388914654085e-01,8.328881381871791056e-01,8.106734163016174888e-01,6.023196130990982056e-02,6.536911241710186005e-04,3.779817745089530945e-02,3.825043886899948120e-02,5.370716378092765808e-02,6.276532593165649043e-01,3.025794644290185492e-02,7.427249721192606957e-01,7.321564399718462068e-01,6.630480505758957754e-01,5.454458282743140929e-01,1.487224212418345459e-01,5.636291401743753759e-01,3.761236095987761652e-01,3.047638127886744819e-01,4.767652687284456431e-02,3.318484113513537892e-01,3.933327346715422279e-01 -7.000000000000000000e+00,8.397044241428375244e-02,5.454177449248397425e-01,6.567811965942382812e-02,3.296529190938821685e-01,1.000000000000000021e-03,4.575878381729125977e-02,8.211127133108675480e-04,2.928980439901351929e-02,3.056729398667812347e-02,4.057361558079719543e-02,7.909265393099840225e-01,7.771252355228436270e-02,8.451621372874504878e-01,8.331802795242353454e-01,8.122646093462853045e-01,6.321127712726593018e-02,4.775344568770378828e-04,3.779856115579605103e-02,4.165362194180488586e-02,5.752434208989143372e-02,6.332849796716126800e-01,3.639127957694833493e-02,7.445063607304056585e-01,7.304949047675072249e-01,6.655040270535693692e-01,5.536482511279675611e-01,1.309219956720971967e-01,5.684799286193154000e-01,3.703783991526826136e-01,3.100192455908276079e-01,3.533682433665723266e-02,3.363407503874519255e-01,3.893300762394926728e-01 -8.000000000000000000e+00,7.932690531015396118e-02,5.582815030417074276e-01,5.237221717834472656e-02,3.340726441925265799e-01,1.000000000000000021e-03,4.299703985452651978e-02,8.145723841153085232e-04,2.827190607786178589e-02,2.760162949562072754e-02,3.740537166595458984e-02,7.971513246111363582e-01,4.942613349235330106e-02,8.506182705909921538e-01,8.374494236667009428e-01,8.179940128038997171e-01,5.951761454343795776e-02,4.477837937884032726e-04,3.352825716137886047e-02,3.847572952508926392e-02,5.108420550823211670e-02,6.266715202161995402e-01,5.474103983132304341e-02,7.435485424447159097e-01,7.338903823378927216e-01,6.652732645359187291e-01,5.742735421688209829e-01,1.349266156713314069e-01,5.865511050648093416e-01,3.641521699647172206e-01,3.124377730571293310e-01,4.111003383586240428e-02,3.384491038277656072e-01,3.718153188329691994e-01 -9.000000000000000000e+00,7.904511690139770508e-02,5.650366056915427926e-01,4.784649610519409180e-02,3.360747481594478225e-01,1.000000000000000021e-03,4.097953066229820251e-02,7.262713043019175529e-04,2.636589109897613525e-02,2.707981504499912262e-02,3.672679513692855835e-02,8.011406049594625989e-01,8.184587861598646708e-02,8.525136531793285899e-01,8.391137622169869692e-01,8.216666105301617673e-01,6.167176365852355957e-02,3.881674201693385839e-04,3.504731878638267517e-02,3.860588744282722473e-02,5.474837496876716614e-02,6.288495700353141649e-01,6.697507963883096715e-02,7.402487613039686609e-01,7.330606577567296833e-01,6.682398542183080048e-01,5.746754602825498992e-01,7.563367138892368446e-02,5.882577255826275664e-01,3.789453452980684478e-01,3.127768395502930621e-01,1.541690944289706745e-02,3.394110095896446522e-01,3.878069671015842435e-01 -1.000000000000000000e+01,7.689129561185836792e-02,5.776432205722596969e-01,5.536097660660743713e-02,3.413896982038953642e-01,1.000000000000000021e-03,4.202426597476005554e-02,6.829157355241477489e-04,3.145125880837440491e-02,3.008835576474666595e-02,3.676103428006172180e-02,8.051306298644963499e-01,1.043719686279931530e-01,8.540243584935583998e-01,8.405825732097117475e-01,8.262232117460068803e-01,6.519529968500137329e-02,3.890781954396516085e-04,4.766941443085670471e-02,4.384284839034080505e-02,5.613239854574203491e-02,6.316056430066069316e-01,3.294144611561136693e-02,7.459347545625676368e-01,7.356252546667766401e-01,6.703888185909948616e-01,5.841334619136506756e-01,1.479103288774953062e-01,5.959824190433531399e-01,3.707404388453034993e-01,3.155141152755229772e-01,5.384112108945592057e-02,3.406913478994477162e-01,3.788207564887718370e-01 -1.100000000000000000e+01,7.516384124755859375e-02,5.914801923276814533e-01,4.760764539241790771e-02,3.483196833867099329e-01,1.000000000000000021e-03,4.065796732902526855e-02,7.364017073996365070e-04,2.592927962541580200e-02,2.613618224859237671e-02,3.549587726593017578e-02,8.087561591048159082e-01,7.958508800689907681e-02,8.556992770720274200e-01,8.415271552833636370e-01,8.285827151333120533e-01,5.945572257041931152e-02,3.861584118567407131e-04,3.543989360332489014e-02,3.745276108384132385e-02,5.191485211253166199e-02,6.229969702595520298e-01,6.281145466019341650e-02,7.397628520376408057e-01,7.312510635331408437e-01,6.618655838036759942e-01,6.043028196305714195e-01,1.060545625305443773e-01,6.171694270678337313e-01,3.595423438258240623e-01,3.149798370223247934e-01,2.745311107611971002e-02,3.418123225833971102e-01,3.633849619530142849e-01 -1.200000000000000000e+01,7.663895934820175171e-02,5.997901646405072729e-01,6.157444044947624207e-02,3.468672964819129456e-01,1.000000000000000021e-03,3.920639306306838989e-02,7.200848194770514965e-04,2.613169886171817780e-02,2.673601917922496796e-02,3.415981680154800415e-02,8.116596138560332463e-01,7.243813638614614303e-02,8.570480618383445881e-01,8.442193388473763216e-01,8.330602093696122257e-01,6.306268274784088135e-02,3.563576610758900642e-04,3.395630046725273132e-02,3.661862760782241821e-02,5.546560510993003845e-02,6.304151407170361932e-01,9.210440100728198298e-02,7.433763895498277652e-01,7.354283789871293164e-01,6.671798055380051551e-01,5.979152664819351592e-01,1.571473732632979736e-01,6.082983081070993947e-01,3.693969070139038191e-01,3.118508839069054628e-01,5.883939534569676555e-02,3.370823225553667979e-01,3.799641527374392203e-01 -1.300000000000000000e+01,7.256346195936203003e-02,6.098782952290799919e-01,5.524610355496406555e-02,3.542463643554487618e-01,1.000000000000000021e-03,3.843601420521736145e-02,8.357077604159712791e-04,2.614173851907253265e-02,2.665366418659687042e-02,3.454660996794700623e-02,8.144846763541699897e-01,7.492669135169920114e-02,8.570755867672109618e-01,8.449939293996406864e-01,8.335468067718763141e-01,6.179256364703178406e-02,4.695496463682502508e-04,3.769916668534278870e-02,3.874914720654487610e-02,5.201447010040283203e-02,6.225628455283348517e-01,9.648262583582849217e-02,7.424723665114357773e-01,7.330119067794130805e-01,6.598358610773447097e-01,6.110371157194449676e-01,1.552750881937589311e-01,6.246053003526816916e-01,3.665856355335136985e-01,3.189198594517477781e-01,5.958419476997803971e-02,3.459633092613857985e-01,3.805706792897113333e-01 -1.400000000000000000e+01,7.195486128330230713e-02,6.169794118565439245e-01,4.993401467800140381e-02,3.392562008434108489e-01,1.000000000000000021e-03,4.383291304111480713e-02,7.470826385542750359e-04,2.761650644242763519e-02,2.762824855744838715e-02,4.176798462867736816e-02,8.168654544164080100e-01,8.989541314315742382e-02,8.568601612763651065e-01,8.443383740427758966e-01,8.353573513014010965e-01,6.755137443542480469e-02,4.235668457113206387e-04,3.518375381827354431e-02,3.951911628246307373e-02,6.108940392732620239e-02,6.087498558206331234e-01,7.872335351492198985e-02,7.336116943863905115e-01,7.258784055892653075e-01,6.511477998726845628e-01,6.364816304845191119e-01,1.601424668561550746e-01,6.481992154516424964e-01,3.693914464094895655e-01,3.083383534991637753e-01,5.489005947919788769e-02,3.322964769383936479e-01,3.704947441740806813e-01 -1.500000000000000000e+01,7.075122743844985962e-02,6.323892591565722920e-01,5.910111218690872192e-02,3.447981679203572791e-01,1.000000000000000021e-03,3.858285024762153625e-02,7.073186570778489113e-04,2.751739509403705597e-02,2.719741687178611755e-02,3.248418867588043213e-02,8.215097414902410300e-01,8.740473396015147056e-02,8.617868267862002218e-01,8.467433481412670604e-01,8.414161078562124585e-01,6.167950481176376343e-02,3.493003605399280787e-04,3.442856296896934509e-02,3.846492990851402283e-02,5.255946889519691467e-02,6.165435109975533345e-01,1.490365179083074643e-01,7.385942566868495263e-01,7.251184387416174104e-01,6.612034657340111199e-01,6.239650975157681190e-01,1.682825843195471516e-01,6.347013315289149471e-01,3.780849372705800682e-01,3.048308048922340752e-01,6.156359888784206091e-02,3.311269076812738410e-01,3.888617018279006410e-01 -1.600000000000000000e+01,6.941830366849899292e-02,6.367579718055026428e-01,5.368442833423614502e-02,3.582530429930391169e-01,1.000000000000000021e-03,3.857583552598953247e-02,7.032497669570147991e-04,2.830678969621658325e-02,3.184502571821212769e-02,3.400620073080062866e-02,8.241257037848728206e-01,3.477050389087385507e-02,8.658223416019931173e-01,8.504439691558483005e-01,8.453646623834510931e-01,5.808711051940917969e-02,3.656651824712753296e-04,3.896261751651763916e-02,4.351807758212089539e-02,5.077878013253211975e-02,6.306182923610124114e-01,1.320119897689596977e-01,7.469628697170999088e-01,7.343568750931779299e-01,6.737555269781565492e-01,6.605669086693081171e-01,1.107345599251453594e-01,6.701111607763260425e-01,3.850484142984801350e-01,3.240116505199102659e-01,2.097613555844252825e-02,3.468377814469588705e-01,3.931040748811758245e-01 -1.700000000000000000e+01,6.827208399772644043e-02,6.481063655746305274e-01,5.909809842705726624e-02,3.475036295651883766e-01,1.000000000000000021e-03,3.632614016532897949e-02,7.615093491040170193e-04,2.656896598637104034e-02,2.723619155585765839e-02,3.201103582978248596e-02,8.297603619793432195e-01,9.376895544185308295e-02,8.629920386293501444e-01,8.485437188797493313e-01,8.490615288659018045e-01,6.571350246667861938e-02,4.412145353853702545e-04,3.586862981319427490e-02,3.940239176154136658e-02,5.732339620590209961e-02,6.227764555590322715e-01,1.378991925938969076e-01,7.401593588933328416e-01,7.280205074888045358e-01,6.610552541057019837e-01,6.447963468612175619e-01,1.666588143018238877e-01,6.560366075213918124e-01,3.752414580503733443e-01,3.106617599148195907e-01,6.066518750136679072e-02,3.327274566071386497e-01,3.845188215080038718e-01 -1.800000000000000000e+01,6.528741866350173950e-02,6.577194496671199264e-01,5.303359031677246094e-02,3.426573666809243357e-01,1.000000000000000021e-03,3.519031032919883728e-02,8.660148014314472675e-04,2.426595240831375122e-02,2.568129636347293854e-02,3.062949888408184052e-02,8.334083089643693487e-01,9.549110851307869574e-02,8.655011270354117103e-01,8.519881670885902647e-01,8.522890235698877825e-01,6.542401015758514404e-02,5.303072975948452950e-04,3.759600967168807983e-02,3.885564953088760376e-02,5.690687149763107300e-02,6.160673859807292985e-01,1.228819312296807881e-01,7.393793767864327293e-01,7.311372807855845979e-01,6.573841244302103259e-01,6.635511890365026755e-01,1.782893507093815666e-01,6.744458129873126540e-01,3.759633985952385293e-01,2.978070946697530252e-01,5.052960950363397097e-02,3.214569181446781387e-01,3.780565556255954252e-01 -1.900000000000000000e+01,6.402742117643356323e-02,6.663314603670023040e-01,5.399615690112113953e-02,3.502948722834527406e-01,1.000000000000000021e-03,3.565825149416923523e-02,7.032151916064321995e-04,2.377996407449245453e-02,2.467401139438152313e-02,3.069304488599300385e-02,8.364699034314022619e-01,4.329379913005938080e-02,8.699819300887646767e-01,8.539097249667736422e-01,8.561120357656288871e-01,5.949262902140617371e-02,3.949175297748297453e-04,3.383481875061988831e-02,3.783671557903289795e-02,5.248850211501121521e-02,6.211871966230475550e-01,9.049038679806505059e-02,7.436686035531492323e-01,7.310939059559175002e-01,6.640955940383881373e-01,6.752341535107614368e-01,1.555600875127526039e-01,6.839357817704022624e-01,3.592474331377061292e-01,3.135504575542004679e-01,3.731551735251175533e-02,3.361986741430235126e-01,3.632362839247926800e-01 -2.000000000000000000e+01,6.391590833663940430e-02,6.702765494447086025e-01,5.623666942119598389e-02,3.398963422630594255e-01,5.000000000000000104e-04,3.360487893223762512e-02,7.457135943695902824e-04,2.449966594576835632e-02,2.608380652964115143e-02,2.952133491635322571e-02,8.410428875245757885e-01,7.426608414107375988e-02,8.710016255252929218e-01,8.555186001865857648e-01,8.590339066366601273e-01,6.533356010913848877e-02,4.211958730593323708e-04,3.688760101795196533e-02,3.923613578081130981e-02,5.684324353933334351e-02,6.204506197661368017e-01,1.465976489839573849e-01,7.432043748793344395e-01,7.304846104798988771e-01,6.633517185264909966e-01,6.816812835194285825e-01,1.847466358996510127e-01,6.925770051728732390e-01,3.633060944337104248e-01,3.069802425104836696e-01,5.826202973205892727e-02,3.283637256519282288e-01,3.659883887738401564e-01 -2.100000000000000000e+01,6.346534937620162964e-02,6.756393246410333786e-01,5.631577968597412109e-02,3.463531266388009677e-01,5.000000000000000104e-04,3.620840236544609070e-02,6.411169306375086308e-04,2.427953667938709259e-02,2.642281912267208099e-02,2.981889992952346802e-02,8.435377919936687396e-01,6.254226783423402769e-02,8.728355680857047272e-01,8.578676027967189199e-01,8.610370873207828790e-01,6.033084169030189514e-02,3.083940246142446995e-04,3.329208493232727051e-02,3.785052523016929626e-02,5.135870352387428284e-02,6.260232389540949516e-01,1.727440049436962666e-01,7.438323497894350211e-01,7.325367970944491880e-01,6.640035333519742622e-01,6.862486985766825809e-01,1.899596652027064903e-01,6.942660647571701205e-01,3.646062845673220254e-01,3.127599055248252991e-01,5.709049394248971038e-02,3.329020664847050504e-01,3.689723508809851227e-01 -2.200000000000000000e+01,6.295169889926910400e-02,6.780346181846128584e-01,5.676514282822608948e-02,3.432412128917491922e-01,5.000000000000000104e-04,3.258477523922920227e-02,6.418189150281250477e-04,2.285112440586090088e-02,2.355079539120197296e-02,2.924986369907855988e-02,8.461488834607181486e-01,7.821668715462797017e-02,8.737032069582920668e-01,8.588698701288256521e-01,8.648705321234475552e-01,6.416442990303039551e-02,3.368620236869901419e-04,3.700662776827812195e-02,3.842322528362274170e-02,5.764890834689140320e-02,6.239184557144704657e-01,1.329812942224762040e-01,7.445485726717759878e-01,7.299535929335742024e-01,6.655939715414124214e-01,6.738925058911863220e-01,1.866534561351652355e-01,6.809724404980760371e-01,3.550303821584157027e-01,3.087244545220975134e-01,6.268585859060217536e-02,3.303643966729859494e-01,3.610599724255625920e-01 -2.300000000000000000e+01,6.340137869119644165e-02,6.819126628302820681e-01,5.921486020088195801e-02,3.443549204251065698e-01,5.000000000000000104e-04,3.249366953969001770e-02,7.036869646981358528e-04,2.305609732866287231e-02,2.333074621856212616e-02,2.801304310560226440e-02,8.481754688227125527e-01,7.420298712759899884e-02,8.748908580912736488e-01,8.602331467124194608e-01,8.657512753154646967e-01,6.462273001670837402e-02,3.948313533328473568e-04,3.498147428035736084e-02,3.754160553216934204e-02,5.454888567328453064e-02,6.222505577742677429e-01,1.112495009168680687e-01,7.422312879239346683e-01,7.316176496065041057e-01,6.625461393696500112e-01,6.879837139298451421e-01,1.884064663216354629e-01,6.975923975110001063e-01,3.598806180781239372e-01,3.131195083225753462e-01,5.908461815423164676e-02,3.338137094565032936e-01,3.638793502767964649e-01 -2.400000000000000000e+01,6.068088486790657043e-02,6.878450946415769485e-01,4.875090345740318298e-02,3.495979572437574734e-01,5.000000000000000104e-04,3.169814869761466980e-02,6.767227896489202976e-04,2.255837433040142059e-02,2.353114634752273560e-02,2.739009819924831390e-02,8.510547445059198912e-01,5.374846872144546650e-02,8.749255968808360429e-01,8.601015198365780101e-01,8.678228506331330250e-01,6.364411115646362305e-02,3.961643087677657604e-04,3.456138074398040771e-02,3.772752359509468079e-02,5.551146715879440308e-02,6.160173881401913576e-01,8.228247847731386122e-02,7.416109201567839815e-01,7.295856202774859689e-01,6.587965295021460665e-01,7.094098410444467095e-01,1.810738551774272731e-01,7.160526811785619117e-01,3.710549099030631126e-01,3.097857026537553793e-01,5.953687827699413737e-02,3.321428938740144665e-01,3.750779033508894189e-01 -2.500000000000000000e+01,6.031619012355804443e-02,6.903506270255110877e-01,5.405574291944503784e-02,3.447442788855238360e-01,2.500000000000000052e-04,3.316438943147659302e-02,6.500548915937542915e-04,2.216979861259460449e-02,2.290121093392372131e-02,2.793949656188488007e-02,8.542046975071778681e-01,6.361110056719258832e-02,8.765686321023247185e-01,8.621832627270408222e-01,8.711761400314569359e-01,6.540291756391525269e-02,3.573002177290618420e-04,3.609022498130798340e-02,3.782694414258003235e-02,5.669248849153518677e-02,6.204851417326243679e-01,7.425108800889966554e-02,7.429793642403799137e-01,7.313579265650005379e-01,6.604005397865415627e-01,7.091463938627056152e-01,1.755177398158697111e-01,7.160381087432259317e-01,3.739973357197518555e-01,3.136034318675789967e-01,4.697654178146810910e-02,3.331712712970533730e-01,3.770217931719293536e-01 -2.600000000000000000e+01,5.995142832398414612e-02,6.925230946428559964e-01,5.355495586991310120e-02,3.480550134195181666e-01,2.500000000000000052e-04,3.069485351443290710e-02,6.226680707186460495e-04,2.242030017077922821e-02,2.348239347338676453e-02,2.665530703961849213e-02,8.558991322783168210e-01,6.722210060324336489e-02,8.778781881413928456e-01,8.635594894731659643e-01,8.724823635795103671e-01,6.362553685903549194e-02,3.200087521690875292e-04,3.666429966688156128e-02,3.818965703248977661e-02,5.505591258406639099e-02,6.189094838140793975e-01,8.073578155585253713e-02,7.420012235392176025e-01,7.307268868382146287e-01,6.581269510944628420e-01,7.080442795821242363e-01,1.849471162040889072e-01,7.149346957329287822e-01,3.646297491359525855e-01,3.114020355996068301e-01,6.005806856794900644e-02,3.318427496268828158e-01,3.685824861506054595e-01 -2.700000000000000000e+01,6.004891544580459595e-02,6.944908849671526108e-01,5.587754026055335999e-02,3.438676260494581416e-01,2.500000000000000052e-04,3.003809042274951935e-02,6.549322861246764660e-04,2.234407328069210052e-02,2.300366759300231934e-02,2.640154585242271423e-02,8.583373243555245669e-01,7.155713566229512934e-02,8.784953218374323969e-01,8.636326825438849220e-01,8.734295978982050679e-01,6.402294337749481201e-02,3.640253853518515825e-04,3.432694450020790100e-02,3.740804642438888550e-02,5.422083288431167603e-02,6.161971631897648072e-01,8.228573713468846640e-02,7.423702622157385411e-01,7.297789570118994318e-01,6.577781285912499554e-01,7.158898295450024651e-01,1.826371018872875174e-01,7.228272105761712751e-01,3.651851656905684140e-01,3.116621158277260717e-01,5.258706168642443557e-02,3.320296904305072849e-01,3.672945495827650841e-01 -2.800000000000000000e+01,5.985029786825180054e-02,6.933653109572712747e-01,5.290323868393898010e-02,3.477972857564285425e-01,2.500000000000000052e-04,3.010958060622215271e-02,6.784298457205295563e-04,2.205792628228664398e-02,2.261771820485591888e-02,2.600004151463508606e-02,8.590121304461194596e-01,7.584280348114019743e-02,8.782511458347288524e-01,8.643014307332648194e-01,8.752394966512057062e-01,6.669440120458602905e-02,3.805161977652460337e-04,3.770961984992027283e-02,3.835452720522880554e-02,5.673299357295036316e-02,6.193146975274594901e-01,6.284355805472434386e-02,7.423264996160044982e-01,7.310498206422872958e-01,6.590836649000640923e-01,7.148949942827074189e-01,1.761373511014341364e-01,7.235392770178671329e-01,3.689076861609350000e-01,3.142230032554600427e-01,4.580595596497590016e-02,3.336598231082767985e-01,3.704537116271839348e-01 -2.900000000000000000e+01,6.027451157569885254e-02,6.952877317139389834e-01,5.719231069087982178e-02,3.498466440879555717e-01,2.500000000000000052e-04,2.996739745140075684e-02,6.906153284944593906e-04,2.196395210921764374e-02,2.332052588462829590e-02,2.610654383897781372e-02,8.599966075740608229e-01,6.384125756763842086e-02,8.788804356193581357e-01,8.649910539251590702e-01,8.754611535242440290e-01,6.195820868015289307e-02,3.826686297543346882e-04,3.450454771518707275e-02,3.754130378365516663e-02,5.339368060231208801e-02,6.210951529452348741e-01,7.290467448662243943e-02,7.438691092082123646e-01,7.319431625813266340e-01,6.602139442371556255e-01,7.062189224953392408e-01,1.978882261501348216e-01,7.141785287545380223e-01,3.597772425307489974e-01,3.119770970686542300e-01,6.165929141645252326e-02,3.336554498264133195e-01,3.609263518099656842e-01 -3.000000000000000000e+01,5.975107476115226746e-02,6.979072263829914080e-01,5.740753188729286194e-02,3.478860044026280685e-01,1.250000000000000026e-04,2.965832501649856567e-02,6.463322788476943970e-04,2.169117704033851624e-02,2.342507243156433105e-02,2.658935450017452240e-02,8.616706941163232436e-01,8.684818374757541370e-02,8.792070951012203039e-01,8.654324593950811773e-01,8.772109937120813328e-01,6.756551563739776611e-02,3.524999774526804686e-04,3.672973066568374634e-02,4.049425944685935974e-02,5.925842374563217163e-02,6.156634660885346166e-01,7.274489335521647226e-02,7.397050040545084526e-01,7.273484004209838094e-01,6.546979110931987478e-01,7.174872316051424948e-01,2.001236838568846432e-01,7.250422641568589066e-01,3.675869928830769462e-01,3.167808567355248628e-01,5.998355715627732426e-02,3.365922374717836840e-01,3.681417042652462279e-01 -3.100000000000000000e+01,5.989413708448410034e-02,6.996315708299917224e-01,5.842041969299316406e-02,3.440624748909637542e-01,1.250000000000000026e-04,2.961734123528003693e-02,6.601685890927910805e-04,2.166771516203880310e-02,2.242912910878658295e-02,2.569067478179931641e-02,8.634551951189386454e-01,7.373518933681830201e-02,8.794441878022366543e-01,8.659882946775833146e-01,8.779229845445655211e-01,6.907349079847335815e-02,3.751260228455066681e-04,3.653013333678245544e-02,3.888595849275588989e-02,5.839163437485694885e-02,6.150854278556651122e-01,5.802537093317107486e-02,7.416038716429277367e-01,7.289021462955227459e-01,6.544694563937497600e-01,7.150284744404634685e-01,1.958093039968815674e-01,7.224319784724553273e-01,3.575101864052698808e-01,3.111619973530036498e-01,5.537481546693692747e-02,3.316298114154574428e-01,3.588923688312974369e-01 -3.200000000000000000e+01,5.988566949963569641e-02,6.992238174807317019e-01,5.906623601913452148e-02,3.437693362988800683e-01,1.250000000000000026e-04,2.921968512237071991e-02,6.518669542856514454e-04,2.243194915354251862e-02,2.250174246728420258e-02,2.535537071526050568e-02,8.634937917269943641e-01,7.241407914803683898e-02,8.800457878841222437e-01,8.668112739215135809e-01,8.787675865989853508e-01,6.810630857944488525e-02,3.643998352345079184e-04,3.903735056519508362e-02,3.912184387445449829e-02,5.827815830707550049e-02,6.137886526556087796e-01,5.542250585126605456e-02,7.402951479130426282e-01,7.279087452110757361e-01,6.535956841824600572e-01,7.211685484736051199e-01,2.004402482862068791e-01,7.284616385881582667e-01,3.627351777170784164e-01,3.146118776179099852e-01,5.612319413387305278e-02,3.336771553828679071e-01,3.634197948389671917e-01 -3.300000000000000000e+01,5.856835097074508667e-02,7.027648290299935985e-01,5.547048524022102356e-02,3.456412281611375703e-01,1.250000000000000026e-04,2.878449857234954834e-02,6.364382570609450340e-04,2.215472981333732605e-02,2.266022749245166779e-02,2.541560120880603790e-02,8.653584049018316904e-01,7.378762485576129126e-02,8.803915105983948219e-01,8.672222542835896775e-01,8.795875652758127217e-01,6.736468523740768433e-02,3.489613591227680445e-04,3.795114904642105103e-02,3.924616053700447083e-02,5.776481330394744873e-02,6.131427290828318499e-01,6.886720737441570650e-02,7.408723291529872856e-01,7.279738433197148195e-01,6.535120331035212393e-01,7.287091148572059085e-01,1.953318361844819939e-01,7.354631804938983608e-01,3.657085513064761151e-01,3.124106198230188203e-01,5.519759918668131621e-02,3.316457071033748760e-01,3.667481801553459930e-01 -3.400000000000000000e+01,5.956137180328369141e-02,7.015111903412459826e-01,5.840645357966423035e-02,3.472559838709036728e-01,1.250000000000000026e-04,2.853194996714591980e-02,6.652665906585752964e-04,2.143907174468040466e-02,2.226617559790611267e-02,2.497347444295883179e-02,8.664504678222918477e-01,7.810052549555511481e-02,8.808924968244327136e-01,8.675718060196130343e-01,8.806561384852223950e-01,6.732786446809768677e-02,3.809542104136198759e-04,3.673619404435157776e-02,3.906324505805969238e-02,5.760419741272926331e-02,6.123279002002739446e-01,5.472623831975714087e-02,7.406030033460383466e-01,7.286484246560003264e-01,6.535712251404711681e-01,7.182941983251204254e-01,1.935832419876346022e-01,7.257508294253484094e-01,3.560281604373304876e-01,3.137823674085809533e-01,5.510003893718258550e-02,3.338001031978982125e-01,3.562527470882380642e-01 -3.500000000000000000e+01,5.860019847750663757e-02,7.042685941720621123e-01,5.681401118636131287e-02,3.426948570678647887e-01,6.250000000000000130e-05,2.852385118603706360e-02,6.606067763641476631e-04,2.189970575273036957e-02,2.214490994811058044e-02,2.511783875524997711e-02,8.671265816255088188e-01,6.056621990584185045e-02,8.810910783324238382e-01,8.679369290638075940e-01,8.806758001445005313e-01,6.550332158803939819e-02,3.746953443624079227e-04,3.482795879244804382e-02,3.776421770453453064e-02,5.584855005145072937e-02,6.110341124228617637e-01,6.315143251565817628e-02,7.419664169244968299e-01,7.294856629996301356e-01,6.534160308873315781e-01,7.239311916665248647e-01,1.959648329695103386e-01,7.307705664689683189e-01,3.615640951859294683e-01,3.089042672495866393e-01,5.472984329952629984e-02,3.291205437424626901e-01,3.613079785138656463e-01 -3.600000000000000000e+01,5.800328776240348816e-02,7.058639554149160888e-01,5.480755493044853210e-02,3.457778184903980145e-01,6.250000000000000130e-05,2.823890186846256256e-02,6.616351893171668053e-04,2.135722525417804718e-02,2.201527170836925507e-02,2.483780682086944580e-02,8.680317355375335442e-01,7.052221606300879131e-02,8.811202254223819974e-01,8.680425841307216617e-01,8.813524163465211725e-01,6.680154800415039062e-02,3.719100786838680506e-04,3.627144917845726013e-02,3.855656832456588745e-02,5.701784789562225342e-02,6.110060303671205340e-01,6.047594143758559804e-02,7.416879238707400068e-01,7.291988567987940373e-01,6.538546130955125157e-01,7.258998137388515959e-01,1.937728568144377050e-01,7.325817537818388736e-01,3.635695842678671186e-01,3.106436235208112073e-01,5.457905856713080039e-02,3.309423285163805017e-01,3.634895597850825166e-01 -3.700000000000000000e+01,5.821143090724945068e-02,7.060490856412066085e-01,5.624023824930191040e-02,3.451095352632748137e-01,6.250000000000000130e-05,2.808584831655025482e-02,6.540680187754333019e-04,2.130166999995708466e-02,2.194941602647304535e-02,2.463362924754619598e-02,8.682341968461753101e-01,6.500924821837479606e-02,8.817616510640799987e-01,8.685528059703553350e-01,8.816875118489447827e-01,6.636561453342437744e-02,3.663054085336625576e-04,3.565122187137603760e-02,3.786234930157661438e-02,5.651423335075378418e-02,6.104779852515527239e-01,6.361121036485652136e-02,7.411132242911566692e-01,7.284491089149587317e-01,6.527329296195616415e-01,7.267961672123041117e-01,2.003436210825304820e-01,7.334647103090474740e-01,3.609690281656690036e-01,3.109696475770241664e-01,5.698784088164550454e-02,3.308524113313969228e-01,3.598523409197552092e-01 -3.800000000000000000e+01,5.858330428600311279e-02,7.056686596762939967e-01,5.770558491349220276e-02,3.433030890213782382e-01,6.250000000000000130e-05,2.818251028656959534e-02,6.572849233634769917e-04,2.158987522125244141e-02,2.188542298972606659e-02,2.477445080876350403e-02,8.683318048718714488e-01,6.912307268689021900e-02,8.816780630369920324e-01,8.686194430565205016e-01,8.819711959246643307e-01,6.794276088476181030e-02,3.768432652577757835e-04,3.758767247200012207e-02,3.849954158067703247e-02,5.828216671943664551e-02,6.102192081982115157e-01,5.582113165320360532e-02,7.409289530500461352e-01,7.279011496602600939e-01,6.528841149421040768e-01,7.225824821515871577e-01,2.009601693270930967e-01,7.290785916522167787e-01,3.584961730876087826e-01,3.099739849808434977e-01,5.843306431368194137e-02,3.301805421857078593e-01,3.573073511771043265e-01 -3.900000000000000000e+01,5.797545984387397766e-02,7.068249875867739229e-01,5.639252811670303345e-02,3.423814455008474811e-01,6.250000000000000130e-05,2.825962379574775696e-02,6.672614836134016514e-04,2.137997560203075409e-02,2.201181091368198395e-02,2.472093515098094940e-02,8.688877439572811889e-01,7.045663515915893960e-02,8.818967518319136278e-01,8.687278933009655590e-01,8.821898320856362830e-01,6.889443099498748779e-02,3.906847268808633089e-04,3.601168841123580933e-02,3.854733332991600037e-02,5.851984769105911255e-02,6.075133286488839657e-01,4.874245942327867093e-02,7.411498427443522496e-01,7.275979376853332070e-01,6.509654718424938702e-01,7.300784090103903390e-01,2.012783311615001791e-01,7.370016376253487600e-01,3.628737269023813994e-01,3.108207783531933277e-01,5.479218483292316866e-02,3.306985008802184600e-01,3.614559856482376654e-01 -4.000000000000000000e+01,5.780132487416267395e-02,7.076845682885440914e-01,5.582342669367790222e-02,3.447100529096328581e-01,3.125000000000000065e-05,2.790156006813049316e-02,6.595281884074211121e-04,2.118394710123538971e-02,2.181223779916763306e-02,2.448670379817485809e-02,8.693170685028146494e-01,6.852327820707168615e-02,8.821605652506244732e-01,8.689914506207102596e-01,8.825441761734389434e-01,6.704224646091461182e-02,3.740004613064229488e-04,3.573477268218994141e-02,3.825870901346206665e-02,5.731629207730293274e-02,6.093766484870757338e-01,4.931480233138274549e-02,7.411405513262409039e-01,7.274726165098253094e-01,6.522141273082791013e-01,7.315319166110029192e-01,2.013658223387820856e-01,7.382315810834915171e-01,3.636219105701390397e-01,3.116874921760072192e-01,5.699874742054832771e-02,3.315820495724637329e-01,3.624326583095542897e-01 -4.100000000000000000e+01,5.828995257616043091e-02,7.066286048497344430e-01,5.706362426280975342e-02,3.459699185008684452e-01,3.125000000000000065e-05,2.797951176762580872e-02,6.603868096135556698e-04,2.129152789711952209e-02,2.179086208343505859e-02,2.451370097696781158e-02,8.692540251607590029e-01,7.082228896083442304e-02,8.820935766079378570e-01,8.691655499903775395e-01,8.825804557586213184e-01,6.761421263217926025e-02,3.823030274361371994e-04,3.566716611385345459e-02,3.842425718903541565e-02,5.755558609962463379e-02,6.106474249991158398e-01,5.239089712007670430e-02,7.410667829313017929e-01,7.282225875622945210e-01,6.529481295853148959e-01,7.287269169212345910e-01,2.018144693099795106e-01,7.355872323539961455e-01,3.601301513283056144e-01,3.128390640007575607e-01,5.681476265570255257e-02,3.325660584907124684e-01,3.581642467692969234e-01 -4.200000000000000000e+01,5.767818540334701538e-02,7.083593697349319651e-01,5.567393824458122253e-02,3.450525812276888926e-01,3.125000000000000065e-05,2.789531648159027100e-02,6.614017183892428875e-04,2.144028805196285248e-02,2.214754559099674225e-02,2.443265542387962341e-02,8.698934244766330925e-01,6.995147792279096666e-02,8.823073802449288294e-01,8.692241960798464673e-01,8.828946757919553523e-01,6.766057014465332031e-02,3.737104416359215975e-04,3.752689063549041748e-02,3.932658955454826355e-02,5.757582560181617737e-02,6.091655170830136967e-01,5.521279379669469939e-02,7.410967425174687095e-01,7.276310310991033203e-01,6.519055576492363002e-01,7.321361008107423185e-01,2.008564024727396979e-01,7.385725644515125365e-01,3.631703024360398713e-01,3.104354000475741393e-01,5.580264291672666632e-02,3.302157017348057444e-01,3.622790181555390343e-01 -4.300000000000000000e+01,5.759618058800697327e-02,7.085554611848238205e-01,5.555627495050430298e-02,3.450387041283258238e-01,3.125000000000000065e-05,2.773241326212882996e-02,6.654032622464001179e-04,2.112060785293579102e-02,2.173044160008430481e-02,2.436096593737602234e-02,8.700636425271700558e-01,6.696098733771610467e-02,8.824468771804726552e-01,8.695095127901067977e-01,8.830525099645826215e-01,6.669093668460845947e-02,3.802514693234115839e-04,3.605126589536666870e-02,3.825873881578445435e-02,5.703527480363845825e-02,6.093725491128805238e-01,5.349416532629409221e-02,7.415783275786098638e-01,7.283704175611198650e-01,6.525071638422642595e-01,7.303498572629313346e-01,2.002654578875795177e-01,7.371714364026081823e-01,3.619188686608916794e-01,3.099812941028922131e-01,5.565063753053853951e-02,3.299581036331036277e-01,3.605957982918240323e-01 -4.400000000000000000e+01,5.822703987360000610e-02,7.075455458741118919e-01,5.765088647603988647e-02,3.462342105836703765e-01,3.125000000000000065e-05,2.777497842907905579e-02,6.628511473536491394e-04,2.117313444614410400e-02,2.174271829426288605e-02,2.438138052821159363e-02,8.700455257953249033e-01,6.796645807946677387e-02,8.824540086649047543e-01,8.695612044219637182e-01,8.831718854438014299e-01,6.752336025238037109e-02,3.799579862970858812e-04,3.667435050010681152e-02,3.855218365788459778e-02,5.765973031520843506e-02,6.095982785396706349e-01,5.466589094564063694e-02,7.405244689229176780e-01,7.274844330826566452e-01,6.515848106624280156e-01,7.295350220072881475e-01,2.059644071069134108e-01,7.364478398577973817e-01,3.621229527844233020e-01,3.128254244499993897e-01,5.804053561308113868e-02,3.322142502772474915e-01,3.604570526307017686e-01 -4.500000000000000000e+01,5.769359692931175232e-02,7.088952219240789443e-01,5.611725896596908569e-02,3.457854467122016828e-01,1.562500000000000033e-05,2.767258509993553162e-02,6.651677540503442287e-04,2.108610421419143677e-02,2.170417644083499908e-02,2.434734068810939789e-02,8.704508903408876286e-01,6.714432446217231953e-02,8.826457559752397541e-01,8.697000307649652706e-01,8.833458586902458443e-01,6.731349974870681763e-02,3.842133446596562862e-04,3.603804111480712891e-02,3.825381025671958923e-02,5.746502429246902466e-02,6.087264313957002626e-01,5.315064640925604850e-02,7.408080425410550340e-01,7.277592053589144738e-01,6.514728543804696459e-01,7.327779654086312711e-01,2.024004856589385615e-01,7.395825228860876122e-01,3.616162917402771515e-01,3.116594983302576893e-01,5.662300786174526840e-02,3.312077718562869699e-01,3.598959023096113818e-01 -4.600000000000000000e+01,5.745465308427810669e-02,7.093090052191836081e-01,5.534964427351951599e-02,3.458918012321102187e-01,1.562500000000000033e-05,2.762340381741523743e-02,6.656824261881411076e-04,2.107143960893154144e-02,2.172498032450675964e-02,2.431985363364219666e-02,8.705947439892899320e-01,6.757555349179884818e-02,8.827781726566783504e-01,8.697761021354575295e-01,8.835025464756910418e-01,6.718486547470092773e-02,3.804236184805631638e-04,3.601611778140068054e-02,3.843561187386512756e-02,5.741376802325248718e-02,6.077893411843272586e-01,5.001972933418522699e-02,7.405460099978279365e-01,7.271469445069219661e-01,6.504525764632010931e-01,7.360548475941092184e-01,2.017586109909301761e-01,7.427582127472494022e-01,3.626873048749004180e-01,3.125231373892896625e-01,5.544993939067584948e-02,3.317397689311892273e-01,3.605279768709976351e-01 -4.700000000000000000e+01,5.755202844738960266e-02,7.094526245926545682e-01,5.603271350264549255e-02,3.436986831991284408e-01,1.562500000000000033e-05,2.761166542768478394e-02,6.623791414313018322e-04,2.107540890574455261e-02,2.169752866029739380e-02,2.426778897643089294e-02,8.706998947355369944e-01,6.624190698800845600e-02,8.827928573609269414e-01,8.697687837970961011e-01,8.835294958386371578e-01,6.708716601133346558e-02,3.838978882413357496e-04,3.574781119823455811e-02,3.820417821407318115e-02,5.716274306178092957e-02,6.069471741938499143e-01,5.111831078369336728e-02,7.407809113987623428e-01,7.273025784631999002e-01,6.501304704598123152e-01,7.336412752850877128e-01,2.038583258365815054e-01,7.401499917193310463e-01,3.608014601519458076e-01,3.102317670183311615e-01,5.707784324779167223e-02,3.296459424914170988e-01,3.588569573464798212e-01 -4.800000000000000000e+01,5.773221328854560852e-02,7.091742106206258001e-01,5.671997740864753723e-02,3.434390243436385992e-01,1.562500000000000033e-05,2.763002924621105194e-02,6.727011641487479210e-04,2.109275013208389282e-02,2.168871462345123291e-02,2.432486228644847870e-02,8.707913166638922009e-01,6.690043756836742961e-02,8.827819345601858325e-01,8.698173358497038876e-01,8.835564698481661594e-01,6.732903420925140381e-02,3.897958667948842049e-04,3.587563335895538330e-02,3.841435164213180542e-02,5.726577341556549072e-02,6.071362488653184730e-01,5.433829709532146668e-02,7.409303220453330452e-01,7.277695362485639974e-01,6.503840816440107364e-01,7.320757418118554183e-01,2.053662484820551470e-01,7.386397963519978349e-01,3.624746603871766282e-01,3.096988676000239082e-01,5.772596753198275948e-02,3.292777611974421204e-01,3.606933941165191837e-01 -4.900000000000000000e+01,5.744978040456771851e-02,7.093154408998256777e-01,5.561470240354537964e-02,3.444123957010851722e-01,1.562500000000000033e-05,2.764600142836570740e-02,6.590643315576016903e-04,2.105278149247169495e-02,2.165265567600727081e-02,2.437323331832885742e-02,8.708487731923589825e-01,6.608317857522315319e-02,8.829438927414984262e-01,8.700246898896746295e-01,8.837622376542761948e-01,6.782389432191848755e-02,3.755304787773638964e-04,3.631832078099250793e-02,3.838998079299926758e-02,5.780165642499923706e-02,6.078100862332325161e-01,5.935557787600220098e-02,7.407617383560607394e-01,7.274707542544325278e-01,6.510144586348578510e-01,7.331774862231902334e-01,2.021975615192862230e-01,7.396517237089234031e-01,3.613093074463315513e-01,3.106812137270248964e-01,5.521973921801121704e-02,3.298824469686564287e-01,3.589976688376887992e-01 -5.000000000000000000e+01,5.744143947958946228e-02,7.096113973815068032e-01,5.578177794814109802e-02,3.440315274742876128e-01,7.812500000000000163e-06,2.758510597050189972e-02,6.609005504287779331e-04,2.105022780597209930e-02,2.167608402669429779e-02,2.424302324652671814e-02,8.709811809435680230e-01,6.677995588459902099e-02,8.829151597688368325e-01,8.699930227440740849e-01,8.838281586068192919e-01,6.783218681812286377e-02,3.785888548009097576e-04,3.638352081179618835e-02,3.856224194169044495e-02,5.775172635912895203e-02,6.077613343840500004e-01,5.516893543981719189e-02,7.409062808528776856e-01,7.277482362042895225e-01,6.509364047043794121e-01,7.337173362346266492e-01,2.039715474619706592e-01,7.402187135041840005e-01,3.617603782530501300e-01,3.102615198805290797e-01,5.667052811720077465e-02,3.296842553492516092e-01,3.594805250401529872e-01 -5.100000000000000000e+01,5.746058002114295959e-02,7.096573657180469397e-01,5.589713528752326965e-02,3.443466027509430316e-01,7.812500000000000163e-06,2.756033092737197876e-02,6.627957336604595184e-04,2.108188718557357788e-02,2.164329215884208679e-02,2.425745688378810883e-02,8.710167152754775266e-01,6.569096697135820562e-02,8.829446448338443831e-01,8.700608138395168334e-01,8.837941146224719269e-01,6.732848286628723145e-02,3.802987630479037762e-04,3.573525324463844299e-02,3.827473148703575134e-02,5.732126533985137939e-02,6.076442981306482416e-01,5.461907718325954147e-02,7.409988985411296580e-01,7.278288417045507552e-01,6.508177928270638679e-01,7.343908303498809520e-01,2.035377593945188468e-01,7.409945037241421062e-01,3.624381373643129622e-01,3.106487420758040074e-01,5.555166539029344347e-02,3.299577067962531918e-01,3.602340987901400671e-01 -5.200000000000000000e+01,5.738569423556327820e-02,7.099512803252361337e-01,5.574252083897590637e-02,3.441396789367732190e-01,7.812500000000000163e-06,2.754599787294864655e-02,6.607761024497449398e-04,2.102622576057910919e-02,2.166540734469890594e-02,2.420506067574024200e-02,8.711537022378423867e-01,6.543294074551236905e-02,8.830061080640903004e-01,8.700840736724950730e-01,8.839310295663087569e-01,6.759815663099288940e-02,3.784334985539317131e-04,3.612096607685089111e-02,3.848814219236373901e-02,5.745160952210426331e-02,6.075964732096398313e-01,5.593347406072308320e-02,7.409179484254615478e-01,7.276072011916628890e-01,6.509216219801829961e-01,7.347097594234488493e-01,2.026618912124049376e-01,7.412273077491132733e-01,3.618820826802758295e-01,3.101322328973821763e-01,5.558650150301541748e-02,3.295844654713537825e-01,3.596749711973725172e-01 -5.300000000000000000e+01,5.726695433259010315e-02,7.099092009597289810e-01,5.506875365972518921e-02,3.448645051657324156e-01,7.812500000000000163e-06,2.753267809748649597e-02,6.609478732571005821e-04,2.107972465455532074e-02,2.165041863918304443e-02,2.422757446765899658e-02,8.711347038217133187e-01,6.577574063057256559e-02,8.830393593638441452e-01,8.701435287650705064e-01,8.838324106851745965e-01,6.722164154052734375e-02,3.794580115936696529e-04,3.561870753765106201e-02,3.819055855274200439e-02,5.719408392906188965e-02,6.070218216437966996e-01,5.198784401657766813e-02,7.408011083228955851e-01,7.275787722839508476e-01,6.501541018088694557e-01,7.370305291565372174e-01,2.022317206845467563e-01,7.435495241228671226e-01,3.627283076848499266e-01,3.114589174387702997e-01,5.477136767835608794e-02,3.306253956319393228e-01,3.602222168156140047e-01 -5.400000000000000000e+01,5.749739706516265869e-02,7.099768000574888660e-01,5.629877001047134399e-02,3.435642449469926141e-01,7.812500000000000163e-06,2.749819681048393250e-02,6.618950865231454372e-04,2.104782499372959137e-02,2.163715288043022156e-02,2.419226616621017456e-02,8.712632372035862272e-01,6.457463255110587608e-02,8.830277765559811920e-01,8.700969804745376512e-01,8.839593674779178123e-01,6.745953857898712158e-02,3.796762612182646990e-04,3.572872281074523926e-02,3.828851878643035889e-02,5.735072493553161621e-02,6.070244758575673583e-01,5.501328047543069949e-02,7.407822708789688626e-01,7.273625368430606253e-01,6.504314565645372692e-01,7.338703054532845771e-01,2.037055377244740284e-01,7.404006892535789364e-01,3.608267107595114487e-01,3.097512729440159429e-01,5.595773492613229094e-02,3.293947202124622997e-01,3.586948945963912561e-01 -5.500000000000000000e+01,5.744592472910881042e-02,7.099502447958720985e-01,5.605857446789741516e-02,3.440822106348935816e-01,3.906250000000000081e-06,2.750833705067634583e-02,6.614544545300304890e-04,2.101761102676391602e-02,2.164744585752487183e-02,2.418000809848308563e-02,8.712630698303130972e-01,6.575795292532818359e-02,8.830568487743437611e-01,8.701431496428014833e-01,8.840183839907495011e-01,6.754182279109954834e-02,3.790056507568806410e-04,3.599338233470916748e-02,3.844262659549713135e-02,5.744356289505958557e-02,6.071553680617974846e-01,5.538666302768226191e-02,7.405784465696630958e-01,7.272834916682324735e-01,6.502788928308976812e-01,7.344872764498233675e-01,2.039611062079114967e-01,7.410120574928570347e-01,3.622459033902148406e-01,3.102944620565963318e-01,5.621457463940952859e-02,3.297463352021089977e-01,3.599476293087465750e-01 -5.600000000000000000e+01,5.746303126215934753e-02,7.099635005156946788e-01,5.614554136991500854e-02,3.439336098482917992e-01,3.906250000000000081e-06,2.751494385302066803e-02,6.622456712648272514e-04,2.102038636803627014e-02,2.164217457175254822e-02,2.418814785778522491e-02,8.712946808144153010e-01,6.554859784255236133e-02,8.830379431413794000e-01,8.701335894882702426e-01,8.840337577906892674e-01,6.765138357877731323e-02,3.801561833824962378e-04,3.606564179062843323e-02,3.847213834524154663e-02,5.756577849388122559e-02,6.070577713647951068e-01,5.566291200979119752e-02,7.405575932262146166e-01,7.272849178545600646e-01,6.502626324498993471e-01,7.340726998346212007e-01,2.033669902555134135e-01,7.406457469733201959e-01,3.616563648407477016e-01,3.100256766548040166e-01,5.593236919252329853e-02,3.295938089942700433e-01,3.593854559770280344e-01 -5.700000000000000000e+01,5.748935043811798096e-02,7.099813197060538261e-01,5.631250515580177307e-02,3.437170825525101003e-01,3.906250000000000081e-06,2.751132473349571228e-02,6.638185004703700542e-04,2.102210000157356262e-02,2.163031511008739471e-02,2.418697997927665710e-02,8.713340250157509681e-01,6.594080996969724218e-02,8.830353768040084539e-01,8.701472339562361658e-01,8.840857498130265668e-01,6.779824197292327881e-02,3.823727893177419901e-04,3.607602044939994812e-02,3.841697052121162415e-02,5.771909281611442566e-02,6.070268507093916632e-01,5.523025315558896531e-02,7.405728137837412905e-01,7.272655890373751486e-01,6.502818643337041626e-01,7.338888727480074037e-01,2.034808955781119699e-01,7.404993973829826492e-01,3.612731567732452298e-01,3.100130420248641827e-01,5.618285865226124026e-02,3.295905327230008175e-01,3.589679277044617312e-01 -5.800000000000000000e+01,5.745500326156616211e-02,7.100520055173937806e-01,5.618080496788024902e-02,3.439299963749520295e-01,3.906250000000000081e-06,2.748979255557060242e-02,6.636264733970165253e-04,2.101479843258857727e-02,2.162936888635158539e-02,2.416725456714630127e-02,8.714037647121626318e-01,6.638927770915006854e-02,8.830848436809125568e-01,8.701791992659164698e-01,8.841333273198243026e-01,6.774181127548217773e-02,3.816561074927449226e-04,3.600073605775833130e-02,3.844484314322471619e-02,5.765548348426818848e-02,6.069957855584394713e-01,5.484584515529485060e-02,7.405033353968931698e-01,7.272297042634101594e-01,6.501928909772668463e-01,7.344980635267722713e-01,2.035563248389018476e-01,7.410796593347169781e-01,3.620049125807568990e-01,3.102097996031332738e-01,5.611079887527249677e-02,3.297294828354042084e-01,3.595955216620245198e-01 -5.900000000000000000e+01,5.758251622319221497e-02,7.099037073395471076e-01,5.662655457854270935e-02,3.439635165985814869e-01,3.906250000000000081e-06,2.749112620949745178e-02,6.636538892053067684e-04,2.101693116128444672e-02,2.163022197782993317e-02,2.416982501745223999e-02,8.714278858185701138e-01,6.632164256115566370e-02,8.830627070952667967e-01,8.701511792836306158e-01,8.841536428611110887e-01,6.779840588569641113e-02,3.819456615019589663e-04,3.601596131920814514e-02,3.840891271829605103e-02,5.769450217485427856e-02,6.071504341831778229e-01,5.515850220565964718e-02,7.403165391151330654e-01,7.270850253579197453e-01,6.502341220190568372e-01,7.335112982184727182e-01,2.046558771622793427e-01,7.401405102076468179e-01,3.614544687204442885e-01,3.105029894514958477e-01,5.667124680036145917e-02,3.300118707392660222e-01,3.589813260740831735e-01 -6.000000000000000000e+01,5.750261992216110229e-02,7.100298328197944819e-01,5.636451765894889832e-02,3.438838045476164673e-01,1.953125000000000041e-06,2.748706191778182983e-02,6.626528920605778694e-04,2.101116254925727844e-02,2.163318917155265808e-02,2.416505478322505951e-02,8.714440609389956238e-01,6.643742194557779313e-02,8.830893986407003515e-01,8.701764642334249844e-01,8.841600853386872849e-01,6.775550544261932373e-02,3.810750204138457775e-04,3.611311316490173340e-02,3.846086561679840088e-02,5.765195190906524658e-02,6.070095771636930815e-01,5.501938157445027816e-02,7.403823023680670135e-01,7.271268339545726711e-01,6.501884122178752667e-01,7.338650128192699684e-01,2.041193825277973217e-01,7.404693941472164642e-01,3.614324956331061989e-01,3.102934198398368260e-01,5.633098881812795278e-02,3.297916667773376220e-01,3.590016348394912127e-01 -6.100000000000000000e+01,5.747239291667938232e-02,7.100768114204669690e-01,5.626931041479110718e-02,3.439365447182763935e-01,1.953125000000000041e-06,2.747968956828117371e-02,6.619442719966173172e-04,2.100781723856925964e-02,2.162843756377696991e-02,2.416320890188217163e-02,8.714569874907842628e-01,6.659394519421914238e-02,8.831089530212642424e-01,8.701930727936474375e-01,8.841699136549296956e-01,6.778241693973541260e-02,3.806125023402273655e-04,3.609474375844001770e-02,3.844692185521125793e-02,5.768891796469688416e-02,6.069438787520539114e-01,5.535387902445150499e-02,7.403574306710092312e-01,7.270986131176008227e-01,6.501294715026701976e-01,7.342165450768297630e-01,2.039093186302871619e-01,7.408261259316137881e-01,3.616949636917873856e-01,3.103177510311216358e-01,5.614140965732253297e-02,3.297947445288641477e-01,3.592100906461591636e-01 -6.200000000000000000e+01,5.746459960937500000e-02,7.100954651034809828e-01,5.624506995081901550e-02,3.439711506156754584e-01,1.953125000000000041e-06,2.747949771583080292e-02,6.624918896704912186e-04,2.100725285708904266e-02,2.163183130323886871e-02,2.416116371750831604e-02,8.714739594260987321e-01,6.672604597846470975e-02,8.831149008602924289e-01,8.702029745773181002e-01,8.841927019913112806e-01,6.782055646181106567e-02,3.808027831837534904e-04,3.615681082010269165e-02,3.848693892359733582e-02,5.771644786000251770e-02,6.069152541184574812e-01,5.572132985734255806e-02,7.403267779546696126e-01,7.270852823131191967e-01,6.500916139521180082e-01,7.342327062846002450e-01,2.042021921463162415e-01,7.408494357672560371e-01,3.614715809750129738e-01,3.102934626020606435e-01,5.644253990570220758e-02,3.297711858555714692e-01,3.590089602660738732e-01 -6.300000000000000000e+01,5.744896084070205688e-02,7.101646034684171438e-01,5.623002350330352783e-02,3.438030499367885628e-01,1.953125000000000041e-06,2.747701667249202728e-02,6.622786750085651875e-04,2.100756950676441193e-02,2.162049338221549988e-02,2.416110970079898834e-02,8.714915366816392561e-01,6.672908403116362130e-02,8.831199580932652671e-01,8.702139938330905045e-01,8.841768239195370027e-01,6.778392195701599121e-02,3.816551761701703072e-04,3.604271262884140015e-02,3.843371570110321045e-02,5.768740922212600708e-02,6.067463913864807878e-01,5.468604846667494968e-02,7.403845391950052424e-01,7.271417171701070048e-01,6.500002166688594318e-01,7.346104551545374894e-01,2.041861597972399467e-01,7.412228067091590766e-01,3.616012191394945008e-01,3.102571322292139167e-01,5.626679479673205725e-02,3.297149303789014274e-01,3.591025463489887493e-01 -6.400000000000000000e+01,5.737597122788429260e-02,7.102790380416147409e-01,5.594910308718681335e-02,3.440291630858124949e-01,1.953125000000000041e-06,2.745947800576686859e-02,6.628466653637588024e-04,2.100154012441635132e-02,2.161486633121967316e-02,2.414684183895587921e-02,8.715167208854792680e-01,6.663791033460179924e-02,8.831506117808006762e-01,8.702436333903951216e-01,8.842038666303311256e-01,6.763724237680435181e-02,3.813193761743605137e-04,3.602033108472824097e-02,3.839222714304924011e-02,5.756296962499618530e-02,6.066215904891890665e-01,5.462397042410631343e-02,7.403788276418387104e-01,7.271107596709052157e-01,6.499326042803451609e-01,7.350360101939639179e-01,2.037992325926081538e-01,7.416203556735097013e-01,3.614885406456637695e-01,3.104073318576248686e-01,5.628447374123765612e-02,3.298390288829440853e-01,3.589506423431298443e-01 -6.500000000000000000e+01,5.742330849170684814e-02,7.102498495237604681e-01,5.615479126572608948e-02,3.438248638467049645e-01,9.765625000000000203e-07,2.746735513210296631e-02,6.624046945944428444e-04,2.100297436118125916e-02,2.161747589707374573e-02,2.415156923234462738e-02,8.715226440095005245e-01,6.662532191158315742e-02,8.831408454158657939e-01,8.702381230362054021e-01,8.842093549178463574e-01,6.771884113550186157e-02,3.814140218310058117e-04,3.604901954531669617e-02,3.842851519584655762e-02,5.762577056884765625e-02,6.066099091433172497e-01,5.480663671696575645e-02,7.403786493495110310e-01,7.271063989182965370e-01,6.499111084779034542e-01,7.347419887624648815e-01,2.040652269559434795e-01,7.413429098350969859e-01,3.615473024798027124e-01,3.101995896802399177e-01,5.639015446311485685e-02,3.296759007834815236e-01,3.590577368393563784e-01 -6.600000000000000000e+01,5.743084847927093506e-02,7.102458390551315004e-01,5.619189888238906860e-02,3.437223281006636655e-01,9.765625000000000203e-07,2.746964804828166962e-02,6.623897934332489967e-04,2.100237645208835602e-02,2.161710336804389954e-02,2.415246516466140747e-02,8.715239695041208101e-01,6.680110964960517261e-02,8.831428916515681182e-01,8.702413473815729938e-01,8.842140637364832578e-01,6.778001040220260620e-02,3.814703086391091347e-04,3.608370944857597351e-02,3.843955323100090027e-02,5.767344683408737183e-02,6.065907863892668894e-01,5.480893479841097982e-02,7.403868191174977076e-01,7.271154265714514509e-01,6.499082967719681525e-01,7.345655244079198898e-01,2.041366339695062093e-01,7.411724055749353557e-01,3.615937466484192009e-01,3.100744881473868619e-01,5.643906446673701421e-02,3.295617429962663381e-01,3.591223140172120076e-01 -6.700000000000000000e+01,5.742966383695602417e-02,7.102276910859203207e-01,5.616797134280204773e-02,3.438750019743646580e-01,9.765625000000000203e-07,2.746456302702426910e-02,6.620165659114718437e-04,2.100214920938014984e-02,2.161811105906963348e-02,2.414805628359317780e-02,8.715300259666258764e-01,6.661088202982859419e-02,8.831511863294048137e-01,8.702485664725656545e-01,8.842212554124229129e-01,6.773312389850616455e-02,3.811963542830199003e-04,3.603926673531532288e-02,3.844437748193740845e-02,5.762740597128868103e-02,6.066108230143272273e-01,5.494236575551991741e-02,7.403686133376564671e-01,7.271292363145139825e-01,6.499158466610417406e-01,7.345826176530317886e-01,2.041374430034333942e-01,7.411916060699529352e-01,3.615420531365333146e-01,3.101976754017236049e-01,5.635779141127397751e-02,3.296675423609912170e-01,3.590533129951267166e-01 -6.800000000000000000e+01,5.744453147053718567e-02,7.101912353749495477e-01,5.621329694986343384e-02,3.439541669591849593e-01,9.765625000000000203e-07,2.746905013918876648e-02,6.624023662880063057e-04,2.100083045661449432e-02,2.161679789423942566e-02,2.414926886558532715e-02,8.715216710079438656e-01,6.686462762640484059e-02,8.831522530561179973e-01,8.702580736671434725e-01,8.842256963318463336e-01,6.779894232749938965e-02,3.813615185208618641e-04,3.608727455139160156e-02,3.845654800534248352e-02,5.767928063869476318e-02,6.066489740043111700e-01,5.514803987322123430e-02,7.403531417310654783e-01,7.271265485903766201e-01,6.499131376244264846e-01,7.345535053173876117e-01,2.041591845041441367e-01,7.411710204180917971e-01,3.615164223696791246e-01,3.102713116455638187e-01,5.637762968686108045e-02,3.297313494457086436e-01,3.590069624682669658e-01 -6.900000000000000000e+01,5.741333588957786560e-02,7.102344719011565166e-01,5.610705539584159851e-02,3.438906163069733735e-01,9.765625000000000203e-07,2.746745012700557709e-02,6.620911299251019955e-04,2.099974639713764191e-02,2.161715179681777954e-02,2.414671331644058228e-02,8.715295877193216523e-01,6.683181535985072141e-02,8.831582617509405875e-01,8.702657265821421850e-01,8.842268641732424772e-01,6.775505840778350830e-02,3.812537470366805792e-04,3.609113395214080811e-02,3.846439346671104431e-02,5.765100196003913879e-02,6.065827827516634407e-01,5.499353293042178598e-02,7.403678755139304624e-01,7.271498666099009967e-01,6.498810361927637169e-01,7.346256213232769117e-01,2.040405239921606606e-01,7.412257716723893441e-01,3.614186606072066765e-01,3.101862189384682611e-01,5.631335244027101811e-02,3.296347005457743173e-01,3.589207643789073532e-01 -7.000000000000000000e+01,5.741957575082778931e-02,7.102338759210974350e-01,5.613540112972259521e-02,3.438565519280359362e-01,4.882812500000000102e-07,2.746713533997535706e-02,6.622620276175439358e-04,2.100080437958240509e-02,2.161522209644317627e-02,2.414687536656856537e-02,8.715329194263845558e-01,6.680114083732613395e-02,8.831555895355329699e-01,8.702661176641476315e-01,8.842277415884156611e-01,6.776099652051925659e-02,3.813746734522283077e-04,3.607115894556045532e-02,3.845753893256187439e-02,5.765837803483009338e-02,6.065597806446760831e-01,5.491732931327965306e-02,7.403657343645365652e-01,7.271482386203614867e-01,6.498592251183369362e-01,7.346088142577709146e-01,2.040645957742745487e-01,7.412128134982870487e-01,3.613981219948474433e-01,3.101717848451308046e-01,5.628795248480193691e-02,3.296199044585383930e-01,3.588923755329502807e-01 -7.100000000000000000e+01,5.743572488427162170e-02,7.102025293807017192e-01,5.619068816304206848e-02,3.438917688213767865e-01,4.882812500000000102e-07,2.746425755321979523e-02,6.623473600484430790e-04,2.099950797855854034e-02,2.161705493927001953e-02,2.414534427225589752e-02,8.715370933640044226e-01,6.680158793679501217e-02,8.831599715635095604e-01,8.702678064043369854e-01,8.842362622394025484e-01,6.778512895107269287e-02,3.813570365309715271e-04,3.609488159418106079e-02,3.846958279609680176e-02,5.767019465565681458e-02,6.066114257530637044e-01,5.517179878912516905e-02,7.403524103149407010e-01,7.271451906747401495e-01,6.498958894936933683e-01,7.344465778515022469e-01,2.040861550498316579e-01,7.410578372863244612e-01,3.613194215880365379e-01,3.102081560806959071e-01,5.626919462228825025e-02,3.296579241971322460e-01,3.588155066651922964e-01 -7.200000000000000000e+01,5.742456763982772827e-02,7.102330874794131610e-01,5.615560337901115417e-02,3.438496383175498883e-01,4.882812500000000102e-07,2.746473066508769989e-02,6.623619119636714458e-04,2.099896781146526337e-02,2.161580696702003479e-02,2.414513006806373596e-02,8.715425118069819455e-01,6.680827397049549088e-02,8.831623669097378171e-01,8.702705559340625507e-01,8.842386380628706188e-01,6.778574734926223755e-02,3.813081129919737577e-04,3.610007464885711670e-02,3.846602514386177063e-02,5.767326802015304565e-02,6.065865652272027786e-01,5.515785854182109205e-02,7.403676238964812528e-01,7.271459364112643486e-01,6.498823077501467704e-01,7.345185652658234865e-01,2.040652932886340698e-01,7.411264224684612767e-01,3.614207807064758193e-01,3.101370057278158288e-01,5.628216519104396742e-02,3.295882582440780029e-01,3.589288847564161000e-01 -7.300000000000000000e+01,5.744622275233268738e-02,7.102085440379439785e-01,5.624263361096382141e-02,3.438078231277241215e-01,4.882812500000000102e-07,2.746675536036491394e-02,6.622779183089733124e-04,2.099933102726936340e-02,2.161627635359764099e-02,2.414718270301818848e-02,8.715486005796245772e-01,6.681960083939397776e-02,8.831601373665650678e-01,8.702650369683572196e-01,8.842437072602662429e-01,6.783352047204971313e-02,3.813345101661980152e-04,3.611586242914199829e-02,3.846872225403785706e-02,5.771346017718315125e-02,6.066047430300115506e-01,5.530605698219152183e-02,7.403510049412492799e-01,7.271327409855227186e-01,6.498895821470151990e-01,7.343251359196801831e-01,2.042279057627584826e-01,7.409417212156231836e-01,3.613473336454958718e-01,3.101037521015050369e-01,5.636500249825535103e-02,3.295673234357141546e-01,3.588698875484411244e-01 -7.400000000000000000e+01,5.745136737823486328e-02,7.101988652753689069e-01,5.626487359404563904e-02,3.437961959620443042e-01,4.882812500000000102e-07,2.746806852519512177e-02,6.624182569794356823e-04,2.100029215216636658e-02,2.161525748670101166e-02,2.414771541953086853e-02,8.715464962571461971e-01,6.673250778543272921e-02,8.831571289386703771e-01,8.702652558859645948e-01,8.842419306220477004e-01,6.784765422344207764e-02,3.814064257312566042e-04,3.609406203031539917e-02,3.846426680684089661e-02,5.771929025650024414e-02,6.065959654872017381e-01,5.517422321250689543e-02,7.403405030580366697e-01,7.271262946793806137e-01,6.498627731350653525e-01,7.343356287452170728e-01,2.042494631860750920e-01,7.409576015036694052e-01,3.613675009667304261e-01,3.101217650133613057e-01,5.629325226478007482e-02,3.295818792319797352e-01,3.588877992376497961e-01 -7.500000000000000000e+01,5.744588002562522888e-02,7.102078285940360836e-01,5.624829977750778198e-02,3.437983046230574380e-01,2.441406250000000051e-07,2.746831253170967102e-02,6.624551606364548206e-04,2.099987678229808807e-02,2.161517180502414703e-02,2.414772287011146545e-02,8.715481559739700623e-01,6.672828455264281922e-02,8.831588453122196647e-01,8.702672689314630006e-01,8.842446283828105935e-01,6.786394119262695312e-02,3.813432704191654921e-04,3.610038384795188904e-02,3.846692293882369995e-02,5.772996321320533752e-02,6.065904907838698401e-01,5.520335012537037206e-02,7.403407249192688333e-01,7.271236230294804148e-01,6.498558244496220881e-01,7.343600900759987837e-01,2.042524123136491288e-01,7.409805332907912767e-01,3.614077350502166719e-01,3.101093339909245516e-01,5.630572561695176836e-02,3.295716581338060669e-01,3.589284385806786326e-01 -7.600000000000000000e+01,5.743892490863800049e-02,7.102216325694971077e-01,5.622515082359313965e-02,3.437954216054376344e-01,2.441406250000000051e-07,2.746747434139251709e-02,6.626070244237780571e-04,2.100008539855480194e-02,2.161485888063907623e-02,2.414709888398647308e-02,8.715492001269232736e-01,6.670314663601538407e-02,8.831602269790401749e-01,8.702697340896236033e-01,8.842413607944816789e-01,6.783617287874221802e-02,3.813692019321024418e-04,3.608340770006179810e-02,3.846577182412147522e-02,5.770989507436752319e-02,6.065669487708768015e-01,5.507845098411880136e-02,7.403505736808677629e-01,7.271360778216400256e-01,6.498418034119605169e-01,7.344514811222639938e-01,2.042009962502181475e-01,7.410714216144047572e-01,3.614115257143830640e-01,3.101078123435152545e-01,5.626472263132843016e-02,3.295700648258561016e-01,3.589282743186844038e-01 -7.700000000000000000e+01,5.743740871548652649e-02,7.102277645436181341e-01,5.621990188956260681e-02,3.437912222676542395e-01,2.441406250000000051e-07,2.746638841927051544e-02,6.626519025303423405e-04,2.099964395165443420e-02,2.161437086760997772e-02,2.414614520967006683e-02,8.715510605716333403e-01,6.668044542525251861e-02,8.831618085627179759e-01,8.702718690627626597e-01,8.842433024221280080e-01,6.783072650432586670e-02,3.813685907516628504e-04,3.608386218547821045e-02,3.846294432878494263e-02,5.770359560847282410e-02,6.065518996553731501e-01,5.512295738221845848e-02,7.403490945075877905e-01,7.271339920355295305e-01,6.498351631318796118e-01,7.344367821116366546e-01,2.042106800712302217e-01,7.410545454497475815e-01,3.613939652687481185e-01,3.100906819358428823e-01,5.629561459838820781e-02,3.295534443168421923e-01,3.589142486480900729e-01 -7.800000000000000000e+01,5.742450430989265442e-02,7.102489533366833641e-01,5.617469176650047302e-02,3.437790764511438057e-01,2.441406250000000051e-07,2.746506966650485992e-02,6.624925299547612667e-04,2.100067958235740662e-02,2.161271870136260986e-02,2.414591051638126373e-02,8.715520732867861886e-01,6.664341673793017229e-02,8.831628856262063731e-01,8.702750003923352962e-01,8.842404304654249980e-01,6.780597567558288574e-02,3.813672810792922974e-04,3.604932129383087158e-02,3.845183923840522766e-02,5.768522620201110840e-02,6.065137423796700400e-01,5.495576474417412927e-02,7.403605034412954478e-01,7.271430670287354348e-01,6.498163814275317307e-01,7.345507906434630696e-01,2.041300058224560510e-01,7.411677319636353900e-01,3.614287691137362257e-01,3.100878057155768697e-01,5.622565621818903514e-02,3.295461832279625303e-01,3.589406211929877522e-01 -7.900000000000000000e+01,5.741957202553749084e-02,7.102535173267034985e-01,5.615540221333503723e-02,3.438023976347557298e-01,2.441406250000000051e-07,2.746395580470561981e-02,6.624498637393116951e-04,2.100028656423091888e-02,2.161260321736335754e-02,2.414489351212978363e-02,8.715540603538532993e-01,6.665346977670373596e-02,8.831650306271450201e-01,8.702775371404991578e-01,8.842427695310736135e-01,6.780055165290832520e-02,3.813297662418335676e-04,3.604963421821594238e-02,3.845350816845893860e-02,5.768076702952384949e-02,6.065057029300869873e-01,5.494590809392143477e-02,7.403565822759506920e-01,7.271388317076141750e-01,6.498053591684698205e-01,7.345912936291569828e-01,2.041239682220660767e-01,7.412080624280539265e-01,3.614513459967580999e-01,3.101168658392585153e-01,5.621218204044639566e-02,3.295692281711170568e-01,3.589595529608528568e-01 -8.000000000000000000e+01,5.742327868938446045e-02,7.102504219218946924e-01,5.617029592394828796e-02,3.437985082666789594e-01,1.220703125000000025e-07,2.746420912444591522e-02,6.624478264711797237e-04,2.100002393126487732e-02,2.161327749490737915e-02,2.414488419890403748e-02,8.715553793996473342e-01,6.668622610354618674e-02,8.831649061447780502e-01,8.702772064294299614e-01,8.842449672757642931e-01,6.780930608510971069e-02,3.813274670392274857e-04,3.605801984667778015e-02,3.845958784222602844e-02,5.768844112753868103e-02,6.065086159650444619e-01,5.495675849027614052e-02,7.403526602871517426e-01,7.271364830789397438e-01,6.498056284249777992e-01,7.345706335879287341e-01,2.041451938521659237e-01,7.411880511018625883e-01,3.614587231489704289e-01,3.101153737674690603e-01,5.622062298497036009e-02,3.295674922735567502e-01,3.589650043976567728e-01 -8.100000000000000000e+01,5.742004513740539551e-02,7.102552233824797057e-01,5.615895241498947144e-02,3.438009832114546360e-01,1.220703125000000025e-07,2.746364288032054901e-02,6.624411325901746750e-04,2.099973335862159729e-02,2.161274664103984833e-02,2.414433844387531281e-02,8.715567418555276724e-01,6.667365819663925719e-02,8.831662958821379084e-01,8.702785747588579479e-01,8.842461137663830684e-01,6.780733168125152588e-02,3.813440271187573671e-04,3.605687990784645081e-02,3.845658153295516968e-02,5.768571048974990845e-02,6.065045349047678558e-01,5.493589447177506246e-02,7.403531421841038629e-01,7.271358950685630207e-01,6.498024614359654283e-01,7.345784323300510454e-01,2.041305808100165875e-01,7.411949400847568370e-01,3.614325347432615354e-01,3.101178326569315469e-01,5.622187147412986696e-02,3.295680858940626123e-01,3.589360490815998728e-01 -8.200000000000000000e+01,5.742454528808593750e-02,7.102536211330112703e-01,5.617781728506088257e-02,3.437949748221078572e-01,1.220703125000000025e-07,2.746343612670898438e-02,6.624619127251207829e-04,2.099967002868652344e-02,2.161291614174842834e-02,2.414404414594173431e-02,8.715582469488831752e-01,6.667628739681512318e-02,8.831660680878352654e-01,8.702780360038786522e-01,8.842482640540055838e-01,6.781229376792907715e-02,3.813602670561522245e-04,3.605883195996284485e-02,3.845781832933425903e-02,5.768891796469688416e-02,6.065076667294944102e-01,5.495254475954052670e-02,7.403493774394225291e-01,7.271307410576480779e-01,6.498010496227788479e-01,7.345430041073197636e-01,2.041551692820713915e-01,7.411600160967464213e-01,3.614112487133256946e-01,3.101169881487820246e-01,5.624037693540302751e-02,3.295691186051292743e-01,3.589150673760931887e-01 -8.300000000000000000e+01,5.741937085986137390e-02,7.102646833694312711e-01,5.616059526801109314e-02,3.437875116461047154e-01,1.220703125000000025e-07,2.746262215077877045e-02,6.624469533562660217e-04,2.099954150617122650e-02,2.161208540201187134e-02,2.414362318813800812e-02,8.715596380042260893e-01,6.665438315321364771e-02,8.831675816643849153e-01,8.702796044123495278e-01,8.842474870367829087e-01,6.780055910348892212e-02,3.813409712165594101e-04,3.605354949831962585e-02,3.845212981104850769e-02,5.768060684204101562e-02,6.064956414959886688e-01,5.493389466612151606e-02,7.403580775376392697e-01,7.271369333260118140e-01,6.497981526826565046e-01,7.345749001675088152e-01,2.041367756464162186e-01,7.411899318080075183e-01,3.614002741940437469e-01,3.101005109603698906e-01,5.623601058817087606e-02,3.295541032431022477e-01,3.589059645250776143e-01 -8.400000000000000000e+01,5.742282792925834656e-02,7.102602077522777169e-01,5.617344006896018982e-02,3.437879448014057870e-01,1.220703125000000025e-07,2.746327593922615051e-02,6.624107481911778450e-04,2.099902927875518799e-02,2.161283418536186218e-02,2.414352260529994965e-02,8.715599722999042287e-01,6.668134927302638015e-02,8.831673466751756019e-01,8.702795956575404279e-01,8.842507511258999031e-01,6.781244277954101562e-02,3.813021467067301273e-04,3.606931120157241821e-02,3.845940902829170227e-02,5.769089236855506897e-02,6.065012723608875778e-01,5.499186535075765991e-02,7.403508380939906042e-01,7.271287527484887603e-01,6.497969210242429128e-01,7.345521057569089907e-01,2.041456915753170898e-01,7.411681356864782133e-01,3.614087352742270109e-01,3.101010336203619544e-01,5.624676560807435888e-02,3.295551977613382921e-01,3.589165827975167034e-01 -8.500000000000000000e+01,5.742383003234863281e-02,7.102593869730534637e-01,5.617755278944969177e-02,3.437851166294035865e-01,6.103515625000000127e-08,2.746325172483921051e-02,6.624160450883209705e-04,2.099900133907794952e-02,2.161286771297454834e-02,2.414354868233203888e-02,8.715608062245510101e-01,6.668276563026212522e-02,8.831674927718244916e-01,8.702796529290203198e-01,8.842511316899783758e-01,6.781384348869323730e-02,3.813048533629626036e-04,3.606985881924629211e-02,3.845983371138572693e-02,5.769224092364311218e-02,6.065017000850139173e-01,5.500202172672521289e-02,7.403500074081836857e-01,7.271286242946808365e-01,6.497979597943042140e-01,7.345461560816259894e-01,2.041580107852390413e-01,7.411625852311527485e-01,3.614117454931655149e-01,3.100988984322044506e-01,5.625210006108104926e-02,3.295532419031205196e-01,3.589201405935464884e-01 -8.600000000000000000e+01,5.742476135492324829e-02,7.102577166814763032e-01,5.618143454194068909e-02,3.437860673037613224e-01,6.103515625000000127e-08,2.746317721903324127e-02,6.624088273383677006e-04,2.099902741611003876e-02,2.161268331110477448e-02,2.414346486330032349e-02,8.715609745634425032e-01,6.668429221677837915e-02,8.831675716440425816e-01,8.702801914155418039e-01,8.842517808547284419e-01,6.781657040119171143e-02,3.813170769717544317e-04,3.606923297047615051e-02,3.845962882041931152e-02,5.769429728388786316e-02,6.065015667970146129e-01,5.501792494191445199e-02,7.403491660686467579e-01,7.271283221611252179e-01,6.497967066819320126e-01,7.345436121881204761e-01,2.041618529719605168e-01,7.411608221796346374e-01,3.614174993926673740e-01,3.100996006103592384e-01,5.625190901768166440e-02,3.295539167726508345e-01,3.589251923969645763e-01 -8.700000000000000000e+01,5.742425099015235901e-02,7.102597402265301563e-01,5.618052184581756592e-02,3.437816513065331536e-01,6.103515625000000127e-08,2.746314555406570435e-02,6.624137749895453453e-04,2.099907957017421722e-02,2.161258272826671600e-02,2.414346486330032349e-02,8.715616197665645437e-01,6.668009172373261240e-02,8.831678667479145872e-01,8.702805211557190779e-01,8.842518682405621222e-01,6.781435012817382812e-02,3.813206567429006100e-04,3.606607764959335327e-02,3.845885768532752991e-02,5.769266933202743530e-02,6.065005489542699690e-01,5.500491741334506690e-02,7.403505796290379415e-01,7.271300146719492652e-01,6.497975534486524207e-01,7.345501588966292239e-01,2.041616479228390568e-01,7.411670201525287771e-01,3.614134888071269258e-01,3.100970349862665065e-01,5.625026578452416159e-02,3.295516220044625300e-01,3.589199517714117271e-01 -8.800000000000000000e+01,5.742482095956802368e-02,7.102610341983937037e-01,5.618404969573020935e-02,3.437716071276898377e-01,6.103515625000000127e-08,2.746328897774219513e-02,6.624396773986518383e-04,2.099916152656078339e-02,2.161259576678276062e-02,2.414366602897644043e-02,8.715621148233181348e-01,6.668368526771051297e-02,8.831676130337948738e-01,8.702803624611001876e-01,8.842520066339106810e-01,6.781849265098571777e-02,3.813256043940782547e-04,3.606628254055976868e-02,3.845921531319618225e-02,5.769608914852142334e-02,6.064983040540150583e-01,5.501151616932171279e-02,7.403516565604084665e-01,7.271295040258479725e-01,6.497967397218882279e-01,7.345460186766975541e-01,2.041725718048502392e-01,7.411631172426720315e-01,3.614178419427707678e-01,3.100866926065189433e-01,5.625602693862640641e-02,3.295421033584158832e-01,3.589255757506658595e-01 -8.900000000000000000e+01,5.742535740137100220e-02,7.102602700873654751e-01,5.618613958358764648e-02,3.437749806570415956e-01,6.103515625000000127e-08,2.746353484690189362e-02,6.624433444812893867e-04,2.099914476275444031e-02,2.161250449717044830e-02,2.414372749626636505e-02,8.715623620935524229e-01,6.667737659294606378e-02,8.831675821657406500e-01,8.702805849956876116e-01,8.842521383030135240e-01,6.781842559576034546e-02,3.813384973909705877e-04,3.606744483113288879e-02,3.845893591642379761e-02,5.769626796245574951e-02,6.065021882422694244e-01,5.501647321737686974e-02,7.403518650629383746e-01,7.271322890442554199e-01,6.497994543215112051e-01,7.345403284212455031e-01,2.041695695030512625e-01,7.411579896989215488e-01,3.614340780278993415e-01,3.100864449011108692e-01,5.625480940280294662e-02,3.295422640160611261e-01,3.589414591791941778e-01 -9.000000000000000000e+01,5.742720514535903931e-02,7.102574562376572365e-01,5.619290471076965332e-02,3.437764460693469859e-01,3.051757812500000064e-08,2.746373228728771210e-02,6.624161615036427975e-04,2.099910192191600800e-02,2.161275967955589294e-02,2.414384670555591583e-02,8.715623132075172030e-01,6.668807637986462478e-02,8.831674153196664712e-01,8.702805237292446927e-01,8.842525469967530416e-01,6.782269477844238281e-02,3.813300572801381350e-04,3.607061877846717834e-02,3.846121206879615784e-02,5.769957974553108215e-02,6.065060219820423981e-01,5.503423987277752255e-02,7.403500209198955462e-01,7.271312575679095280e-01,6.498009542043783338e-01,7.345292694679929069e-01,2.041793018001358817e-01,7.411475698598882778e-01,3.614327498634438141e-01,3.100892356773357061e-01,5.625932627504737216e-02,3.295452059159525438e-01,3.589403043226604417e-01 -9.100000000000000000e+01,5.742630735039710999e-02,7.102588910144457257e-01,5.618974566459655762e-02,3.437782352952818976e-01,3.051757812500000064e-08,2.746357209980487823e-02,6.623930530622601509e-04,2.099904604256153107e-02,2.161267399787902832e-02,2.414374239742755890e-02,8.715624175541218932e-01,6.668484338112633247e-02,8.831677245896590867e-01,8.702808713766587712e-01,8.842525653260127072e-01,6.782145798206329346e-02,3.813205112237483263e-04,3.607034683227539062e-02,3.846084699034690857e-02,5.769851058721542358e-02,6.065037941992372783e-01,5.502904275149276409e-02,7.403492967169220673e-01,7.271310026517361358e-01,6.497990451241880683e-01,7.345395487245528487e-01,2.041752937338662255e-01,7.411575976380556652e-01,3.614393885949500618e-01,3.100922308855101894e-01,5.625429539251478039e-02,3.295469858190657741e-01,3.589457473718164482e-01 -9.200000000000000000e+01,5.742597207427024841e-02,7.102592754383779683e-01,5.618848279118537903e-02,3.437810267037063605e-01,3.051757812500000064e-08,2.746345847845077515e-02,6.623783847317099571e-04,2.099903672933578491e-02,2.161254547536373138e-02,2.414366416633129120e-02,8.715624646103242723e-01,6.668456966930118301e-02,8.831679259620964784e-01,8.702811981563622901e-01,8.842526408152533435e-01,6.782101094722747803e-02,3.813080256804823875e-04,3.606924414634704590e-02,3.846025466918945312e-02,5.769795551896095276e-02,6.065019717847847103e-01,5.502628692895356749e-02,7.403497489148200827e-01,7.271307707089539329e-01,6.497979019243056431e-01,7.345463889467864771e-01,2.041730743630215394e-01,7.411644707540356869e-01,3.614368745602211663e-01,3.100943990664665750e-01,5.625078781013140988e-02,3.295488505874840657e-01,3.589439006174725555e-01 -9.300000000000000000e+01,5.742697045207023621e-02,7.102574923029804088e-01,5.619199946522712708e-02,3.437837338260280595e-01,3.051757812500000064e-08,2.746360935270786285e-02,6.624151137657463551e-04,2.099906280636787415e-02,2.161253057420253754e-02,2.414369955658912659e-02,8.715624958332319761e-01,6.668857907904449100e-02,8.831677699435963591e-01,8.702811425971618275e-01,8.842530038548164217e-01,6.782369315624237061e-02,3.813255170825868845e-04,3.607001155614852905e-02,3.846047818660736084e-02,5.770011991262435913e-02,6.065051917421470096e-01,5.502141280420194680e-02,7.403477283781759732e-01,7.271301766202132866e-01,6.497982940777305982e-01,7.345412190348534764e-01,2.041792869080393258e-01,7.411600235732921371e-01,3.614369759222857970e-01,3.100994729535130334e-01,5.625291258045726772e-02,3.295536287179154922e-01,3.589429192136726621e-01 -9.400000000000000000e+01,5.742746219038963318e-02,7.102563154624900177e-01,5.619365721940994263e-02,3.437862046159803620e-01,3.051757812500000064e-08,2.746367827057838440e-02,6.624052766710519791e-04,2.099899388849735260e-02,2.161255665123462677e-02,2.414371073246002197e-02,8.715623925121640525e-01,6.669259301730738609e-02,8.831678098162296653e-01,8.702813134274873796e-01,8.842534607436839389e-01,6.782675534486770630e-02,3.813199873548001051e-04,3.607209771871566772e-02,3.846112638711929321e-02,5.770229920744895935e-02,6.065070089296641376e-01,5.503022576882060646e-02,7.403466347282283699e-01,7.271294141216424478e-01,6.497990071087068609e-01,7.345372821665852037e-01,2.041820663731753194e-01,7.411561034109079849e-01,3.614360982622374374e-01,3.101021480963429555e-01,5.625362064777472693e-02,3.295559569789580645e-01,3.589423428538700556e-01 -9.500000000000000000e+01,5.742703750729560852e-02,7.102569368484444867e-01,5.619209259748458862e-02,3.437863875497129129e-01,1.525878906250000032e-08,2.746364288032054901e-02,6.623973604291677475e-04,2.099897712469100952e-02,2.161252126097679138e-02,2.414368651807308197e-02,8.715624576018268233e-01,6.669376552850886375e-02,8.831679109726302546e-01,8.702814666682135991e-01,8.842534967828880044e-01,6.782664358615875244e-02,3.813143412116914988e-04,3.607213124632835388e-02,3.846103325486183167e-02,5.770227313041687012e-02,6.065063963792194368e-01,5.502879930785751356e-02,7.403467771952495502e-01,7.271294226491348267e-01,6.497986774818259592e-01,7.345407597214546058e-01,2.041818029266593004e-01,7.411594022836662798e-01,3.614371247467591530e-01,3.101022643236751031e-01,5.625301273860582735e-02,3.295556554624058387e-01,3.589432466792510934e-01 -9.600000000000000000e+01,5.742678791284561157e-02,7.102575520972506107e-01,5.619135499000549316e-02,3.437856280610490645e-01,1.525878906250000032e-08,2.746361866593360901e-02,6.624010857194662094e-04,2.099897339940071106e-02,2.161247096955776215e-02,2.414365112781524658e-02,8.715625138140986605e-01,6.669376107974200885e-02,8.831680326898636579e-01,8.702816169756135700e-01,8.842534472271667001e-01,6.782566010951995850e-02,3.813155053649097681e-04,3.607146814465522766e-02,3.846075013279914856e-02,5.770148709416389465e-02,6.065047930719577041e-01,5.502466650980317869e-02,7.403471140747229784e-01,7.271298053896527724e-01,6.497974098810830323e-01,7.345431741808966519e-01,2.041813274201347839e-01,7.411617321492262045e-01,3.614393388577165078e-01,3.101010506631156072e-01,5.625284969015263009e-02,3.295544392626322816e-01,3.589454730277931160e-01 -9.700000000000000000e+01,5.742698535323143005e-02,7.102573362458866058e-01,5.619213730096817017e-02,3.437870707514761870e-01,1.525878906250000032e-08,2.746362797915935516e-02,6.623939843848347664e-04,2.099893055856227875e-02,2.161259949207305908e-02,2.414362877607345581e-02,8.715625979873579121e-01,6.669771919788446135e-02,8.831680724676759242e-01,8.702816760955561781e-01,8.842538026328752299e-01,6.782711297273635864e-02,3.813042712863534689e-04,3.607279434800148010e-02,3.846183791756629944e-02,5.770270153880119324e-02,6.065066086491071040e-01,5.503128305077718829e-02,7.403467665509644302e-01,7.271292686309098752e-01,6.497982853711653517e-01,7.345432199076017410e-01,2.041833803809668946e-01,7.411617869837417993e-01,3.614402063993495395e-01,3.101021552493902211e-01,5.625366139488278960e-02,3.295553474636763736e-01,3.589460570228465430e-01 -9.800000000000000000e+01,5.742775276303291321e-02,7.102563257942547947e-01,5.619505420327186584e-02,3.437868536375007777e-01,1.525878906250000032e-08,2.746368013322353363e-02,6.624005036428570747e-04,2.099893055856227875e-02,2.161265723407268524e-02,2.414363436400890350e-02,8.715626216531162651e-01,6.669872117073184781e-02,8.831679648722633447e-01,8.702815725062246210e-01,8.842540431483839614e-01,6.782810389995574951e-02,3.813096263911575079e-04,3.607365116477012634e-02,3.846231102943420410e-02,5.770342797040939331e-02,6.065077478649176790e-01,5.503514446043885483e-02,7.403463647436743233e-01,7.271291605538280356e-01,6.497988977719499903e-01,7.345372687393231237e-01,2.041856672287047370e-01,7.411561993314802477e-01,3.614395982609147628e-01,3.101020264633129742e-01,5.625488237129971925e-02,3.295555820748442000e-01,3.589459024230869932e-01 -9.900000000000000000e+01,5.742808803915977478e-02,7.102558540605663495e-01,5.619632825255393982e-02,3.437867991928307276e-01,1.525878906250000032e-08,2.746366523206233978e-02,6.624017842113971710e-04,2.099892869591712952e-02,2.161265537142753601e-02,2.414361946284770966e-02,8.715626273732197671e-01,6.669814984436445160e-02,8.831679477860365779e-01,8.702816305084354331e-01,8.842541294929460172e-01,6.782823801040649414e-02,3.813100629486143589e-04,3.607377037405967712e-02,3.846235945820808411e-02,5.770352855324745178e-02,6.065081304513683103e-01,5.503931070687841792e-02,7.403462395819607744e-01,7.271290619693382418e-01,6.497991553380486618e-01,7.345340126649899659e-01,2.041871967844338664e-01,7.411530658095542012e-01,3.614379600582254271e-01,3.101018571036791571e-01,5.625574519011593277e-02,3.295554763053956671e-01,3.589443249033947292e-01 diff --git a/streaming_gopt_best/test_metrics.json b/streaming_gopt_best/test_metrics.json deleted file mode 100644 index bd0da1d320c1e88a6eeeb7c523538cd1a9c5b04e..0000000000000000000000000000000000000000 --- a/streaming_gopt_best/test_metrics.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "phone_test_mse": 0.04919730871915817, - "phone_test_pcc": 0.3975705055993251, - "utt_test_mse": [ - 0.051985688507556915, - 0.0016903950599953532, - 0.03446277603507042, - 0.03239584341645241, - 0.04794545844197273 - ], - "utt_test_pcc": [ - 0.651909193610124, - 0.012690043750859805, - 0.7249977587357453, - 0.7332794084754206, - 0.681940037784353 - ], - "word_test_mse": [ - 0.06279397755861282, - 0.0037991644348949194, - 0.04641091078519821, - 0.14399507641792297 - ], - "word_test_pcc": [ - 0.4047142491023989, - -0.0039119825110344765, - 0.4122583381095728, - 0.41746734262039764 - ], - "word_score_names": [ - "accuracy", - "stress", - "total", - "asr_accuracy" - ], - "best_epoch": 11 -} \ No newline at end of file diff --git a/streampa/__init__.py b/streampa/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..822b12d10a391c36a7409a678a86c992e20fca0e --- /dev/null +++ b/streampa/__init__.py @@ -0,0 +1,4 @@ +from .pipeline import StreamPAPipeline, StreamPASession + +__all__ = ['StreamPAPipeline', 'StreamPASession'] +__version__ = '1.0.0' diff --git a/streampa/charsiu_model.py b/streampa/charsiu_model.py new file mode 100644 index 0000000000000000000000000000000000000000..c8aa86545f88ea5b9c2da8d3aa3c7b06f803de29 --- /dev/null +++ b/streampa/charsiu_model.py @@ -0,0 +1,55 @@ +# MIT-licensed Charsiu frame classifier, extracted without numerical changes. +import torch +import torch.nn as nn +from transformers import Wav2Vec2ForCTC +from transformers.modeling_outputs import CausalLMOutput +class Wav2Vec2ForFrameClassification(Wav2Vec2ForCTC): + + def forward( + self, + input_values, + attention_mask=None, + output_attentions=None, + output_hidden_states=None, + return_dict=None, + labels=None, + ): + + return_dict = return_dict if return_dict is not None else self.config.use_return_dict + + outputs = self.wav2vec2( + input_values, + attention_mask=attention_mask, + output_attentions=output_attentions, + output_hidden_states=output_hidden_states, + return_dict=return_dict, + ) + + hidden_states = outputs[0] + hidden_states = self.dropout(hidden_states) + + logits = self.lm_head(hidden_states) + + loss = None + if labels is not None: + + if labels.max() >= self.config.vocab_size: + raise ValueError(f"Label values must be <= vocab_size: {self.config.vocab_size}") + + # retrieve loss input_lengths from attention_mask + attention_mask = ( + attention_mask if attention_mask is not None else torch.ones_like(input_values, dtype=torch.long) + ) +# input_lengths = self._get_feat_extract_output_lengths(attention_mask.sum(-1)).to(torch.long) + + loss = nn.functional.cross_entropy(logits.view(-1,logits.size(2)), labels.flatten(), reduction="mean") + + + + if not return_dict: + output = (logits,) + outputs[2:] + return ((loss,) + output) if loss is not None else output + + return CausalLMOutput( + loss=loss, logits=logits, hidden_states=outputs.hidden_states, attentions=outputs.attentions + ) diff --git a/streampa/frontend.py b/streampa/frontend.py new file mode 100644 index 0000000000000000000000000000000000000000..c8f6b7a3f99facc208ca9497c178585b54620bf5 --- /dev/null +++ b/streampa/frontend.py @@ -0,0 +1,1556 @@ +# Frozen inference function extraction. See source provenance and licenses. +import gc +import math +import re +from collections import Counter +from itertools import groupby +import numpy as np +import librosa +import torch +from transformers import AutoProcessor, AutoModelForSpeechSeq2Seq +EPS = 1e-8 +EPS_TOKEN = '' + +def normalize_phone(phone): + phone = phone.upper().strip() + phone = phone.replace('[', '').replace(']', '') + phone = re.sub(r'[_\d].*', '', phone) + return phone + + +def normalize_word(word): + word = word.upper().strip() + word = word.replace('[', '').replace(']', '') + word = re.sub(r"[^A-Z']", '', word) + return word + + +def monotonic_align(neg_log_probs, phone_ids): + frame_num = neg_log_probs.shape[0] + token_num = len(phone_ids) + if frame_num < token_num: + raise ValueError(f'Not enough frames ({frame_num}) to align {token_num} phones.') + + dp = np.full((frame_num, token_num), np.inf, dtype=np.float32) + back = np.zeros((frame_num, token_num), dtype=np.int8) + dp[0, 0] = neg_log_probs[0, phone_ids[0]] + + for t in range(1, frame_num): + max_token = min(t, token_num - 1) + for tok in range(max_token + 1): + stay_cost = dp[t - 1, tok] + move_cost = dp[t - 1, tok - 1] if tok > 0 else np.inf + if move_cost < stay_cost: + dp[t, tok] = move_cost + neg_log_probs[t, phone_ids[tok]] + back[t, tok] = 1 + else: + dp[t, tok] = stay_cost + neg_log_probs[t, phone_ids[tok]] + + path = np.zeros(frame_num, dtype=np.int32) + tok = token_num - 1 + for t in range(frame_num - 1, -1, -1): + path[t] = tok + if t > 0 and back[t, tok] == 1: + tok -= 1 + return path + +def select_visible_frames(probs, keep_mask, audio_end, frame_step): + frame_limit = max(int(math.ceil(audio_end / max(frame_step, EPS))), 1) + frame_mask = np.zeros(len(probs), dtype=bool) + frame_mask[: min(frame_limit, len(probs))] = True + visible_mask = keep_mask & frame_mask + return np.flatnonzero(visible_mask), probs[visible_mask] + +def softmax_1d(values): + arr = np.asarray(values, dtype=np.float64) + if arr.size == 0: + return arr.astype(np.float32) + pos_inf = np.isposinf(arr) + if np.any(pos_inf): + out = np.zeros_like(arr, dtype=np.float64) + out[pos_inf] = 1.0 / float(np.sum(pos_inf)) + return out.astype(np.float32) + finite = np.isfinite(arr) + if not np.any(finite): + return np.full(arr.shape, 1.0 / float(arr.size), dtype=np.float32) + min_finite = np.min(arr[finite]) + arr = np.where(finite, arr, min_finite - 50.0) + arr = arr - np.max(arr) + exp_arr = np.exp(arr) + return (exp_arr / np.clip(exp_arr.sum(), EPS, None)).astype(np.float32) + + +def entropy_np(probs): + probs = np.asarray(probs, dtype=np.float64) + probs = probs[probs > 0] + if probs.size == 0: + return 0.0 + return float(-np.sum(probs * np.log(np.clip(probs, EPS, None)))) + + +def top_margin(probs): + probs = np.asarray(probs, dtype=np.float32) + if probs.size == 0: + return 0.0, 0.0 + top = np.sort(probs)[::-1] + top1 = float(top[0]) + top2 = float(top[1]) if top.size > 1 else 0.0 + return top1, float(top1 - top2) + + +def js_divergence(p, q): + p = np.asarray(p, dtype=np.float64) + q = np.asarray(q, dtype=np.float64) + p = p / np.clip(p.sum(), EPS, None) + q = q / np.clip(q.sum(), EPS, None) + m = 0.5 * (p + q) + kl_pm = np.sum(p * (np.log(np.clip(p, EPS, None)) - np.log(np.clip(m, EPS, None)))) + kl_qm = np.sum(q * (np.log(np.clip(q, EPS, None)) - np.log(np.clip(m, EPS, None)))) + return float(0.5 * (kl_pm + kl_qm)) + + +def safe_json(value): + if isinstance(value, dict): + return {str(key): safe_json(val) for key, val in value.items()} + if isinstance(value, (list, tuple)): + return [safe_json(item) for item in value] + if isinstance(value, np.ndarray): + return safe_json(value.tolist()) + if isinstance(value, (np.floating, np.integer)): + return value.item() + return value + + +def softmax_np_matrix(values): + arr = np.asarray(values, dtype=np.float64) + if arr.size == 0: + return arr.astype(np.float32) + arr = arr - np.max(arr, axis=-1, keepdims=True) + exp_arr = np.exp(arr) + return (exp_arr / np.clip(np.sum(exp_arr, axis=-1, keepdims=True), EPS, None)).astype(np.float32) + + +def audio_array_logits(audio, processor, model, sample_rate, device): + audio = np.asarray(audio, dtype=np.float32) + if hasattr(processor, 'audio_preprocess'): + inputs = processor.audio_preprocess(audio, sr=sample_rate) + inputs = torch.tensor(inputs, dtype=torch.float32).unsqueeze(0).to(device) + model_inputs = {'input_values': inputs} + else: + model_inputs = processor(audio, sampling_rate=sample_rate, return_tensors='pt') + model_inputs = {key: value.to(device) for key, value in model_inputs.items()} + with torch.no_grad(): + logits = model(**model_inputs).logits[0].detach().cpu().numpy() + return softmax_np_matrix(logits), float(len(audio) / sample_rate) + + +def non_overlapping_occurrences(tokens, pattern): + positions = [] + pattern_size = len(pattern) + cursor = 0 + while cursor <= len(tokens) - pattern_size: + if tokens[cursor : cursor + pattern_size] == pattern: + positions.append(cursor) + cursor += pattern_size + else: + cursor += 1 + return positions + + +def find_repeated_ngram( + words, + min_repeats, + max_ngram_size=12, + strict=False, + min_coverage=0.6, + dominant_token_ratio=0.5, +): + if min_repeats <= 0: + return None + tokens = [str(word['text']) for word in words] + if not tokens: + return None + + for ngram_size in range(1, min(max_ngram_size, len(tokens)) + 1): + span = ngram_size * min_repeats + for start in range(0, len(tokens) - span + 1): + pattern = tokens[start : start + ngram_size] + repeats = 1 + cursor = start + ngram_size + while tokens[cursor : cursor + ngram_size] == pattern: + repeats += 1 + cursor += ngram_size + if repeats >= min_repeats: + return { + 'start': int(start), + 'ngram_size': int(ngram_size), + 'repeats': int(repeats), + 'pattern': pattern, + 'detection': 'contiguous_cycle', + } + + if not strict: + return None + + token_counts = Counter(tokens) + dominant_token, dominant_count = token_counts.most_common(1)[0] + token_ratio = float(dominant_count) / float(len(tokens)) + if dominant_count >= max(min_repeats * 2, 8) and token_ratio >= dominant_token_ratio: + return { + 'start': None, + 'ngram_size': 1, + 'repeats': int(dominant_count), + 'pattern': [dominant_token], + 'coverage': token_ratio, + 'detection': 'dominant_token', + } + + max_size = min(max_ngram_size, len(tokens) // max(min_repeats, 1)) + for ngram_size in range(max_size, 1, -1): + candidates = Counter( + tuple(tokens[start : start + ngram_size]) + for start in range(0, len(tokens) - ngram_size + 1) + ) + for pattern, raw_count in candidates.most_common(): + if raw_count < min_repeats: + break + positions = non_overlapping_occurrences(tokens, list(pattern)) + if len(positions) < min_repeats: + continue + coverage = float(len(positions) * ngram_size) / float(len(tokens)) + if coverage >= min_coverage: + return { + 'start': int(positions[0]), + 'ngram_size': int(ngram_size), + 'repeats': int(len(positions)), + 'pattern': list(pattern), + 'coverage': coverage, + 'detection': 'high_coverage_periodicity', + } + return None + + +class PhoneMapper: + def __init__(self, lexicon, phn_dict): + self.lexicon = lexicon + self.phn_dict = phn_dict + self.cache = {} + self.fallback_phone = 'AH' if 'AH' in phn_dict else (next(iter(phn_dict)) if phn_dict else None) + self.g2p = None + try: + from g2p_en import G2p + + self.g2p = G2p() + except Exception: + pass + + def word_to_phones(self, word): + word = normalize_word(word) + if word in self.lexicon: + return list(self.lexicon[word]), 'lexicon' + if word in self.cache: + return self.cache[word] + if self.g2p is not None: + try: + phones = [] + for raw_phone in self.g2p(word.lower()): + phone = normalize_phone(raw_phone) + if phone and phone in self.phn_dict: + phones.append(phone) + if phones: + result = (phones, 'g2p_en') + self.cache[word] = result + return result + except Exception: + self.g2p = None + if self.fallback_phone is None: + result = ([], 'unmapped') + else: + approx_len = max(1, int(math.ceil(len(re.sub(r'[^A-Z]', '', word)) / 3.0))) + result = ([self.fallback_phone] * approx_len, 'fallback_phone') + self.cache[word] = result + return result + + def words_to_phone_sequence(self, words): + phones = [] + phone_to_word = [] + source_counts = Counter() + for word_idx, word in enumerate(words): + cur_phones, source = self.word_to_phones(word) + source_counts[source] += 1 + for phone in cur_phones: + phones.append(phone) + phone_to_word.append(word_idx) + return phones, phone_to_word, dict(source_counts) + + +class WhisperNBestGenerator: + def __init__(self, model_name, language, device, nbest, beam_size, max_new_tokens, no_repeat_ngram_size): + self.processor = AutoProcessor.from_pretrained(model_name) + torch_dtype = torch.float16 if str(device).startswith('cuda') else torch.float32 + self.model = AutoModelForSpeechSeq2Seq.from_pretrained(model_name, torch_dtype=torch_dtype) + self.model.to(device) + self.model.eval() + self.model_dtype = next(self.model.parameters()).dtype + self.language = language + self.device = device + self.nbest = int(nbest) + self.beam_size = max(int(beam_size), int(nbest)) + self.max_new_tokens = int(max_new_tokens) + self.no_repeat_ngram_size = int(no_repeat_ngram_size) + self.forced_decoder_ids = None + if hasattr(self.processor, 'get_decoder_prompt_ids'): + try: + self.forced_decoder_ids = self.processor.get_decoder_prompt_ids( + language=language, + task='transcribe', + ) + except Exception: + self.forced_decoder_ids = None + + @torch.inference_mode() + def generate(self, audio, sample_rate, audio_end): + inputs = self.processor( + np.asarray(audio, dtype=np.float32), + sampling_rate=sample_rate, + return_tensors='pt', + return_attention_mask=True, + ) + inputs = {key: value.to(self.device) for key, value in inputs.items()} + for key in ('input_features', 'input_values'): + if key in inputs and torch.is_floating_point(inputs[key]): + inputs[key] = inputs[key].to(dtype=self.model_dtype) + generate_kwargs = { + 'num_beams': self.beam_size, + 'num_return_sequences': self.nbest, + 'max_new_tokens': self.max_new_tokens, + 'return_dict_in_generate': True, + 'output_scores': True, + 'do_sample': False, + } + if self.no_repeat_ngram_size > 0: + generate_kwargs['no_repeat_ngram_size'] = self.no_repeat_ngram_size + if self.forced_decoder_ids is not None: + generate_kwargs['forced_decoder_ids'] = self.forced_decoder_ids + output = self.model.generate(**inputs, **generate_kwargs) + if torch.is_tensor(output): + sequences = output + sequence_scores = [0.0 for _ in range(int(sequences.shape[0]))] + transition_scores = [] + else: + sequences = output.sequences + if getattr(output, 'sequences_scores', None) is not None: + sequence_scores = output.sequences_scores.detach().float().cpu().numpy().tolist() + else: + sequence_scores = [0.0 for _ in range(int(sequences.shape[0]))] + transition_scores = self._transition_scores(output) + texts = self.processor.batch_decode(sequences, skip_special_tokens=True) + + rows = [] + for rank, (text, sequence_score) in enumerate(zip(texts, sequence_scores)): + token_ids = sequences[rank].detach().cpu().tolist() + token_logprobs = ( + transition_scores[rank] + if rank < len(transition_scores) + else [float(sequence_score) for _ in token_ids] + ) + token_rows, word_rows = self._token_word_scores(token_ids, token_logprobs) + words = [row['word'] for row in word_rows] + length_norm = ( + float(np.mean([row['logprob'] for row in token_rows])) + if token_rows + else float(sequence_score) + ) + rows.append({ + 'rank': int(rank), + 'text': ' '.join(words).lower(), + 'words': words, + 'logprob': float(length_norm), + 'sequence_score': float(sequence_score), + 'length_normalized_sequence_score': float(length_norm), + 'token_ids': [int(row['token_id']) for row in token_rows], + 'token_logprobs': [float(row['logprob']) for row in token_rows], + 'token_confidences': [float(row['confidence']) for row in token_rows], + 'word_token_ranges': [[int(row['token_start']), int(row['token_end'])] for row in word_rows], + 'word_logprobs': [float(row['logprob']) for row in word_rows], + 'word_confidences': [float(row['confidence']) for row in word_rows], + 'word_timestamps': estimate_word_timestamps(words, audio_end), + }) + if str(self.device).startswith('cuda'): + torch.cuda.empty_cache() + gc.collect() + return rows + + def _transition_scores(self, output): + if getattr(output, 'scores', None) is None: + return [] + try: + sequences = output.sequences.detach().cpu() + step_scores = [score.detach().float().cpu() for score in output.scores] + if not step_scores: + return [] + beam_indices = getattr(output, 'beam_indices', None) + if beam_indices is not None: + beam_indices = beam_indices.detach().cpu() + generated_steps = len(step_scores) + start = max(0, int(sequences.shape[1]) - generated_steps) + rows = [] + for seq_idx in range(int(sequences.shape[0])): + cur = [] + for step, logits in enumerate(step_scores): + token_pos = start + step + if token_pos >= int(sequences.shape[1]): + break + token_id = int(sequences[seq_idx, token_pos]) + if token_id < 0 or token_id >= int(logits.shape[-1]): + cur.append(0.0) + continue + score_row = min(seq_idx, int(logits.shape[0]) - 1) + if beam_indices is not None and seq_idx < int(beam_indices.shape[0]) and token_pos < int(beam_indices.shape[1]): + candidate = int(beam_indices[seq_idx, token_pos]) + if 0 <= candidate < int(logits.shape[0]): + score_row = candidate + log_probs = torch.log_softmax(logits[score_row], dim=-1) + cur.append(float(log_probs[token_id].item())) + rows.append(cur) + return rows + except Exception: + return [] + + def _token_word_scores(self, token_ids, token_logprobs): + tokenizer = self.processor.tokenizer + special_ids = set(getattr(tokenizer, 'all_special_ids', []) or []) + if len(token_logprobs) != len(token_ids): + aligned = [0.0 for _ in token_ids] + offset = max(0, len(token_ids) - len(token_logprobs)) + for idx, value in enumerate(token_logprobs[-len(token_ids) :]): + pos = offset + idx + if pos < len(aligned): + aligned[pos] = float(value) + token_logprobs = aligned + token_rows = [] + words = [] + current = [] + current_token_ids = [] + current_logprobs = [] + current_start = None + + def flush(): + nonlocal current, current_token_ids, current_logprobs, current_start + word = normalize_word(''.join(current)) + if word: + avg_logprob = float(np.mean(current_logprobs)) if current_logprobs else 0.0 + words.append({ + 'word': word, + 'token_start': int(current_start if current_start is not None else 0), + 'token_end': int((current_token_ids[-1] + 1) if current_token_ids else 0), + 'logprob': avg_logprob, + 'confidence': float(np.clip(np.exp(avg_logprob), 0.0, 1.0)), + }) + current = [] + current_token_ids = [] + current_logprobs = [] + current_start = None + + for pos, token_id in enumerate(token_ids): + if int(token_id) in special_ids: + continue + logprob = float(token_logprobs[pos]) if pos < len(token_logprobs) else 0.0 + try: + text = tokenizer.decode([int(token_id)], skip_special_tokens=True, clean_up_tokenization_spaces=False) + except TypeError: + text = tokenizer.decode([int(token_id)], skip_special_tokens=True) + if not text: + continue + token_rows.append({ + 'token_id': int(token_id), + 'logprob': logprob, + 'confidence': float(np.clip(np.exp(logprob), 0.0, 1.0)), + }) + for char in text: + if char.isalpha() or char == "'": + if current_start is None: + current_start = pos + current.append(char) + current_token_ids.append(pos) + current_logprobs.append(logprob) + else: + flush() + flush() + return token_rows, words + + +def normalize_text_to_words(text): + tokens = [] + for token in re.findall(r"[A-Za-z']+", text): + norm = normalize_word(token) + if norm: + tokens.append(norm) + return tokens + + +def estimate_word_timestamps(words, audio_end): + if not words: + return [] + step = float(audio_end) / max(len(words), 1) + rows = [] + for idx, word in enumerate(words): + rows.append({ + 'word': word.lower(), + 'start': float(idx * step), + 'end': float(min(audio_end, (idx + 1) * step)), + 'source': 'duration_proportional_estimate', + }) + return rows + + +def hypothesis_phone_rows(row, phone_mapper, phn_dict): + phones = [] + phone_ids = [] + phone_to_word = [] + phone_confidences = [] + source_counts = Counter() + word_confidences = row.get('word_confidences') or [1.0 for _ in row.get('words', [])] + for word_idx, word in enumerate(row.get('words', [])): + cur_phones, source = phone_mapper.word_to_phones(word) + source_counts[source] += 1 + word_conf = float(word_confidences[word_idx]) if word_idx < len(word_confidences) else 1.0 + word_conf = float(np.clip(word_conf, 0.0, 1.0)) + for phone in cur_phones: + if phone not in phn_dict: + continue + phones.append(phone) + phone_ids.append(int(phn_dict[phone])) + phone_to_word.append(int(word_idx)) + phone_confidences.append(word_conf) + return { + 'phones': phones, + 'phone_ids': phone_ids, + 'phone_to_word': phone_to_word, + 'phone_confidences': phone_confidences, + 'source_counts': dict(source_counts), + } + + +def align_hypothesis_with_charsiu(item, row, phone_mapper, phn_dict, phone_to_frame_id, audio_end): + hyp = hypothesis_phone_rows(row, phone_mapper, phn_dict) + words = row.get('words', []) + if not words or not hyp['phone_ids']: + row['word_timestamps'] = [] + row['timestamp_source'] = 'empty_hypothesis' + row['phone_times'] = [] + row['phone_acoustic_supports'] = [] + return row + + kept_indices, kept_probs = select_visible_frames(item['probs'], item['keep_mask'], audio_end, item['frame_step']) + frame_phone_ids = [] + id_to_phone = {idx: phone for phone, idx in phn_dict.items()} + try: + for phone_idx in hyp['phone_ids']: + phone = id_to_phone[int(phone_idx)] + frame_phone_ids.append(phone_to_frame_id[phone]) + if kept_probs.shape[0] < len(frame_phone_ids): + raise ValueError('not_enough_visible_frames_for_hypothesis') + path = monotonic_align(-np.log(np.clip(kept_probs, EPS, None)), frame_phone_ids) + phone_times = [] + phone_acoustic_supports = [] + for phone_pos, frame_phone_id in enumerate(frame_phone_ids): + local_frames = kept_indices[path == phone_pos] + if local_frames.size == 0: + raise ValueError('empty_aligned_phone_span') + start_time = float(local_frames.min() * item['frame_step']) + end_time = float((local_frames.max() + 1) * item['frame_step']) + support = float(np.mean(item['probs'][local_frames, frame_phone_id])) + phone_times.append((start_time, min(float(audio_end), end_time))) + phone_acoustic_supports.append(float(np.clip(support, 0.0, 1.0))) + word_rows = [] + for word_idx, word in enumerate(words): + positions = [idx for idx, cur_word in enumerate(hyp['phone_to_word']) if cur_word == word_idx] + if not positions: + continue + start = min(phone_times[idx][0] for idx in positions) + end = max(phone_times[idx][1] for idx in positions) + word_rows.append({ + 'word': word, + 'start': float(start), + 'end': float(end), + 'source': 'charsiu_hypothesis_alignment', + 'word_logprob': float(row.get('word_logprobs', [0.0] * len(words))[word_idx]) + if word_idx < len(row.get('word_logprobs', [])) + else 0.0, + 'word_confidence': float(row.get('word_confidences', [1.0] * len(words))[word_idx]) + if word_idx < len(row.get('word_confidences', [])) + else 1.0, + }) + row['word_timestamps'] = word_rows + row['timestamp_source'] = 'charsiu_hypothesis_alignment' + row['phone_times'] = phone_times + row['phone_acoustic_supports'] = phone_acoustic_supports + except Exception as exc: + row['word_timestamps'] = estimate_word_timestamps(words, audio_end) + row['timestamp_source'] = 'duration_proportional_fallback' + row['timestamp_fallback_reason'] = repr(exc) + phone_times = [] + phone_acoustic_supports = [] + for phone_idx, word_idx in enumerate(hyp['phone_to_word']): + if word_idx < len(row['word_timestamps']): + word_time = row['word_timestamps'][word_idx] + phone_times.append((float(word_time['start']), float(word_time['end']))) + else: + phone_times.append((0.0, float(audio_end))) + phone_acoustic_supports.append(0.0) + row['phone_times'] = phone_times + row['phone_acoustic_supports'] = phone_acoustic_supports + row.update(hyp) + return row + + +def interval_overlap_ratio(a, b): + if a is None or b is None: + return 0.0 + a0, a1 = a + b0, b1 = b + inter = max(0.0, min(float(a1), float(b1)) - max(float(a0), float(b0))) + union = max(float(a1), float(b1)) - min(float(a0), float(b0)) + if union <= 0: + return 0.0 + return inter / union + + +def align_token_sequences( + ref_tokens, + hyp_tokens, + mismatch_cost=1.0, + ref_times=None, + hyp_times=None, + hyp_confidences=None, + time_overlap_reward=0.0, +): + n = len(ref_tokens) + m = len(hyp_tokens) + dp = np.zeros((n + 1, m + 1), dtype=np.float32) + back = {} + for i in range(1, n + 1): + dp[i, 0] = dp[i - 1, 0] + 1.0 + back[(i, 0)] = (i - 1, 0, 'delete') + for j in range(1, m + 1): + dp[0, j] = dp[0, j - 1] + 1.0 + back[(0, j)] = (0, j - 1, 'insert') + for i in range(1, n + 1): + for j in range(1, m + 1): + sub_cost = 0.0 if ref_tokens[i - 1] == hyp_tokens[j - 1] else mismatch_cost + if ref_times is not None and hyp_times is not None: + sub_cost -= float(time_overlap_reward) * interval_overlap_ratio(ref_times[i - 1], hyp_times[j - 1]) + if hyp_confidences is not None: + sub_cost -= 0.1 * float(np.clip(hyp_confidences[j - 1], 0.0, 1.0)) + sub_cost = max(0.0, sub_cost) + candidates = [ + (dp[i - 1, j - 1] + sub_cost, i - 1, j - 1, 'match'), + (dp[i - 1, j] + 1.0, i - 1, j, 'delete'), + (dp[i, j - 1] + 1.0, i, j - 1, 'insert'), + ] + cost, prev_i, prev_j, op = min(candidates, key=lambda item: item[0]) + dp[i, j] = cost + back[(i, j)] = (prev_i, prev_j, op) + + pairs = [] + i, j = n, m + while i > 0 or j > 0: + prev_i, prev_j, op = back[(i, j)] + if op == 'match': + pairs.append((i - 1, j - 1)) + elif op == 'delete': + pairs.append((i - 1, None)) + else: + pairs.append((None, j - 1)) + i, j = prev_i, prev_j + pairs.reverse() + return pairs + + +def slot_top_phone(slot_counts, eps_index): + best_idx = None + best_mass = -1.0 + for phone_idx, mass in slot_counts.items(): + if phone_idx == eps_index: + continue + if mass > best_mass: + best_idx = phone_idx + best_mass = mass + return best_idx + + +def slot_time(slot): + mass = max(float(slot.get('time_mass', 0.0)), EPS) + if mass <= EPS: + return None + return float(slot.get('start_sum', 0.0) / mass), float(slot.get('end_sum', 0.0) / mass) + + +def add_slot_phone_mass(slot, phone_idx, phone_mass, eps_index, eps_mass=0.0, phone_time=None, confidence=1.0): + if phone_mass > 0: + slot['counts'][int(phone_idx)] += float(phone_mass) + if eps_mass > 0: + slot['counts'][eps_index] += float(eps_mass) + if phone_time is not None and phone_mass > 0: + slot['start_sum'] = slot.get('start_sum', 0.0) + float(phone_time[0]) * float(phone_mass) + slot['end_sum'] = slot.get('end_sum', 0.0) + float(phone_time[1]) * float(phone_mass) + slot['time_mass'] = slot.get('time_mass', 0.0) + float(phone_mass) + slot['confidence_sum'] = slot.get('confidence_sum', 0.0) + float(confidence) * max(float(phone_mass), 0.0) + slot['confidence_mass'] = slot.get('confidence_mass', 0.0) + max(float(phone_mass), 0.0) + + +def insert_slot(slots, insert_at, eps_index, prior_mass): + slot = {'counts': Counter(), 'start_sum': 0.0, 'end_sum': 0.0, 'time_mass': 0.0} + if prior_mass > 0: + slot['counts'][eps_index] += float(prior_mass) + slots.insert(insert_at, slot) + return slot + + +def build_pcn_from_hypotheses(hypotheses, phone_mapper, phn_dict): + eps_index = len(phn_dict) + phone_dim = len(phn_dict) + 1 + hyp_logprobs = [float(row.get('length_normalized_sequence_score', row.get('logprob', 0.0))) for row in hypotheses] + hyp_weights = softmax_1d(hyp_logprobs) + id_to_phone = {idx: phone for phone, idx in phn_dict.items()} + + hyp_phone_rows = [] + for row, weight in zip(hypotheses, hyp_weights): + if 'phone_ids' not in row: + row = align_hypothesis_with_charsiu( + item={'probs': np.zeros((0, phone_dim), dtype=np.float32), 'keep_mask': np.zeros((0,), dtype=np.int32), 'frame_step': 0.02}, + row=row, + phone_mapper=phone_mapper, + phn_dict=phn_dict, + phone_to_frame_id={}, + audio_end=0.0, + ) + phone_ids = [int(phone_idx) for phone_idx in row.get('phone_ids', [])] + phone_confidences = [float(x) for x in row.get('phone_confidences', [1.0] * len(phone_ids))] + phone_acoustic = [float(x) for x in row.get('phone_acoustic_supports', [0.0] * len(phone_ids))] + phone_times = row.get('phone_times', [None] * len(phone_ids)) + hyp_phone_rows.append({ + 'phones': row.get('phones', []), + 'phone_ids': phone_ids, + 'phone_to_word': list(row.get('phone_to_word', [])), + 'phone_confidences': phone_confidences, + 'phone_acoustic_supports': phone_acoustic, + 'phone_times': phone_times, + 'weight': float(weight), + 'source_counts': row.get('source_counts', {}), + }) + + slots = [] + total_mass = 0.0 + for hyp_idx, hyp in enumerate(hyp_phone_rows): + phone_ids = hyp['phone_ids'] + weight = float(hyp['weight']) + if hyp_idx == 0: + for local_idx, phone_idx in enumerate(phone_ids): + slot = {'counts': Counter(), 'start_sum': 0.0, 'end_sum': 0.0, 'time_mass': 0.0} + quality = float(np.clip( + 0.5 * hyp['phone_confidences'][local_idx] + 0.5 * hyp['phone_acoustic_supports'][local_idx], + 0.0, + 1.0, + )) + add_slot_phone_mass( + slot, + phone_idx, + weight * quality, + eps_index, + eps_mass=weight * (1.0 - quality), + phone_time=hyp['phone_times'][local_idx] if local_idx < len(hyp['phone_times']) else None, + confidence=hyp['phone_confidences'][local_idx], + ) + slots.append(slot) + total_mass += weight + continue + + consensus_slot_ids = [] + consensus_phone_ids = [] + for slot_idx, slot in enumerate(slots): + top_idx = slot_top_phone(slot['counts'], eps_index) + if top_idx is not None: + consensus_slot_ids.append(slot_idx) + consensus_phone_ids.append(top_idx) + consensus_times = [slot_time(slots[slot_idx]) for slot_idx in consensus_slot_ids] + pairs = align_token_sequences( + consensus_phone_ids, + phone_ids, + ref_times=consensus_times, + hyp_times=hyp.get('phone_times'), + hyp_confidences=hyp.get('phone_confidences'), + time_overlap_reward=0.3, + ) + cursor = 0 + matched_slots = set() + for ref_pos, hyp_pos in pairs: + if ref_pos is None: + insert_at = consensus_slot_ids[cursor] if cursor < len(consensus_slot_ids) else len(slots) + slot = insert_slot(slots, insert_at, eps_index, total_mass) + quality = float(np.clip( + 0.5 * hyp['phone_confidences'][hyp_pos] + 0.5 * hyp['phone_acoustic_supports'][hyp_pos], + 0.0, + 1.0, + )) + add_slot_phone_mass( + slot, + phone_ids[hyp_pos], + weight * quality, + eps_index, + eps_mass=weight * (1.0 - quality), + phone_time=hyp['phone_times'][hyp_pos] if hyp_pos < len(hyp['phone_times']) else None, + confidence=hyp['phone_confidences'][hyp_pos], + ) + cursor += 1 + else: + slot_idx = consensus_slot_ids[ref_pos] + matched_slots.add(slot_idx) + cursor = ref_pos + 1 + if hyp_pos is None: + slots[slot_idx]['counts'][eps_index] += weight + else: + quality = float(np.clip( + 0.5 * hyp['phone_confidences'][hyp_pos] + 0.5 * hyp['phone_acoustic_supports'][hyp_pos], + 0.0, + 1.0, + )) + add_slot_phone_mass( + slots[slot_idx], + phone_ids[hyp_pos], + weight * quality, + eps_index, + eps_mass=weight * (1.0 - quality), + phone_time=hyp['phone_times'][hyp_pos] if hyp_pos < len(hyp['phone_times']) else None, + confidence=hyp['phone_confidences'][hyp_pos], + ) + for slot_idx, slot in enumerate(slots): + if slot_idx not in matched_slots and sum(slot['counts'].values()) < total_mass + weight - EPS: + if slot_top_phone(slot['counts'], eps_index) is not None: + slot['counts'][eps_index] += weight + total_mass += weight + + if not slots: + slot = {'counts': Counter()} + slot['counts'][eps_index] = 1.0 + slots = [slot] + total_mass = 1.0 + + cn_post = np.zeros((len(slots), phone_dim), dtype=np.float32) + top_phone_ids = [] + slot_times = [] + slot_confidences = [] + for slot_idx, slot in enumerate(slots): + slot_mass = sum(slot['counts'].values()) + if slot_mass < total_mass: + slot['counts'][eps_index] += total_mass - slot_mass + for phone_idx, mass in slot['counts'].items(): + cn_post[slot_idx, int(phone_idx)] = float(mass) / max(float(total_mass), EPS) + cn_post[slot_idx] /= np.clip(cn_post[slot_idx].sum(), EPS, None) + top_phone_ids.append(slot_top_phone(slot['counts'], eps_index)) + slot_times.append(slot_time(slot)) + conf_mass = max(float(slot.get('confidence_mass', 0.0)), EPS) + slot_confidences.append(float(np.clip(slot.get('confidence_sum', 0.0) / conf_mass, 0.0, 1.0))) + + return { + 'cn_post': cn_post, + 'top_phone_ids': top_phone_ids, + 'slot_times': slot_times, + 'slot_confidences': slot_confidences, + 'hyp_phone_rows': hyp_phone_rows, + 'hyp_weights': hyp_weights.tolist(), + 'id_to_phone': id_to_phone, + 'eps_index': eps_index, + } + + +def top_hyp_word_ids_for_slots(pcn): + slot_word_ids = np.zeros((len(pcn['top_phone_ids']),), dtype=np.int32) - 1 + if not pcn['hyp_phone_rows']: + return slot_word_ids + top_hyp = pcn['hyp_phone_rows'][0] + hyp_phone_ids = list(top_hyp['phone_ids']) + hyp_phone_to_word = list(top_hyp['phone_to_word']) + consensus_slot_ids = [] + consensus_phone_ids = [] + for slot_idx, phone_idx in enumerate(pcn['top_phone_ids']): + if phone_idx is not None: + consensus_slot_ids.append(slot_idx) + consensus_phone_ids.append(phone_idx) + pairs = align_token_sequences(consensus_phone_ids, hyp_phone_ids) + for ref_pos, hyp_pos in pairs: + if ref_pos is None or hyp_pos is None: + continue + slot_idx = consensus_slot_ids[ref_pos] + if hyp_pos < len(hyp_phone_to_word): + slot_word_ids[slot_idx] = int(hyp_phone_to_word[hyp_pos]) + return slot_word_ids + + +def pcn_stats(cn_post, top_phone_ids, prev_top_phone_ids, eps_index): + stats = np.zeros((cn_post.shape[0], 5), dtype=np.float32) + stable_prefix = 0 + for idx, phone_idx in enumerate(top_phone_ids): + if idx < len(prev_top_phone_ids) and phone_idx == prev_top_phone_ids[idx]: + stable_prefix += 1 + else: + break + prefix_stability = float(stable_prefix) / float(max(len(top_phone_ids), 1)) + for idx, probs in enumerate(cn_post): + non_eps = np.delete(probs, eps_index) + top1, margin = top_margin(non_eps) + stats[idx] = np.array( + [ + float(probs[eps_index]), + entropy_np(probs), + top1, + margin, + prefix_stability, + ], + dtype=np.float32, + ) + return stats, prefix_stability + + +def validate_pcn(pcn): + cn_post = np.asarray(pcn['cn_post'], dtype=np.float32) + if not np.isfinite(cn_post).all(): + raise ValueError('pcn_contains_nan_or_inf') + sums = cn_post.sum(axis=-1) + if not np.allclose(sums, 1.0, atol=1e-3): + raise ValueError(f'pcn_posterior_not_normalized:max_abs_err={float(np.max(np.abs(sums - 1.0)))}') + eps_index = int(pcn['eps_index']) + if eps_index < 0 or eps_index >= cn_post.shape[-1]: + raise ValueError('invalid_epsilon_index') + eps_probs = cn_post[:, eps_index] + if np.any(eps_probs < -1e-6) or np.any(eps_probs > 1.0 + 1e-6): + raise ValueError('epsilon_probability_out_of_range') + for row in pcn.get('hyp_phone_rows', []): + for value in row.get('phone_confidences', []): + if not np.isfinite(value) or value < -1e-6 or value > 1.0 + 1e-6: + raise ValueError('phone_confidence_out_of_range') + for value in pcn.get('slot_confidences', []): + if not np.isfinite(value) or value < -1e-6 or value > 1.0 + 1e-6: + raise ValueError('slot_confidence_out_of_range') + + +def cumulative_candidate_mask_from_asr(pcn_word_id, word_timestamps, commit_time, audio_end, is_final): + mask = np.zeros((pcn_word_id.shape[0],), dtype=np.float32) + committed_words = set() + for word_idx, word_time in enumerate(word_timestamps or []): + end_time = float(word_time.get('end', 0.0)) + if end_time <= commit_time + 1e-6 or (is_final and end_time <= audio_end + 1e-6): + committed_words.add(int(word_idx)) + for slot_idx, word_idx in enumerate(pcn_word_id.tolist()): + if int(word_idx) in committed_words: + mask[slot_idx] = 1.0 + return mask + + +def align_previous_commits(prev_state, current_top_phone_ids): + if prev_state is None: + return {}, [], [] + prev_top_phone_ids = prev_state.get('top_phone_ids', []) + prev_committed = set(int(x) for x in prev_state.get('committed_slots', [])) + pairs = align_token_sequences(prev_top_phone_ids, current_top_phone_ids, mismatch_cost=1.0) + prev_to_current = {} + for prev_idx, cur_idx in pairs: + if prev_idx is None or cur_idx is None: + continue + if prev_idx < len(prev_top_phone_ids) and cur_idx < len(current_top_phone_ids): + if prev_top_phone_ids[prev_idx] == current_top_phone_ids[cur_idx]: + prev_to_current[int(prev_idx)] = int(cur_idx) + mapped_old = sorted(prev_to_current[idx] for idx in prev_committed if idx in prev_to_current) + dropped = sorted(idx for idx in prev_committed if idx not in prev_to_current) + return prev_to_current, mapped_old, dropped + + +def _top_word_timestamps(word_timestamps): + rows = word_timestamps or [] + if rows and isinstance(rows[0], list): + rows = rows[0] + return rows if isinstance(rows, list) else [] + + +def _commit_word_metadata(word_timestamps, word_idx): + rows = _top_word_timestamps(word_timestamps) + row = rows[word_idx] if 0 <= int(word_idx) < len(rows) and isinstance(rows[word_idx], dict) else {} + text = normalize_word(str(row.get('word', ''))).casefold() + try: + start = float(row.get('start')) + end = float(row.get('end')) + except (TypeError, ValueError): + start = None + end = None + return {'text': text, 'start': start, 'end': end} + + +def _commit_time_iou(left, right): + if any(item.get(key) is None for item in (left, right) for key in ('start', 'end')): + return 0.0 + overlap = max(0.0, min(left['end'], right['end']) - max(left['start'], right['start'])) + union = max(left['end'], right['end']) - min(left['start'], right['start']) + return overlap / union if union > 0 else 0.0 + + +def _word_level_lineage(prev_state, pcn_word_id, current_to_prev, word_timestamps): + """Build deterministic one-to-one predecessor decisions without using supervision.""" + current_positions = { + word_idx: np.flatnonzero(pcn_word_id == word_idx) + for word_idx in sorted(set(int(value) for value in pcn_word_id.tolist() if int(value) >= 0)) + } + if prev_state is None: + return current_positions, { + word_idx: { + 'candidate_prev_word_id': None, + 'selected_prev_word_id': None, + 'predecessor_word_ids': [], + 'vote_counts': {}, + 'mapping_status': 'first_seen', + 'split_competitor_count': 0, + 'reliable': True, + 'text_equal': False, + 'time_iou': 0.0, + } + for word_idx in current_positions + } + + prev_word_ids = np.asarray(prev_state.get('pcn_word_id', []), dtype=np.int32) + prev_word_states = prev_state.get('word_states', {}) + decisions = {} + competitors_by_prev = {} + for word_idx, positions in current_positions.items(): + votes = Counter() + for position in positions.tolist(): + old_slot = int(current_to_prev[position]) if position < len(current_to_prev) else -1 + if 0 <= old_slot < len(prev_word_ids): + prev_word_idx = int(prev_word_ids[old_slot]) + if prev_word_idx >= 0: + votes[prev_word_idx] += 1 + strict = [key for key, count in votes.items() if count > len(positions) / 2.0] + decision = { + 'candidate_prev_word_id': None, + 'selected_prev_word_id': None, + 'predecessor_word_ids': sorted(int(key) for key in votes), + 'vote_counts': {str(key): int(value) for key, value in sorted(votes.items())}, + 'mapping_status': 'unmatched_new' if not votes else 'ambiguous_no_majority', + 'split_competitor_count': 0, + 'reliable': not votes, + 'text_equal': False, + 'time_iou': 0.0, + } + if len(strict) == 1: + prev_word_idx = int(strict[0]) + prev_meta = prev_word_states.get(prev_word_idx, {}).get('metadata', {}) + cur_meta = _commit_word_metadata(word_timestamps, word_idx) + decision.update({ + 'candidate_prev_word_id': prev_word_idx, + 'mapping_status': 'candidate', + 'text_equal': bool(prev_meta.get('text') and cur_meta['text'] and prev_meta['text'] == cur_meta['text']), + 'time_iou': float(_commit_time_iou(prev_meta, cur_meta)), + }) + competitors_by_prev.setdefault(prev_word_idx, []).append((word_idx, decision)) + decisions[word_idx] = decision + + # A strict-majority edge is unique for each current word. Selecting the + # highest-weight edge for each predecessor is therefore the global maximum + # weight one-to-one matching for this candidate graph. + for prev_word_idx, competitors in sorted(competitors_by_prev.items()): + for _, decision in competitors: + decision['split_competitor_count'] = len(competitors) + ranked = sorted( + competitors, + key=lambda item: ( + -int(item[1]['vote_counts'][str(prev_word_idx)]), + -round(float(item[1]['time_iou']), 12), + -int(item[1]['text_equal']), + int(item[0]), + ), + ) + winner_key = ( + int(ranked[0][1]['vote_counts'][str(prev_word_idx)]), + round(float(ranked[0][1]['time_iou']), 12), + int(ranked[0][1]['text_equal']), + ) + tied = [ + item for item in ranked + if ( + int(item[1]['vote_counts'][str(prev_word_idx)]), + round(float(item[1]['time_iou']), 12), + int(item[1]['text_equal']), + ) == winner_key + ] + if len(tied) == 1: + _, winner = ranked[0] + winner['selected_prev_word_id'] = int(prev_word_idx) + winner['mapping_status'] = 'accepted' + winner['reliable'] = True + else: + for _, decision in tied: + decision['mapping_status'] = 'ambiguous_competition_tie' + decision['reliable'] = False + for _, loser in ranked[1:]: + if loser['mapping_status'] == 'candidate': + loser['mapping_status'] = 'split_new_successor' + loser['reliable'] = True + return current_positions, decisions + + +def build_stateful_commit_masks( + prev_state, + pcn, + pcn_word_id, + word_timestamps, + commit_time, + audio_end, + is_final, + current_to_prev_override=None, + commit_rule='legacy', +): + if commit_rule not in {'legacy', 'merge_aware'}: + raise ValueError(f"commit_rule must be 'legacy' or 'merge_aware', got {commit_rule!r}") + word_timestamps = _top_word_timestamps(word_timestamps) + candidate = cumulative_candidate_mask_from_asr(pcn_word_id, word_timestamps, commit_time, audio_end, is_final) + if current_to_prev_override is None: + prev_to_current, mapped_old_slots, dropped_or_revised = align_previous_commits(prev_state, pcn['top_phone_ids']) + current_to_prev = np.zeros((len(pcn['top_phone_ids']),), dtype=np.int32) - 1 + for prev_idx, cur_idx in prev_to_current.items(): + if 0 <= cur_idx < current_to_prev.shape[0]: + current_to_prev[cur_idx] = int(prev_idx) + else: + current_to_prev = np.asarray(current_to_prev_override, dtype=np.int32).copy() + prev_to_current = { + int(prev_idx): int(cur_idx) + for cur_idx, prev_idx in enumerate(current_to_prev.tolist()) + if int(prev_idx) >= 0 + } + prev_committed = set(int(value) for value in (prev_state or {}).get('committed_slots', [])) + mapped_old_slots = sorted(cur for prev, cur in prev_to_current.items() if prev in prev_committed) + dropped_or_revised = sorted(prev for prev in prev_committed if prev not in prev_to_current) + mapped_old_set = set(mapped_old_slots) + cumulative = candidate.copy() + for slot_idx in mapped_old_set: + if 0 <= slot_idx < cumulative.shape[0]: + cumulative[slot_idx] = 1.0 + + if commit_rule == 'legacy': + new_mask = np.zeros_like(cumulative) + for word_idx in sorted(set(int(value) for value in pcn_word_id.tolist() if int(value) >= 0)): + positions = np.flatnonzero(pcn_word_id == word_idx) + if positions.size == 0 or not bool(np.all(candidate[positions] > 0)): + continue + if any(int(position) in mapped_old_set for position in positions.tolist()): + continue + new_mask[positions] = 1.0 + committed_slots = sorted(np.flatnonzero(cumulative > 0).astype(int).tolist()) + new_slots = sorted(np.flatnonzero(new_mask > 0).astype(int).tolist()) + diagnostics = { + 'mapped_old_slots': mapped_old_slots, + 'new_slots': new_slots, + 'dropped_or_revised_slots': dropped_or_revised, + 'state_event_semantics': 'legacy_slot_any_v1', + } + next_state = { + 'top_phone_ids': list(pcn['top_phone_ids']), + 'committed_slots': committed_slots, + } + return cumulative.astype(np.float32), new_mask.astype(np.float32), current_to_prev, diagnostics, next_state + + current_positions, lineage = _word_level_lineage( + prev_state, + np.asarray(pcn_word_id, dtype=np.int32), + current_to_prev, + word_timestamps, + ) + prev_word_states = (prev_state or {}).get('word_states', {}) + next_logical_id = int((prev_state or {}).get('next_logical_word_id', 0)) + next_event_id = int((prev_state or {}).get('next_state_event_id', 0)) + next_word_states = {} + word_event_rows = [] + new_mask = np.zeros_like(cumulative) + + for word_idx, positions in sorted(current_positions.items()): + decision = lineage[word_idx] + selected_prev = decision['selected_prev_word_id'] + predecessor_ids = decision['predecessor_word_ids'] + predecessor_states = [prev_word_states.get(value, {}) for value in predecessor_ids] + predecessor_committed = [bool(value.get('committed', False)) for value in predecessor_states] + completed = bool(np.all(candidate[positions] > 0)) + split = int(decision['split_competitor_count']) > 1 + merge = len(predecessor_ids) > 1 + inherited_state = prev_word_states.get(selected_prev, {}) if selected_prev is not None else {} + has_old_committed_slot = any(int(position) in mapped_old_set for position in positions.tolist()) + prev_word_ids_array = np.asarray((prev_state or {}).get('pcn_word_id', []), dtype=np.int32) + prev_committed_slots = set(int(value) for value in (prev_state or {}).get('committed_slots', [])) + unassigned_committed_predecessors = 0 + for position in positions.tolist(): + old_slot = int(current_to_prev[position]) if position < len(current_to_prev) else -1 + if old_slot not in prev_committed_slots: + continue + if old_slot >= len(prev_word_ids_array) or int(prev_word_ids_array[old_slot]) < 0: + unassigned_committed_predecessors += 1 + if unassigned_committed_predecessors: + decision['mapping_reliable'] = False + decision['reliable'] = False + decision['mapping_status'] = 'lineage_broken_unassigned_committed_slot' + legacy_emit = completed and not has_old_committed_slot + mixed_merge = bool( + merge + and predecessor_committed + and any(predecessor_committed) + and not all(predecessor_committed) + ) + partial_word_completed = bool( + completed + and selected_prev is not None + and not inherited_state.get('committed', False) + and not merge + and bool(decision['reliable']) + ) + # A3-Lite is intentionally minimal: reproduce the legacy mask exactly, + # then add one event for a completed mixed committed/partial merge or + # for a reliably inherited partial word that has now become complete. + emit_event = bool(legacy_emit or (completed and mixed_merge) or partial_word_completed) + committed = bool(completed or inherited_state.get('committed', False)) + + if selected_prev is not None and not (completed and mixed_merge): + logical_id = int(inherited_state['logical_word_id']) + else: + logical_id = next_logical_id + next_logical_id += 1 + + if completed and mixed_merge: + event_reason = 'mixed_committed_partial_merge_completed' + elif mixed_merge: + event_reason = 'mixed_committed_partial_merge_partial' + elif split: + event_reason = 'split_completed' if completed else 'split_partial' + elif merge: + if completed: + event_reason = 'merge_completed' if emit_event else 'merge_completed_legacy_suppressed' + else: + event_reason = 'merge_partial' + elif unassigned_committed_predecessors and completed and not emit_event: + event_reason = 'lineage_broken_completed_legacy_suppressed' + elif selected_prev is not None and inherited_state.get('committed', False): + event_reason = 'persistent_committed' + elif selected_prev is not None: + event_reason = 'partial_became_completed' if completed else 'partial_persistent' + elif predecessor_ids: + event_reason = 'ambiguous_completed' if completed else 'ambiguous_partial' + else: + event_reason = 'newly_completed' if completed else 'new_partial' + + state_event_id = -1 + if emit_event: + new_mask[positions] = 1.0 + state_event_id = next_event_id + next_event_id += 1 + metadata = _commit_word_metadata(word_timestamps, word_idx) + next_word_states[int(word_idx)] = { + 'logical_word_id': int(logical_id), + 'committed': bool(committed), + 'state_event_id': int(state_event_id if state_event_id >= 0 else inherited_state.get('state_event_id', -1)), + 'metadata': metadata, + } + word_event_rows.append({ + 'current_word_id': int(word_idx), + 'logical_word_id': int(logical_id), + 'state_event_id': int(state_event_id), + 'completed': bool(completed), + 'emit_state_event': bool(emit_event), + 'event_reason': event_reason, + 'mapping_status': decision['mapping_status'], + 'mapping_reliable': bool(decision['reliable']), + 'selected_prev_word_id': selected_prev, + 'predecessor_word_ids': predecessor_ids, + 'predecessor_committed': predecessor_committed, + 'vote_counts': decision['vote_counts'], + 'split_competitor_count': int(decision['split_competitor_count']), + 'text': metadata['text'], + 'text_equal': bool(decision['text_equal']), + 'time_iou': float(decision['time_iou']), + 'unassigned_committed_predecessor_slots': int(unassigned_committed_predecessors), + }) + + committed_slots = sorted(np.flatnonzero(cumulative > 0).astype(int).tolist()) + new_slots = sorted(np.flatnonzero(new_mask > 0).astype(int).tolist()) + diagnostics = { + 'mapped_old_slots': mapped_old_slots, + 'new_slots': new_slots, + 'dropped_or_revised_slots': dropped_or_revised, + 'word_level_state_events': word_event_rows, + 'state_event_semantics': 'word_predecessor_one_to_one_v1', + } + next_state = { + 'top_phone_ids': list(pcn['top_phone_ids']), + 'pcn_word_id': np.asarray(pcn_word_id, dtype=np.int32).tolist(), + 'committed_slots': committed_slots, + 'word_states': next_word_states, + 'next_logical_word_id': int(next_logical_id), + 'next_state_event_id': int(next_event_id), + } + return cumulative.astype(np.float32), new_mask.astype(np.float32), current_to_prev, diagnostics, next_state + + +def acoustic_distribution_for_frames(frame_probs, phone_to_frame_id, phn_dict, phone_dim): + out = np.zeros((phone_dim,), dtype=np.float32) + if frame_probs.size == 0: + return out + mean_probs = frame_probs.mean(axis=0) + for phone, phone_idx in phn_dict.items(): + frame_idx = phone_to_frame_id.get(phone) + if frame_idx is not None and frame_idx < mean_probs.shape[0]: + out[int(phone_idx)] = float(mean_probs[frame_idx]) + if out.sum() > 0: + out /= out.sum() + return out + + +def build_acoustic_evidence(item, cn_post, top_phone_ids, phone_to_frame_id, phn_dict, audio_end): + phone_dim = cn_post.shape[-1] + acoustic_post = np.zeros_like(cn_post, dtype=np.float32) + acoustic_stats = np.zeros((cn_post.shape[0], 4), dtype=np.float32) + kept_indices, kept_probs = select_visible_frames(item['probs'], item['keep_mask'], audio_end, item['frame_step']) + alignable = [ + (slot_idx, phone_idx) + for slot_idx, phone_idx in enumerate(top_phone_ids) + if phone_idx is not None + ] + if kept_probs.shape[0] < len(alignable) or not alignable: + for slot_idx in range(cn_post.shape[0]): + acoustic_stats[slot_idx, 3] = js_divergence(cn_post[slot_idx], acoustic_post[slot_idx]) + return acoustic_post, acoustic_stats, 0 + + id_to_phone = {idx: phone for phone, idx in phn_dict.items()} + frame_phone_ids = [phone_to_frame_id[id_to_phone[phone_idx]] for _, phone_idx in alignable] + try: + path = monotonic_align(-np.log(np.clip(kept_probs, EPS, None)), frame_phone_ids) + except Exception: + for slot_idx in range(cn_post.shape[0]): + acoustic_stats[slot_idx, 3] = js_divergence(cn_post[slot_idx], acoustic_post[slot_idx]) + return acoustic_post, acoustic_stats, 0 + + for local_idx, (slot_idx, _) in enumerate(alignable): + tok_frames = kept_indices[path == local_idx] + if tok_frames.size == 0: + acoustic_stats[slot_idx, 3] = js_divergence(cn_post[slot_idx], acoustic_post[slot_idx]) + continue + dist = acoustic_distribution_for_frames( + item['probs'][tok_frames], + phone_to_frame_id, + phn_dict, + phone_dim, + ) + acoustic_post[slot_idx] = dist + non_eps = dist[:-1] + _, margin = top_margin(non_eps) + duration = float(tok_frames.size * item['frame_step']) + acoustic_stats[slot_idx] = np.array( + [ + entropy_np(dist), + margin, + duration, + js_divergence(cn_post[slot_idx], dist), + ], + dtype=np.float32, + ) + return acoustic_post, acoustic_stats, int(kept_probs.shape[0]) + + +def compute_prosody(audio, sample_rate, audio_end, word_count, phone_count): + audio = np.asarray(audio, dtype=np.float32) + duration = float(max(audio_end, EPS)) + if audio.size == 0: + return np.zeros((14,), dtype=np.float32) + hop_length = max(int(0.01 * sample_rate), 1) + frame_length = max(int(0.025 * sample_rate), hop_length) + rms = librosa.feature.rms(y=audio, frame_length=frame_length, hop_length=hop_length)[0] + log_energy = np.log(np.clip(rms, EPS, None)) + energy_threshold = np.percentile(rms, 20) if rms.size else 0.0 + silence = rms <= max(energy_threshold, EPS) + silence_ratio = float(np.mean(silence)) if silence.size else 0.0 + pause_count, longest_pause = count_pauses(silence, hop_length / sample_rate) + try: + f0, voiced_flag, voiced_prob = librosa.pyin( + audio, + fmin=50, + fmax=500, + sr=sample_rate, + frame_length=frame_length, + hop_length=hop_length, + ) + voiced = np.isfinite(f0) + f0_values = f0[voiced] + voiced_prob_mean = float(np.nanmean(voiced_prob)) if voiced_prob is not None else float(np.mean(voiced)) + except Exception: + f0_values = np.array([], dtype=np.float32) + voiced = np.zeros_like(rms, dtype=bool) + voiced_prob_mean = 0.0 + f0_mean = float(np.mean(f0_values)) if f0_values.size else 0.0 + f0_std = float(np.std(f0_values)) if f0_values.size else 0.0 + f0_slope = slope(f0_values) + energy_mean = float(np.mean(log_energy)) if log_energy.size else 0.0 + energy_std = float(np.std(log_energy)) if log_energy.size else 0.0 + energy_slope = slope(log_energy) + voiced_duration = max(float(np.mean(voiced)) * duration, EPS) if voiced.size else EPS + return np.array( + [ + duration, + f0_mean, + f0_std, + f0_slope, + voiced_prob_mean, + energy_mean, + energy_std, + energy_slope, + silence_ratio, + float(pause_count), + float(longest_pause), + float(word_count) / duration, + float(phone_count) / duration, + float(phone_count) / voiced_duration, + ], + dtype=np.float32, + ) + + +def slot_prosody_feature_names(): + return [ + 'slot_duration', + 'slot_log_energy_mean', + 'slot_log_energy_std', + 'slot_log_energy_max', + 'slot_f0_mean', + 'slot_f0_std', + 'slot_f0_max', + 'slot_voiced_ratio', + 'slot_position_in_word', + 'word_phone_count', + 'energy_relative_to_word_mean', + 'duration_relative_to_word_mean', + 'f0_relative_to_word_mean', + 'is_vowel', + 'lexical_stress_0', + 'lexical_stress_1', + 'lexical_stress_2', + ] + + +def compute_slot_prosody(audio, sample_rate, slot_times, pcn_word_id, top_phone_ids, phn_dict): + feature_names = slot_prosody_feature_names() + slot_count = len(top_phone_ids) + out = np.zeros((slot_count, len(feature_names)), dtype=np.float32) + if slot_count <= 0: + return out + audio = np.asarray(audio, dtype=np.float32) + id_to_phone = {int(idx): phone for phone, idx in phn_dict.items()} + hop_length = max(int(0.01 * sample_rate), 1) + frame_length = max(int(0.025 * sample_rate), hop_length) + if audio.size: + rms = librosa.feature.rms(y=audio, frame_length=frame_length, hop_length=hop_length)[0] + log_energy = np.log(np.clip(rms, EPS, None)) + frame_times = librosa.frames_to_time(np.arange(rms.shape[0]), sr=sample_rate, hop_length=hop_length) + else: + log_energy = np.zeros((0,), dtype=np.float32) + frame_times = np.zeros((0,), dtype=np.float32) + try: + f0, _, _ = librosa.pyin( + audio, + fmin=50, + fmax=500, + sr=sample_rate, + frame_length=frame_length, + hop_length=hop_length, + ) + except Exception: + f0 = np.zeros_like(log_energy, dtype=np.float32) * np.nan + if f0 is None: + f0 = np.zeros_like(log_energy, dtype=np.float32) * np.nan + f0 = np.asarray(f0, dtype=np.float32) + common_frames = min(frame_times.shape[0], log_energy.shape[0], f0.shape[0]) + frame_times = frame_times[:common_frames] + log_energy = log_energy[:common_frames] + f0 = f0[:common_frames] + + durations = np.zeros((slot_count,), dtype=np.float32) + energy_means = np.zeros((slot_count,), dtype=np.float32) + f0_means = np.zeros((slot_count,), dtype=np.float32) + pcn_word_id = np.asarray(pcn_word_id, dtype=np.int32) + for slot_idx in range(slot_count): + if slot_idx < len(slot_times) and slot_times[slot_idx] is not None: + start, end = slot_times[slot_idx] + start = float(start) + end = float(max(end, start)) + else: + start = 0.0 + end = 0.0 + durations[slot_idx] = max(end - start, 0.0) + frame_mask = (frame_times >= start) & (frame_times <= end) if frame_times.size else np.zeros((0,), dtype=bool) + energy_values = log_energy[frame_mask] + f0_values = f0[frame_mask] + f0_values = f0_values[np.isfinite(f0_values)] + if energy_values.size: + out[slot_idx, 1] = float(np.mean(energy_values)) + out[slot_idx, 2] = float(np.std(energy_values)) + out[slot_idx, 3] = float(np.max(energy_values)) + energy_means[slot_idx] = out[slot_idx, 1] + if f0_values.size: + out[slot_idx, 4] = float(np.mean(f0_values)) + out[slot_idx, 5] = float(np.std(f0_values)) + out[slot_idx, 6] = float(np.max(f0_values)) + out[slot_idx, 7] = float(f0_values.size / max(frame_mask.sum(), 1)) + f0_means[slot_idx] = out[slot_idx, 4] + out[slot_idx, 0] = durations[slot_idx] + word_idx = int(pcn_word_id[slot_idx]) if slot_idx < pcn_word_id.shape[0] else -1 + same_word = np.flatnonzero(pcn_word_id == word_idx) if word_idx >= 0 else np.asarray([slot_idx], dtype=np.int64) + if same_word.size: + position = np.flatnonzero(same_word == slot_idx) + out[slot_idx, 8] = float(position[0] / max(same_word.size - 1, 1)) if position.size else 0.0 + out[slot_idx, 9] = float(same_word.size) + phone_idx = top_phone_ids[slot_idx] if slot_idx < len(top_phone_ids) else None + phone = id_to_phone.get(int(phone_idx), '') if phone_idx is not None else '' + out[slot_idx, 13] = 1.0 if phone[:1].upper() in {'A', 'E', 'I', 'O', 'U'} else 0.0 + + for slot_idx in range(slot_count): + word_idx = int(pcn_word_id[slot_idx]) if slot_idx < pcn_word_id.shape[0] else -1 + same_word = np.flatnonzero(pcn_word_id == word_idx) if word_idx >= 0 else np.asarray([slot_idx], dtype=np.int64) + if same_word.size: + word_energy = float(np.mean(energy_means[same_word])) + word_duration = float(np.mean(durations[same_word])) + word_f0 = float(np.mean(f0_means[same_word])) + out[slot_idx, 10] = out[slot_idx, 1] - word_energy + out[slot_idx, 11] = durations[slot_idx] / max(word_duration, EPS) + out[slot_idx, 12] = out[slot_idx, 4] - word_f0 + return out.astype(np.float32) + + +def slope(values): + values = np.asarray(values, dtype=np.float32) + if values.size < 2: + return 0.0 + x = np.arange(values.size, dtype=np.float32) + x = x - x.mean() + y = values - values.mean() + denom = float(np.sum(x * x)) + if denom <= EPS: + return 0.0 + return float(np.sum(x * y) / denom) + + +def count_pauses(silence_mask, frame_step): + pause_count = 0 + longest = 0.0 + cur = 0 + for value in silence_mask.tolist(): + if value: + cur += 1 + elif cur > 0: + pause_count += 1 + longest = max(longest, cur * frame_step) + cur = 0 + if cur > 0: + pause_count += 1 + longest = max(longest, cur * frame_step) + return pause_count, longest diff --git a/streampa/infer.py b/streampa/infer.py new file mode 100644 index 0000000000000000000000000000000000000000..5a5dcb92d272f28da383da8885fae3fefb4c8d5c --- /dev/null +++ b/streampa/infer.py @@ -0,0 +1,19 @@ +import argparse +import json +from pathlib import Path +from .pipeline import StreamPAPipeline + +def main(): + p=argparse.ArgumentParser(description='Frozen StreamPA raw-WAV inference') + p.add_argument('--audio',required=True) + p.add_argument('--bundle-dir',required=True) + p.add_argument('--device',default='cpu') + p.add_argument('--threads',type=int,default=2) + p.add_argument('--output',required=True) + a=p.parse_args() + result=StreamPAPipeline(a.bundle_dir,a.device,a.threads).score_file(a.audio) + dest=Path(a.output); dest.parent.mkdir(parents=True,exist_ok=True) + with dest.open('x',encoding='utf-8') as f: json.dump(result,f,indent=2,allow_nan=False) + print(json.dumps(dict(output=str(dest),prefixes=len(result['prefixes']),final_status=result['final']['status']))) + +if __name__=='__main__': main() diff --git a/streampa/pipeline.py b/streampa/pipeline.py new file mode 100644 index 0000000000000000000000000000000000000000..d3562a1df834f6633f30bda44eb8b55c0d4e283a --- /dev/null +++ b/streampa/pipeline.py @@ -0,0 +1,318 @@ +"""Reference-free deployment of the frozen StreamPA scorer and frontends.""" +import hashlib +import json +import os +import time +from itertools import groupby +from pathlib import Path + +import numpy as np +import soundfile as sf +import torch +from safetensors.torch import load_file +from transformers import Wav2Vec2CTCTokenizer, Wav2Vec2FeatureExtractor, Wav2Vec2Processor + +from . import frontend as fe +from .charsiu_model import Wav2Vec2ForFrameClassification +from .streaming_pcn_gopt import PCNStreamingScorer + + +def read_json(path): + return json.loads(Path(path).read_text(encoding='utf-8-sig')) + + +def load_scorer(bundle, device='cpu'): + bundle = Path(bundle) + c = read_json(bundle / 'scorer/config.json') + a = c['args'] + model = PCNStreamingScorer(phone_dim=c['phone_dim'], seq_len=c['seq_len'], + prosody_dim=c['prosody_dim'], embed_dim=a['embed_dim'], num_heads=a['heads'], + depth=a['depth'], gru_dim=a['gru_dim'], main_context_tokens=a['main_context_tokens'], + utt_pooling_head=c['utt_pooling_head'], fusion_mode=c['fusion_mode'], + slot_prosody_dim=c['slot_prosody_dim'], stress_branch=c['stress_branch'], + stress_grad_scale=c['stress_grad_scale']) + if c['preserve_unused_legacy_utt_head']: + model.utt_head = torch.nn.Sequential(torch.nn.LayerNorm(a['gru_dim']), torch.nn.Linear(a['gru_dim'], 5)) + weights = load_file(str(bundle / 'scorer/model.safetensors'), device='cpu') + model.load_state_dict(weights, strict=True) + return model.to(device).eval(), c + + +class CharsiuFrontend: + def __init__(self, bundle, device, min_sil_frames): + self.device = device + self.min_sil_frames = min_sil_frames + tokenizer = Wav2Vec2CTCTokenizer.from_pretrained(str(bundle / 'charsiu/tokenizer'), local_files_only=True) + feature_extractor = Wav2Vec2FeatureExtractor(feature_size=1, sampling_rate=16000, + padding_value=0.0, do_normalize=True, return_attention_mask=False) + self.processor = Wav2Vec2Processor(feature_extractor=feature_extractor, tokenizer=tokenizer) + self.model = Wav2Vec2ForFrameClassification.from_pretrained(str(bundle / 'charsiu/model'), + local_files_only=True).to(device).eval() + self.phone_to_id = {} + for label, idx in tokenizer.get_vocab().items(): + phone = fe.normalize_phone(label) + if phone and phone not in self.phone_to_id: + self.phone_to_id[phone] = int(idx) + self.sil_idx = tokenizer.convert_tokens_to_ids('[SIL]') + + @torch.inference_mode() + def __call__(self, audio, audio_end): + if len(audio) > round(audio_end * 16000): + raise AssertionError('Charsiu received audio beyond the current boundary') + # Exact official audio_preprocess: Wav2Vec2Processor normalization, no text. + x = self.processor(audio, sampling_rate=16000, return_tensors='pt').input_values.to(self.device) + probs = fe.softmax_np_matrix(self.model(input_values=x).logits[0].cpu().numpy()) + pred = probs.argmax(-1) + silence = [] + for key, group in groupby(pred): + group = list(group) + silence.extend([-1] * len(group) if key == self.sil_idx and len(group) < self.min_sil_frames else group) + keep = np.asarray(silence) != self.sil_idx + if not keep.any(): keep[:] = True + return dict(probs=probs, keep_mask=keep, frame_step=len(audio)/16000/len(probs)) + + +def filter_hypotheses(rows, mapper, config): + """Keep the historical repetition policy; no reference-length test.""" + kept, rejected = [], [] + for row in rows: + phones, _, sources = mapper.words_to_phone_sequence(row['words']) + strict = len(row['words']) > config['strict_repeat_word_trigger'] or len(phones) > config['strict_repeat_phone_trigger'] + repeat = fe.find_repeated_ngram([{'text': w} for w in row['words']], + min_repeats=config['repeat_ngram_min_repeats'], max_ngram_size=config['repeat_max_ngram_size'], + strict=strict, min_coverage=config['repeat_ngram_coverage'], dominant_token_ratio=config['repeat_token_ratio']) + if repeat is not None: + rejected.append(dict(rank=row['rank'], reason='repetitive_asr_hypothesis', details=repeat)) + elif sources.get('fallback_phone', 0) or sources.get('unmapped', 0): + rejected.append(dict(rank=row['rank'], reason='g2p_unavailable_for_word', sources=sources)) + elif not row['words'] or not phones: + rejected.append(dict(rank=row['rank'], reason='empty_hypothesis')) + else: + kept.append(dict(row, asr_phone_count=len(phones), phone_source_counts=sources)) + return kept, rejected + + +class StreamPAPipeline: + def __init__(self, bundle_dir, device='cpu', threads=2): + self.bundle_dir = Path(bundle_dir).resolve() + if device not in ('cpu', 'cuda', 'cuda:0'): + raise ValueError('Select cpu or one externally isolated CUDA device') + if device.startswith('cuda') and not torch.cuda.is_available(): + raise RuntimeError('CUDA is not available') + self.device = device + torch.set_num_threads(threads) + torch.manual_seed(1337) + torch.backends.cuda.matmul.allow_tf32 = False + self.assets = read_json(self.bundle_dir / 'scorer/inference_assets.json') + if self.assets['sample_rate'] != 16000 or self.assets['commit_rule'] != 'legacy': + raise ValueError('Bundle is not the frozen 16-kHz legacy-commit configuration') + self.model, self.config = load_scorer(self.bundle_dir, device) + self.manifest = read_json(self.bundle_dir / 'model_manifest.json') + os.environ['NLTK_DATA'] = str(self.bundle_dir / 'assets/nltk_data') + import nltk + nltk.data.path[:] = [os.environ['NLTK_DATA']] + self.phn_dict = read_json(self.bundle_dir / 'assets/phn_dict.json') + self.mapper = fe.PhoneMapper(read_json(self.bundle_dir / 'assets/pronunciation_lexicon.json'), self.phn_dict) + if self.mapper.g2p is None: + raise RuntimeError('G2P runtime resources missing. Run scripts/setup_assets.py first.') + self.charsiu = CharsiuFrontend(self.bundle_dir, device, self.assets['min_sil_frames']) + missing = set(self.phn_dict) - set(self.charsiu.phone_to_id) + if missing: + raise RuntimeError(f'Charsiu label mapping missing: {sorted(missing)}') + self.asr = fe.WhisperNBestGenerator(str(self.bundle_dir / 'whisper'), self.assets['language'], + device, self.assets['nbest'], self.assets['beam_size'], self.assets['max_new_tokens'], + self.assets['no_repeat_ngram_size']) + + @classmethod + def from_pretrained(cls, repo_id='faeea/StreamPA', revision=None, device='cpu', **kwargs): + if Path(repo_id).is_dir(): + return cls(repo_id, device=device, **kwargs) + if revision is None: + raise ValueError('Specify a fixed Hub commit or release tag') + from huggingface_hub import snapshot_download + path = snapshot_download(repo_id, revision=revision) + # Optional assets are deliberately fetched only by the explicit setup script. + return cls(path, device=device, **kwargs) + + def create_session(self): + return StreamPASession(self) + + def score_file(self, audio_path, block_samples=4096): + session = self.create_session() + rows = [] + with sf.SoundFile(audio_path) as f: + if f.samplerate != self.assets['sample_rate'] or f.channels != 1: + raise ValueError('Input must be mono 16000-Hz WAV; convert before starting a session') + while True: + block = f.read(block_samples, dtype='float32') + if len(block) == 0: break + rows.extend(session.append(block)) + rows.append(session.finish()) + return dict(model='StreamPA', seed=1337, prefixes=rows, final=rows[-1]) + + def make_batch(self, example): + n = len(example['cn_post']); limit = self.config['seq_len'] + if n > limit: raise ValueError(f'{n} PCN slots exceeds supported {limit}') + batch = {} + for key in ['cn_post','cn_stats','acoustic_post','acoustic_stats','slot_prosody', + 'pcn_word_id','cumulative_commit_mask','new_commit_mask']: + src = np.asarray(example[key]) + arr = np.full((limit,)+src.shape[1:], -1 if key=='pcn_word_id' else 0, dtype=src.dtype) + arr[:n] = src + batch['word_ids' if key=='pcn_word_id' else key] = arr[None] + batch['prosody'] = example['prosody'][None] + for key in ['prosody','slot_prosody']: + mean = np.asarray(self.config[key+'_norm_mean'],np.float32) + std = np.asarray(self.config[key+'_norm_std'],np.float32) + batch[key] = (batch[key]-mean)/np.clip(std,1e-6,None) + batch['visible_len'] = np.asarray([n],np.int64) + return {k:torch.from_numpy(v).to(self.device) for k,v in batch.items()} + + +class StreamPASession: + def __init__(self, pipeline): + self.pipeline = pipeline + self.reset() + + def reset(self): + self.audio = np.empty(0,np.float32) + self.state = None + self.commit_state = None + self.previous_phones = [] + self.next_step = 1 + self.prefix_index = 0 + self.closed = False + self.last_result = None + + def append(self, audio_block): + if self.closed: raise RuntimeError('Session ended; reset before appending another recording') + block = np.asarray(audio_block,dtype=np.float32) + if block.ndim != 1 or not np.isfinite(block).all(): + raise ValueError('Audio block must be finite mono samples') + if (len(self.audio)+len(block))/16000 > self.pipeline.assets['max_audio_sec']: + raise ValueError('Recording exceeds supported 30-second frontend limit; no audio was appended') + self.audio = np.concatenate([self.audio,block]) + rows = [] + while True: + commit = self.next_step * self.pipeline.assets['chunk_sec'] + end_samples = round((commit+self.pipeline.assets['right_context_sec'])*16000) + if len(self.audio) < end_samples: break + rows.append(self._step(round(commit*16000),end_samples,False)) + self.next_step += 1 + return rows + + def finish(self): + if self.closed: raise RuntimeError('Session already ended') + self.closed = True + return self._step(len(self.audio),len(self.audio),True) + + def current(self): + return self.last_result + + @torch.inference_mode() + def _step(self, commit_samples, end_samples, is_final): + started = time.perf_counter(); p = self.pipeline + audio = self.audio[:end_samples].copy() + assert len(audio) == end_samples <= len(self.audio) + commit, end = commit_samples/16000, end_samples/16000 + base = dict(prefix_index=self.prefix_index,commit_time=commit,audio_end=end, + received_audio_end=len(self.audio)/16000,is_final=is_final, + lookahead_sec=end-commit,model='StreamPA',seed=1337, + checkpoint_sha256=p.manifest['original_checkpoint_sha256'], + input_audio_sha256=hashlib.sha256(audio.tobytes()).hexdigest(), + frontend_received_samples=dict(whisper=0,charsiu=0,prosody=0,pcn=0), + state_updated=False,new_committed_word_count=0,scores=None) + self.prefix_index += 1 + def finish(status, **kw): + self.last_result=dict(base,status=status,wall_time_sec=time.perf_counter()-started,**kw) + return self.last_result + if end_samples == 0: return finish('empty_audio') + if end_samples < 400: return finish('audio_too_short') + if float(np.max(np.abs(audio))) < 1e-7: return finish('silence') + stages={} + t=time.perf_counter() + base['frontend_received_samples']['whisper']=end_samples + try: raw = p.asr.generate(audio,16000,end) + except Exception as exc: return finish('asr_failed',error=str(exc)) + stages['whisper_sec']=time.perf_counter()-t + hypotheses, rejected = filter_hypotheses(raw,p.mapper,p.assets['filter']) + if not hypotheses: return finish('no_usable_hypothesis',rejected_hypotheses=rejected,stages=stages) + t=time.perf_counter() + try: + base['frontend_received_samples']['charsiu']=end_samples + item=p.charsiu(audio,end) + hypotheses=[fe.align_hypothesis_with_charsiu(item,dict(row),p.mapper,p.phn_dict,p.charsiu.phone_to_id,end) for row in hypotheses] + failures=[r.get('timestamp_fallback_reason') for r in hypotheses if r.get('timestamp_source')!='charsiu_hypothesis_alignment'] + if failures: return finish('alignment_failed',reasons=failures,stages=stages) + base['frontend_received_samples']['pcn']=end_samples + pcn=fe.build_pcn_from_hypotheses(hypotheses,p.mapper,p.phn_dict) + fe.validate_pcn(pcn) + except Exception as exc: return finish('pcn_or_alignment_failed',error=str(exc),stages=stages) + stages['charsiu_alignment_pcn_sec']=time.perf_counter()-t + n=len(pcn['top_phone_ids']) + if n>p.config['seq_len']: return finish('unsupported_slot_length',slot_count=n,limit=p.config['seq_len'],stages=stages) + if n==0: return finish('no_scorable_slots',stages=stages) + ids=fe.top_hyp_word_ids_for_slots(pcn) + stats,_=fe.pcn_stats(pcn['cn_post'],pcn['top_phone_ids'],self.previous_phones,pcn['eps_index']) + acoustic,astats,frames=fe.build_acoustic_evidence(item,pcn['cn_post'],pcn['top_phone_ids'],p.charsiu.phone_to_id,p.phn_dict,end) + if frames==0: return finish('acoustic_alignment_failed',stages=stages) + t=time.perf_counter() + base['frontend_received_samples']['prosody']=end_samples + prosody=fe.compute_prosody(audio,16000,end,len(hypotheses[0]['words']),sum(x is not None for x in pcn['top_phone_ids'])) + slot_prosody=fe.compute_slot_prosody(audio,16000,pcn['slot_times'],ids,pcn['top_phone_ids'],p.phn_dict) + stages['prosody_sec']=time.perf_counter()-t + cumulative,new,mapping,diagnostics,next_commit=fe.build_stateful_commit_masks(self.commit_state,pcn,ids, + hypotheses[0]['word_timestamps'],commit,end,is_final,commit_rule='legacy') + example=dict(cn_post=pcn['cn_post'],cn_stats=stats,acoustic_post=acoustic,acoustic_stats=astats, + prosody=prosody,slot_prosody=slot_prosody,pcn_word_id=ids,cumulative_commit_mask=cumulative,new_commit_mask=new) + batch=p.make_batch(example) + if any(not torch.isfinite(v).all() for v in batch.values()): return finish('nonfinite_features',stages=stages) + t=time.perf_counter() + before=None if self.state is None else self.state.clone() + out=p.model(**batch,prev_state=self.state) + if p.device.startswith('cuda'): torch.cuda.synchronize() + stages['scorer_sec']=time.perf_counter()-t + if any(not torch.isfinite(v).all() for v in out.values() if torch.is_tensor(v)): + return finish('nonfinite_scores',stages=stages) + count=len(set(int(x) for x in ids[new>0] if x>=0)) + scorer_count=int(out['new_word_mask'].sum().item()) + if scorer_count!=count: + raise AssertionError('Scorer GRU input count differs from distinct newly committed ASR words') + if count==0 and before is not None: + assert torch.equal(before,out['next_state']), 'GRU state changed without a new committed word' + self.state=out['next_state'] + self.commit_state=next_commit + self.previous_phones=list(pcn['top_phone_ids']) + phone=out['phone_score'][0,:n,0].cpu().numpy() + word=out['word_scores'][0,:n].cpu().numpy() + utt=out['utt_scores'][0].cpu().numpy() + word_names=['accuracy','stress','total'] + utt_names=['accuracy','completeness','fluency','prosodic','total'] + slots=[] + reverse={v:k for k,v in p.phn_dict.items()} + for i in range(n): + ph=pcn['top_phone_ids'][i] + slots.append(dict(slot_index=i,asr_word_id=int(ids[i]),phone=reverse.get(ph,''), + time=pcn['slot_times'][i],phone_network_raw=float(phone[i]),phone_0_2=float(phone[i]*5), + phone_0_5=float(phone[i]*12.5),word_network_raw=word[i].tolist(), + word_0_5=(word[i]*2.5).tolist(),is_committed=bool(cumulative[i]),is_new_commit=bool(new[i]), + valid_phone=ph is not None)) + words=[] + for wid in sorted(set(int(v) for v in ids if v>=0)): + pos=np.flatnonzero(ids==wid) + values=word[pos].mean(0) + words.append(dict(asr_word_id=wid,text=hypotheses[0]['words'][wid],slot_indices=pos.tolist(), + scores_0_5=dict(zip(word_names,(values*2.5).tolist())),scores_network_raw=dict(zip(word_names,values.tolist())), + committed=bool(np.all(cumulative[pos]>0)),new_commit=bool(np.all(new[pos]>0)), + revisable=True,aggregation='arithmetic mean of visible slots assigned to this current ASR word')) + base['state_updated']=count>0 + base['new_committed_word_count']=count + base['scores']=dict(utterance_network_raw=dict(zip(utt_names,utt.tolist())), + utterance_0_5={k:float(utt[j]*2.5) for j,k in enumerate(utt_names) if k!='completeness'}, + completeness_status='untrained_not_displayed',clipped=False) + return finish('ok',slots=slots,words=words,visible_len=n, + cumulative_commit_mask=cumulative.tolist(),new_commit_mask=new.tolist(),mapped_old_slot=mapping.tolist(), + commit_diagnostics=diagnostics,stages=stages,rejected_hypotheses=rejected, + scorer_new_word_count=scorer_count, + state_sha256=hashlib.sha256(self.state.cpu().numpy().tobytes()).hexdigest(), + hypothesis_count=len(hypotheses)) diff --git a/streampa/stream.py b/streampa/stream.py new file mode 100644 index 0000000000000000000000000000000000000000..ef09d04d6c842a34ffd5f5920980a77a0cba4413 --- /dev/null +++ b/streampa/stream.py @@ -0,0 +1,28 @@ +import argparse +import json +from pathlib import Path +import soundfile as sf +from .pipeline import StreamPAPipeline + +def main(): + p=argparse.ArgumentParser(description='Append raw audio blocks and emit each StreamPA prefix') + p.add_argument('--audio',required=True) + p.add_argument('--bundle-dir',required=True) + p.add_argument('--device',default='cpu') + p.add_argument('--threads',type=int,default=2) + p.add_argument('--block-samples',type=int,default=1600) + p.add_argument('--output',required=True) + a=p.parse_args() + session=StreamPAPipeline(a.bundle_dir,a.device,a.threads).create_session() + dest=Path(a.output); dest.parent.mkdir(parents=True,exist_ok=True) + with sf.SoundFile(a.audio) as audio, dest.open('x',encoding='utf-8') as f: + if audio.samplerate!=16000 or audio.channels!=1: raise ValueError('Input must be mono 16000-Hz WAV') + while True: + block=audio.read(a.block_samples,dtype='float32') + if not len(block): break + for row in session.append(block): + f.write(json.dumps(row,allow_nan=False)+'\n'); f.flush() + f.write(json.dumps(session.finish(),allow_nan=False)+'\n') + print(json.dumps(dict(output=str(dest),prefixes=session.prefix_index))) + +if __name__=='__main__': main() diff --git a/streampa/streaming_gopt.py b/streampa/streaming_gopt.py new file mode 100644 index 0000000000000000000000000000000000000000..7f60a3a47b961fc0826e0c8969c6899a254b45bf --- /dev/null +++ b/streampa/streaming_gopt.py @@ -0,0 +1,238 @@ +# -*- coding: utf-8 -*- + +import math +import warnings + +import numpy as np +import torch +import torch.nn as nn +import torch.nn.functional as F + + +def _no_grad_trunc_normal_(tensor, mean, std, a, b): + def norm_cdf(x): + return (1. + math.erf(x / math.sqrt(2.))) / 2. + + if (mean < a - 2 * std) or (mean > b + 2 * std): + warnings.warn( + "mean is more than 2 std from [a, b] in nn.init.trunc_normal_. " + "The distribution of values may be incorrect.", + stacklevel=2, + ) + + with torch.no_grad(): + l = norm_cdf((a - mean) / std) + u = norm_cdf((b - mean) / std) + tensor.uniform_(2 * l - 1, 2 * u - 1) + tensor.erfinv_() + tensor.mul_(std * math.sqrt(2.)) + tensor.add_(mean) + tensor.clamp_(min=a, max=b) + return tensor + + +def trunc_normal_(tensor, mean=0., std=1., a=-2., b=2.): + return _no_grad_trunc_normal_(tensor, mean, std, a, b) + + +class MaskedAttention(nn.Module): + def __init__(self, dim, num_heads=8, qkv_bias=False, qk_scale=None, attn_drop=0., proj_drop=0.): + super().__init__() + self.num_heads = num_heads + head_dim = dim // num_heads + self.scale = qk_scale or head_dim ** -0.5 + + self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias) + self.attn_drop = nn.Dropout(attn_drop) + self.proj = nn.Linear(dim, dim) + self.proj_drop = nn.Dropout(proj_drop) + + def forward(self, x, attn_mask): + bsz, seq_len, dim = x.shape + qkv = self.qkv(x).reshape(bsz, seq_len, 3, self.num_heads, dim // self.num_heads) + qkv = qkv.permute(2, 0, 3, 1, 4) + q, k, v = qkv[0], qkv[1], qkv[2] + + attn = (q @ k.transpose(-2, -1)) * self.scale + attn = attn.masked_fill(~attn_mask.unsqueeze(1), torch.finfo(attn.dtype).min) + attn = attn.softmax(dim=-1) + attn = self.attn_drop(attn) + + x = (attn @ v).transpose(1, 2).reshape(bsz, seq_len, dim) + x = self.proj(x) + x = self.proj_drop(x) + return x + + +class Mlp(nn.Module): + def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.): + super().__init__() + out_features = out_features or in_features + hidden_features = hidden_features or in_features + self.fc1 = nn.Linear(in_features, hidden_features) + self.act = act_layer() + self.fc2 = nn.Linear(hidden_features, out_features) + self.drop = nn.Dropout(drop) + + def forward(self, x): + x = self.fc1(x) + x = self.act(x) + x = self.drop(x) + x = self.fc2(x) + x = self.drop(x) + return x + + +class StreamingBlock(nn.Module): + def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop=0., attn_drop=0., + act_layer=nn.GELU, norm_layer=nn.LayerNorm): + super().__init__() + self.norm1 = norm_layer(dim) + self.attn = MaskedAttention( + dim, num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop, + ) + self.norm2 = norm_layer(dim) + mlp_hidden_dim = int(dim * mlp_ratio) + self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop) + + def forward(self, x, attn_mask): + x = x + self.attn(self.norm1(x), attn_mask) + x = x + self.mlp(self.norm2(x)) + return x + + +class StreamingGOPT(nn.Module): + def __init__(self, embed_dim, num_heads, depth, input_dim, seq_len, phn_num, use_phone_embedding=True): + super().__init__() + self.input_dim = input_dim + self.embed_dim = embed_dim + self.seq_len = seq_len + self.phn_num = phn_num + self.use_phone_embedding = use_phone_embedding + + self.blocks = nn.ModuleList([StreamingBlock(dim=embed_dim, num_heads=num_heads) for _ in range(depth)]) + self.pos_embed = nn.Parameter(torch.zeros(1, self.seq_len + 5, self.embed_dim)) + trunc_normal_(self.pos_embed, std=.02) + + self.in_proj = nn.Linear(self.input_dim, embed_dim) + self.phn_proj = nn.Linear(self.phn_num, embed_dim) + self.cls_tokens = nn.Parameter(torch.zeros(1, 5, embed_dim)) + trunc_normal_(self.cls_tokens, std=.02) + + self.mlp_head_phn = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.mlp_head_word1 = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.mlp_head_word2 = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.mlp_head_word3 = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.mlp_head_word4 = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.mlp_head_utt1 = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.mlp_head_utt2 = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.mlp_head_utt3 = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.mlp_head_utt4 = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.mlp_head_utt5 = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + + def build_streaming_mask(self, visible_lens, max_phone_tokens, main_context_tokens, right_context_tokens, device): + total_len = max_phone_tokens + 5 + mask = torch.zeros((visible_lens.shape[0], total_len, total_len), dtype=torch.bool, device=device) + for row, visible_len in enumerate(visible_lens.tolist()): + visible_len = int(visible_len) + cls_start = visible_len + valid_len = visible_len + 5 + + for tok_idx in range(visible_len): + block_end = ((tok_idx // main_context_tokens) + 1) * main_context_tokens - 1 + max_key = min(visible_len - 1, block_end + right_context_tokens) + mask[row, tok_idx, :max_key + 1] = True + + for cls_offset in range(5): + query_idx = cls_start + cls_offset + mask[row, query_idx, :query_idx + 1] = True + + for pad_idx in range(valid_len, total_len): + mask[row, pad_idx, pad_idx] = True + + return mask + + def pack_sequence(self, token_embed, phn_ids): + batch_size, max_phone_tokens, embed_dim = token_embed.shape + visible_mask = phn_ids >= 0 + visible_lens = visible_mask.sum(dim=1) + total_len = max_phone_tokens + 5 + + packed = token_embed.new_zeros(batch_size, total_len, embed_dim) + cls_positions = torch.zeros(batch_size, 5, dtype=torch.long, device=token_embed.device) + + cls_tokens = self.cls_tokens.expand(batch_size, -1, -1) + for row, visible_len in enumerate(visible_lens.tolist()): + visible_len = int(visible_len) + if visible_len > 0: + packed[row, :visible_len] = token_embed[row, :visible_len] + cls_start = visible_len + packed[row, cls_start:cls_start + 5] = cls_tokens[row] + cls_positions[row] = torch.arange(cls_start, cls_start + 5, device=token_embed.device) + + packed = packed + self.pos_embed[:, :total_len] + return packed, visible_lens, cls_positions + + def unpack_phone_states(self, hidden, visible_lens, max_phone_tokens): + phone_hidden = hidden.new_zeros(hidden.shape[0], max_phone_tokens, hidden.shape[-1]) + for row, visible_len in enumerate(visible_lens.tolist()): + visible_len = int(visible_len) + if visible_len > 0: + phone_hidden[row, :visible_len] = hidden[row, :visible_len] + return phone_hidden + + def forward(self, x, phn, main_context_tokens=8, right_context_tokens=2): + main_context_tokens = max(int(main_context_tokens), 1) + right_context_tokens = max(int(right_context_tokens), 0) + + batch_size, max_phone_tokens, _ = x.shape + visible_mask = phn >= 0 + x = self.in_proj(x) if self.embed_dim != self.input_dim else x + + phn_clamped = torch.clamp(phn.long() + 1, min=0, max=self.phn_num - 1) + phn_one_hot = F.one_hot(phn_clamped, num_classes=self.phn_num).float() + phn_embed = self.phn_proj(phn_one_hot) * visible_mask.unsqueeze(-1) + token_embed = x + phn_embed if self.use_phone_embedding else x + packed, visible_lens, cls_positions = self.pack_sequence(token_embed, phn) + + attn_mask = self.build_streaming_mask( + visible_lens=visible_lens, + max_phone_tokens=max_phone_tokens, + main_context_tokens=main_context_tokens, + right_context_tokens=right_context_tokens, + device=x.device, + ) + + hidden = packed + for blk in self.blocks: + hidden = blk(hidden, attn_mask) + + phone_hidden = self.unpack_phone_states(hidden, visible_lens, max_phone_tokens) + batch_index = torch.arange(batch_size, device=x.device).unsqueeze(1) + cls_hidden = hidden[batch_index, cls_positions] + + u1 = self.mlp_head_utt1(cls_hidden[:, 0]) + u2 = self.mlp_head_utt2(cls_hidden[:, 1]) + u3 = self.mlp_head_utt3(cls_hidden[:, 2]) + u4 = self.mlp_head_utt4(cls_hidden[:, 3]) + u5 = self.mlp_head_utt5(cls_hidden[:, 4]) + + p = self.mlp_head_phn(phone_hidden) + w1 = self.mlp_head_word1(phone_hidden) + w2 = self.mlp_head_word2(phone_hidden) + w3 = self.mlp_head_word3(phone_hidden) + w4 = self.mlp_head_word4(phone_hidden) + return u1, u2, u3, u4, u5, p, w1, w2, w3, w4 + + +class StreamingGOPTNoPhn(StreamingGOPT): + def __init__(self, embed_dim, num_heads, depth, input_dim, seq_len, phn_num): + super().__init__( + embed_dim=embed_dim, + num_heads=num_heads, + depth=depth, + input_dim=input_dim, + seq_len=seq_len, + phn_num=phn_num, + use_phone_embedding=False, + ) diff --git a/streampa/streaming_pcn_gopt.py b/streampa/streaming_pcn_gopt.py new file mode 100644 index 0000000000000000000000000000000000000000..0d46982ce9c911efd0436e8f202b26636706f9a2 --- /dev/null +++ b/streampa/streaming_pcn_gopt.py @@ -0,0 +1,422 @@ +# -*- coding: utf-8 -*- + +import torch +import torch.nn as nn + +from .streaming_gopt import StreamingBlock, trunc_normal_ + + +def masked_mean(values, mask, dim, keepdim=False): + mask = mask.to(dtype=values.dtype) + while mask.dim() < values.dim(): + mask = mask.unsqueeze(-1) + denom = mask.sum(dim=dim, keepdim=keepdim).clamp_min(1.0) + return (values * mask).sum(dim=dim, keepdim=keepdim) / denom + + +class ReliabilityGate(nn.Module): + def __init__(self, hidden_dim=16, output_dim=1): + super().__init__() + self.net = nn.Sequential( + nn.Linear(4, hidden_dim), + nn.GELU(), + nn.Linear(hidden_dim, int(output_dim)), + ) + + def forward(self, cn_stats, acoustic_stats): + # cn_stats: eps, entropy, top1, margin, prefix_stability + # acoustic_stats: entropy, margin, duration, PCN-Charsiu JS divergence + gate_input = torch.stack( + [ + cn_stats[..., 1], + acoustic_stats[..., 0], + acoustic_stats[..., 3], + cn_stats[..., 4], + ], + dim=-1, + ) + return torch.sigmoid(self.net(gate_input)) + + +class PCNStreamingScorer(nn.Module): + """ + Stateful streaming scorer for streaming_pcn_gopt_v2_stateful. + + Local phone/word heads read all visible PCN slots. The sentence GRU is + updated only from slots selected by new_commit_mask. cumulative_commit_mask + is retained for losses/diagnostics and must not be used for GRU updates. + """ + + def __init__( + self, + phone_dim, + seq_len, + prosody_dim=14, + embed_dim=40, + num_heads=2, + depth=2, + pcn_embed_dim=16, + acoustic_embed_dim=16, + prosody_embed_dim=8, + gru_dim=32, + main_context_tokens=16, + dropout=0.0, + use_state_projection=False, + teacher_state_dim=128, + utt_pooling_head='gru', + fusion_mode='scalar_gate', + slot_prosody_dim=0, + slot_prosody_embed_dim=8, + stress_branch='none', + stress_grad_scale=0.2, + use_acoustic=True, + use_prosody=True, + use_uncertainty_stats=True, + ): + super().__init__() + self.phone_dim = int(phone_dim) + self.seq_len = int(seq_len) + self.prosody_dim = int(prosody_dim) + self.embed_dim = int(embed_dim) + self.gru_dim = int(gru_dim) + self.main_context_tokens = max(int(main_context_tokens), 1) + self.use_state_projection = bool(use_state_projection) + self.utt_pooling_head = str(utt_pooling_head) + self.fusion_mode = str(fusion_mode) + self.slot_prosody_dim = int(slot_prosody_dim or 0) + self.stress_branch = str(stress_branch) + self.stress_grad_scale = float(stress_grad_scale) + self.use_acoustic = bool(use_acoustic) + self.use_prosody = bool(use_prosody) + self.use_uncertainty_stats = bool(use_uncertainty_stats) + + if self.utt_pooling_head not in {'gru', 'gru_visible', 'visible_committed'}: + raise ValueError("utt_pooling_head must be 'gru', 'gru_visible', or 'visible_committed'.") + if self.fusion_mode not in {'scalar_gate', 'concat_vector_gate', 'fixed_average'}: + raise ValueError("fusion_mode must be 'scalar_gate', 'concat_vector_gate', or 'fixed_average'.") + if self.stress_branch not in {'none', 'detached', 'gradscale'}: + raise ValueError("stress_branch must be 'none', 'detached', or 'gradscale'.") + + if pcn_embed_dim != acoustic_embed_dim: + raise ValueError('pcn_embed_dim and acoustic_embed_dim must match for gated interpolation.') + + self.pcn_proj = nn.Sequential( + nn.Linear(self.phone_dim + 5, pcn_embed_dim), + nn.LayerNorm(pcn_embed_dim), + nn.GELU(), + ) + self.acoustic_proj = None + if self.use_acoustic: + self.acoustic_proj = nn.Sequential( + nn.Linear(self.phone_dim + 4, acoustic_embed_dim), + nn.LayerNorm(acoustic_embed_dim), + nn.GELU(), + ) + self.prosody_proj = None + prosody_fused_dim = 0 + if self.use_prosody: + prosody_fused_dim = int(prosody_embed_dim) + self.prosody_proj = nn.Sequential( + nn.Linear(self.prosody_dim, max(16, prosody_embed_dim * 2)), + nn.GELU(), + nn.Linear(max(16, prosody_embed_dim * 2), prosody_embed_dim), + nn.LayerNorm(prosody_embed_dim), + ) + if self.use_acoustic and self.fusion_mode != 'fixed_average': + gate_dim = pcn_embed_dim if self.fusion_mode == 'concat_vector_gate' else 1 + self.reliability_gate = ReliabilityGate(output_dim=gate_dim) + else: + self.reliability_gate = None + self.slot_prosody_proj = None + slot_prosody_fused_dim = 0 + if self.slot_prosody_dim > 0: + slot_prosody_fused_dim = int(slot_prosody_embed_dim) + self.slot_prosody_proj = nn.Sequential( + nn.Linear(self.slot_prosody_dim, max(16, slot_prosody_fused_dim * 2)), + nn.GELU(), + nn.Linear(max(16, slot_prosody_fused_dim * 2), slot_prosody_fused_dim), + nn.LayerNorm(slot_prosody_fused_dim), + ) + if not self.use_acoustic: + evidence_dim = pcn_embed_dim + elif self.fusion_mode == 'concat_vector_gate': + evidence_dim = pcn_embed_dim * 4 + else: + evidence_dim = pcn_embed_dim + self.fused_proj = nn.Sequential( + nn.Linear(evidence_dim + prosody_fused_dim + slot_prosody_fused_dim, embed_dim), + nn.LayerNorm(embed_dim), + nn.Dropout(dropout), + ) + self.pos_embed = nn.Parameter(torch.zeros(1, self.seq_len, self.embed_dim)) + trunc_normal_(self.pos_embed, std=.02) + self.blocks = nn.ModuleList( + [ + StreamingBlock( + dim=embed_dim, + num_heads=num_heads, + mlp_ratio=2.0, + qkv_bias=True, + drop=dropout, + attn_drop=dropout, + ) + for _ in range(depth) + ] + ) + + self.word_pool_proj = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, embed_dim), nn.GELU()) + self.sentence_gru = None + if self.utt_pooling_head != 'visible_committed': + self.sentence_gru = nn.GRU(input_size=embed_dim, hidden_size=gru_dim, batch_first=True) + + self.phone_head = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.word_head = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 3)) + self.stress_head = None + if self.stress_branch != 'none': + self.stress_head = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.asr_correct_head = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.uncertainty_head = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.confidence_head = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.abstention_head = nn.Sequential(nn.LayerNorm(embed_dim), nn.Linear(embed_dim, 1)) + self.utt_head = None + if self.utt_pooling_head == 'gru': + self.utt_head = nn.Sequential(nn.LayerNorm(gru_dim), nn.Linear(gru_dim, 5)) + self.utt_visible_head = None + if self.utt_pooling_head == 'gru_visible': + visible_dim = gru_dim + embed_dim + embed_dim + 2 + self.utt_visible_head = nn.Sequential(nn.LayerNorm(visible_dim), nn.Linear(visible_dim, 5)) + elif self.utt_pooling_head == 'visible_committed': + visible_dim = embed_dim + embed_dim + 2 + self.utt_visible_head = nn.Sequential(nn.LayerNorm(visible_dim), nn.Linear(visible_dim, 5)) + self.state_projection = ( + nn.Sequential(nn.LayerNorm(gru_dim), nn.Linear(gru_dim, int(teacher_state_dim))) + if self.use_state_projection + else None + ) + + def build_local_causal_mask(self, valid_mask): + batch_size, seq_len = valid_mask.shape + idx = torch.arange(seq_len, device=valid_mask.device) + causal = idx.view(1, -1) <= idx.view(-1, 1) + local = idx.view(1, -1) >= (idx.view(-1, 1) - self.main_context_tokens + 1) + base = causal & local + mask = base.unsqueeze(0).expand(batch_size, -1, -1).clone() + key_valid = valid_mask.unsqueeze(1).expand(-1, seq_len, -1) + query_valid = valid_mask.unsqueeze(2).expand(-1, -1, seq_len) + mask = mask & key_valid & query_valid + diag = torch.eye(seq_len, dtype=torch.bool, device=valid_mask.device).unsqueeze(0) + return mask | diag + + def encode_slots(self, cn_post, cn_stats, acoustic_post, acoustic_stats, prosody, valid_mask, slot_prosody=None): + if not self.use_uncertainty_stats: + cn_stats = cn_stats.clone() + acoustic_stats = acoustic_stats.clone() + cn_stats[..., 1] = 0.0 # PCN entropy + cn_stats[..., 3] = 0.0 # PCN margin + cn_stats[..., 4] = 0.0 # prefix stability + acoustic_stats[..., 0] = 0.0 # acoustic entropy + acoustic_stats[..., 1] = 0.0 # acoustic margin + acoustic_stats[..., 3] = 0.0 # PCN/Charsiu JS divergence + z_pcn = self.pcn_proj(torch.cat([cn_post, cn_stats], dim=-1)) + if self.use_acoustic: + z_acoustic = self.acoustic_proj(torch.cat([acoustic_post, acoustic_stats], dim=-1)) + if self.fusion_mode == 'fixed_average': + gate = cn_post.new_full((*cn_post.shape[:2], 1), 0.5) + interpolation = 0.5 * z_acoustic + 0.5 * z_pcn + else: + gate = self.reliability_gate(cn_stats, acoustic_stats) + interpolation = gate * z_acoustic + (1.0 - gate) * z_pcn + if self.fusion_mode == 'concat_vector_gate': + evidence = torch.cat([z_pcn, z_acoustic, z_acoustic - z_pcn, interpolation], dim=-1) + else: + evidence = interpolation + else: + gate = cn_post.new_zeros((*cn_post.shape[:2], 1)) + evidence = z_pcn + fused_parts = [evidence] + if self.prosody_proj is not None: + z_prosody = self.prosody_proj(prosody).unsqueeze(1).expand(-1, cn_post.shape[1], -1) + fused_parts.append(z_prosody) + if self.slot_prosody_proj is not None: + if slot_prosody is None: + slot_prosody = cn_post.new_zeros(cn_post.shape[0], cn_post.shape[1], self.slot_prosody_dim) + fused_parts.append(self.slot_prosody_proj(slot_prosody)) + token = self.fused_proj(torch.cat(fused_parts, dim=-1)) + token = token + self.pos_embed[:, : token.shape[1]] + token = token * valid_mask.unsqueeze(-1).to(token.dtype) + return token, gate + + def local_causal_transformer(self, token, valid_mask): + attn_mask = self.build_local_causal_mask(valid_mask) + hidden = token + for block in self.blocks: + hidden = block(hidden, attn_mask) + return hidden * valid_mask.unsqueeze(-1).to(hidden.dtype) + + def pool_new_committed_words(self, hidden, new_commit_mask, word_ids=None): + batch_size, _, dim = hidden.shape + row_groups = [] + max_words = 0 + for row in range(batch_size): + active = torch.nonzero(new_commit_mask[row] > 0, as_tuple=False).squeeze(1).tolist() + groups = [] + if active: + if word_ids is None: + groups = [[idx] for idx in active] + else: + cur_group = [active[0]] + cur_word = int(word_ids[row, active[0]].item()) + for idx in active[1:]: + next_word = int(word_ids[row, idx].item()) + if next_word == cur_word and next_word >= 0: + cur_group.append(idx) + else: + groups.append(cur_group) + cur_group = [idx] + cur_word = next_word + groups.append(cur_group) + row_groups.append(groups) + max_words = max(max_words, len(groups)) + + max_words = max(max_words, 1) + pooled_rows = [] + pooled_masks = [] + for row, groups in enumerate(row_groups): + pooled = hidden.new_zeros(max_words, dim) + mask = hidden.new_zeros(max_words) + for group_idx, positions in enumerate(groups): + pos = torch.tensor(positions, dtype=torch.long, device=hidden.device) + pooled[group_idx] = self.word_pool_proj(hidden[row, pos].mean(dim=0)) + mask[group_idx] = 1.0 + pooled_rows.append(pooled) + pooled_masks.append(mask) + return torch.stack(pooled_rows, dim=0), torch.stack(pooled_masks, dim=0) + + def update_sentence_state(self, new_words, word_mask, prev_state): + batch_size = new_words.shape[0] + if prev_state is not None and prev_state.dim() == 2: + prev_state = prev_state.unsqueeze(0) + states = [] + for row in range(batch_size): + if prev_state is None: + h0 = new_words.new_zeros(1, 1, self.gru_dim) + else: + h0 = prev_state[:, row : row + 1, :] + word_count = int(word_mask[row].sum().item()) + if word_count <= 0: + states.append(h0) + continue + _, h_row = self.sentence_gru(new_words[row : row + 1, :word_count], h0) + states.append(h_row) + return torch.cat(states, dim=1) + + def forward( + self, + cn_post, + cn_stats, + acoustic_post, + acoustic_stats, + prosody, + visible_len, + cumulative_commit_mask=None, + new_commit_mask=None, + commit_mask=None, + word_ids=None, + slot_prosody=None, + prev_state=None, + detach_next_state=False, + ): + batch_size, seq_len, _ = cn_post.shape + device = cn_post.device + token_idx = torch.arange(seq_len, device=device).unsqueeze(0) + valid_mask = token_idx < visible_len.to(device).unsqueeze(1) + + if cumulative_commit_mask is None: + cumulative_commit_mask = commit_mask + if cumulative_commit_mask is None: + cumulative_commit_mask = torch.zeros((batch_size, seq_len), dtype=torch.bool, device=device) + if new_commit_mask is None: + # Legacy fallback: safe only for stateless/full-sentence use. + new_commit_mask = cumulative_commit_mask + cumulative_commit_mask = (cumulative_commit_mask > 0) & valid_mask + new_commit_mask = (new_commit_mask > 0) & valid_mask + + token, gate = self.encode_slots(cn_post, cn_stats, acoustic_post, acoustic_stats, prosody, valid_mask, slot_prosody=slot_prosody) + slot_hidden = self.local_causal_transformer(token, valid_mask) + new_words, new_word_mask = self.pool_new_committed_words(slot_hidden, new_commit_mask, word_ids=word_ids) + if self.sentence_gru is None: + final_state = slot_hidden.new_zeros(1, batch_size, self.gru_dim) + else: + final_state = self.update_sentence_state(new_words, new_word_mask, prev_state) + next_state = final_state.detach() if detach_next_state else final_state + sentence_state = final_state[-1] + + confidence_logit = self.confidence_head(slot_hidden) + abstention_logit = self.abstention_head(slot_hidden) + confidence = torch.sigmoid(confidence_logit) + abstention_probability = torch.sigmoid(abstention_logit) + if self.utt_pooling_head in {'gru_visible', 'visible_committed'}: + committed_pool = masked_mean(slot_hidden, cumulative_commit_mask, dim=1) + visible_pool = masked_mean(slot_hidden, valid_mask, dim=1) + mean_confidence = masked_mean(confidence, valid_mask, dim=1) + mean_abstention = masked_mean(abstention_probability, valid_mask, dim=1) + if self.utt_pooling_head == 'gru_visible': + utt_input = torch.cat([sentence_state, committed_pool, visible_pool, mean_confidence, mean_abstention], dim=-1) + else: + utt_input = torch.cat([committed_pool, visible_pool, mean_confidence, mean_abstention], dim=-1) + utt_scores = self.utt_visible_head(utt_input) + else: + utt_scores = self.utt_head(sentence_state) + base_word_scores = self.word_head(slot_hidden) + if self.stress_head is None: + word_scores = base_word_scores + else: + if self.stress_branch == 'detached': + stress_input = slot_hidden.detach() + else: + scale = float(self.stress_grad_scale) + stress_input = scale * slot_hidden + (1.0 - scale) * slot_hidden.detach() + stress_score = self.stress_head(stress_input) + word_scores = torch.cat([base_word_scores[..., 0:1], stress_score, base_word_scores[..., 2:3]], dim=-1) + + output = { + 'phone_score': self.phone_head(slot_hidden), + 'word_scores': word_scores, + 'utt_scores': utt_scores, + 'asr_correct_logits': self.asr_correct_head(slot_hidden), + 'uncertainty_logits': self.uncertainty_head(slot_hidden), + 'confidence_logit': confidence_logit, + 'confidence': confidence, + 'abstention_logit': abstention_logit, + 'abstention_probability': abstention_probability, + 'reliability_gate': gate, + 'slot_hidden': slot_hidden, + 'new_word_states': new_words, + 'new_word_mask': new_word_mask, + 'word_states': new_words, + 'word_mask': new_word_mask, + 'sentence_state': sentence_state, + 'next_state': next_state, + 'cumulative_commit_mask': cumulative_commit_mask, + 'new_commit_mask': new_commit_mask, + } + if self.state_projection is not None: + output['state_projection'] = self.state_projection(sentence_state) + return output + + @torch.inference_mode() + def stream_step(self, batch, prev_state=None): + return self.forward( + cn_post=batch['cn_post'], + cn_stats=batch['cn_stats'], + acoustic_post=batch['acoustic_post'], + acoustic_stats=batch['acoustic_stats'], + prosody=batch['prosody'], + visible_len=batch['visible_len'], + cumulative_commit_mask=batch.get('cumulative_commit_mask', batch.get('commit_mask')), + new_commit_mask=batch.get('new_commit_mask'), + word_ids=batch.get('pcn_word_id'), + slot_prosody=batch.get('slot_prosody'), + prev_state=prev_state, + detach_next_state=True, + ) diff --git a/tests/test_runtime.py b/tests/test_runtime.py new file mode 100644 index 0000000000000000000000000000000000000000..26671daad0b8450e7ee0c1eb4335fda55112e746 --- /dev/null +++ b/tests/test_runtime.py @@ -0,0 +1,88 @@ +"""Deterministic contract tests; real audio validation is documented separately.""" +from types import SimpleNamespace +from pathlib import Path +import numpy as np +import pytest +import torch +from streampa.pipeline import StreamPASession, load_scorer +from streampa import frontend as fe + +class ScheduleSession(StreamPASession): + def _step(self,commit_samples,end_samples,is_final): + row=dict(commit=commit_samples,end=end_samples,final=is_final,samples=self.audio[:end_samples].copy()) + self.last_result=row + return row + +def session(): + return ScheduleSession(SimpleNamespace(assets={'max_audio_sec':30,'chunk_sec':.64,'right_context_sec':.16})) + +def test_received_boundary_and_short_eof(): + s=session() + assert s.append(np.zeros(12799,np.float32))==[] + r=s.append(np.ones(1,np.float32))[0] + assert r['commit']==10240 and r['end']==12800 and not r['final'] + s.append(np.ones(100,np.float32)) + r=s.finish() + assert r['end']==12900 and r['commit']==12900 and r['final'] + +def test_reset_and_new_session_do_not_share_state(): + a=session(); b=session() + a.state=torch.ones(1,64); a.commit_state={'committed_slots':[0]} + a.append(np.ones(100)); a.reset() + assert a.state is None and a.commit_state is None and len(a.audio)==0 + assert b.state is None and len(b.audio)==0 + +def test_suffix_is_not_in_current_input(): + prefix=np.arange(12800,dtype=np.float32) + a=session(); b=session() + x=a.append(np.concatenate([prefix,np.ones(10000)]))[0] + y=b.append(np.concatenate([prefix,-np.ones(10000)]))[0] + assert np.array_equal(x['samples'],y['samples']) + +def test_closed_empty_and_invalid_input(): + s=session(); assert s.finish()['end']==0 + with pytest.raises(RuntimeError): s.append(np.zeros(1)) + s.reset() + with pytest.raises(ValueError): s.append(np.array([np.nan])) + with pytest.raises(ValueError): s.append(np.zeros((2,2))) + with pytest.raises(ValueError): s.append(np.zeros(480001)) + assert len(s.audio)==0 + +def test_normalization_and_gap_mass(): + assert fe.normalize_phone('AH0')=='AH' + assert fe.normalize_word('Hello!')=='HELLO' + post=np.array([[.6,.1,.3],[.2,.6,.2]],np.float32) + pcn={'cn_post':post,'eps_index':2} + fe.validate_pcn(pcn) + stats,_=fe.pcn_stats(post,[0,1],[],2) + assert np.allclose(stats[:,0],[.3,.2]) + with pytest.raises(ValueError): fe.validate_pcn({'cn_post':post*0,'eps_index':2}) + +def test_partial_commit_and_legacy_persistence(): + pcn={'top_phone_ids':[1,2],'slot_times':[(0,.3),(.3,.8)]} + ids=np.array([0,1],np.int32) + times=[{'word':'A','start':0,'end':.3},{'word':'B','start':.3,'end':.8}] + cum,new,_,_,state=fe.build_stateful_commit_masks(None,pcn,ids,times,.64,.8,False,commit_rule='legacy') + assert new.tolist()==[1.,0.] and cum.tolist()==[1.,0.] + cum,new,_,_,state=fe.build_stateful_commit_masks(state,pcn,ids,times,.8,.8,True,commit_rule='legacy') + assert new.tolist()==[0.,1.] and cum.tolist()==[1.,1.] + _,new,_,_,_=fe.build_stateful_commit_masks(state,pcn,ids,times,1,1,True,commit_rule='legacy') + assert new.sum()==0 + +def test_no_new_words_keeps_state_but_visible_path_remains_active(): + torch.set_num_threads(2); torch.manual_seed(1337) + model,c=load_scorer(Path(__file__).resolve().parents[1]) + n=c['seq_len']; d=c['phone_dim'] + batch=dict(cn_post=torch.softmax(torch.randn(1,n,d),-1),cn_stats=torch.randn(1,n,5), + acoustic_post=torch.softmax(torch.randn(1,n,d),-1),acoustic_stats=torch.randn(1,n,4), + prosody=torch.randn(1,c['prosody_dim']),slot_prosody=torch.randn(1,n,c['slot_prosody_dim']), + visible_len=torch.tensor([4]),cumulative_commit_mask=torch.zeros(1,n),new_commit_mask=torch.zeros(1,n), + word_ids=torch.arange(n)[None]) + state=torch.randn(1,1,64) + with torch.inference_mode(): + first=model(**batch,prev_state=state) + batch['cn_stats'][:,:4]+=2 + second=model(**batch,prev_state=state) + assert torch.equal(first['next_state'],state) and torch.equal(second['next_state'],state) + assert first['new_word_mask'].sum()==0 + assert not torch.equal(first['utt_scores'],second['utt_scores']) diff --git a/validation_summary.json b/validation_summary.json new file mode 100644 index 0000000000000000000000000000000000000000..a70ed23483407809ec2e41ebd9613ee4a98a37fc --- /dev/null +++ b/validation_summary.json @@ -0,0 +1,139 @@ +{ + "status": "LOCAL_VALIDATION_PASS_HUB_VERIFICATION_REQUIRED", + "created_at": "2026-09-10T10:50:20.386964+00:00", + "python": "3.10.19", + "torch": "2.5.1+cpu", + "platform": "Ubuntu WSL2 on local Windows computer", + "device": "cpu", + "dtype": "float32", + "no_training": true, + "no_finetuning": true, + "checkpoint_values_unchanged": true, + "scorer_equivalence": { + "status": "PASS", + "atol": 1e-05, + "rtol": 1e-05, + "dtype": "float32", + "device": "cpu", + "prefixes": 4, + "server_torch": "2.3.1+cu121", + "local_torch": "2.5.1+cpu", + "max_abs": 3.814697265625e-06, + "max_mse": 1.655095813488414e-13 + }, + "frontend_real_audio": { + "model_load_sec": 5.285994583999999, + "platform": "local Ubuntu WSL2", + "device": "cpu", + "dtype": "float32", + "audios": [ + { + "name": "real_short", + "duration_sec": 1.951, + "sha256": "cfc3105c2ac4db72dbd23ad052261ed812a8d1c51a6c98700d89f45835348cc0", + "prefixes": 3, + "valid": 2, + "updates": 2, + "statuses": [ + "no_usable_hypothesis", + "ok", + "ok" + ], + "end_to_end_compute_sec": 162.954407101, + "scorer_compute_sec": 0.01154370499997981 + }, + { + "name": "real_medium", + "duration_sec": 2.889, + "sha256": "165bcc252817fac922eecba9447293fa04d79bb215e05c3eb7934061ed501a58", + "prefixes": 5, + "valid": 3, + "updates": 2, + "statuses": [ + "no_usable_hypothesis", + "no_usable_hypothesis", + "ok", + "ok", + "ok" + ], + "end_to_end_compute_sec": 250.548563628, + "scorer_compute_sec": 0.007423772000038298 + }, + { + "name": "real_long", + "duration_sec": 4.387, + "sha256": "450eccef92e195845254f9915cb9b28ea6acffe0a2962526af435e29f330f397", + "prefixes": 7, + "valid": 4, + "updates": 2, + "statuses": [ + "no_usable_hypothesis", + "no_usable_hypothesis", + "ok", + "no_usable_hypothesis", + "ok", + "ok", + "ok" + ], + "end_to_end_compute_sec": 383.971490372, + "scorer_compute_sec": 0.008973775000185924 + } + ], + "status": "PASS", + "suffix_invariance": "PASS", + "reset": "PASS", + "empty_audio": "PASS", + "silence": "PASS", + "audio_source": "SpeechOcean762 CC BY 4.0 read speech; fixed availability/duration selection; interface tests only, no accuracy calculation" + }, + "cli": { + "status": "PASS", + "stage": "cli", + "prefixes": 3, + "exact_single_stream_match": true, + "device": "cpu", + "dtype": "float32" + }, + "offline": { + "status": "PASS", + "stage": "offline", + "prefixes": 3, + "exact_single_stream_match": true, + "device": "cpu", + "dtype": "float32" + }, + "valid_prefix_causal_test": { + "status": "PASS", + "implementation": "actual fine-tuned Whisper, Charsiu, PCN/prosody and scorer", + "boundary_samples": 23040, + "received_samples": 24000, + "lookahead_seconds": 0.16, + "prefix_outputs_exact": true, + "state_hash_exact": true, + "actual_frontend_samples": { + "whisper": 23040, + "charsiu": 23040, + "prosody": 23040, + "pcn": 23040 + }, + "prior_history_reused": "one actually executed identical prefix, including original state; no saved prediction substituted for current inference", + "no_gpu": true + }, + "failed_synthetic_test": { + "audio": "local SAPI Good morning", + "prefixes": 3, + "statuses": [ + "no_usable_hypothesis", + "no_usable_hypothesis", + "no_usable_hypothesis" + ], + "reason": "frozen Whisper repetition policy; no false zero score emitted" + }, + "untested": [ + "native Windows", + "CUDA", + "assessment accuracy on new recordings", + "concurrent sessions" + ], + "hub_verification": "Only a release tag created after fresh-download validation marks a verified release." +} diff --git a/whisper_best_model/added_tokens.json b/whisper/added_tokens.json similarity index 100% rename from whisper_best_model/added_tokens.json rename to whisper/added_tokens.json diff --git a/whisper_best_model/config.json b/whisper/config.json similarity index 94% rename from whisper_best_model/config.json rename to whisper/config.json index b9525def43814000133a63ed185c72c0b23e3aa2..e88c6ea67e43b64fd6599e4038ae500048f11275 100644 --- a/whisper_best_model/config.json +++ b/whisper/config.json @@ -1,5 +1,4 @@ { - "_name_or_path": "/DATA_2/guest/custom-gopt/server_assets/models/whisper-base", "activation_dropout": 0.0, "activation_function": "gelu", "apply_spec_augment": false, diff --git a/whisper_best_model/generation_config.json b/whisper/generation_config.json similarity index 100% rename from whisper_best_model/generation_config.json rename to whisper/generation_config.json diff --git a/whisper_best_model/merges.txt b/whisper/merges.txt similarity index 100% rename from whisper_best_model/merges.txt rename to whisper/merges.txt diff --git a/whisper_best_model/model.safetensors b/whisper/model.safetensors similarity index 100% rename from whisper_best_model/model.safetensors rename to whisper/model.safetensors diff --git a/whisper_best_model/normalizer.json b/whisper/normalizer.json similarity index 100% rename from whisper_best_model/normalizer.json rename to whisper/normalizer.json diff --git a/whisper_best_model/preprocessor_config.json b/whisper/preprocessor_config.json similarity index 100% rename from whisper_best_model/preprocessor_config.json rename to whisper/preprocessor_config.json diff --git a/whisper_best_model/special_tokens_map.json b/whisper/special_tokens_map.json similarity index 100% rename from whisper_best_model/special_tokens_map.json rename to whisper/special_tokens_map.json diff --git a/whisper_best_model/tokenizer_config.json b/whisper/tokenizer_config.json similarity index 100% rename from whisper_best_model/tokenizer_config.json rename to whisper/tokenizer_config.json diff --git a/whisper_best_model/vocab.json b/whisper/vocab.json similarity index 100% rename from whisper_best_model/vocab.json rename to whisper/vocab.json diff --git a/whisper_best_model/eval_preview.json b/whisper_best_model/eval_preview.json deleted file mode 100644 index 430814b55385fa7d24b33c3f87939053851561db..0000000000000000000000000000000000000000 --- a/whisper_best_model/eval_preview.json +++ /dev/null @@ -1,82 +0,0 @@ -[ - { - "reference": "mark is going to see elephant", - "prediction": "mark is going to see elephant" - }, - { - "reference": "kate loves china", - "prediction": "kate loves china" - }, - { - "reference": "two six four eight", - "prediction": " two six four eight" - }, - { - "reference": "seven three four two", - "prediction": " seven three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four two three four" - }, - { - "reference": "two eight nine one", - "prediction": " two eight nine one two three four five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five five" - }, - { - "reference": "one zero one zero", - "prediction": " one zero one zero" - }, - { - "reference": "two five nine nine", - "prediction": "two five nine nine two five nine nine two five nine nine two five nine nine two five nine nine two five nine nine two five nine nine two five nine nine two five nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine nine" - }, - { - "reference": "tomato spring photo", - "prediction": "to measure spring photo" - }, - { - "reference": "layla is good at swimming", - "prediction": "layla is good at swimming" - }, - { - "reference": "alice give up boxing", - "prediction": " Alice give a boxing." - }, - { - "reference": "layla wants have some salad", - "prediction": "lilla wants have some salad" - }, - { - "reference": "does he know the biscuit", - "prediction": "does he know the biscuit?" - }, - { - "reference": "here is time's cloth", - "prediction": "here is tim's clothes" - }, - { - "reference": "look at bob's t shirt", - "prediction": "look at buff's t shirt" - }, - { - "reference": "so billy went into the pet shop", - "prediction": "so a bee went into the pet shop and she was so happy to see her dog again she was so happy to see her dog again so happy to see her dog again so happy to see her dog again so happy to see her dog again so happy to see her dog again so happy to see her dog again so happy to see her dog again so happy to see her dog again so happy to see her dog again so happy to see her dog again so happy to see her dog" - }, - { - "reference": "so tina went into the washroom", - "prediction": "satina went into the washroom" - }, - { - "reference": "billy lived in new york", - "prediction": "billy lived in new york" - }, - { - "reference": "more than that", - "prediction": "more than that" - }, - { - "reference": "my map will show us", - "prediction": "my map will show us" - }, - { - "reference": "yummy", - "prediction": " let me know what you think of it in the comments below if you have any questions or questions please leave a comment below if you have any questions please leave a comment if you have any questions please leave a comment if you have any questions please leave a comment if you have any questions please leave a comment if you have any questions please leave a comment if you have any questions please leave a comment if you have any questions please leave a comment if you have any questions please leave a comment" - } -] \ No newline at end of file