feat(scoring): measure against فدوى too, and show every native baseline in the trace dashboard
Browse files- The native baseline now uses two TTS voices: ראאף (generated on demand) and فدوى (used when cached).
Each sound is still measured against the lowest score any voice got on it.
- References are read with wav_for_voice: wav() turned any voice outside playback into ראאף.
- Each Reference carries its voice name; the trace keeps every voice's score per sound
(baseline stage `refs`, references[].voice).
- Trace dashboard: a row per voice under each sound (the voice used in bold), a marker per
voice on the waterfall's baseline step, per-voice tooltip and table columns.
- The mock trace has two voices.
Bench on 2,828 lab recordings (all said right): false rejections 3.6% -> 2.9%
(ħ 6.0 -> 2.8%, h 9.7 -> 5.4%, ɣ 20.6 -> 12.5%, ʕ 12.5 -> 9.5%). Detection is not measured:
the lab has no recordings with a planted mistake yet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- README.md +1 -1
- app/main.py +7 -5
- app/reference.py +6 -2
- app/scorer.py +17 -4
- app/tts.py +14 -3
- docs/trace-schema.ts +5 -2
- scripts/bench.py +2 -2
- scripts/import_minerva.py +2 -2
- scripts/mock_trace.py +8 -5
- static/assets/trace-mock.json +217 -188
- static/index.html +1 -1
- static/trace.html +79 -8
- tests/test_scoring.py +23 -1
|
@@ -361,7 +361,7 @@ insert into storage.buckets (id, name) values ('lab', 'lab') on conflict (id) do
|
|
| 361 |
1. the frames around the sound: target, competitor and neighbour posteriors, frame energy, and the window it was read from (the end of the sound before to the start of the one after)
|
| 362 |
2. its score stage by stage: raw GOP → exemptions → cluster cap → native baseline → teacher floor → final
|
| 363 |
3. the readings the audio was aligned to, with the winning CTC path, and the edit-distance gauge for a different sentence
|
| 364 |
-
4. the sentence by word and sound, coloured by score, with how sounds add up to words and words to the sentence
|
| 365 |
|
| 366 |
The data's schema is [docs/trace-schema.ts](docs/trace-schema.ts). `python scripts/mock_trace.py` regenerates the example (`static/assets/trace-mock.json`, the "דוגמה" button) by running the real scorer on synthetic posteriors, with a substitution, a teacher floor, a native baseline and a noise spike beside a short vowel planted in it (the spike shows how a sound's window takes in its neighbours' blank frames). `?src=mock` opens the example, `?i=6` pins a sound.
|
| 367 |
|
|
|
|
| 361 |
1. the frames around the sound: target, competitor and neighbour posteriors, frame energy, and the window it was read from (the end of the sound before to the start of the one after)
|
| 362 |
2. its score stage by stage: raw GOP → exemptions → cluster cap → native baseline → teacher floor → final
|
| 363 |
3. the readings the audio was aligned to, with the winning CTC path, and the edit-distance gauge for a different sentence
|
| 364 |
+
4. the sentence by word and sound, coloured by score, with how sounds add up to words and words to the sentence. When the recording was scored against native baselines, each TTS voice gets a row of its own scores under the sounds; the voice a sound was measured against (the lowest) is in bold. The waterfall marks every voice on the baseline step, and the table has a column per voice
|
| 365 |
|
| 366 |
The data's schema is [docs/trace-schema.ts](docs/trace-schema.ts). `python scripts/mock_trace.py` regenerates the example (`static/assets/trace-mock.json`, the "דוגמה" button) by running the real scorer on synthetic posteriors, with a substitution, a teacher floor, a native baseline and a noise spike beside a short vowel planted in it (the spike shows how a sound's window takes in its neighbours' blank frames). `?src=mock` opens the example, `?i=6` pins a sound.
|
| 367 |
|
|
@@ -28,6 +28,7 @@ import urllib.parse
|
|
| 28 |
import uuid
|
| 29 |
import zipfile
|
| 30 |
from contextlib import asynccontextmanager
|
|
|
|
| 31 |
from datetime import date, datetime, timedelta, timezone
|
| 32 |
from pathlib import Path
|
| 33 |
from queue import Queue
|
|
@@ -54,7 +55,7 @@ from .rules import TOGGLES, check_detectable
|
|
| 54 |
from .scorer import SAMPLE_RATE, Scorer, decode_audio, decode_audio_with_timing, frame_energy, load_scorer
|
| 55 |
from .speech_evaluation import SpeechEvaluationService
|
| 56 |
from .texts import read_line, text_phrases
|
| 57 |
-
from .tts import LINE_VOICES, RAEF_VOICE_ID, VOICES, SawtakTTS, TTSUnavailable, load_tts
|
| 58 |
from .tutor import (BY_ID, DAILY_LIMIT, MAX_TEXT, MAX_TURNS, SCENARIOS, Tutor, TutorLimit,
|
| 59 |
DEFAULT_MODEL as DEFAULT_TUTOR_MODEL, TutorUnavailable, load_tutor, tutor_client)
|
| 60 |
from .verb_game import VerbExerciseGenerator
|
|
@@ -490,7 +491,7 @@ def create_app(scorer: Scorer | None = None, tts: SawtakTTS | None = None,
|
|
| 490 |
app.state.tts_warm_stop = threading.Event() # set by POST /api/tts-cache/warm/stop
|
| 491 |
app.state.tutor = tutor or load_tutor(app.state.keys.get("ANTHROPIC_API_KEY"), app.state.keys.get("TUTOR_MODEL"))
|
| 492 |
# the playback voices double as the native baseline of the scores (see reference.py)
|
| 493 |
-
app.state.refs = References(app.state.scorer, app.state.tts, list(
|
| 494 |
if app.state.auth and hasattr(app.state.auth, "calibrations"):
|
| 495 |
try:
|
| 496 |
rows = app.state.auth.calibrations("applied")
|
|
@@ -1572,7 +1573,7 @@ def create_app(scorer: Scorer | None = None, tts: SawtakTTS | None = None,
|
|
| 1572 |
try:
|
| 1573 |
if not refs.tts.cached(text, voice):
|
| 1574 |
continue
|
| 1575 |
-
data, _ = refs.tts.
|
| 1576 |
except Exception as e: # provider down: score without this voice, as References does
|
| 1577 |
log.warning("sweep: no %s voice for %r: %s", voice, text, e)
|
| 1578 |
continue
|
|
@@ -1586,7 +1587,8 @@ def create_app(scorer: Scorer | None = None, tts: SawtakTTS | None = None,
|
|
| 1586 |
key = (*emitted, phrase["key"], setting, scorer.disabled)
|
| 1587 |
if key not in sweep_refs:
|
| 1588 |
logp, energy = sweep_emits[emitted]
|
| 1589 |
-
|
|
|
|
| 1590 |
if sweep_refs[key] is not None:
|
| 1591 |
out.append(sweep_refs[key])
|
| 1592 |
return out
|
|
@@ -2869,7 +2871,7 @@ def create_app(scorer: Scorer | None = None, tts: SawtakTTS | None = None,
|
|
| 2869 |
app.state.tts.api_key = value
|
| 2870 |
else:
|
| 2871 |
app.state.tts = load_tts(value)
|
| 2872 |
-
app.state.refs = References(app.state.scorer, app.state.tts, list(
|
| 2873 |
elif app.state.tutor is not None and value:
|
| 2874 |
app.state.tutor.client = tutor_client(value)
|
| 2875 |
else:
|
|
|
|
| 28 |
import uuid
|
| 29 |
import zipfile
|
| 30 |
from contextlib import asynccontextmanager
|
| 31 |
+
from dataclasses import replace as dc_replace
|
| 32 |
from datetime import date, datetime, timedelta, timezone
|
| 33 |
from pathlib import Path
|
| 34 |
from queue import Queue
|
|
|
|
| 55 |
from .scorer import SAMPLE_RATE, Scorer, decode_audio, decode_audio_with_timing, frame_energy, load_scorer
|
| 56 |
from .speech_evaluation import SpeechEvaluationService
|
| 57 |
from .texts import read_line, text_phrases
|
| 58 |
+
from .tts import BASELINE_VOICES, LINE_VOICES, RAEF_VOICE_ID, VOICES, SawtakTTS, TTSUnavailable, load_tts, voice_name
|
| 59 |
from .tutor import (BY_ID, DAILY_LIMIT, MAX_TEXT, MAX_TURNS, SCENARIOS, Tutor, TutorLimit,
|
| 60 |
DEFAULT_MODEL as DEFAULT_TUTOR_MODEL, TutorUnavailable, load_tutor, tutor_client)
|
| 61 |
from .verb_game import VerbExerciseGenerator
|
|
|
|
| 491 |
app.state.tts_warm_stop = threading.Event() # set by POST /api/tts-cache/warm/stop
|
| 492 |
app.state.tutor = tutor or load_tutor(app.state.keys.get("ANTHROPIC_API_KEY"), app.state.keys.get("TUTOR_MODEL"))
|
| 493 |
# the playback voices double as the native baseline of the scores (see reference.py)
|
| 494 |
+
app.state.refs = References(app.state.scorer, app.state.tts, list(BASELINE_VOICES.values())) if app.state.tts else None
|
| 495 |
if app.state.auth and hasattr(app.state.auth, "calibrations"):
|
| 496 |
try:
|
| 497 |
rows = app.state.auth.calibrations("applied")
|
|
|
|
| 1573 |
try:
|
| 1574 |
if not refs.tts.cached(text, voice):
|
| 1575 |
continue
|
| 1576 |
+
data, _ = refs.tts.wav_for_voice(text, voice, source="baseline")
|
| 1577 |
except Exception as e: # provider down: score without this voice, as References does
|
| 1578 |
log.warning("sweep: no %s voice for %r: %s", voice, text, e)
|
| 1579 |
continue
|
|
|
|
| 1587 |
key = (*emitted, phrase["key"], setting, scorer.disabled)
|
| 1588 |
if key not in sweep_refs:
|
| 1589 |
logp, energy = sweep_emits[emitted]
|
| 1590 |
+
ref = scorer.reference_logp(logp, phrase, energy)
|
| 1591 |
+
sweep_refs[key] = dc_replace(ref, voice=voice_name(voice)) if ref is not None else None
|
| 1592 |
if sweep_refs[key] is not None:
|
| 1593 |
out.append(sweep_refs[key])
|
| 1594 |
return out
|
|
|
|
| 2871 |
app.state.tts.api_key = value
|
| 2872 |
else:
|
| 2873 |
app.state.tts = load_tts(value)
|
| 2874 |
+
app.state.refs = References(app.state.scorer, app.state.tts, list(BASELINE_VOICES.values())) if app.state.tts else None
|
| 2875 |
elif app.state.tutor is not None and value:
|
| 2876 |
app.state.tutor.client = tutor_client(value)
|
| 2877 |
else:
|
|
@@ -14,10 +14,12 @@ from __future__ import annotations
|
|
| 14 |
import logging
|
| 15 |
import threading
|
| 16 |
import time
|
|
|
|
| 17 |
from concurrent.futures import Future, ThreadPoolExecutor, wait
|
| 18 |
|
| 19 |
from .arabic_diacritics import point_arabic
|
| 20 |
from .scorer import Reference, Scorer, decode_audio
|
|
|
|
| 21 |
|
| 22 |
log = logging.getLogger("ihki.reference")
|
| 23 |
|
|
@@ -32,11 +34,13 @@ class References:
|
|
| 32 |
self._lock = threading.Lock()
|
| 33 |
|
| 34 |
def _build(self, phrase: dict, text: str, voice: str) -> Reference | None:
|
| 35 |
-
|
|
|
|
| 36 |
ref = self.scorer.reference(decode_audio(data), phrase)
|
| 37 |
if ref is None:
|
| 38 |
log.info("reference not usable: %r by voice %s", text, voice)
|
| 39 |
-
|
|
|
|
| 40 |
|
| 41 |
def get(self, phrase_id: int, phrase: dict) -> list[Reference]:
|
| 42 |
"""The references of a phrase that are ready within the wait."""
|
|
|
|
| 14 |
import logging
|
| 15 |
import threading
|
| 16 |
import time
|
| 17 |
+
from dataclasses import replace
|
| 18 |
from concurrent.futures import Future, ThreadPoolExecutor, wait
|
| 19 |
|
| 20 |
from .arabic_diacritics import point_arabic
|
| 21 |
from .scorer import Reference, Scorer, decode_audio
|
| 22 |
+
from .tts import voice_name
|
| 23 |
|
| 24 |
log = logging.getLogger("ihki.reference")
|
| 25 |
|
|
|
|
| 34 |
self._lock = threading.Lock()
|
| 35 |
|
| 36 |
def _build(self, phrase: dict, text: str, voice: str) -> Reference | None:
|
| 37 |
+
# wav() would turn a voice it does not offer for playback (فدوى) into Raef's
|
| 38 |
+
data, _ = self.tts.wav_for_voice(text, voice, source="baseline", upload=True)
|
| 39 |
ref = self.scorer.reference(decode_audio(data), phrase)
|
| 40 |
if ref is None:
|
| 41 |
log.info("reference not usable: %r by voice %s", text, voice)
|
| 42 |
+
return None
|
| 43 |
+
return replace(ref, voice=voice_name(voice))
|
| 44 |
|
| 45 |
def get(self, phrase_id: int, phrase: dict) -> list[Reference]:
|
| 46 |
"""The references of a phrase that are ready within the wait."""
|
|
@@ -192,6 +192,7 @@ class Reference:
|
|
| 192 |
"""How the model scored a native voice saying a phrase: the baseline a learner is measured against."""
|
| 193 |
sounds: list[tuple[int, str]] # (word, sound) of each sound of the variant the voice said (Q, not ʔ / k)
|
| 194 |
scores: list[float] # their scores, same order
|
|
|
|
| 195 |
|
| 196 |
|
| 197 |
@dataclass
|
|
@@ -361,12 +362,22 @@ class Scorer:
|
|
| 361 |
References may have said another accepted variant: only the sounds the two variants share are matched.
|
| 362 |
Sounds are compared by symbol, so a voice that said ق as q is a baseline for a learner who says ʔ.
|
| 363 |
"""
|
| 364 |
-
sounds = [(t.word, t.sound) for t in toks]
|
| 365 |
out: list[float | None] = [None] * len(toks)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 366 |
for ref in refs:
|
|
|
|
| 367 |
for a, b, n in SequenceMatcher(None, ref.sounds, sounds, autojunk=False).get_matching_blocks():
|
| 368 |
for k in range(n):
|
| 369 |
-
|
|
|
|
| 370 |
return out
|
| 371 |
|
| 372 |
def _carriers(self, ipa: str) -> list[list[list[int]]]:
|
|
@@ -736,6 +747,7 @@ class Scorer:
|
|
| 736 |
"""Every stage of the classification with its numbers, weights and thresholds, for the teacher's view
|
| 737 |
(the 'stages' part of the phoneme analysis). Nothing here changes the result."""
|
| 738 |
cfg, g, i2t = self.cfg, self.cfg.gop, self.vocab.i2t
|
|
|
|
| 739 |
p = lambda lp: round(float(np.exp(lp)), 4) if lp > -1e20 else 0.0
|
| 740 |
max_tips = self._max_tips()
|
| 741 |
n, T = len(fit.toks), len(fit.logp)
|
|
@@ -759,7 +771,7 @@ class Scorer:
|
|
| 759 |
{"stage": "exemption", "score": fit.exempt_scores[i].score, "applied": fit.exempted[i]},
|
| 760 |
{"stage": "insertion", "score": fit.scores[i].score, "applied": fit.inserted.get(i)},
|
| 761 |
{"stage": "baseline", "score": after_baseline[i].score, "ref": b,
|
| 762 |
-
"applied": b is not None and b < 100},
|
| 763 |
{"stage": "calibration", "score": sc.score, "floor": floors[i],
|
| 764 |
"applied": floors[i] is not None and after_baseline[i].score < floors[i]},
|
| 765 |
]
|
|
@@ -812,7 +824,8 @@ class Scorer:
|
|
| 812 |
"unrelated": {"heard": heard, "distance": fit.distance, "tokens": n,
|
| 813 |
"ratio": round(fit.distance / max(1, n), 3), "threshold": cfg.unrelated_ratio,
|
| 814 |
"unrelated": fit.unrelated},
|
| 815 |
-
"references": [{"mean": round(float(np.mean(r.scores)), 1),
|
|
|
|
| 816 |
"tokens": tokens,
|
| 817 |
"words": [{"tr": w["tr"], "scores": [ph["score"] for ph in w["phonemes"]],
|
| 818 |
"min": min((ph["score"] for ph in w["phonemes"]), default=0.0),
|
|
|
|
| 192 |
"""How the model scored a native voice saying a phrase: the baseline a learner is measured against."""
|
| 193 |
sounds: list[tuple[int, str]] # (word, sound) of each sound of the variant the voice said (Q, not ʔ / k)
|
| 194 |
scores: list[float] # their scores, same order
|
| 195 |
+
voice: str = "" # who said it (the TTS voice's name), for the trace dashboard
|
| 196 |
|
| 197 |
|
| 198 |
@dataclass
|
|
|
|
| 362 |
References may have said another accepted variant: only the sounds the two variants share are matched.
|
| 363 |
Sounds are compared by symbol, so a voice that said ق as q is a baseline for a learner who says ʔ.
|
| 364 |
"""
|
|
|
|
| 365 |
out: list[float | None] = [None] * len(toks)
|
| 366 |
+
for per_ref in Scorer._ref_scores(toks, refs):
|
| 367 |
+
out = [x if y is None else y if x is None else min(x, y) for x, y in zip(out, per_ref)]
|
| 368 |
+
return out
|
| 369 |
+
|
| 370 |
+
@staticmethod
|
| 371 |
+
def _ref_scores(toks: list[TargetToken], refs: list[Reference]) -> list[list[float | None]]:
|
| 372 |
+
"""Per reference, per target token, the score that reference got on the same sound (None: it does not have it)."""
|
| 373 |
+
sounds = [(t.word, t.sound) for t in toks]
|
| 374 |
+
out = []
|
| 375 |
for ref in refs:
|
| 376 |
+
row: list[float | None] = [None] * len(toks)
|
| 377 |
for a, b, n in SequenceMatcher(None, ref.sounds, sounds, autojunk=False).get_matching_blocks():
|
| 378 |
for k in range(n):
|
| 379 |
+
row[b + k] = ref.scores[a + k]
|
| 380 |
+
out.append(row)
|
| 381 |
return out
|
| 382 |
|
| 383 |
def _carriers(self, ipa: str) -> list[list[list[int]]]:
|
|
|
|
| 747 |
"""Every stage of the classification with its numbers, weights and thresholds, for the teacher's view
|
| 748 |
(the 'stages' part of the phoneme analysis). Nothing here changes the result."""
|
| 749 |
cfg, g, i2t = self.cfg, self.cfg.gop, self.vocab.i2t
|
| 750 |
+
per_ref = self._ref_scores(fit.toks, refs)
|
| 751 |
p = lambda lp: round(float(np.exp(lp)), 4) if lp > -1e20 else 0.0
|
| 752 |
max_tips = self._max_tips()
|
| 753 |
n, T = len(fit.toks), len(fit.logp)
|
|
|
|
| 771 |
{"stage": "exemption", "score": fit.exempt_scores[i].score, "applied": fit.exempted[i]},
|
| 772 |
{"stage": "insertion", "score": fit.scores[i].score, "applied": fit.inserted.get(i)},
|
| 773 |
{"stage": "baseline", "score": after_baseline[i].score, "ref": b,
|
| 774 |
+
"refs": [row[i] for row in per_ref], "applied": b is not None and b < 100},
|
| 775 |
{"stage": "calibration", "score": sc.score, "floor": floors[i],
|
| 776 |
"applied": floors[i] is not None and after_baseline[i].score < floors[i]},
|
| 777 |
]
|
|
|
|
| 824 |
"unrelated": {"heard": heard, "distance": fit.distance, "tokens": n,
|
| 825 |
"ratio": round(fit.distance / max(1, n), 3), "threshold": cfg.unrelated_ratio,
|
| 826 |
"unrelated": fit.unrelated},
|
| 827 |
+
"references": [{"voice": r.voice or f"קול {k + 1}", "mean": round(float(np.mean(r.scores)), 1),
|
| 828 |
+
"sounds": len(r.sounds)} for k, r in enumerate(refs)],
|
| 829 |
"tokens": tokens,
|
| 830 |
"words": [{"tr": w["tr"], "scores": [ph["score"] for ph in w["phonemes"]],
|
| 831 |
"min": min((ph["score"] for ph in w["phonemes"]), default=0.0),
|
|
@@ -45,6 +45,16 @@ RAEF_VOICE_ID = "273d81b2-991b-5b76-8525-eeacc6a3d759"
|
|
| 45 |
VOICES = {"רַאאִף": RAEF_VOICE_ID}
|
| 46 |
# A female voice, only for the lines a dialogue gives her (workbook.LINE_VOICES); never offered on the page.
|
| 47 |
LINE_VOICES = {"חנאן": "e41781f5-127c-5eb0-b83c-50bf52a64caf"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
class TTSUnavailable(Exception):
|
| 50 |
"""No key configured, or the provider refused / failed. The message is safe to show."""
|
|
@@ -424,9 +434,10 @@ class SawtakTTS:
|
|
| 424 |
voice = voice if voice in LINE_VOICES.values() else RAEF_VOICE_ID
|
| 425 |
return self._wav(text, voice, upload=True, source="playback")
|
| 426 |
|
| 427 |
-
def wav_for_voice(self, text: str, voice: str, source: str = "sweep") -> tuple[bytes, str]:
|
| 428 |
-
"""(WAV, voice id) for a teacher-selected, validated Sawtak voice.
|
| 429 |
-
|
|
|
|
| 430 |
|
| 431 |
|
| 432 |
def load_tts(key: str | None = None) -> SawtakTTS | None:
|
|
|
|
| 45 |
VOICES = {"רַאאִף": RAEF_VOICE_ID}
|
| 46 |
# A female voice, only for the lines a dialogue gives her (workbook.LINE_VOICES); never offered on the page.
|
| 47 |
LINE_VOICES = {"חנאן": "e41781f5-127c-5eb0-b83c-50bf52a64caf"}
|
| 48 |
+
FADWA_VOICE_ID = "39a7e0e0-087e-52b3-afff-5203e430fc39" # فدوى: Palestinian, female, conversational
|
| 49 |
+
# The native voices the scores are measured against (reference.py), first one first: only it is generated for
|
| 50 |
+
# the baseline; the others count when their recording is already cached (the cache-warm sweep made them).
|
| 51 |
+
BASELINE_VOICES = {"ראאף": RAEF_VOICE_ID, "פדוא": FADWA_VOICE_ID}
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def voice_name(voice_id: str) -> str:
|
| 55 |
+
"""A voice id's display name, without vowel points (ראאף, חנאן); the id itself when it is not one of ours."""
|
| 56 |
+
names = {v: k for k, v in {**VOICES, **LINE_VOICES, **BASELINE_VOICES}.items()}
|
| 57 |
+
return names.get(voice_id, voice_id).translate({c: None for c in range(0x591, 0x5c8)})
|
| 58 |
|
| 59 |
class TTSUnavailable(Exception):
|
| 60 |
"""No key configured, or the provider refused / failed. The message is safe to show."""
|
|
|
|
| 434 |
voice = voice if voice in LINE_VOICES.values() else RAEF_VOICE_ID
|
| 435 |
return self._wav(text, voice, upload=True, source="playback")
|
| 436 |
|
| 437 |
+
def wav_for_voice(self, text: str, voice: str, source: str = "sweep", upload: bool = False) -> tuple[bytes, str]:
|
| 438 |
+
"""(WAV, voice id) for a teacher-selected, validated Sawtak voice. Unlike wav(), any voice id is kept.
|
| 439 |
+
`upload`: a new recording also goes to the bucket in the background."""
|
| 440 |
+
return self._wav(text, voice, upload=upload, source=source)
|
| 441 |
|
| 442 |
|
| 443 |
def load_tts(key: str | None = None) -> SawtakTTS | None:
|
|
@@ -75,7 +75,8 @@ export interface Trace {
|
|
| 75 |
frames: TraceFrames;
|
| 76 |
aipa: string; // the chosen reading with archi symbols
|
| 77 |
unrelated: TraceUnrelated;
|
| 78 |
-
|
|
|
|
| 79 |
/** Stages 1–5 per sound, in order: gop → exemption → insertion → baseline → calibration → final. */
|
| 80 |
tokens: TraceToken[];
|
| 81 |
words: TraceWord[];
|
|
@@ -137,7 +138,9 @@ export type Stage =
|
|
| 137 |
| { stage: "gop"; score: number }
|
| 138 |
| { stage: "exemption"; score: number; applied: TraceConfig["exemptions"][number] | null }
|
| 139 |
| { stage: "insertion"; score: number; applied: Ipa | null } // the vowel heard inside the cluster
|
| 140 |
-
| { stage: "baseline"; score: number; ref: number | null;
|
|
|
|
|
|
|
| 141 |
| { stage: "calibration"; score: number; floor: number | null; applied: boolean };
|
| 142 |
|
| 143 |
export interface TraceToken {
|
|
|
|
| 75 |
frames: TraceFrames;
|
| 76 |
aipa: string; // the chosen reading with archi symbols
|
| 77 |
unrelated: TraceUnrelated;
|
| 78 |
+
/** The native baselines, one per TTS voice; each sound is measured against the lowest of them (Stage "baseline"). */
|
| 79 |
+
references: { voice: string; mean: number; sounds: number }[];
|
| 80 |
/** Stages 1–5 per sound, in order: gop → exemption → insertion → baseline → calibration → final. */
|
| 81 |
tokens: TraceToken[];
|
| 82 |
words: TraceWord[];
|
|
|
|
| 138 |
| { stage: "gop"; score: number }
|
| 139 |
| { stage: "exemption"; score: number; applied: TraceConfig["exemptions"][number] | null }
|
| 140 |
| { stage: "insertion"; score: number; applied: Ipa | null } // the vowel heard inside the cluster
|
| 141 |
+
| { stage: "baseline"; score: number; ref: number | null; refs: (number | null)[]; applied: boolean }
|
| 142 |
+
// ref: the lowest native score on this sound (what it is measured against); refs: each voice's, in
|
| 143 |
+
// Trace.references order (null: that voice's reading has no such sound)
|
| 144 |
| { stage: "calibration"; score: number; floor: number | null; applied: boolean };
|
| 145 |
|
| 146 |
export interface TraceToken {
|
|
@@ -30,7 +30,7 @@ from app import lab # noqa: E402
|
|
| 30 |
from app.auth import AuthUnavailable, load_auth # noqa: E402
|
| 31 |
from app.reference import References # noqa: E402
|
| 32 |
from app.scorer import decode_audio, load_scorer # noqa: E402
|
| 33 |
-
from app.tts import
|
| 34 |
|
| 35 |
|
| 36 |
def pct(x: float | None) -> str:
|
|
@@ -68,7 +68,7 @@ def main() -> int:
|
|
| 68 |
model = os.environ.get("MODEL_ID", "facebook/wav2vec2-xlsr-53-espeak-cv-ft")
|
| 69 |
scorer = load_scorer(model)
|
| 70 |
tts = None if args.no_baseline else load_tts()
|
| 71 |
-
refs = References(scorer, tts, list(
|
| 72 |
|
| 73 |
def score(audio: bytes, phrase: dict, key) -> dict:
|
| 74 |
return scorer.score(decode_audio(audio), phrase, refs.get(key, phrase) if refs else [])
|
|
|
|
| 30 |
from app.auth import AuthUnavailable, load_auth # noqa: E402
|
| 31 |
from app.reference import References # noqa: E402
|
| 32 |
from app.scorer import decode_audio, load_scorer # noqa: E402
|
| 33 |
+
from app.tts import BASELINE_VOICES, load_tts # noqa: E402
|
| 34 |
|
| 35 |
|
| 36 |
def pct(x: float | None) -> str:
|
|
|
|
| 68 |
model = os.environ.get("MODEL_ID", "facebook/wav2vec2-xlsr-53-espeak-cv-ft")
|
| 69 |
scorer = load_scorer(model)
|
| 70 |
tts = None if args.no_baseline else load_tts()
|
| 71 |
+
refs = References(scorer, tts, list(BASELINE_VOICES.values())) if tts else None
|
| 72 |
|
| 73 |
def score(audio: bytes, phrase: dict, key) -> dict:
|
| 74 |
return scorer.score(decode_audio(audio), phrase, refs.get(key, phrase) if refs else [])
|
|
@@ -29,7 +29,7 @@ from app.auth import AuthUnavailable, load_auth # noqa: E402
|
|
| 29 |
from app.main import MODEL_ID, build_version # noqa: E402
|
| 30 |
from app.reference import References # noqa: E402
|
| 31 |
from app.scorer import decode_audio, load_scorer # noqa: E402
|
| 32 |
-
from app.tts import
|
| 33 |
|
| 34 |
SPEAKER = "מינרווה"
|
| 35 |
|
|
@@ -117,7 +117,7 @@ def main() -> int:
|
|
| 117 |
model = os.environ.get("MODEL_ID", MODEL_ID)
|
| 118 |
scorer = load_scorer(model)
|
| 119 |
tts = None if args.no_baseline else load_tts()
|
| 120 |
-
refs = References(scorer, tts, list(
|
| 121 |
saved = skipped = 0
|
| 122 |
for n, (video, segment, phrase) in enumerate(entries, 1):
|
| 123 |
item, start, end = phrase["key"], segment["start"], segment["end"]
|
|
|
|
| 29 |
from app.main import MODEL_ID, build_version # noqa: E402
|
| 30 |
from app.reference import References # noqa: E402
|
| 31 |
from app.scorer import decode_audio, load_scorer # noqa: E402
|
| 32 |
+
from app.tts import BASELINE_VOICES, load_tts # noqa: E402
|
| 33 |
|
| 34 |
SPEAKER = "מינרווה"
|
| 35 |
|
|
|
|
| 117 |
model = os.environ.get("MODEL_ID", MODEL_ID)
|
| 118 |
scorer = load_scorer(model)
|
| 119 |
tts = None if args.no_baseline else load_tts()
|
| 120 |
+
refs = References(scorer, tts, list(BASELINE_VOICES.values())) if tts else None
|
| 121 |
saved = skipped = 0
|
| 122 |
for n, (video, segment, phrase) in enumerate(entries, 1):
|
| 123 |
item, start, end = phrase["key"], segment["start"], segment["end"]
|
|
@@ -10,7 +10,9 @@ readings: سيدي / جدّي, بيت / بيت with the diphthong), with what th
|
|
| 10 |
- ع of قعد said as a glottal stop (ء): flagged, with a severity-3 tip, and raised by a teacher's calibration floor
|
| 11 |
- a spike of h in a near-silent frame two frames after the short a of سيدك, inside the a's window and the k's
|
| 12 |
(the window runs from the end of the sound before to the start of the one after)
|
| 13 |
-
- k at the end of سيدك weak, as the native TTS
|
|
|
|
|
|
|
| 14 |
"""
|
| 15 |
from __future__ import annotations
|
| 16 |
|
|
@@ -67,11 +69,12 @@ def main() -> int:
|
|
| 67 |
logp, energy = emissions()
|
| 68 |
scorer = Scorer(lambda wav: logp, Vocab(VOCAB))
|
| 69 |
scorer.set_calibrations([{"expected": "ʕ", "heard": "ʔ", "floor": 45, "scope": "global"}])
|
| 70 |
-
# the native
|
| 71 |
toks = scorer._variants(PHRASE)[0][3]
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
|
|
|
| 75 |
result["phrase"] = {"he": PHRASE["he"], "ar": PHRASE["variants"][0][0]}
|
| 76 |
args.out.write_text(json.dumps(result, ensure_ascii=False, indent=1), encoding="utf-8")
|
| 77 |
print(f"{args.out}: score {result['score']}, {len(result['trace']['tokens'])} sounds, "
|
|
|
|
| 10 |
- ع of قعد said as a glottal stop (ء): flagged, with a severity-3 tip, and raised by a teacher's calibration floor
|
| 11 |
- a spike of h in a near-silent frame two frames after the short a of سيدك, inside the a's window and the k's
|
| 12 |
(the window runs from the end of the sound before to the start of the one after)
|
| 13 |
+
- k at the end of سيدك weak, as the native TTS voices' is too: the native baseline raises it. Two voices: the
|
| 14 |
+
male one (ראאף) weaker on that k (55) than the female one (פדוא, 70), so the score is measured against the lower; the female
|
| 15 |
+
voice also has a weak ع (80), which the calibration floor then still decides
|
| 16 |
"""
|
| 17 |
from __future__ import annotations
|
| 18 |
|
|
|
|
| 69 |
logp, energy = emissions()
|
| 70 |
scorer = Scorer(lambda wav: logp, Vocab(VOCAB))
|
| 71 |
scorer.set_calibrations([{"expected": "ʕ", "heard": "ʔ", "floor": 45, "scope": "global"}])
|
| 72 |
+
# the native voices: everything right but their own weak k at the end of سيدك (and the female voice's ع)
|
| 73 |
toks = scorer._variants(PHRASE)[0][3]
|
| 74 |
+
weak = {"ראאף": {(1, "K"): 55.0}, "פדוא": {(1, "K"): 70.0, (3, "ʕ"): 80.0}}
|
| 75 |
+
refs = [Reference([(t.word, t.sound) for t in toks], [w.get((t.word, t.sound), 100.0) for t in toks], voice)
|
| 76 |
+
for voice, w in weak.items()]
|
| 77 |
+
result = scorer.score_logp(logp, PHRASE, refs, diagnostics=True, duration_s=len(logp) * 0.02, energy=energy)
|
| 78 |
result["phrase"] = {"he": PHRASE["he"], "ar": PHRASE["variants"][0][0]}
|
| 79 |
args.out.write_text(json.dumps(result, ensure_ascii=False, indent=1), encoding="utf-8")
|
| 80 |
print(f"{args.out}: score {result['score']}, {len(result['trace']['tokens'])} sounds, "
|
|
@@ -1,12 +1,12 @@
|
|
| 1 |
{
|
| 2 |
-
"score":
|
| 3 |
"variant": {
|
| 4 |
"ar": "وين سيدك؟ سيدي قعد في بيته.",
|
| 5 |
"tr": "וֵין סִידַכּ סִידִי קַעַד פִי בֵּיתוֹ",
|
| 6 |
"ipa": "w eː n | s iː d a k | s iː d i | ʔ a ʕ a d | f i | b eː t o"
|
| 7 |
},
|
| 8 |
"heard_ipa": "w e n s i d a h k s i d i ʔ a ʔ a d f i b e t o",
|
| 9 |
-
"heard_tr": "וֵין סִידַ
|
| 10 |
"unrelated": false,
|
| 11 |
"words": [
|
| 12 |
{
|
|
@@ -51,8 +51,8 @@
|
|
| 51 |
{
|
| 52 |
"ar": "سيدك؟",
|
| 53 |
"tr": "סִידַכּ",
|
| 54 |
-
"heard_tr": "סִידַ
|
| 55 |
-
"score":
|
| 56 |
"letters": [
|
| 57 |
{
|
| 58 |
"t": "סִי",
|
|
@@ -60,8 +60,7 @@
|
|
| 60 |
},
|
| 61 |
{
|
| 62 |
"t": "דַ",
|
| 63 |
-
"score":
|
| 64 |
-
"why": "תנועת אַ נשמעה כמו ה (ه)"
|
| 65 |
},
|
| 66 |
{
|
| 67 |
"t": "כּ",
|
|
@@ -93,7 +92,7 @@
|
|
| 93 |
{
|
| 94 |
"ipa": "a",
|
| 95 |
"word": 1,
|
| 96 |
-
"score":
|
| 97 |
"flagged": false,
|
| 98 |
"heard": null
|
| 99 |
},
|
|
@@ -158,7 +157,7 @@
|
|
| 158 |
"ar": "قعد",
|
| 159 |
"tr": "קַעַד",
|
| 160 |
"heard_tr": "קַקַד",
|
| 161 |
-
"score":
|
| 162 |
"letters": [
|
| 163 |
{
|
| 164 |
"t": "קַ",
|
|
@@ -301,22 +300,14 @@
|
|
| 301 |
"score": 45
|
| 302 |
}
|
| 303 |
],
|
| 304 |
-
"issues": [
|
| 305 |
-
|
| 306 |
-
"sound": "תנועת אַ",
|
| 307 |
-
"word_tr": "סִידַכּ",
|
| 308 |
-
"score": 68,
|
| 309 |
-
"missing": false,
|
| 310 |
-
"heard": "ה (ه)"
|
| 311 |
-
}
|
| 312 |
-
],
|
| 313 |
-
"references": 1,
|
| 314 |
"dialect": "urban",
|
| 315 |
"calibrated": [
|
| 316 |
{
|
| 317 |
"expected": "ʕ",
|
| 318 |
"heard": "ʔ",
|
| 319 |
-
"from":
|
| 320 |
"to": 45
|
| 321 |
}
|
| 322 |
],
|
|
@@ -2899,14 +2890,16 @@
|
|
| 2899 |
},
|
| 2900 |
"trace": {
|
| 2901 |
"config": {
|
| 2902 |
-
"leniency": 0.
|
| 2903 |
"confident_peak": 0.3,
|
|
|
|
| 2904 |
"deleted_peak": 0.05,
|
| 2905 |
"deleted_comp": 0.2,
|
| 2906 |
"flag_below": 50.0,
|
|
|
|
| 2907 |
"issue_below": 90.0,
|
| 2908 |
"near_vowel_floor": 90.0,
|
| 2909 |
-
"word_min_weight": 0.
|
| 2910 |
"vowel_weight": 0.5,
|
| 2911 |
"unrelated_ratio": 0.65,
|
| 2912 |
"unrelated_cap": 30.0,
|
|
@@ -2916,6 +2909,7 @@
|
|
| 2916 |
"ref_min_mean": 60.0,
|
| 2917 |
"margin_default": 0.0,
|
| 2918 |
"ayin_deleted_floor": 60.0,
|
|
|
|
| 2919 |
"margins": [
|
| 2920 |
{
|
| 2921 |
"target": "dˤ",
|
|
@@ -3055,8 +3049,12 @@
|
|
| 3055 |
],
|
| 3056 |
"exemptions": [
|
| 3057 |
"glottal_dropped",
|
|
|
|
| 3058 |
"article_vowel_elided",
|
| 3059 |
-
"near_vowel"
|
|
|
|
|
|
|
|
|
|
| 3060 |
],
|
| 3061 |
"insertion": {
|
| 3062 |
"score_cap": 60,
|
|
@@ -3727,8 +3725,14 @@
|
|
| 3727 |
},
|
| 3728 |
"references": [
|
| 3729 |
{
|
|
|
|
| 3730 |
"mean": 98.0,
|
| 3731 |
"sounds": 23
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3732 |
}
|
| 3733 |
],
|
| 3734 |
"tokens": [
|
|
@@ -3811,6 +3815,7 @@
|
|
| 3811 |
"competitor": "i",
|
| 3812 |
"competitor_other": false,
|
| 3813 |
"p_competitor": 0.0107,
|
|
|
|
| 3814 |
"gop": 0.0,
|
| 3815 |
"confidence": 1.0,
|
| 3816 |
"gop_factor": 1.0,
|
|
@@ -3835,6 +3840,10 @@
|
|
| 3835 |
"stage": "baseline",
|
| 3836 |
"score": 100.0,
|
| 3837 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3838 |
"applied": false
|
| 3839 |
},
|
| 3840 |
{
|
|
@@ -3969,6 +3978,7 @@
|
|
| 3969 |
"competitor": "i",
|
| 3970 |
"competitor_other": false,
|
| 3971 |
"p_competitor": 0.0071,
|
|
|
|
| 3972 |
"gop": 0.0,
|
| 3973 |
"confidence": 1.0,
|
| 3974 |
"gop_factor": 1.0,
|
|
@@ -3993,6 +4003,10 @@
|
|
| 3993 |
"stage": "baseline",
|
| 3994 |
"score": 100.0,
|
| 3995 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3996 |
"applied": false
|
| 3997 |
},
|
| 3998 |
{
|
|
@@ -4032,7 +4046,7 @@
|
|
| 4032 |
],
|
| 4033 |
"window": [
|
| 4034 |
12,
|
| 4035 |
-
|
| 4036 |
],
|
| 4037 |
"curves": {
|
| 4038 |
"start": 8,
|
|
@@ -4052,9 +4066,7 @@
|
|
| 4052 |
0.001,
|
| 4053 |
0.001,
|
| 4054 |
0.004,
|
| 4055 |
-
0.004
|
| 4056 |
-
0.004,
|
| 4057 |
-
0.002
|
| 4058 |
],
|
| 4059 |
"competitor": [
|
| 4060 |
0.007,
|
|
@@ -4072,9 +4084,7 @@
|
|
| 4072 |
0.002,
|
| 4073 |
0.002,
|
| 4074 |
0.007,
|
| 4075 |
-
0.007
|
| 4076 |
-
0.007,
|
| 4077 |
-
0.004
|
| 4078 |
],
|
| 4079 |
"prev": [
|
| 4080 |
0.904,
|
|
@@ -4092,9 +4102,7 @@
|
|
| 4092 |
0.002,
|
| 4093 |
0.002,
|
| 4094 |
0.007,
|
| 4095 |
-
0.007
|
| 4096 |
-
0.007,
|
| 4097 |
-
0.004
|
| 4098 |
],
|
| 4099 |
"next": [
|
| 4100 |
0.004,
|
|
@@ -4112,9 +4120,7 @@
|
|
| 4112 |
0.001,
|
| 4113 |
0.001,
|
| 4114 |
0.9,
|
| 4115 |
-
0.9
|
| 4116 |
-
0.9,
|
| 4117 |
-
0.002
|
| 4118 |
],
|
| 4119 |
"blank": [
|
| 4120 |
0.004,
|
|
@@ -4132,15 +4138,14 @@
|
|
| 4132 |
0.97,
|
| 4133 |
0.97,
|
| 4134 |
0.004,
|
| 4135 |
-
0.004
|
| 4136 |
-
0.004,
|
| 4137 |
-
0.95
|
| 4138 |
]
|
| 4139 |
},
|
| 4140 |
"p_target": 0.8001,
|
| 4141 |
"competitor": "i",
|
| 4142 |
"competitor_other": false,
|
| 4143 |
"p_competitor": 0.0143,
|
|
|
|
| 4144 |
"gop": 0.0,
|
| 4145 |
"confidence": 1.0,
|
| 4146 |
"gop_factor": 1.0,
|
|
@@ -4165,6 +4170,10 @@
|
|
| 4165 |
"stage": "baseline",
|
| 4166 |
"score": 100.0,
|
| 4167 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4168 |
"applied": false
|
| 4169 |
},
|
| 4170 |
{
|
|
@@ -4199,14 +4208,12 @@
|
|
| 4199 |
25
|
| 4200 |
],
|
| 4201 |
"window": [
|
| 4202 |
-
|
| 4203 |
27
|
| 4204 |
],
|
| 4205 |
"curves": {
|
| 4206 |
-
"start":
|
| 4207 |
"target": [
|
| 4208 |
-
0.002,
|
| 4209 |
-
0.002,
|
| 4210 |
0.007,
|
| 4211 |
0.007,
|
| 4212 |
0.001,
|
|
@@ -4226,8 +4233,6 @@
|
|
| 4226 |
0.004
|
| 4227 |
],
|
| 4228 |
"competitor": [
|
| 4229 |
-
0.004,
|
| 4230 |
-
0.004,
|
| 4231 |
0.014,
|
| 4232 |
0.014,
|
| 4233 |
0.002,
|
|
@@ -4247,8 +4252,6 @@
|
|
| 4247 |
0.009
|
| 4248 |
],
|
| 4249 |
"prev": [
|
| 4250 |
-
0.002,
|
| 4251 |
-
0.002,
|
| 4252 |
0.8,
|
| 4253 |
0.8,
|
| 4254 |
0.001,
|
|
@@ -4268,8 +4271,6 @@
|
|
| 4268 |
0.004
|
| 4269 |
],
|
| 4270 |
"next": [
|
| 4271 |
-
0.004,
|
| 4272 |
-
0.004,
|
| 4273 |
0.014,
|
| 4274 |
0.014,
|
| 4275 |
0.002,
|
|
@@ -4289,8 +4290,6 @@
|
|
| 4289 |
0.884
|
| 4290 |
],
|
| 4291 |
"blank": [
|
| 4292 |
-
0.95,
|
| 4293 |
-
0.95,
|
| 4294 |
0.007,
|
| 4295 |
0.007,
|
| 4296 |
0.97,
|
|
@@ -4314,6 +4313,7 @@
|
|
| 4314 |
"competitor": "e",
|
| 4315 |
"competitor_other": false,
|
| 4316 |
"p_competitor": 0.0071,
|
|
|
|
| 4317 |
"gop": 0.0,
|
| 4318 |
"confidence": 1.0,
|
| 4319 |
"gop_factor": 1.0,
|
|
@@ -4338,6 +4338,10 @@
|
|
| 4338 |
"stage": "baseline",
|
| 4339 |
"score": 100.0,
|
| 4340 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4341 |
"applied": false
|
| 4342 |
},
|
| 4343 |
{
|
|
@@ -4472,6 +4476,7 @@
|
|
| 4472 |
"competitor": "e",
|
| 4473 |
"competitor_other": false,
|
| 4474 |
"p_competitor": 0.0086,
|
|
|
|
| 4475 |
"gop": 0.0,
|
| 4476 |
"confidence": 1.0,
|
| 4477 |
"gop_factor": 1.0,
|
|
@@ -4496,6 +4501,10 @@
|
|
| 4496 |
"stage": "baseline",
|
| 4497 |
"score": 100.0,
|
| 4498 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4499 |
"applied": false
|
| 4500 |
},
|
| 4501 |
{
|
|
@@ -4620,6 +4629,7 @@
|
|
| 4620 |
"competitor": "e",
|
| 4621 |
"competitor_other": false,
|
| 4622 |
"p_competitor": 0.0143,
|
|
|
|
| 4623 |
"gop": 0.0,
|
| 4624 |
"confidence": 1.0,
|
| 4625 |
"gop_factor": 1.0,
|
|
@@ -4644,6 +4654,10 @@
|
|
| 4644 |
"stage": "baseline",
|
| 4645 |
"score": 100.0,
|
| 4646 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4647 |
"applied": false
|
| 4648 |
},
|
| 4649 |
{
|
|
@@ -4700,20 +4714,20 @@
|
|
| 4700 |
0.001
|
| 4701 |
],
|
| 4702 |
"competitor": [
|
| 4703 |
-
0.002,
|
| 4704 |
-
0.002,
|
| 4705 |
-
0.007,
|
| 4706 |
-
0.007,
|
| 4707 |
-
0.002,
|
| 4708 |
-
0.002,
|
| 4709 |
-
0.02,
|
| 4710 |
0.004,
|
| 4711 |
-
0.96,
|
| 4712 |
0.004,
|
| 4713 |
-
0.
|
| 4714 |
-
0.
|
|
|
|
|
|
|
|
|
|
| 4715 |
0.007,
|
| 4716 |
-
0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4717 |
],
|
| 4718 |
"prev": [
|
| 4719 |
0.002,
|
|
@@ -4765,46 +4779,51 @@
|
|
| 4765 |
]
|
| 4766 |
},
|
| 4767 |
"p_target": 0.4498,
|
| 4768 |
-
"competitor": "
|
| 4769 |
"competitor_other": false,
|
| 4770 |
-
"p_competitor": 0.
|
| 4771 |
-
"
|
|
|
|
| 4772 |
"confidence": 1.0,
|
| 4773 |
-
"gop_factor":
|
| 4774 |
"confidence_factor": 1.0,
|
| 4775 |
"deleted": false,
|
| 4776 |
"stages": [
|
| 4777 |
{
|
| 4778 |
"stage": "gop",
|
| 4779 |
-
"score":
|
| 4780 |
},
|
| 4781 |
{
|
| 4782 |
"stage": "exemption",
|
| 4783 |
-
"score":
|
| 4784 |
-
"applied":
|
| 4785 |
},
|
| 4786 |
{
|
| 4787 |
"stage": "insertion",
|
| 4788 |
-
"score":
|
| 4789 |
"applied": null
|
| 4790 |
},
|
| 4791 |
{
|
| 4792 |
"stage": "baseline",
|
| 4793 |
-
"score":
|
| 4794 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4795 |
"applied": false
|
| 4796 |
},
|
| 4797 |
{
|
| 4798 |
"stage": "calibration",
|
| 4799 |
-
"score":
|
| 4800 |
"floor": null,
|
| 4801 |
"applied": false
|
| 4802 |
}
|
| 4803 |
],
|
| 4804 |
-
"final":
|
| 4805 |
"margin": {
|
| 4806 |
"needed": 0.0,
|
| 4807 |
-
"got": 0.
|
| 4808 |
"beyond": true
|
| 4809 |
},
|
| 4810 |
"vowel": true,
|
|
@@ -4812,7 +4831,7 @@
|
|
| 4812 |
"flagged": false,
|
| 4813 |
"rule": null,
|
| 4814 |
"tip": false,
|
| 4815 |
-
"issue":
|
| 4816 |
},
|
| 4817 |
{
|
| 4818 |
"i": 7,
|
|
@@ -4830,7 +4849,7 @@
|
|
| 4830 |
],
|
| 4831 |
"window": [
|
| 4832 |
38,
|
| 4833 |
-
|
| 4834 |
],
|
| 4835 |
"curves": {
|
| 4836 |
"start": 34,
|
|
@@ -4851,10 +4870,7 @@
|
|
| 4851 |
0.002,
|
| 4852 |
0.002,
|
| 4853 |
0.002,
|
| 4854 |
-
0.007
|
| 4855 |
-
0.007,
|
| 4856 |
-
0.007,
|
| 4857 |
-
0.004
|
| 4858 |
],
|
| 4859 |
"competitor": [
|
| 4860 |
0.007,
|
|
@@ -4873,10 +4889,7 @@
|
|
| 4873 |
0.001,
|
| 4874 |
0.001,
|
| 4875 |
0.001,
|
| 4876 |
-
0.004
|
| 4877 |
-
0.004,
|
| 4878 |
-
0.004,
|
| 4879 |
-
0.002
|
| 4880 |
],
|
| 4881 |
"prev": [
|
| 4882 |
0.007,
|
|
@@ -4895,10 +4908,7 @@
|
|
| 4895 |
0.001,
|
| 4896 |
0.001,
|
| 4897 |
0.001,
|
| 4898 |
-
0.004
|
| 4899 |
-
0.004,
|
| 4900 |
-
0.004,
|
| 4901 |
-
0.002
|
| 4902 |
],
|
| 4903 |
"next": [
|
| 4904 |
0.007,
|
|
@@ -4917,10 +4927,7 @@
|
|
| 4917 |
0.001,
|
| 4918 |
0.001,
|
| 4919 |
0.001,
|
| 4920 |
-
0.9
|
| 4921 |
-
0.9,
|
| 4922 |
-
0.9,
|
| 4923 |
-
0.002
|
| 4924 |
],
|
| 4925 |
"blank": [
|
| 4926 |
0.007,
|
|
@@ -4939,40 +4946,42 @@
|
|
| 4939 |
0.97,
|
| 4940 |
0.97,
|
| 4941 |
0.97,
|
| 4942 |
-
0.004
|
| 4943 |
-
0.004,
|
| 4944 |
-
0.004,
|
| 4945 |
-
0.95
|
| 4946 |
]
|
| 4947 |
},
|
| 4948 |
"p_target": 0.325,
|
| 4949 |
"competitor": "h",
|
| 4950 |
"competitor_other": false,
|
| 4951 |
"p_competitor": 0.9598,
|
|
|
|
| 4952 |
"gop": -1.083,
|
| 4953 |
"confidence": 1.0,
|
| 4954 |
-
"gop_factor": 0.
|
| 4955 |
"confidence_factor": 1.0,
|
| 4956 |
"deleted": false,
|
| 4957 |
"stages": [
|
| 4958 |
{
|
| 4959 |
"stage": "gop",
|
| 4960 |
-
"score":
|
| 4961 |
},
|
| 4962 |
{
|
| 4963 |
"stage": "exemption",
|
| 4964 |
-
"score":
|
| 4965 |
"applied": null
|
| 4966 |
},
|
| 4967 |
{
|
| 4968 |
"stage": "insertion",
|
| 4969 |
-
"score":
|
| 4970 |
"applied": null
|
| 4971 |
},
|
| 4972 |
{
|
| 4973 |
"stage": "baseline",
|
| 4974 |
"score": 100.0,
|
| 4975 |
"ref": 55.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4976 |
"applied": true
|
| 4977 |
},
|
| 4978 |
{
|
|
@@ -5007,15 +5016,12 @@
|
|
| 5007 |
53
|
| 5008 |
],
|
| 5009 |
"window": [
|
| 5010 |
-
|
| 5011 |
55
|
| 5012 |
],
|
| 5013 |
"curves": {
|
| 5014 |
-
"start":
|
| 5015 |
"target": [
|
| 5016 |
-
0.001,
|
| 5017 |
-
0.004,
|
| 5018 |
-
0.025,
|
| 5019 |
0.025,
|
| 5020 |
0.007,
|
| 5021 |
0.001,
|
|
@@ -5035,9 +5041,6 @@
|
|
| 5035 |
0.004
|
| 5036 |
],
|
| 5037 |
"competitor": [
|
| 5038 |
-
0.003,
|
| 5039 |
-
0.007,
|
| 5040 |
-
0.05,
|
| 5041 |
0.05,
|
| 5042 |
0.014,
|
| 5043 |
0.002,
|
|
@@ -5057,9 +5060,6 @@
|
|
| 5057 |
0.007
|
| 5058 |
],
|
| 5059 |
"prev": [
|
| 5060 |
-
0.003,
|
| 5061 |
-
0.007,
|
| 5062 |
-
0.325,
|
| 5063 |
0.325,
|
| 5064 |
0.014,
|
| 5065 |
0.002,
|
|
@@ -5079,9 +5079,6 @@
|
|
| 5079 |
0.007
|
| 5080 |
],
|
| 5081 |
"next": [
|
| 5082 |
-
0.003,
|
| 5083 |
-
0.007,
|
| 5084 |
-
0.05,
|
| 5085 |
0.05,
|
| 5086 |
0.014,
|
| 5087 |
0.002,
|
|
@@ -5101,9 +5098,6 @@
|
|
| 5101 |
0.904
|
| 5102 |
],
|
| 5103 |
"blank": [
|
| 5104 |
-
0.001,
|
| 5105 |
-
0.9,
|
| 5106 |
-
0.025,
|
| 5107 |
0.025,
|
| 5108 |
0.8,
|
| 5109 |
0.97,
|
|
@@ -5126,7 +5120,8 @@
|
|
| 5126 |
"p_target": 0.9003,
|
| 5127 |
"competitor": "e",
|
| 5128 |
"competitor_other": false,
|
| 5129 |
-
"p_competitor": 0.
|
|
|
|
| 5130 |
"gop": 0.0,
|
| 5131 |
"confidence": 1.0,
|
| 5132 |
"gop_factor": 1.0,
|
|
@@ -5151,6 +5146,10 @@
|
|
| 5151 |
"stage": "baseline",
|
| 5152 |
"score": 100.0,
|
| 5153 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5154 |
"applied": false
|
| 5155 |
},
|
| 5156 |
{
|
|
@@ -5285,6 +5284,7 @@
|
|
| 5285 |
"competitor": "e",
|
| 5286 |
"competitor_other": false,
|
| 5287 |
"p_competitor": 0.0071,
|
|
|
|
| 5288 |
"gop": 0.0,
|
| 5289 |
"confidence": 1.0,
|
| 5290 |
"gop_factor": 1.0,
|
|
@@ -5309,6 +5309,10 @@
|
|
| 5309 |
"stage": "baseline",
|
| 5310 |
"score": 100.0,
|
| 5311 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5312 |
"applied": false
|
| 5313 |
},
|
| 5314 |
{
|
|
@@ -5433,6 +5437,7 @@
|
|
| 5433 |
"competitor": "e",
|
| 5434 |
"competitor_other": false,
|
| 5435 |
"p_competitor": 0.0107,
|
|
|
|
| 5436 |
"gop": 0.0,
|
| 5437 |
"confidence": 1.0,
|
| 5438 |
"gop_factor": 1.0,
|
|
@@ -5457,6 +5462,10 @@
|
|
| 5457 |
"stage": "baseline",
|
| 5458 |
"score": 100.0,
|
| 5459 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5460 |
"applied": false
|
| 5461 |
},
|
| 5462 |
{
|
|
@@ -5601,6 +5610,7 @@
|
|
| 5601 |
"competitor": "e",
|
| 5602 |
"competitor_other": false,
|
| 5603 |
"p_competitor": 0.0143,
|
|
|
|
| 5604 |
"gop": 0.0,
|
| 5605 |
"confidence": 1.0,
|
| 5606 |
"gop_factor": 1.0,
|
|
@@ -5625,6 +5635,10 @@
|
|
| 5625 |
"stage": "baseline",
|
| 5626 |
"score": 100.0,
|
| 5627 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5628 |
"applied": false
|
| 5629 |
},
|
| 5630 |
{
|
|
@@ -5663,14 +5677,12 @@
|
|
| 5663 |
75
|
| 5664 |
],
|
| 5665 |
"window": [
|
| 5666 |
-
|
| 5667 |
77
|
| 5668 |
],
|
| 5669 |
"curves": {
|
| 5670 |
-
"start":
|
| 5671 |
"target": [
|
| 5672 |
-
0.005,
|
| 5673 |
-
0.005,
|
| 5674 |
0.021,
|
| 5675 |
0.021,
|
| 5676 |
0.003,
|
|
@@ -5689,8 +5701,6 @@
|
|
| 5689 |
0.005
|
| 5690 |
],
|
| 5691 |
"competitor": [
|
| 5692 |
-
0.004,
|
| 5693 |
-
0.004,
|
| 5694 |
0.014,
|
| 5695 |
0.014,
|
| 5696 |
0.002,
|
|
@@ -5709,8 +5719,6 @@
|
|
| 5709 |
0.004
|
| 5710 |
],
|
| 5711 |
"prev": [
|
| 5712 |
-
0.004,
|
| 5713 |
-
0.004,
|
| 5714 |
0.807,
|
| 5715 |
0.807,
|
| 5716 |
0.002,
|
|
@@ -5729,8 +5737,6 @@
|
|
| 5729 |
0.004
|
| 5730 |
],
|
| 5731 |
"next": [
|
| 5732 |
-
0.002,
|
| 5733 |
-
0.002,
|
| 5734 |
0.007,
|
| 5735 |
0.007,
|
| 5736 |
0.001,
|
|
@@ -5749,8 +5755,6 @@
|
|
| 5749 |
0.002
|
| 5750 |
],
|
| 5751 |
"blank": [
|
| 5752 |
-
0.95,
|
| 5753 |
-
0.95,
|
| 5754 |
0.007,
|
| 5755 |
0.007,
|
| 5756 |
0.97,
|
|
@@ -5773,6 +5777,7 @@
|
|
| 5773 |
"competitor": "e",
|
| 5774 |
"competitor_other": false,
|
| 5775 |
"p_competitor": 0.0129,
|
|
|
|
| 5776 |
"gop": 0.0,
|
| 5777 |
"confidence": 1.0,
|
| 5778 |
"gop_factor": 1.0,
|
|
@@ -5797,6 +5802,10 @@
|
|
| 5797 |
"stage": "baseline",
|
| 5798 |
"score": 100.0,
|
| 5799 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5800 |
"applied": false
|
| 5801 |
},
|
| 5802 |
{
|
|
@@ -5921,6 +5930,7 @@
|
|
| 5921 |
"competitor": "i",
|
| 5922 |
"competitor_other": false,
|
| 5923 |
"p_competitor": 0.0107,
|
|
|
|
| 5924 |
"gop": 0.0,
|
| 5925 |
"confidence": 1.0,
|
| 5926 |
"gop_factor": 1.0,
|
|
@@ -5934,7 +5944,7 @@
|
|
| 5934 |
{
|
| 5935 |
"stage": "exemption",
|
| 5936 |
"score": 100.0,
|
| 5937 |
-
"applied":
|
| 5938 |
},
|
| 5939 |
{
|
| 5940 |
"stage": "insertion",
|
|
@@ -5945,6 +5955,10 @@
|
|
| 5945 |
"stage": "baseline",
|
| 5946 |
"score": 100.0,
|
| 5947 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5948 |
"applied": false
|
| 5949 |
},
|
| 5950 |
{
|
|
@@ -6069,31 +6083,36 @@
|
|
| 6069 |
"competitor": "ʔ",
|
| 6070 |
"competitor_other": false,
|
| 6071 |
"p_competitor": 0.8001,
|
|
|
|
| 6072 |
"gop": -4.718,
|
| 6073 |
"confidence": 0.024,
|
| 6074 |
-
"gop_factor": 0.
|
| 6075 |
"confidence_factor": 0.154,
|
| 6076 |
"deleted": false,
|
| 6077 |
"stages": [
|
| 6078 |
{
|
| 6079 |
"stage": "gop",
|
| 6080 |
-
"score":
|
| 6081 |
},
|
| 6082 |
{
|
| 6083 |
"stage": "exemption",
|
| 6084 |
-
"score":
|
| 6085 |
"applied": null
|
| 6086 |
},
|
| 6087 |
{
|
| 6088 |
"stage": "insertion",
|
| 6089 |
-
"score":
|
| 6090 |
"applied": null
|
| 6091 |
},
|
| 6092 |
{
|
| 6093 |
"stage": "baseline",
|
| 6094 |
-
"score":
|
| 6095 |
-
"ref":
|
| 6096 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6097 |
},
|
| 6098 |
{
|
| 6099 |
"stage": "calibration",
|
|
@@ -6226,6 +6245,7 @@
|
|
| 6226 |
"competitor": "ʔ",
|
| 6227 |
"competitor_other": false,
|
| 6228 |
"p_competitor": 0.8001,
|
|
|
|
| 6229 |
"gop": 0.0,
|
| 6230 |
"confidence": 1.0,
|
| 6231 |
"gop_factor": 1.0,
|
|
@@ -6239,7 +6259,7 @@
|
|
| 6239 |
{
|
| 6240 |
"stage": "exemption",
|
| 6241 |
"score": 100.0,
|
| 6242 |
-
"applied":
|
| 6243 |
},
|
| 6244 |
{
|
| 6245 |
"stage": "insertion",
|
|
@@ -6250,6 +6270,10 @@
|
|
| 6250 |
"stage": "baseline",
|
| 6251 |
"score": 100.0,
|
| 6252 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6253 |
"applied": false
|
| 6254 |
},
|
| 6255 |
{
|
|
@@ -6285,7 +6309,7 @@
|
|
| 6285 |
],
|
| 6286 |
"window": [
|
| 6287 |
87,
|
| 6288 |
-
|
| 6289 |
],
|
| 6290 |
"curves": {
|
| 6291 |
"start": 83,
|
|
@@ -6305,9 +6329,7 @@
|
|
| 6305 |
0.001,
|
| 6306 |
0.001,
|
| 6307 |
0.005,
|
| 6308 |
-
0.005
|
| 6309 |
-
0.005,
|
| 6310 |
-
0.002
|
| 6311 |
],
|
| 6312 |
"competitor": [
|
| 6313 |
0.004,
|
|
@@ -6325,9 +6347,7 @@
|
|
| 6325 |
0.002,
|
| 6326 |
0.002,
|
| 6327 |
0.011,
|
| 6328 |
-
0.011
|
| 6329 |
-
0.011,
|
| 6330 |
-
0.004
|
| 6331 |
],
|
| 6332 |
"prev": [
|
| 6333 |
0.002,
|
|
@@ -6345,9 +6365,7 @@
|
|
| 6345 |
0.001,
|
| 6346 |
0.001,
|
| 6347 |
0.005,
|
| 6348 |
-
0.005
|
| 6349 |
-
0.005,
|
| 6350 |
-
0.002
|
| 6351 |
],
|
| 6352 |
"next": [
|
| 6353 |
0.002,
|
|
@@ -6365,9 +6383,7 @@
|
|
| 6365 |
0.001,
|
| 6366 |
0.001,
|
| 6367 |
0.85,
|
| 6368 |
-
0.85
|
| 6369 |
-
0.85,
|
| 6370 |
-
0.002
|
| 6371 |
],
|
| 6372 |
"blank": [
|
| 6373 |
0.95,
|
|
@@ -6385,15 +6401,14 @@
|
|
| 6385 |
0.97,
|
| 6386 |
0.97,
|
| 6387 |
0.005,
|
| 6388 |
-
0.005
|
| 6389 |
-
0.005,
|
| 6390 |
-
0.95
|
| 6391 |
]
|
| 6392 |
},
|
| 6393 |
"p_target": 0.8496,
|
| 6394 |
"competitor": "i",
|
| 6395 |
"competitor_other": false,
|
| 6396 |
"p_competitor": 0.0107,
|
|
|
|
| 6397 |
"gop": 0.0,
|
| 6398 |
"confidence": 1.0,
|
| 6399 |
"gop_factor": 1.0,
|
|
@@ -6418,6 +6433,10 @@
|
|
| 6418 |
"stage": "baseline",
|
| 6419 |
"score": 100.0,
|
| 6420 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6421 |
"applied": false
|
| 6422 |
},
|
| 6423 |
{
|
|
@@ -6452,14 +6471,12 @@
|
|
| 6452 |
100
|
| 6453 |
],
|
| 6454 |
"window": [
|
| 6455 |
-
|
| 6456 |
102
|
| 6457 |
],
|
| 6458 |
"curves": {
|
| 6459 |
-
"start":
|
| 6460 |
"target": [
|
| 6461 |
-
0.002,
|
| 6462 |
-
0.002,
|
| 6463 |
0.005,
|
| 6464 |
0.005,
|
| 6465 |
0.001,
|
|
@@ -6479,8 +6496,6 @@
|
|
| 6479 |
0.001
|
| 6480 |
],
|
| 6481 |
"competitor": [
|
| 6482 |
-
0.004,
|
| 6483 |
-
0.004,
|
| 6484 |
0.011,
|
| 6485 |
0.011,
|
| 6486 |
0.002,
|
|
@@ -6500,8 +6515,6 @@
|
|
| 6500 |
0.002
|
| 6501 |
],
|
| 6502 |
"prev": [
|
| 6503 |
-
0.002,
|
| 6504 |
-
0.002,
|
| 6505 |
0.85,
|
| 6506 |
0.85,
|
| 6507 |
0.001,
|
|
@@ -6521,8 +6534,6 @@
|
|
| 6521 |
0.001
|
| 6522 |
],
|
| 6523 |
"next": [
|
| 6524 |
-
0.004,
|
| 6525 |
-
0.004,
|
| 6526 |
0.011,
|
| 6527 |
0.011,
|
| 6528 |
0.002,
|
|
@@ -6542,8 +6553,6 @@
|
|
| 6542 |
0.002
|
| 6543 |
],
|
| 6544 |
"blank": [
|
| 6545 |
-
0.95,
|
| 6546 |
-
0.95,
|
| 6547 |
0.005,
|
| 6548 |
0.005,
|
| 6549 |
0.97,
|
|
@@ -6567,6 +6576,7 @@
|
|
| 6567 |
"competitor": "e",
|
| 6568 |
"competitor_other": false,
|
| 6569 |
"p_competitor": 0.0107,
|
|
|
|
| 6570 |
"gop": 0.0,
|
| 6571 |
"confidence": 1.0,
|
| 6572 |
"gop_factor": 1.0,
|
|
@@ -6591,6 +6601,10 @@
|
|
| 6591 |
"stage": "baseline",
|
| 6592 |
"score": 100.0,
|
| 6593 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6594 |
"applied": false
|
| 6595 |
},
|
| 6596 |
{
|
|
@@ -6735,6 +6749,7 @@
|
|
| 6735 |
"competitor": "e",
|
| 6736 |
"competitor_other": false,
|
| 6737 |
"p_competitor": 0.0107,
|
|
|
|
| 6738 |
"gop": 0.0,
|
| 6739 |
"confidence": 1.0,
|
| 6740 |
"gop_factor": 1.0,
|
|
@@ -6759,6 +6774,10 @@
|
|
| 6759 |
"stage": "baseline",
|
| 6760 |
"score": 100.0,
|
| 6761 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6762 |
"applied": false
|
| 6763 |
},
|
| 6764 |
{
|
|
@@ -6793,14 +6812,12 @@
|
|
| 6793 |
112
|
| 6794 |
],
|
| 6795 |
"window": [
|
| 6796 |
-
|
| 6797 |
114
|
| 6798 |
],
|
| 6799 |
"curves": {
|
| 6800 |
-
"start":
|
| 6801 |
"target": [
|
| 6802 |
-
0.002,
|
| 6803 |
-
0.002,
|
| 6804 |
0.005,
|
| 6805 |
0.005,
|
| 6806 |
0.001,
|
|
@@ -6819,8 +6836,6 @@
|
|
| 6819 |
0.004
|
| 6820 |
],
|
| 6821 |
"competitor": [
|
| 6822 |
-
0.002,
|
| 6823 |
-
0.002,
|
| 6824 |
0.005,
|
| 6825 |
0.005,
|
| 6826 |
0.001,
|
|
@@ -6839,8 +6854,6 @@
|
|
| 6839 |
0.004
|
| 6840 |
],
|
| 6841 |
"prev": [
|
| 6842 |
-
0.004,
|
| 6843 |
-
0.004,
|
| 6844 |
0.855,
|
| 6845 |
0.855,
|
| 6846 |
0.002,
|
|
@@ -6859,8 +6872,6 @@
|
|
| 6859 |
0.007
|
| 6860 |
],
|
| 6861 |
"next": [
|
| 6862 |
-
0.004,
|
| 6863 |
-
0.004,
|
| 6864 |
0.011,
|
| 6865 |
0.011,
|
| 6866 |
0.002,
|
|
@@ -6879,8 +6890,6 @@
|
|
| 6879 |
0.904
|
| 6880 |
],
|
| 6881 |
"blank": [
|
| 6882 |
-
0.95,
|
| 6883 |
-
0.95,
|
| 6884 |
0.005,
|
| 6885 |
0.005,
|
| 6886 |
0.97,
|
|
@@ -6903,6 +6912,7 @@
|
|
| 6903 |
"competitor": "w",
|
| 6904 |
"competitor_other": false,
|
| 6905 |
"p_competitor": 0.0054,
|
|
|
|
| 6906 |
"gop": 0.0,
|
| 6907 |
"confidence": 1.0,
|
| 6908 |
"gop_factor": 1.0,
|
|
@@ -6927,6 +6937,10 @@
|
|
| 6927 |
"stage": "baseline",
|
| 6928 |
"score": 100.0,
|
| 6929 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6930 |
"applied": false
|
| 6931 |
},
|
| 6932 |
{
|
|
@@ -7061,6 +7075,7 @@
|
|
| 7061 |
"competitor": "i",
|
| 7062 |
"competitor_other": false,
|
| 7063 |
"p_competitor": 0.0071,
|
|
|
|
| 7064 |
"gop": 0.0,
|
| 7065 |
"confidence": 1.0,
|
| 7066 |
"gop_factor": 1.0,
|
|
@@ -7085,6 +7100,10 @@
|
|
| 7085 |
"stage": "baseline",
|
| 7086 |
"score": 100.0,
|
| 7087 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7088 |
"applied": false
|
| 7089 |
},
|
| 7090 |
{
|
|
@@ -7213,6 +7232,7 @@
|
|
| 7213 |
"competitor": "i",
|
| 7214 |
"competitor_other": false,
|
| 7215 |
"p_competitor": 0.0107,
|
|
|
|
| 7216 |
"gop": 0.0,
|
| 7217 |
"confidence": 1.0,
|
| 7218 |
"gop_factor": 1.0,
|
|
@@ -7237,6 +7257,10 @@
|
|
| 7237 |
"stage": "baseline",
|
| 7238 |
"score": 100.0,
|
| 7239 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7240 |
"applied": false
|
| 7241 |
},
|
| 7242 |
{
|
|
@@ -7342,6 +7366,7 @@
|
|
| 7342 |
"competitor": "i",
|
| 7343 |
"competitor_other": false,
|
| 7344 |
"p_competitor": 0.0107,
|
|
|
|
| 7345 |
"gop": 0.0,
|
| 7346 |
"confidence": 1.0,
|
| 7347 |
"gop_factor": 1.0,
|
|
@@ -7355,7 +7380,7 @@
|
|
| 7355 |
{
|
| 7356 |
"stage": "exemption",
|
| 7357 |
"score": 100.0,
|
| 7358 |
-
"applied":
|
| 7359 |
},
|
| 7360 |
{
|
| 7361 |
"stage": "insertion",
|
|
@@ -7366,6 +7391,10 @@
|
|
| 7366 |
"stage": "baseline",
|
| 7367 |
"score": 100.0,
|
| 7368 |
"ref": 100.0,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7369 |
"applied": false
|
| 7370 |
},
|
| 7371 |
{
|
|
@@ -7407,12 +7436,12 @@
|
|
| 7407 |
100.0,
|
| 7408 |
100.0,
|
| 7409 |
100.0,
|
| 7410 |
-
|
| 7411 |
100.0
|
| 7412 |
],
|
| 7413 |
-
"min":
|
| 7414 |
-
"mean":
|
| 7415 |
-
"score":
|
| 7416 |
},
|
| 7417 |
{
|
| 7418 |
"tr": "סִידִי",
|
|
@@ -7437,7 +7466,7 @@
|
|
| 7437 |
],
|
| 7438 |
"min": 45.0,
|
| 7439 |
"mean": 89.0,
|
| 7440 |
-
"score":
|
| 7441 |
},
|
| 7442 |
{
|
| 7443 |
"tr": "פִי",
|
|
@@ -7463,12 +7492,12 @@
|
|
| 7463 |
}
|
| 7464 |
],
|
| 7465 |
"sentence": {
|
| 7466 |
-
"phone_mean": 96.
|
| 7467 |
-
"word_mean":
|
| 7468 |
"phone_weight": 0.5,
|
| 7469 |
"word_weight": 0.5,
|
| 7470 |
-
"before_cap":
|
| 7471 |
-
"final":
|
| 7472 |
"capped": false
|
| 7473 |
},
|
| 7474 |
"tips": [
|
|
|
|
| 1 |
{
|
| 2 |
+
"score": 96,
|
| 3 |
"variant": {
|
| 4 |
"ar": "وين سيدك؟ سيدي قعد في بيته.",
|
| 5 |
"tr": "וֵין סִידַכּ סִידִי קַעַד פִי בֵּיתוֹ",
|
| 6 |
"ipa": "w eː n | s iː d a k | s iː d i | ʔ a ʕ a d | f i | b eː t o"
|
| 7 |
},
|
| 8 |
"heard_ipa": "w e n s i d a h k s i d i ʔ a ʔ a d f i b e t o",
|
| 9 |
+
"heard_tr": "וֵין סִידַכּ סִידִי קַקַד פִי בֵּיתוֹ",
|
| 10 |
"unrelated": false,
|
| 11 |
"words": [
|
| 12 |
{
|
|
|
|
| 51 |
{
|
| 52 |
"ar": "سيدك؟",
|
| 53 |
"tr": "סִידַכּ",
|
| 54 |
+
"heard_tr": "סִידַכּ",
|
| 55 |
+
"score": 100.0,
|
| 56 |
"letters": [
|
| 57 |
{
|
| 58 |
"t": "סִי",
|
|
|
|
| 60 |
},
|
| 61 |
{
|
| 62 |
"t": "דַ",
|
| 63 |
+
"score": 100.0
|
|
|
|
| 64 |
},
|
| 65 |
{
|
| 66 |
"t": "כּ",
|
|
|
|
| 92 |
{
|
| 93 |
"ipa": "a",
|
| 94 |
"word": 1,
|
| 95 |
+
"score": 100.0,
|
| 96 |
"flagged": false,
|
| 97 |
"heard": null
|
| 98 |
},
|
|
|
|
| 157 |
"ar": "قعد",
|
| 158 |
"tr": "קַעַד",
|
| 159 |
"heard_tr": "קַקַד",
|
| 160 |
+
"score": 73.6,
|
| 161 |
"letters": [
|
| 162 |
{
|
| 163 |
"t": "קַ",
|
|
|
|
| 300 |
"score": 45
|
| 301 |
}
|
| 302 |
],
|
| 303 |
+
"issues": [],
|
| 304 |
+
"references": 2,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 305 |
"dialect": "urban",
|
| 306 |
"calibrated": [
|
| 307 |
{
|
| 308 |
"expected": "ʕ",
|
| 309 |
"heard": "ʔ",
|
| 310 |
+
"from": 4,
|
| 311 |
"to": 45
|
| 312 |
}
|
| 313 |
],
|
|
|
|
| 2890 |
},
|
| 2891 |
"trace": {
|
| 2892 |
"config": {
|
| 2893 |
+
"leniency": 0.35,
|
| 2894 |
"confident_peak": 0.3,
|
| 2895 |
+
"consonant_window": 4,
|
| 2896 |
"deleted_peak": 0.05,
|
| 2897 |
"deleted_comp": 0.2,
|
| 2898 |
"flag_below": 50.0,
|
| 2899 |
+
"flag_below_sound": {},
|
| 2900 |
"issue_below": 90.0,
|
| 2901 |
"near_vowel_floor": 90.0,
|
| 2902 |
+
"word_min_weight": 0.35,
|
| 2903 |
"vowel_weight": 0.5,
|
| 2904 |
"unrelated_ratio": 0.65,
|
| 2905 |
"unrelated_cap": 30.0,
|
|
|
|
| 2909 |
"ref_min_mean": 60.0,
|
| 2910 |
"margin_default": 0.0,
|
| 2911 |
"ayin_deleted_floor": 60.0,
|
| 2912 |
+
"onset_transient_floor": 90.0,
|
| 2913 |
"margins": [
|
| 2914 |
{
|
| 2915 |
"target": "dˤ",
|
|
|
|
| 3049 |
],
|
| 3050 |
"exemptions": [
|
| 3051 |
"glottal_dropped",
|
| 3052 |
+
"onset_transient",
|
| 3053 |
"article_vowel_elided",
|
| 3054 |
+
"near_vowel",
|
| 3055 |
+
"final_b_devoicing",
|
| 3056 |
+
"word_final_vowel_linking",
|
| 3057 |
+
"unmarked_short_vowel"
|
| 3058 |
],
|
| 3059 |
"insertion": {
|
| 3060 |
"score_cap": 60,
|
|
|
|
| 3725 |
},
|
| 3726 |
"references": [
|
| 3727 |
{
|
| 3728 |
+
"voice": "ראאף",
|
| 3729 |
"mean": 98.0,
|
| 3730 |
"sounds": 23
|
| 3731 |
+
},
|
| 3732 |
+
{
|
| 3733 |
+
"voice": "פדוא",
|
| 3734 |
+
"mean": 97.8,
|
| 3735 |
+
"sounds": 23
|
| 3736 |
}
|
| 3737 |
],
|
| 3738 |
"tokens": [
|
|
|
|
| 3815 |
"competitor": "i",
|
| 3816 |
"competitor_other": false,
|
| 3817 |
"p_competitor": 0.0107,
|
| 3818 |
+
"competitor_frames": 0,
|
| 3819 |
"gop": 0.0,
|
| 3820 |
"confidence": 1.0,
|
| 3821 |
"gop_factor": 1.0,
|
|
|
|
| 3840 |
"stage": "baseline",
|
| 3841 |
"score": 100.0,
|
| 3842 |
"ref": 100.0,
|
| 3843 |
+
"refs": [
|
| 3844 |
+
100.0,
|
| 3845 |
+
100.0
|
| 3846 |
+
],
|
| 3847 |
"applied": false
|
| 3848 |
},
|
| 3849 |
{
|
|
|
|
| 3978 |
"competitor": "i",
|
| 3979 |
"competitor_other": false,
|
| 3980 |
"p_competitor": 0.0071,
|
| 3981 |
+
"competitor_frames": 0,
|
| 3982 |
"gop": 0.0,
|
| 3983 |
"confidence": 1.0,
|
| 3984 |
"gop_factor": 1.0,
|
|
|
|
| 4003 |
"stage": "baseline",
|
| 4004 |
"score": 100.0,
|
| 4005 |
"ref": 100.0,
|
| 4006 |
+
"refs": [
|
| 4007 |
+
100.0,
|
| 4008 |
+
100.0
|
| 4009 |
+
],
|
| 4010 |
"applied": false
|
| 4011 |
},
|
| 4012 |
{
|
|
|
|
| 4046 |
],
|
| 4047 |
"window": [
|
| 4048 |
12,
|
| 4049 |
+
20
|
| 4050 |
],
|
| 4051 |
"curves": {
|
| 4052 |
"start": 8,
|
|
|
|
| 4066 |
0.001,
|
| 4067 |
0.001,
|
| 4068 |
0.004,
|
| 4069 |
+
0.004
|
|
|
|
|
|
|
| 4070 |
],
|
| 4071 |
"competitor": [
|
| 4072 |
0.007,
|
|
|
|
| 4084 |
0.002,
|
| 4085 |
0.002,
|
| 4086 |
0.007,
|
| 4087 |
+
0.007
|
|
|
|
|
|
|
| 4088 |
],
|
| 4089 |
"prev": [
|
| 4090 |
0.904,
|
|
|
|
| 4102 |
0.002,
|
| 4103 |
0.002,
|
| 4104 |
0.007,
|
| 4105 |
+
0.007
|
|
|
|
|
|
|
| 4106 |
],
|
| 4107 |
"next": [
|
| 4108 |
0.004,
|
|
|
|
| 4120 |
0.001,
|
| 4121 |
0.001,
|
| 4122 |
0.9,
|
| 4123 |
+
0.9
|
|
|
|
|
|
|
| 4124 |
],
|
| 4125 |
"blank": [
|
| 4126 |
0.004,
|
|
|
|
| 4138 |
0.97,
|
| 4139 |
0.97,
|
| 4140 |
0.004,
|
| 4141 |
+
0.004
|
|
|
|
|
|
|
| 4142 |
]
|
| 4143 |
},
|
| 4144 |
"p_target": 0.8001,
|
| 4145 |
"competitor": "i",
|
| 4146 |
"competitor_other": false,
|
| 4147 |
"p_competitor": 0.0143,
|
| 4148 |
+
"competitor_frames": 0,
|
| 4149 |
"gop": 0.0,
|
| 4150 |
"confidence": 1.0,
|
| 4151 |
"gop_factor": 1.0,
|
|
|
|
| 4170 |
"stage": "baseline",
|
| 4171 |
"score": 100.0,
|
| 4172 |
"ref": 100.0,
|
| 4173 |
+
"refs": [
|
| 4174 |
+
100.0,
|
| 4175 |
+
100.0
|
| 4176 |
+
],
|
| 4177 |
"applied": false
|
| 4178 |
},
|
| 4179 |
{
|
|
|
|
| 4208 |
25
|
| 4209 |
],
|
| 4210 |
"window": [
|
| 4211 |
+
18,
|
| 4212 |
27
|
| 4213 |
],
|
| 4214 |
"curves": {
|
| 4215 |
+
"start": 14,
|
| 4216 |
"target": [
|
|
|
|
|
|
|
| 4217 |
0.007,
|
| 4218 |
0.007,
|
| 4219 |
0.001,
|
|
|
|
| 4233 |
0.004
|
| 4234 |
],
|
| 4235 |
"competitor": [
|
|
|
|
|
|
|
| 4236 |
0.014,
|
| 4237 |
0.014,
|
| 4238 |
0.002,
|
|
|
|
| 4252 |
0.009
|
| 4253 |
],
|
| 4254 |
"prev": [
|
|
|
|
|
|
|
| 4255 |
0.8,
|
| 4256 |
0.8,
|
| 4257 |
0.001,
|
|
|
|
| 4271 |
0.004
|
| 4272 |
],
|
| 4273 |
"next": [
|
|
|
|
|
|
|
| 4274 |
0.014,
|
| 4275 |
0.014,
|
| 4276 |
0.002,
|
|
|
|
| 4290 |
0.884
|
| 4291 |
],
|
| 4292 |
"blank": [
|
|
|
|
|
|
|
| 4293 |
0.007,
|
| 4294 |
0.007,
|
| 4295 |
0.97,
|
|
|
|
| 4313 |
"competitor": "e",
|
| 4314 |
"competitor_other": false,
|
| 4315 |
"p_competitor": 0.0071,
|
| 4316 |
+
"competitor_frames": 0,
|
| 4317 |
"gop": 0.0,
|
| 4318 |
"confidence": 1.0,
|
| 4319 |
"gop_factor": 1.0,
|
|
|
|
| 4338 |
"stage": "baseline",
|
| 4339 |
"score": 100.0,
|
| 4340 |
"ref": 100.0,
|
| 4341 |
+
"refs": [
|
| 4342 |
+
100.0,
|
| 4343 |
+
100.0
|
| 4344 |
+
],
|
| 4345 |
"applied": false
|
| 4346 |
},
|
| 4347 |
{
|
|
|
|
| 4476 |
"competitor": "e",
|
| 4477 |
"competitor_other": false,
|
| 4478 |
"p_competitor": 0.0086,
|
| 4479 |
+
"competitor_frames": 0,
|
| 4480 |
"gop": 0.0,
|
| 4481 |
"confidence": 1.0,
|
| 4482 |
"gop_factor": 1.0,
|
|
|
|
| 4501 |
"stage": "baseline",
|
| 4502 |
"score": 100.0,
|
| 4503 |
"ref": 100.0,
|
| 4504 |
+
"refs": [
|
| 4505 |
+
100.0,
|
| 4506 |
+
100.0
|
| 4507 |
+
],
|
| 4508 |
"applied": false
|
| 4509 |
},
|
| 4510 |
{
|
|
|
|
| 4629 |
"competitor": "e",
|
| 4630 |
"competitor_other": false,
|
| 4631 |
"p_competitor": 0.0143,
|
| 4632 |
+
"competitor_frames": 0,
|
| 4633 |
"gop": 0.0,
|
| 4634 |
"confidence": 1.0,
|
| 4635 |
"gop_factor": 1.0,
|
|
|
|
| 4654 |
"stage": "baseline",
|
| 4655 |
"score": 100.0,
|
| 4656 |
"ref": 100.0,
|
| 4657 |
+
"refs": [
|
| 4658 |
+
100.0,
|
| 4659 |
+
100.0
|
| 4660 |
+
],
|
| 4661 |
"applied": false
|
| 4662 |
},
|
| 4663 |
{
|
|
|
|
| 4714 |
0.001
|
| 4715 |
],
|
| 4716 |
"competitor": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4717 |
0.004,
|
|
|
|
| 4718 |
0.004,
|
| 4719 |
+
0.014,
|
| 4720 |
+
0.014,
|
| 4721 |
+
0.004,
|
| 4722 |
+
0.004,
|
| 4723 |
+
0.039,
|
| 4724 |
0.007,
|
| 4725 |
+
0.003,
|
| 4726 |
+
0.007,
|
| 4727 |
+
0.05,
|
| 4728 |
+
0.05,
|
| 4729 |
+
0.014,
|
| 4730 |
+
0.002
|
| 4731 |
],
|
| 4732 |
"prev": [
|
| 4733 |
0.002,
|
|
|
|
| 4779 |
]
|
| 4780 |
},
|
| 4781 |
"p_target": 0.4498,
|
| 4782 |
+
"competitor": "i",
|
| 4783 |
"competitor_other": false,
|
| 4784 |
+
"p_competitor": 0.0393,
|
| 4785 |
+
"competitor_frames": 0,
|
| 4786 |
+
"gop": 0.0,
|
| 4787 |
"confidence": 1.0,
|
| 4788 |
+
"gop_factor": 1.0,
|
| 4789 |
"confidence_factor": 1.0,
|
| 4790 |
"deleted": false,
|
| 4791 |
"stages": [
|
| 4792 |
{
|
| 4793 |
"stage": "gop",
|
| 4794 |
+
"score": 100.0
|
| 4795 |
},
|
| 4796 |
{
|
| 4797 |
"stage": "exemption",
|
| 4798 |
+
"score": 100.0,
|
| 4799 |
+
"applied": "unmarked_short_vowel"
|
| 4800 |
},
|
| 4801 |
{
|
| 4802 |
"stage": "insertion",
|
| 4803 |
+
"score": 100.0,
|
| 4804 |
"applied": null
|
| 4805 |
},
|
| 4806 |
{
|
| 4807 |
"stage": "baseline",
|
| 4808 |
+
"score": 100.0,
|
| 4809 |
"ref": 100.0,
|
| 4810 |
+
"refs": [
|
| 4811 |
+
100.0,
|
| 4812 |
+
100.0
|
| 4813 |
+
],
|
| 4814 |
"applied": false
|
| 4815 |
},
|
| 4816 |
{
|
| 4817 |
"stage": "calibration",
|
| 4818 |
+
"score": 100.0,
|
| 4819 |
"floor": null,
|
| 4820 |
"applied": false
|
| 4821 |
}
|
| 4822 |
],
|
| 4823 |
+
"final": 100.0,
|
| 4824 |
"margin": {
|
| 4825 |
"needed": 0.0,
|
| 4826 |
+
"got": -0.0,
|
| 4827 |
"beyond": true
|
| 4828 |
},
|
| 4829 |
"vowel": true,
|
|
|
|
| 4831 |
"flagged": false,
|
| 4832 |
"rule": null,
|
| 4833 |
"tip": false,
|
| 4834 |
+
"issue": false
|
| 4835 |
},
|
| 4836 |
{
|
| 4837 |
"i": 7,
|
|
|
|
| 4849 |
],
|
| 4850 |
"window": [
|
| 4851 |
38,
|
| 4852 |
+
47
|
| 4853 |
],
|
| 4854 |
"curves": {
|
| 4855 |
"start": 34,
|
|
|
|
| 4870 |
0.002,
|
| 4871 |
0.002,
|
| 4872 |
0.002,
|
| 4873 |
+
0.007
|
|
|
|
|
|
|
|
|
|
| 4874 |
],
|
| 4875 |
"competitor": [
|
| 4876 |
0.007,
|
|
|
|
| 4889 |
0.001,
|
| 4890 |
0.001,
|
| 4891 |
0.001,
|
| 4892 |
+
0.004
|
|
|
|
|
|
|
|
|
|
| 4893 |
],
|
| 4894 |
"prev": [
|
| 4895 |
0.007,
|
|
|
|
| 4908 |
0.001,
|
| 4909 |
0.001,
|
| 4910 |
0.001,
|
| 4911 |
+
0.004
|
|
|
|
|
|
|
|
|
|
| 4912 |
],
|
| 4913 |
"next": [
|
| 4914 |
0.007,
|
|
|
|
| 4927 |
0.001,
|
| 4928 |
0.001,
|
| 4929 |
0.001,
|
| 4930 |
+
0.9
|
|
|
|
|
|
|
|
|
|
| 4931 |
],
|
| 4932 |
"blank": [
|
| 4933 |
0.007,
|
|
|
|
| 4946 |
0.97,
|
| 4947 |
0.97,
|
| 4948 |
0.97,
|
| 4949 |
+
0.004
|
|
|
|
|
|
|
|
|
|
| 4950 |
]
|
| 4951 |
},
|
| 4952 |
"p_target": 0.325,
|
| 4953 |
"competitor": "h",
|
| 4954 |
"competitor_other": false,
|
| 4955 |
"p_competitor": 0.9598,
|
| 4956 |
+
"competitor_frames": 1,
|
| 4957 |
"gop": -1.083,
|
| 4958 |
"confidence": 1.0,
|
| 4959 |
+
"gop_factor": 0.685,
|
| 4960 |
"confidence_factor": 1.0,
|
| 4961 |
"deleted": false,
|
| 4962 |
"stages": [
|
| 4963 |
{
|
| 4964 |
"stage": "gop",
|
| 4965 |
+
"score": 68.4
|
| 4966 |
},
|
| 4967 |
{
|
| 4968 |
"stage": "exemption",
|
| 4969 |
+
"score": 68.4,
|
| 4970 |
"applied": null
|
| 4971 |
},
|
| 4972 |
{
|
| 4973 |
"stage": "insertion",
|
| 4974 |
+
"score": 68.4,
|
| 4975 |
"applied": null
|
| 4976 |
},
|
| 4977 |
{
|
| 4978 |
"stage": "baseline",
|
| 4979 |
"score": 100.0,
|
| 4980 |
"ref": 55.0,
|
| 4981 |
+
"refs": [
|
| 4982 |
+
55.0,
|
| 4983 |
+
70.0
|
| 4984 |
+
],
|
| 4985 |
"applied": true
|
| 4986 |
},
|
| 4987 |
{
|
|
|
|
| 5016 |
53
|
| 5017 |
],
|
| 5018 |
"window": [
|
| 5019 |
+
46,
|
| 5020 |
55
|
| 5021 |
],
|
| 5022 |
"curves": {
|
| 5023 |
+
"start": 42,
|
| 5024 |
"target": [
|
|
|
|
|
|
|
|
|
|
| 5025 |
0.025,
|
| 5026 |
0.007,
|
| 5027 |
0.001,
|
|
|
|
| 5041 |
0.004
|
| 5042 |
],
|
| 5043 |
"competitor": [
|
|
|
|
|
|
|
|
|
|
| 5044 |
0.05,
|
| 5045 |
0.014,
|
| 5046 |
0.002,
|
|
|
|
| 5060 |
0.007
|
| 5061 |
],
|
| 5062 |
"prev": [
|
|
|
|
|
|
|
|
|
|
| 5063 |
0.325,
|
| 5064 |
0.014,
|
| 5065 |
0.002,
|
|
|
|
| 5079 |
0.007
|
| 5080 |
],
|
| 5081 |
"next": [
|
|
|
|
|
|
|
|
|
|
| 5082 |
0.05,
|
| 5083 |
0.014,
|
| 5084 |
0.002,
|
|
|
|
| 5098 |
0.904
|
| 5099 |
],
|
| 5100 |
"blank": [
|
|
|
|
|
|
|
|
|
|
| 5101 |
0.025,
|
| 5102 |
0.8,
|
| 5103 |
0.97,
|
|
|
|
| 5120 |
"p_target": 0.9003,
|
| 5121 |
"competitor": "e",
|
| 5122 |
"competitor_other": false,
|
| 5123 |
+
"p_competitor": 0.0071,
|
| 5124 |
+
"competitor_frames": 0,
|
| 5125 |
"gop": 0.0,
|
| 5126 |
"confidence": 1.0,
|
| 5127 |
"gop_factor": 1.0,
|
|
|
|
| 5146 |
"stage": "baseline",
|
| 5147 |
"score": 100.0,
|
| 5148 |
"ref": 100.0,
|
| 5149 |
+
"refs": [
|
| 5150 |
+
100.0,
|
| 5151 |
+
100.0
|
| 5152 |
+
],
|
| 5153 |
"applied": false
|
| 5154 |
},
|
| 5155 |
{
|
|
|
|
| 5284 |
"competitor": "e",
|
| 5285 |
"competitor_other": false,
|
| 5286 |
"p_competitor": 0.0071,
|
| 5287 |
+
"competitor_frames": 0,
|
| 5288 |
"gop": 0.0,
|
| 5289 |
"confidence": 1.0,
|
| 5290 |
"gop_factor": 1.0,
|
|
|
|
| 5309 |
"stage": "baseline",
|
| 5310 |
"score": 100.0,
|
| 5311 |
"ref": 100.0,
|
| 5312 |
+
"refs": [
|
| 5313 |
+
100.0,
|
| 5314 |
+
100.0
|
| 5315 |
+
],
|
| 5316 |
"applied": false
|
| 5317 |
},
|
| 5318 |
{
|
|
|
|
| 5437 |
"competitor": "e",
|
| 5438 |
"competitor_other": false,
|
| 5439 |
"p_competitor": 0.0107,
|
| 5440 |
+
"competitor_frames": 0,
|
| 5441 |
"gop": 0.0,
|
| 5442 |
"confidence": 1.0,
|
| 5443 |
"gop_factor": 1.0,
|
|
|
|
| 5462 |
"stage": "baseline",
|
| 5463 |
"score": 100.0,
|
| 5464 |
"ref": 100.0,
|
| 5465 |
+
"refs": [
|
| 5466 |
+
100.0,
|
| 5467 |
+
100.0
|
| 5468 |
+
],
|
| 5469 |
"applied": false
|
| 5470 |
},
|
| 5471 |
{
|
|
|
|
| 5610 |
"competitor": "e",
|
| 5611 |
"competitor_other": false,
|
| 5612 |
"p_competitor": 0.0143,
|
| 5613 |
+
"competitor_frames": 0,
|
| 5614 |
"gop": 0.0,
|
| 5615 |
"confidence": 1.0,
|
| 5616 |
"gop_factor": 1.0,
|
|
|
|
| 5635 |
"stage": "baseline",
|
| 5636 |
"score": 100.0,
|
| 5637 |
"ref": 100.0,
|
| 5638 |
+
"refs": [
|
| 5639 |
+
100.0,
|
| 5640 |
+
100.0
|
| 5641 |
+
],
|
| 5642 |
"applied": false
|
| 5643 |
},
|
| 5644 |
{
|
|
|
|
| 5677 |
75
|
| 5678 |
],
|
| 5679 |
"window": [
|
| 5680 |
+
69,
|
| 5681 |
77
|
| 5682 |
],
|
| 5683 |
"curves": {
|
| 5684 |
+
"start": 65,
|
| 5685 |
"target": [
|
|
|
|
|
|
|
| 5686 |
0.021,
|
| 5687 |
0.021,
|
| 5688 |
0.003,
|
|
|
|
| 5701 |
0.005
|
| 5702 |
],
|
| 5703 |
"competitor": [
|
|
|
|
|
|
|
| 5704 |
0.014,
|
| 5705 |
0.014,
|
| 5706 |
0.002,
|
|
|
|
| 5719 |
0.004
|
| 5720 |
],
|
| 5721 |
"prev": [
|
|
|
|
|
|
|
| 5722 |
0.807,
|
| 5723 |
0.807,
|
| 5724 |
0.002,
|
|
|
|
| 5737 |
0.004
|
| 5738 |
],
|
| 5739 |
"next": [
|
|
|
|
|
|
|
| 5740 |
0.007,
|
| 5741 |
0.007,
|
| 5742 |
0.001,
|
|
|
|
| 5755 |
0.002
|
| 5756 |
],
|
| 5757 |
"blank": [
|
|
|
|
|
|
|
| 5758 |
0.007,
|
| 5759 |
0.007,
|
| 5760 |
0.97,
|
|
|
|
| 5777 |
"competitor": "e",
|
| 5778 |
"competitor_other": false,
|
| 5779 |
"p_competitor": 0.0129,
|
| 5780 |
+
"competitor_frames": 0,
|
| 5781 |
"gop": 0.0,
|
| 5782 |
"confidence": 1.0,
|
| 5783 |
"gop_factor": 1.0,
|
|
|
|
| 5802 |
"stage": "baseline",
|
| 5803 |
"score": 100.0,
|
| 5804 |
"ref": 100.0,
|
| 5805 |
+
"refs": [
|
| 5806 |
+
100.0,
|
| 5807 |
+
100.0
|
| 5808 |
+
],
|
| 5809 |
"applied": false
|
| 5810 |
},
|
| 5811 |
{
|
|
|
|
| 5930 |
"competitor": "i",
|
| 5931 |
"competitor_other": false,
|
| 5932 |
"p_competitor": 0.0107,
|
| 5933 |
+
"competitor_frames": 0,
|
| 5934 |
"gop": 0.0,
|
| 5935 |
"confidence": 1.0,
|
| 5936 |
"gop_factor": 1.0,
|
|
|
|
| 5944 |
{
|
| 5945 |
"stage": "exemption",
|
| 5946 |
"score": 100.0,
|
| 5947 |
+
"applied": "unmarked_short_vowel"
|
| 5948 |
},
|
| 5949 |
{
|
| 5950 |
"stage": "insertion",
|
|
|
|
| 5955 |
"stage": "baseline",
|
| 5956 |
"score": 100.0,
|
| 5957 |
"ref": 100.0,
|
| 5958 |
+
"refs": [
|
| 5959 |
+
100.0,
|
| 5960 |
+
100.0
|
| 5961 |
+
],
|
| 5962 |
"applied": false
|
| 5963 |
},
|
| 5964 |
{
|
|
|
|
| 6083 |
"competitor": "ʔ",
|
| 6084 |
"competitor_other": false,
|
| 6085 |
"p_competitor": 0.8001,
|
| 6086 |
+
"competitor_frames": 2,
|
| 6087 |
"gop": -4.718,
|
| 6088 |
"confidence": 0.024,
|
| 6089 |
+
"gop_factor": 0.192,
|
| 6090 |
"confidence_factor": 0.154,
|
| 6091 |
"deleted": false,
|
| 6092 |
"stages": [
|
| 6093 |
{
|
| 6094 |
"stage": "gop",
|
| 6095 |
+
"score": 3.0
|
| 6096 |
},
|
| 6097 |
{
|
| 6098 |
"stage": "exemption",
|
| 6099 |
+
"score": 3.0,
|
| 6100 |
"applied": null
|
| 6101 |
},
|
| 6102 |
{
|
| 6103 |
"stage": "insertion",
|
| 6104 |
+
"score": 3.0,
|
| 6105 |
"applied": null
|
| 6106 |
},
|
| 6107 |
{
|
| 6108 |
"stage": "baseline",
|
| 6109 |
+
"score": 3.8,
|
| 6110 |
+
"ref": 80.0,
|
| 6111 |
+
"refs": [
|
| 6112 |
+
100.0,
|
| 6113 |
+
80.0
|
| 6114 |
+
],
|
| 6115 |
+
"applied": true
|
| 6116 |
},
|
| 6117 |
{
|
| 6118 |
"stage": "calibration",
|
|
|
|
| 6245 |
"competitor": "ʔ",
|
| 6246 |
"competitor_other": false,
|
| 6247 |
"p_competitor": 0.8001,
|
| 6248 |
+
"competitor_frames": 1,
|
| 6249 |
"gop": 0.0,
|
| 6250 |
"confidence": 1.0,
|
| 6251 |
"gop_factor": 1.0,
|
|
|
|
| 6259 |
{
|
| 6260 |
"stage": "exemption",
|
| 6261 |
"score": 100.0,
|
| 6262 |
+
"applied": "unmarked_short_vowel"
|
| 6263 |
},
|
| 6264 |
{
|
| 6265 |
"stage": "insertion",
|
|
|
|
| 6270 |
"stage": "baseline",
|
| 6271 |
"score": 100.0,
|
| 6272 |
"ref": 100.0,
|
| 6273 |
+
"refs": [
|
| 6274 |
+
100.0,
|
| 6275 |
+
100.0
|
| 6276 |
+
],
|
| 6277 |
"applied": false
|
| 6278 |
},
|
| 6279 |
{
|
|
|
|
| 6309 |
],
|
| 6310 |
"window": [
|
| 6311 |
87,
|
| 6312 |
+
95
|
| 6313 |
],
|
| 6314 |
"curves": {
|
| 6315 |
"start": 83,
|
|
|
|
| 6329 |
0.001,
|
| 6330 |
0.001,
|
| 6331 |
0.005,
|
| 6332 |
+
0.005
|
|
|
|
|
|
|
| 6333 |
],
|
| 6334 |
"competitor": [
|
| 6335 |
0.004,
|
|
|
|
| 6347 |
0.002,
|
| 6348 |
0.002,
|
| 6349 |
0.011,
|
| 6350 |
+
0.011
|
|
|
|
|
|
|
| 6351 |
],
|
| 6352 |
"prev": [
|
| 6353 |
0.002,
|
|
|
|
| 6365 |
0.001,
|
| 6366 |
0.001,
|
| 6367 |
0.005,
|
| 6368 |
+
0.005
|
|
|
|
|
|
|
| 6369 |
],
|
| 6370 |
"next": [
|
| 6371 |
0.002,
|
|
|
|
| 6383 |
0.001,
|
| 6384 |
0.001,
|
| 6385 |
0.85,
|
| 6386 |
+
0.85
|
|
|
|
|
|
|
| 6387 |
],
|
| 6388 |
"blank": [
|
| 6389 |
0.95,
|
|
|
|
| 6401 |
0.97,
|
| 6402 |
0.97,
|
| 6403 |
0.005,
|
| 6404 |
+
0.005
|
|
|
|
|
|
|
| 6405 |
]
|
| 6406 |
},
|
| 6407 |
"p_target": 0.8496,
|
| 6408 |
"competitor": "i",
|
| 6409 |
"competitor_other": false,
|
| 6410 |
"p_competitor": 0.0107,
|
| 6411 |
+
"competitor_frames": 0,
|
| 6412 |
"gop": 0.0,
|
| 6413 |
"confidence": 1.0,
|
| 6414 |
"gop_factor": 1.0,
|
|
|
|
| 6433 |
"stage": "baseline",
|
| 6434 |
"score": 100.0,
|
| 6435 |
"ref": 100.0,
|
| 6436 |
+
"refs": [
|
| 6437 |
+
100.0,
|
| 6438 |
+
100.0
|
| 6439 |
+
],
|
| 6440 |
"applied": false
|
| 6441 |
},
|
| 6442 |
{
|
|
|
|
| 6471 |
100
|
| 6472 |
],
|
| 6473 |
"window": [
|
| 6474 |
+
93,
|
| 6475 |
102
|
| 6476 |
],
|
| 6477 |
"curves": {
|
| 6478 |
+
"start": 89,
|
| 6479 |
"target": [
|
|
|
|
|
|
|
| 6480 |
0.005,
|
| 6481 |
0.005,
|
| 6482 |
0.001,
|
|
|
|
| 6496 |
0.001
|
| 6497 |
],
|
| 6498 |
"competitor": [
|
|
|
|
|
|
|
| 6499 |
0.011,
|
| 6500 |
0.011,
|
| 6501 |
0.002,
|
|
|
|
| 6515 |
0.002
|
| 6516 |
],
|
| 6517 |
"prev": [
|
|
|
|
|
|
|
| 6518 |
0.85,
|
| 6519 |
0.85,
|
| 6520 |
0.001,
|
|
|
|
| 6534 |
0.001
|
| 6535 |
],
|
| 6536 |
"next": [
|
|
|
|
|
|
|
| 6537 |
0.011,
|
| 6538 |
0.011,
|
| 6539 |
0.002,
|
|
|
|
| 6553 |
0.002
|
| 6554 |
],
|
| 6555 |
"blank": [
|
|
|
|
|
|
|
| 6556 |
0.005,
|
| 6557 |
0.005,
|
| 6558 |
0.97,
|
|
|
|
| 6576 |
"competitor": "e",
|
| 6577 |
"competitor_other": false,
|
| 6578 |
"p_competitor": 0.0107,
|
| 6579 |
+
"competitor_frames": 0,
|
| 6580 |
"gop": 0.0,
|
| 6581 |
"confidence": 1.0,
|
| 6582 |
"gop_factor": 1.0,
|
|
|
|
| 6601 |
"stage": "baseline",
|
| 6602 |
"score": 100.0,
|
| 6603 |
"ref": 100.0,
|
| 6604 |
+
"refs": [
|
| 6605 |
+
100.0,
|
| 6606 |
+
100.0
|
| 6607 |
+
],
|
| 6608 |
"applied": false
|
| 6609 |
},
|
| 6610 |
{
|
|
|
|
| 6749 |
"competitor": "e",
|
| 6750 |
"competitor_other": false,
|
| 6751 |
"p_competitor": 0.0107,
|
| 6752 |
+
"competitor_frames": 0,
|
| 6753 |
"gop": 0.0,
|
| 6754 |
"confidence": 1.0,
|
| 6755 |
"gop_factor": 1.0,
|
|
|
|
| 6774 |
"stage": "baseline",
|
| 6775 |
"score": 100.0,
|
| 6776 |
"ref": 100.0,
|
| 6777 |
+
"refs": [
|
| 6778 |
+
100.0,
|
| 6779 |
+
100.0
|
| 6780 |
+
],
|
| 6781 |
"applied": false
|
| 6782 |
},
|
| 6783 |
{
|
|
|
|
| 6812 |
112
|
| 6813 |
],
|
| 6814 |
"window": [
|
| 6815 |
+
106,
|
| 6816 |
114
|
| 6817 |
],
|
| 6818 |
"curves": {
|
| 6819 |
+
"start": 102,
|
| 6820 |
"target": [
|
|
|
|
|
|
|
| 6821 |
0.005,
|
| 6822 |
0.005,
|
| 6823 |
0.001,
|
|
|
|
| 6836 |
0.004
|
| 6837 |
],
|
| 6838 |
"competitor": [
|
|
|
|
|
|
|
| 6839 |
0.005,
|
| 6840 |
0.005,
|
| 6841 |
0.001,
|
|
|
|
| 6854 |
0.004
|
| 6855 |
],
|
| 6856 |
"prev": [
|
|
|
|
|
|
|
| 6857 |
0.855,
|
| 6858 |
0.855,
|
| 6859 |
0.002,
|
|
|
|
| 6872 |
0.007
|
| 6873 |
],
|
| 6874 |
"next": [
|
|
|
|
|
|
|
| 6875 |
0.011,
|
| 6876 |
0.011,
|
| 6877 |
0.002,
|
|
|
|
| 6890 |
0.904
|
| 6891 |
],
|
| 6892 |
"blank": [
|
|
|
|
|
|
|
| 6893 |
0.005,
|
| 6894 |
0.005,
|
| 6895 |
0.97,
|
|
|
|
| 6912 |
"competitor": "w",
|
| 6913 |
"competitor_other": false,
|
| 6914 |
"p_competitor": 0.0054,
|
| 6915 |
+
"competitor_frames": 0,
|
| 6916 |
"gop": 0.0,
|
| 6917 |
"confidence": 1.0,
|
| 6918 |
"gop_factor": 1.0,
|
|
|
|
| 6937 |
"stage": "baseline",
|
| 6938 |
"score": 100.0,
|
| 6939 |
"ref": 100.0,
|
| 6940 |
+
"refs": [
|
| 6941 |
+
100.0,
|
| 6942 |
+
100.0
|
| 6943 |
+
],
|
| 6944 |
"applied": false
|
| 6945 |
},
|
| 6946 |
{
|
|
|
|
| 7075 |
"competitor": "i",
|
| 7076 |
"competitor_other": false,
|
| 7077 |
"p_competitor": 0.0071,
|
| 7078 |
+
"competitor_frames": 0,
|
| 7079 |
"gop": 0.0,
|
| 7080 |
"confidence": 1.0,
|
| 7081 |
"gop_factor": 1.0,
|
|
|
|
| 7100 |
"stage": "baseline",
|
| 7101 |
"score": 100.0,
|
| 7102 |
"ref": 100.0,
|
| 7103 |
+
"refs": [
|
| 7104 |
+
100.0,
|
| 7105 |
+
100.0
|
| 7106 |
+
],
|
| 7107 |
"applied": false
|
| 7108 |
},
|
| 7109 |
{
|
|
|
|
| 7232 |
"competitor": "i",
|
| 7233 |
"competitor_other": false,
|
| 7234 |
"p_competitor": 0.0107,
|
| 7235 |
+
"competitor_frames": 0,
|
| 7236 |
"gop": 0.0,
|
| 7237 |
"confidence": 1.0,
|
| 7238 |
"gop_factor": 1.0,
|
|
|
|
| 7257 |
"stage": "baseline",
|
| 7258 |
"score": 100.0,
|
| 7259 |
"ref": 100.0,
|
| 7260 |
+
"refs": [
|
| 7261 |
+
100.0,
|
| 7262 |
+
100.0
|
| 7263 |
+
],
|
| 7264 |
"applied": false
|
| 7265 |
},
|
| 7266 |
{
|
|
|
|
| 7366 |
"competitor": "i",
|
| 7367 |
"competitor_other": false,
|
| 7368 |
"p_competitor": 0.0107,
|
| 7369 |
+
"competitor_frames": 0,
|
| 7370 |
"gop": 0.0,
|
| 7371 |
"confidence": 1.0,
|
| 7372 |
"gop_factor": 1.0,
|
|
|
|
| 7380 |
{
|
| 7381 |
"stage": "exemption",
|
| 7382 |
"score": 100.0,
|
| 7383 |
+
"applied": "unmarked_short_vowel"
|
| 7384 |
},
|
| 7385 |
{
|
| 7386 |
"stage": "insertion",
|
|
|
|
| 7391 |
"stage": "baseline",
|
| 7392 |
"score": 100.0,
|
| 7393 |
"ref": 100.0,
|
| 7394 |
+
"refs": [
|
| 7395 |
+
100.0,
|
| 7396 |
+
100.0
|
| 7397 |
+
],
|
| 7398 |
"applied": false
|
| 7399 |
},
|
| 7400 |
{
|
|
|
|
| 7436 |
100.0,
|
| 7437 |
100.0,
|
| 7438 |
100.0,
|
| 7439 |
+
100.0,
|
| 7440 |
100.0
|
| 7441 |
],
|
| 7442 |
+
"min": 100.0,
|
| 7443 |
+
"mean": 100.0,
|
| 7444 |
+
"score": 100.0
|
| 7445 |
},
|
| 7446 |
{
|
| 7447 |
"tr": "סִידִי",
|
|
|
|
| 7466 |
],
|
| 7467 |
"min": 45.0,
|
| 7468 |
"mean": 89.0,
|
| 7469 |
+
"score": 73.6
|
| 7470 |
},
|
| 7471 |
{
|
| 7472 |
"tr": "פִי",
|
|
|
|
| 7492 |
}
|
| 7493 |
],
|
| 7494 |
"sentence": {
|
| 7495 |
+
"phone_mean": 96.9,
|
| 7496 |
+
"word_mean": 95.6,
|
| 7497 |
"phone_weight": 0.5,
|
| 7498 |
"word_weight": 0.5,
|
| 7499 |
+
"before_cap": 96.3,
|
| 7500 |
+
"final": 96,
|
| 7501 |
"capped": false
|
| 7502 |
},
|
| 7503 |
"tips": [
|
|
@@ -4990,7 +4990,7 @@ function drawTtsActivity(card){
|
|
| 4990 |
const details=document.createElement("details"), summary=mark("","מה קורה עכשיו","summary"), pace=mark("msg","","div"), stats=mark("msg","","div"), active=mark("","","div"), wrap=mark("","","div"), table=document.createElement("table");
|
| 4991 |
wrap.style.cssText="overflow-x:auto;max-height:340px;overflow-y:auto"; table.style.cssText="width:100%;border-collapse:collapse;font-size:.85em";
|
| 4992 |
details.style.marginTop="12px"; summary.style.cssText="cursor:pointer;font-weight:600"; wrap.append(table); details.append(summary,pace,stats,active,wrap);
|
| 4993 |
-
const SOURCE={sweep:"הכנה",playback:"השמעה",import:"טעינה"}, secs=ms=>ms==null?"–":ms<1000?`${ms} ms`:`${(ms/1000).toFixed(1)} שנ׳`;
|
| 4994 |
const result=e=>e.status===200||e.status==="ok"?"✓":e.status===429?"429 · הגבלת קצב":typeof e.status==="number"&&e.status>=500?`${e.status} · תקלה אצל Sawtak`:typeof e.status==="number"?`${e.status} · נדחה`:"שגיאה";
|
| 4995 |
const what=e=>e.kind==="upload"?(e.files>1?`${e.files} קבצים · ${(e.bytes/1048576).toFixed(1)} MB`:(e.text||"קובץ אחד")):(e.text||"");
|
| 4996 |
const cell=(tr,text,head)=>{ const c=document.createElement(head?"th":"td"); c.textContent=text; c.dir="auto"; c.style.cssText="padding:4px 6px;border-bottom:1px solid #8884;text-align:start;white-space:nowrap"; tr.append(c); return c; };
|
|
|
|
| 4990 |
const details=document.createElement("details"), summary=mark("","מה קורה עכשיו","summary"), pace=mark("msg","","div"), stats=mark("msg","","div"), active=mark("","","div"), wrap=mark("","","div"), table=document.createElement("table");
|
| 4991 |
wrap.style.cssText="overflow-x:auto;max-height:340px;overflow-y:auto"; table.style.cssText="width:100%;border-collapse:collapse;font-size:.85em";
|
| 4992 |
details.style.marginTop="12px"; summary.style.cssText="cursor:pointer;font-weight:600"; wrap.append(table); details.append(summary,pace,stats,active,wrap);
|
| 4993 |
+
const SOURCE={sweep:"הכנה",playback:"השמעה",baseline:"קו בסיס",import:"טעינה"}, secs=ms=>ms==null?"–":ms<1000?`${ms} ms`:`${(ms/1000).toFixed(1)} שנ׳`;
|
| 4994 |
const result=e=>e.status===200||e.status==="ok"?"✓":e.status===429?"429 · הגבלת קצב":typeof e.status==="number"&&e.status>=500?`${e.status} · תקלה אצל Sawtak`:typeof e.status==="number"?`${e.status} · נדחה`:"שגיאה";
|
| 4995 |
const what=e=>e.kind==="upload"?(e.files>1?`${e.files} קבצים · ${(e.bytes/1048576).toFixed(1)} MB`:(e.text||"קובץ אחד")):(e.text||"");
|
| 4996 |
const cell=(tr,text,head)=>{ const c=document.createElement(head?"th":"td"); c.textContent=text; c.dir="auto"; c.style.cssText="padding:4px 6px;border-bottom:1px solid #8884;text-align:start;white-space:nowrap"; tr.append(c); return c; };
|
|
@@ -14,7 +14,8 @@
|
|
| 14 |
(the end of the sound before to the start of the one after, where a substitution peaks)
|
| 15 |
2. its score stage by stage (GOP → exemption → cluster cap → native baseline → teacher floor)
|
| 16 |
3. the readings the audio was aligned to, and the different-sentence gauge
|
| 17 |
-
4. the sentence by word and sound, and how sounds add up to words and words to the sentence
|
|
|
|
| 18 |
-->
|
| 19 |
<style>
|
| 20 |
:root{
|
|
@@ -110,6 +111,19 @@ svg .strong{fill:var(--ink);font-weight:700}
|
|
| 110 |
.ph.good{box-shadow:inset 0 -3px 0 var(--good)} .ph.warn{box-shadow:inset 0 -3px 0 var(--warn)} .ph.crit{box-shadow:inset 0 -3px 0 var(--crit)}
|
| 111 |
.ph.flag::after{content:"!";color:var(--crit-ink);margin-inline-start:2px}
|
| 112 |
.ph.sel{outline:2px solid var(--s1);outline-offset:1px}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
.tree{display:flex;flex-direction:column;gap:8px}
|
| 114 |
.tree .node{background:var(--raise);border-radius:10px;padding:6px 10px;font-size:13px}
|
| 115 |
.tree .node b{font-size:15px}
|
|
@@ -159,6 +173,7 @@ details summary{cursor:pointer;color:var(--ink-2);font-size:12px}
|
|
| 159 |
|
| 160 |
<section class="panel" id="p4" aria-labelledby="p4h">
|
| 161 |
<div class="head"><h2 id="p4h">המשפט, מילה אחר מילה</h2><span class="sub" id="wordHint">▶ לחצו על מילה כדי לשמוע אותה · מעבר עם העכבר על הגה מציג אותו בכל הלוחות; לחיצה מקבעת</span></div>
|
|
|
|
| 162 |
<div class="sentence" id="sentence"></div>
|
| 163 |
<div class="legend"><span><span class="dot good"></span>75 ומעלה</span><span><span class="dot warn"></span>50–74</span><span><span class="dot crit"></span>מתחת ל־50</span><span>! סומן כטעות</span></div>
|
| 164 |
<details><summary>עץ הצבירה: הגאים ← מילים ← משפט</summary><div class="tree" id="tree"></div></details>
|
|
@@ -230,6 +245,39 @@ const PHONE_HEBREW={
|
|
| 230 |
};
|
| 231 |
const phoneHebrew=p=>PHONE_HEBREW[p]||p;
|
| 232 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
let R=null, T=null, PH=[], sel=0, pinned=false, traceSource="";
|
| 234 |
let wordAudio=null, wordAudioEnd=0, wordAudioNode=null;
|
| 235 |
let frameAudio=null, frameRaf=0, frameAudioTimer=0, frameCursor=null, frameX=null, frameCurve=null;
|
|
@@ -287,7 +335,7 @@ function step(d){ if(!T) return; sel=(sel+d+T.tokens.length)%T.tokens.length; pi
|
|
| 287 |
/* ---------- selection: one sound everywhere ---------- */
|
| 288 |
function hover(i){ if(pinned||i===sel) return; sel=i; drawSelected(); }
|
| 289 |
function pick(i){ pinned=!(pinned&&sel===i); sel=i; drawSelected(); }
|
| 290 |
-
function drawAll(){ drawSentence(); drawTree(); drawPaths(); drawGauge(); drawTable(); drawSelected(); }
|
| 291 |
function drawSelected(){
|
| 292 |
$("pos").textContent=`${sel+1}/${T.tokens.length}`+(pinned?" 📌":"");
|
| 293 |
for(const b of document.querySelectorAll(".ph")) b.classList.toggle("sel",+b.dataset.i===sel);
|
|
@@ -310,6 +358,8 @@ function soundTip(i){
|
|
| 310 |
out.push(trow("צפוי",el("span",{class:"ipa",text:`${t.ipa} (${pct(t.p_target)})`})));
|
| 311 |
out.push(trow("המתחרה החזק",el("span",{class:"ipa",text:heard})));
|
| 312 |
out.push(trow("ציון",`${fmt(t.final)} · ${BAND_NAME[band(t.final)]}`+(t.flagged?" · סומן כטעות":"")));
|
|
|
|
|
|
|
| 313 |
out.push(trow("מרווח (נדרש / בפועל)",el("span",{class:"ltr",text:`${fmt(t.margin.needed,2)} / ${fmt(t.margin.got,2)}`+(t.margin.beyond?" ✓ עבר":" ✗ לא עבר")})));
|
| 314 |
out.push(trow("חלון",el("span",{class:"ltr",text:`${t.window[0]}–${t.window[1]}`})));
|
| 315 |
if(t.rule) out.push(trow("כלל",`${t.rule.title} · חומרה ${t.rule.severity}`));
|
|
@@ -331,13 +381,24 @@ function drawSentence(){
|
|
| 331 |
word.onkeydown=e=>{ if(e.key==="Enter"||e.key===" "){ e.preventDefault(); playWord(wi,word); } };
|
| 332 |
}
|
| 333 |
word.append(el("span",{class:"tr",text:w.tr}),el("span",{class:"ar",text:w.ar}),el("span",{class:"ws",text:`${fmt(w.score,0)} · ${BAND_NAME[b]}`}));
|
| 334 |
-
const phones=el("div",{class:"phones"});
|
|
|
|
|
|
|
|
|
|
| 335 |
T.tokens.forEach(t=>{ if(t.word!==wi) return;
|
| 336 |
const c=el("button",{class:`ph ${band(t.final)}${t.flagged?" flag":""}`,"data-i":t.i,
|
| 337 |
"aria-label":`${phoneHebrew(t.ipa)}, IPA ${t.ipa}, ציון ${fmt(t.final,0)}`,title:`IPA: ${t.ipa}`,text:phoneHebrew(t.ipa)});
|
| 338 |
c.onmouseenter=e=>{ hover(t.i); tipShow(e,soundTip(t.i)); }; c.onmousemove=tipMove; c.onmouseleave=tipHide;
|
| 339 |
c.onfocus=()=>hover(t.i); c.onclick=e=>{ e.stopPropagation(); pick(t.i); };
|
| 340 |
-
phones.append(c);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 341 |
word.append(phones);
|
| 342 |
if(traceContext.sample!=null){
|
| 343 |
const toggle=el("button",{class:"word-exclude",text:excluded?"החזרה לציון":"לא תקינה · החרגה"});
|
|
@@ -554,7 +615,10 @@ function drawWaterfall(){
|
|
| 554 |
let note="";
|
| 555 |
if(s.stage==="exemption"&&s.applied) note=EXEMPT_NAME[s.applied]||s.applied;
|
| 556 |
if(s.stage==="insertion"&&s.applied) note=`תנועה ${s.applied} בצרור`;
|
| 557 |
-
if(s.stage==="baseline")
|
|
|
|
|
|
|
|
|
|
| 558 |
if(s.stage==="calibration") note=s.floor==null?"אין רצפה":`רצפה ${fmt(s.floor,0)}`;
|
| 559 |
steps.push({name:s.stage,from:cur,to:s.score,note}); cur=s.score;
|
| 560 |
}
|
|
@@ -575,13 +639,19 @@ function drawWaterfall(){
|
|
| 575 |
if(k&&!total) svg.append(sv("line",{x1:x(s.from),x2:x(s.from),y1:y-rowH+7,y2:y+7,stroke:"var(--axis)"}));
|
| 576 |
const d=s.to-s.from, label=total?fmt(s.to):d?`${d>0?"+":""}${fmt(d)} → ${fmt(s.to)}`:"±0";
|
| 577 |
svg.append(sv("text",{x:Math.min(W-2,x(hi)+5),y:y+rowH/2+4,class:total?"strong":"lbl"},label));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 578 |
const hit=sv("rect",{x:0,y,width:W,height:rowH,fill:"transparent"});
|
| 579 |
hit.onmouseenter=ev=>tipShow(ev,[el("div",{class:"t",text:STAGE_NAME[s.name]}),trow("לפני",fmt(s.from)),trow("אחרי",fmt(s.to)),s.note?el("div",{class:"tiptext ltr",text:s.note}):null].filter(Boolean));
|
| 580 |
hit.onmousemove=tipMove; hit.onmouseleave=tipHide; svg.append(hit);
|
| 581 |
});
|
| 582 |
box.replaceChildren(svg);
|
| 583 |
$("p2sub").replaceChildren(el("span",{class:"ipa",text:t.ipa})," · ",el("span",{class:"dot "+band(t.final)}),`${fmt(t.final,0)} · ${BAND_NAME[band(t.final)]}`);
|
| 584 |
-
|
|
|
|
| 585 |
t.rule?fact("כלל",`${t.rule.title} (${t.rule.severity})`):null, fact("טיפ",t.tip?"כן":"לא")].filter(Boolean));
|
| 586 |
}
|
| 587 |
|
|
@@ -631,11 +701,12 @@ function drawGauge(){
|
|
| 631 |
/* ---------- the table: every number ---------- */
|
| 632 |
function drawTable(){
|
| 633 |
const tb=$("table"); tb.replaceChildren();
|
| 634 |
-
const
|
|
|
|
| 635 |
tb.append(el("tr",{},...head.map(h=>el("th",{text:h}))));
|
| 636 |
for(const t of T.tokens){
|
| 637 |
const st=Object.fromEntries(t.stages.map(s=>[s.stage,s.score]));
|
| 638 |
-
const cells=[t.i,t.ipa,t.word,t.span.join("–"),t.window.join("–"),pct(t.p_target),t.competitor||"—",pct(t.p_competitor),fmt(t.gop,3),fmt(st.gop),fmt(st.exemption),fmt(st.insertion),fmt(st.baseline),fmt(st.calibration),fmt(t.final),t.flagged?"כן":""];
|
| 639 |
const tr=el("tr",{},...cells.map((v,k)=>el("td",{class:[1,3,4,6].includes(k)?"ipa":"",text:String(v)})));
|
| 640 |
tr.onmouseenter=()=>hover(t.i); tr.onclick=()=>pick(t.i); tb.append(tr);
|
| 641 |
}
|
|
|
|
| 14 |
(the end of the sound before to the start of the one after, where a substitution peaks)
|
| 15 |
2. its score stage by stage (GOP → exemption → cluster cap → native baseline → teacher floor)
|
| 16 |
3. the readings the audio was aligned to, and the different-sentence gauge
|
| 17 |
+
4. the sentence by word and sound, and how sounds add up to words and words to the sentence; under each sound,
|
| 18 |
+
one row per native baseline (TTS voice), the voice it was measured against (the lowest) in bold
|
| 19 |
-->
|
| 20 |
<style>
|
| 21 |
:root{
|
|
|
|
| 111 |
.ph.good{box-shadow:inset 0 -3px 0 var(--good)} .ph.warn{box-shadow:inset 0 -3px 0 var(--warn)} .ph.crit{box-shadow:inset 0 -3px 0 var(--crit)}
|
| 112 |
.ph.flag::after{content:"!";color:var(--crit-ink);margin-inline-start:2px}
|
| 113 |
.ph.sel{outline:2px solid var(--s1);outline-offset:1px}
|
| 114 |
+
/* the native baselines under each sound: one row per voice, the one the score was measured against in bold */
|
| 115 |
+
.phcol{display:flex;flex-direction:column;align-items:stretch;gap:2px}
|
| 116 |
+
.phcol.lab{justify-content:flex-end}
|
| 117 |
+
.phcol.lab .ph{visibility:hidden}
|
| 118 |
+
.reflab{font:10.5px var(--font);color:var(--muted);line-height:16px;white-space:nowrap;text-align:start}
|
| 119 |
+
.refcell{font:10.5px var(--font);font-variant-numeric:tabular-nums;line-height:16px;text-align:center;color:var(--ink-2);background:var(--raise);border-radius:4px;padding:0 2px;cursor:default}
|
| 120 |
+
.refcell.good{box-shadow:inset 0 -2px 0 var(--good)} .refcell.warn{box-shadow:inset 0 -2px 0 var(--warn)} .refcell.crit{box-shadow:inset 0 -2px 0 var(--crit)}
|
| 121 |
+
.refcell.used{color:var(--ink);font-weight:700;outline:1px solid var(--ink-2)}
|
| 122 |
+
.refcell.none{color:var(--muted);background:none}
|
| 123 |
+
.refbar{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;font-size:12px;color:var(--ink-2)}
|
| 124 |
+
.refbar .chip{background:var(--raise);border-radius:8px;padding:3px 8px}
|
| 125 |
+
.refbar .chip b{color:var(--ink)}
|
| 126 |
+
.refbar label{display:inline-flex;align-items:center;gap:5px;cursor:pointer}
|
| 127 |
.tree{display:flex;flex-direction:column;gap:8px}
|
| 128 |
.tree .node{background:var(--raise);border-radius:10px;padding:6px 10px;font-size:13px}
|
| 129 |
.tree .node b{font-size:15px}
|
|
|
|
| 173 |
|
| 174 |
<section class="panel" id="p4" aria-labelledby="p4h">
|
| 175 |
<div class="head"><h2 id="p4h">המשפט, מילה אחר מילה</h2><span class="sub" id="wordHint">▶ לחצו על מילה כדי לשמוע אותה · מעבר עם העכבר על הגה מציג אותו בכל הלוחות; לחיצה מקבעת</span></div>
|
| 176 |
+
<div class="refbar" id="refbar"></div>
|
| 177 |
<div class="sentence" id="sentence"></div>
|
| 178 |
<div class="legend"><span><span class="dot good"></span>75 ומעלה</span><span><span class="dot warn"></span>50–74</span><span><span class="dot crit"></span>מתחת ל־50</span><span>! סומן כטעות</span></div>
|
| 179 |
<details><summary>עץ הצבירה: הגאים ← מילים ← משפט</summary><div class="tree" id="tree"></div></details>
|
|
|
|
| 245 |
};
|
| 246 |
const phoneHebrew=p=>PHONE_HEBREW[p]||p;
|
| 247 |
|
| 248 |
+
/* ---------- native baselines: one or more TTS voices scored by the same model ---------- */
|
| 249 |
+
let showRefs=true; try{ showRefs=localStorage.getItem("ihki.trace.refs")!=="0"; }catch{}
|
| 250 |
+
const refList=()=>(T&&T.references)||[];
|
| 251 |
+
const refName=k=>(refList()[k]||{}).voice||`קול ${k+1}`;
|
| 252 |
+
const refTag=k=>{ const n=refName(k); return n.length<=5?n:n.slice(0,4)+"…"; };
|
| 253 |
+
/* each voice's score on sound t (null: that voice has no such sound); older traces carry only the lowest, as `ref` */
|
| 254 |
+
function refScores(t){
|
| 255 |
+
const b=t.stages.find(s=>s.stage==="baseline")||{};
|
| 256 |
+
if(Array.isArray(b.refs)) return b.refs;
|
| 257 |
+
return refList().length===1?[b.ref??null]:[];
|
| 258 |
+
}
|
| 259 |
+
/* the voice the sound was measured against: the lowest score, as Scorer._baseline takes it */
|
| 260 |
+
function refUsed(t){
|
| 261 |
+
const xs=refScores(t); let best=-1;
|
| 262 |
+
xs.forEach((x,k)=>{ if(x!=null&&(best<0||x<xs[best])) best=k; });
|
| 263 |
+
return best>=0&&xs[best]<100?best:-1; // at 100 the baseline changes nothing: no voice was measured against
|
| 264 |
+
}
|
| 265 |
+
function drawRefBar(){
|
| 266 |
+
const box=$("refbar"), n=refList().length; box.replaceChildren();
|
| 267 |
+
if(!n){ box.append(el("span",{text:"קו בסיס ילידי: אין. הציון לא נמדד מול קול יליד (אין מפתח TTS, הקול לא היה מוכן בזמן, או מבחן TTS שבו הבסיס כבוי)."})); return; }
|
| 268 |
+
box.append(el("span",{text:n===1?"קו בסיס ילידי:":`${n} קווי בסיס ילידיים (ההגה נמדד מול הנמוך שבהם):`}));
|
| 269 |
+
refList().forEach((r,k)=>box.append(el("span",{class:"chip"},el("b",{text:refName(k)}),` · ממוצע ${fmt(r.mean,0)} · ${r.sounds} הגאים`)));
|
| 270 |
+
const cb=el("input",{type:"checkbox"}); cb.checked=showRefs;
|
| 271 |
+
cb.onchange=()=>{ showRefs=cb.checked; try{ localStorage.setItem("ihki.trace.refs",showRefs?"1":"0"); }catch{} drawSentence(); drawSelected(); };
|
| 272 |
+
box.append(el("label",{},cb,"הצגה מתחת לכל הגה"));
|
| 273 |
+
}
|
| 274 |
+
function refTip(i){
|
| 275 |
+
const t=T.tokens[i], xs=refScores(t), used=refUsed(t);
|
| 276 |
+
return [el("div",{class:"t",text:`קו בסיס ילידי · ${t.ipa}`}),
|
| 277 |
+
...xs.map((x,k)=>trow(refName(k),x==null?"אין הגה כזה בקריאה שלו":`${fmt(x,0)}`+(k===used?" · נמדד מולו":""))),
|
| 278 |
+
trow("הלומד: לפני → אחרי",(()=>{ const st=Object.fromEntries(t.stages.map(s=>[s.stage,s.score])); return `${fmt(st.insertion)} → ${fmt(st.baseline)}`; })())];
|
| 279 |
+
}
|
| 280 |
+
|
| 281 |
let R=null, T=null, PH=[], sel=0, pinned=false, traceSource="";
|
| 282 |
let wordAudio=null, wordAudioEnd=0, wordAudioNode=null;
|
| 283 |
let frameAudio=null, frameRaf=0, frameAudioTimer=0, frameCursor=null, frameX=null, frameCurve=null;
|
|
|
|
| 335 |
/* ---------- selection: one sound everywhere ---------- */
|
| 336 |
function hover(i){ if(pinned||i===sel) return; sel=i; drawSelected(); }
|
| 337 |
function pick(i){ pinned=!(pinned&&sel===i); sel=i; drawSelected(); }
|
| 338 |
+
function drawAll(){ drawRefBar(); drawSentence(); drawTree(); drawPaths(); drawGauge(); drawTable(); drawSelected(); }
|
| 339 |
function drawSelected(){
|
| 340 |
$("pos").textContent=`${sel+1}/${T.tokens.length}`+(pinned?" 📌":"");
|
| 341 |
for(const b of document.querySelectorAll(".ph")) b.classList.toggle("sel",+b.dataset.i===sel);
|
|
|
|
| 358 |
out.push(trow("צפוי",el("span",{class:"ipa",text:`${t.ipa} (${pct(t.p_target)})`})));
|
| 359 |
out.push(trow("המתחרה החזק",el("span",{class:"ipa",text:heard})));
|
| 360 |
out.push(trow("ציון",`${fmt(t.final)} · ${BAND_NAME[band(t.final)]}`+(t.flagged?" · סומן כטעות":"")));
|
| 361 |
+
const rx=refScores(t), ru=refUsed(t);
|
| 362 |
+
if(rx.length) out.push(trow("קו בסיס",rx.map((x,k)=>`${refName(k)} ${x==null?"—":fmt(x,0)}${k===ru&&rx.length>1?"*":""}`).join(" · ")));
|
| 363 |
out.push(trow("מרווח (נדרש / בפועל)",el("span",{class:"ltr",text:`${fmt(t.margin.needed,2)} / ${fmt(t.margin.got,2)}`+(t.margin.beyond?" ✓ עבר":" ✗ לא עבר")})));
|
| 364 |
out.push(trow("חלון",el("span",{class:"ltr",text:`${t.window[0]}–${t.window[1]}`})));
|
| 365 |
if(t.rule) out.push(trow("כלל",`${t.rule.title} · חומרה ${t.rule.severity}`));
|
|
|
|
| 381 |
word.onkeydown=e=>{ if(e.key==="Enter"||e.key===" "){ e.preventDefault(); playWord(wi,word); } };
|
| 382 |
}
|
| 383 |
word.append(el("span",{class:"tr",text:w.tr}),el("span",{class:"ar",text:w.ar}),el("span",{class:"ws",text:`${fmt(w.score,0)} · ${BAND_NAME[b]}`}));
|
| 384 |
+
const phones=el("div",{class:"phones"}), nref=showRefs?refList().length:0;
|
| 385 |
+
if(nref){ const lab=el("div",{class:"phcol lab"},el("span",{class:"ph",text:"·"}));
|
| 386 |
+
for(let k=0;k<nref;k++) lab.append(el("span",{class:"reflab",title:refName(k),text:refTag(k)}));
|
| 387 |
+
phones.append(lab); }
|
| 388 |
T.tokens.forEach(t=>{ if(t.word!==wi) return;
|
| 389 |
const c=el("button",{class:`ph ${band(t.final)}${t.flagged?" flag":""}`,"data-i":t.i,
|
| 390 |
"aria-label":`${phoneHebrew(t.ipa)}, IPA ${t.ipa}, ציון ${fmt(t.final,0)}`,title:`IPA: ${t.ipa}`,text:phoneHebrew(t.ipa)});
|
| 391 |
c.onmouseenter=e=>{ hover(t.i); tipShow(e,soundTip(t.i)); }; c.onmousemove=tipMove; c.onmouseleave=tipHide;
|
| 392 |
c.onfocus=()=>hover(t.i); c.onclick=e=>{ e.stopPropagation(); pick(t.i); };
|
| 393 |
+
if(!nref){ phones.append(c); return; }
|
| 394 |
+
const col=el("div",{class:"phcol"},c), xs=refScores(t), used=refUsed(t);
|
| 395 |
+
for(let k=0;k<nref;k++){ const x=xs[k];
|
| 396 |
+
const cell=el("span",{class:`refcell ${x==null?"none":band(x)}${k===used?" used":""}`,text:x==null?"—":fmt(x,0),
|
| 397 |
+
"aria-label":`${refName(k)}: ${x==null?"אין":fmt(x,0)}`});
|
| 398 |
+
cell.onmouseenter=e=>{ hover(t.i); tipShow(e,refTip(t.i)); }; cell.onmousemove=tipMove; cell.onmouseleave=tipHide;
|
| 399 |
+
cell.onclick=e=>{ e.stopPropagation(); pick(t.i); };
|
| 400 |
+
col.append(cell); }
|
| 401 |
+
phones.append(col); });
|
| 402 |
word.append(phones);
|
| 403 |
if(traceContext.sample!=null){
|
| 404 |
const toggle=el("button",{class:"word-exclude",text:excluded?"החזרה לציון":"לא תקינה · החרגה"});
|
|
|
|
| 615 |
let note="";
|
| 616 |
if(s.stage==="exemption"&&s.applied) note=EXEMPT_NAME[s.applied]||s.applied;
|
| 617 |
if(s.stage==="insertion"&&s.applied) note=`תנועה ${s.applied} בצרור`;
|
| 618 |
+
if(s.stage==="baseline"){ const xs=refScores(t), u=refUsed(t);
|
| 619 |
+
note=s.ref==null?(refList().length?"לאף קול ילידי אין את ההגה הזה":"אין קול ילידי")
|
| 620 |
+
:xs.length>1?xs.map((x,k)=>`${refName(k)} ${x==null?"—":fmt(x,0)}`).join(" · ")+(u>=0?` → נמדד מול ${refName(u)} (${fmt(s.ref,0)}): 100·s/${fmt(s.ref,0)}`:" (100: לא משנה)")
|
| 621 |
+
:`${refName(0)}: ${fmt(s.ref,0)}`+(s.ref<100?` → 100·s/${fmt(s.ref,0)}`:" (100: לא משנה)"); }
|
| 622 |
if(s.stage==="calibration") note=s.floor==null?"אין רצפה":`רצפה ${fmt(s.floor,0)}`;
|
| 623 |
steps.push({name:s.stage,from:cur,to:s.score,note}); cur=s.score;
|
| 624 |
}
|
|
|
|
| 639 |
if(k&&!total) svg.append(sv("line",{x1:x(s.from),x2:x(s.from),y1:y-rowH+7,y2:y+7,stroke:"var(--axis)"}));
|
| 640 |
const d=s.to-s.from, label=total?fmt(s.to):d?`${d>0?"+":""}${fmt(d)} → ${fmt(s.to)}`:"±0";
|
| 641 |
svg.append(sv("text",{x:Math.min(W-2,x(hi)+5),y:y+rowH/2+4,class:total?"strong":"lbl"},label));
|
| 642 |
+
if(s.name==="baseline"){ const at=new Map(), u=refUsed(t); // voices with the same score share one marker
|
| 643 |
+
refScores(t).forEach((r,k)=>{ if(r!=null) at.set(r,[...(at.get(r)||[]),k]); });
|
| 644 |
+
for(const [r,ks] of at){ const cx=x(r), cy=y+rowH/2, d=5;
|
| 645 |
+
svg.append(sv("path",{d:`M${cx} ${cy-d}L${cx+d} ${cy}L${cx} ${cy+d}L${cx-d} ${cy}Z`,fill:ks.includes(u)?"var(--ink)":"var(--surface)",stroke:"var(--ink)","stroke-width":1.3}));
|
| 646 |
+
svg.append(sv("text",{x:cx,y:y+4,"text-anchor":"middle",style:"font-size:9.5px"},ks.map(refTag).join(" · "))); } }
|
| 647 |
const hit=sv("rect",{x:0,y,width:W,height:rowH,fill:"transparent"});
|
| 648 |
hit.onmouseenter=ev=>tipShow(ev,[el("div",{class:"t",text:STAGE_NAME[s.name]}),trow("לפני",fmt(s.from)),trow("אחרי",fmt(s.to)),s.note?el("div",{class:"tiptext ltr",text:s.note}):null].filter(Boolean));
|
| 649 |
hit.onmousemove=tipMove; hit.onmouseleave=tipHide; svg.append(hit);
|
| 650 |
});
|
| 651 |
box.replaceChildren(svg);
|
| 652 |
$("p2sub").replaceChildren(el("span",{class:"ipa",text:t.ipa})," · ",el("span",{class:"dot "+band(t.final)}),`${fmt(t.final,0)} · ${BAND_NAME[band(t.final)]}`);
|
| 653 |
+
const rx=refScores(t), ru=refUsed(t);
|
| 654 |
+
$("p2facts").replaceChildren(...[...rx.map((x,k)=>fact(`בסיס ${refName(k)}`,(x==null?"—":fmt(x,0))+(k===ru&&rx.length>1?" ◆":""))),fact("סומן",t.flagged?"כן":"לא"),fact("מרווח נדרש",fmt(t.margin.needed,2)),fact("בפועל",fmt(t.margin.got,2)),
|
| 655 |
t.rule?fact("כלל",`${t.rule.title} (${t.rule.severity})`):null, fact("טיפ",t.tip?"כן":"לא")].filter(Boolean));
|
| 656 |
}
|
| 657 |
|
|
|
|
| 701 |
/* ---------- the table: every number ---------- */
|
| 702 |
function drawTable(){
|
| 703 |
const tb=$("table"); tb.replaceChildren();
|
| 704 |
+
const nref=refList().length;
|
| 705 |
+
const head=["#","הגה","מילה","span","חלון","p_target","מתחרה","p_comp","GOP","gop","פטור","צרור",...Array.from({length:nref},(_,k)=>`בסיס ${refName(k)}`),"בסיס","כיול","סופי","סומן"];
|
| 706 |
tb.append(el("tr",{},...head.map(h=>el("th",{text:h}))));
|
| 707 |
for(const t of T.tokens){
|
| 708 |
const st=Object.fromEntries(t.stages.map(s=>[s.stage,s.score]));
|
| 709 |
+
const cells=[t.i,t.ipa,t.word,t.span.join("–"),t.window.join("–"),pct(t.p_target),t.competitor||"—",pct(t.p_competitor),fmt(t.gop,3),fmt(st.gop),fmt(st.exemption),fmt(st.insertion),...Array.from({length:nref},(_,k)=>{ const x=refScores(t)[k]; return x==null?"—":fmt(x,0); }),fmt(st.baseline),fmt(st.calibration),fmt(t.final),t.flagged?"כן":""];
|
| 710 |
const tr=el("tr",{},...cells.map((v,k)=>el("td",{class:[1,3,4,6].includes(k)?"ipa":"",text:String(v)})));
|
| 711 |
tr.onmouseenter=()=>hover(t.i); tr.onclick=()=>pick(t.i); tb.append(tr);
|
| 712 |
}
|
|
@@ -774,6 +774,27 @@ def test_native_reference_keeps_real_errors():
|
|
| 774 |
assert scorer_for(emissions(["ʕ", "χ", "l", "χ", "i", "l", "χ", "a", "χ", "aː", "χ"])).reference(None, ALA) is None
|
| 775 |
|
| 776 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 777 |
def test_references_use_one_generated_voice_and_any_cached_one():
|
| 778 |
from app.reference import References
|
| 779 |
from app.tts import TTSUnavailable
|
|
@@ -786,7 +807,7 @@ def test_references_use_one_generated_voice_and_any_cached_one():
|
|
| 786 |
def cached(self, text, voice):
|
| 787 |
return voice == "played"
|
| 788 |
|
| 789 |
-
def
|
| 790 |
calls.append(voice)
|
| 791 |
if self.down:
|
| 792 |
raise TTSUnavailable("down")
|
|
@@ -798,6 +819,7 @@ def test_references_use_one_generated_voice_and_any_cached_one():
|
|
| 798 |
try:
|
| 799 |
refs = References(s, tts, ["first", "never-played", "played"])
|
| 800 |
assert len(refs.get(7, ALA)) == 2 and calls == ["first", "played"]
|
|
|
|
| 801 |
assert len(refs.get(7, ALA)) == 2 and len(calls) == 2 # kept in memory
|
| 802 |
assert refs.invalidate(7, "first") == 1
|
| 803 |
assert len(refs.get(7, ALA)) == 2 and calls == ["first", "played", "first"]
|
|
|
|
| 774 |
assert scorer_for(emissions(["ʕ", "χ", "l", "χ", "i", "l", "χ", "a", "χ", "aː", "χ"])).reference(None, ALA) is None
|
| 775 |
|
| 776 |
|
| 777 |
+
def test_baseline_voices_are_raef_then_fadwa_by_name():
|
| 778 |
+
from app.tts import BASELINE_VOICES, FADWA_VOICE_ID, RAEF_VOICE_ID, voice_name
|
| 779 |
+
assert list(BASELINE_VOICES.values()) == [RAEF_VOICE_ID, FADWA_VOICE_ID] # Raef first: the one generated
|
| 780 |
+
assert voice_name(RAEF_VOICE_ID) == "ראאף" and voice_name(FADWA_VOICE_ID) == "פדוא" and voice_name("x") == "x"
|
| 781 |
+
|
| 782 |
+
|
| 783 |
+
def test_trace_keeps_every_voices_score_and_measures_against_the_lowest():
|
| 784 |
+
from app.scorer import Reference
|
| 785 |
+
s = scorer_for(emissions(MISHEARD))
|
| 786 |
+
toks = s._variants(ALA)[0][3]
|
| 787 |
+
weak = lambda score_on: Reference([(t.word, t.sound) for t in toks], [score_on.get(t.sound, 100.0) for t in toks])
|
| 788 |
+
a, b = replace(weak({"l": 40.0}), voice="A"), replace(weak({"l": 60.0, "ʕ": 70.0}), voice="B")
|
| 789 |
+
r = s.score_logp(s.emit(None), ALA, [a, b], diagnostics=True)
|
| 790 |
+
assert [x["voice"] for x in r["trace"]["references"]] == ["A", "B"]
|
| 791 |
+
for t in r["trace"]["tokens"]:
|
| 792 |
+
st = next(x for x in t["stages"] if x["stage"] == "baseline")
|
| 793 |
+
assert len(st["refs"]) == 2 and st["ref"] == min(x for x in st["refs"] if x is not None)
|
| 794 |
+
if t["sound"] == "ʕ":
|
| 795 |
+
assert st["refs"] == [100.0, 70.0]
|
| 796 |
+
|
| 797 |
+
|
| 798 |
def test_references_use_one_generated_voice_and_any_cached_one():
|
| 799 |
from app.reference import References
|
| 800 |
from app.tts import TTSUnavailable
|
|
|
|
| 807 |
def cached(self, text, voice):
|
| 808 |
return voice == "played"
|
| 809 |
|
| 810 |
+
def wav_for_voice(self, text, voice, source="", upload=False): # keeps the voice id (wav() would not)
|
| 811 |
calls.append(voice)
|
| 812 |
if self.down:
|
| 813 |
raise TTSUnavailable("down")
|
|
|
|
| 819 |
try:
|
| 820 |
refs = References(s, tts, ["first", "never-played", "played"])
|
| 821 |
assert len(refs.get(7, ALA)) == 2 and calls == ["first", "played"]
|
| 822 |
+
assert [r.voice for r in refs.get(7, ALA)] == ["first", "played"] # named for the trace dashboard
|
| 823 |
assert len(refs.get(7, ALA)) == 2 and len(calls) == 2 # kept in memory
|
| 824 |
assert refs.invalidate(7, "first") == 1
|
| 825 |
assert len(refs.get(7, ALA)) == 2 and calls == ["first", "played", "first"]
|