hatsuon 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. hatsuon-0.1.0/.gitignore +19 -0
  2. hatsuon-0.1.0/DATA_SOURCES.md +18 -0
  3. hatsuon-0.1.0/LICENSE +21 -0
  4. hatsuon-0.1.0/PKG-INFO +121 -0
  5. hatsuon-0.1.0/README.md +81 -0
  6. hatsuon-0.1.0/docs/SPEC.md +867 -0
  7. hatsuon-0.1.0/pyproject.toml +57 -0
  8. hatsuon-0.1.0/src/hatsuon/__init__.py +8 -0
  9. hatsuon-0.1.0/src/hatsuon/acoustic.py +114 -0
  10. hatsuon-0.1.0/src/hatsuon/align.py +217 -0
  11. hatsuon-0.1.0/src/hatsuon/api.py +45 -0
  12. hatsuon-0.1.0/src/hatsuon/audio.py +147 -0
  13. hatsuon-0.1.0/src/hatsuon/calibration/__init__.py +43 -0
  14. hatsuon-0.1.0/src/hatsuon/calibration/default.json +409 -0
  15. hatsuon-0.1.0/src/hatsuon/errors.py +17 -0
  16. hatsuon-0.1.0/src/hatsuon/export.py +94 -0
  17. hatsuon-0.1.0/src/hatsuon/frontend/__init__.py +1 -0
  18. hatsuon-0.1.0/src/hatsuon/frontend/analyze.py +239 -0
  19. hatsuon-0.1.0/src/hatsuon/frontend/morae.py +183 -0
  20. hatsuon-0.1.0/src/hatsuon/frontend/pitch_pattern.py +60 -0
  21. hatsuon-0.1.0/src/hatsuon/gop.py +50 -0
  22. hatsuon-0.1.0/src/hatsuon/pipeline.py +358 -0
  23. hatsuon-0.1.0/src/hatsuon/pitch.py +131 -0
  24. hatsuon-0.1.0/src/hatsuon/targets.py +68 -0
  25. hatsuon-0.1.0/src/hatsuon/timing.py +58 -0
  26. hatsuon-0.1.0/src/hatsuon/types.py +93 -0
  27. hatsuon-0.1.0/tests/test_align.py +96 -0
  28. hatsuon-0.1.0/tests/test_analyze.py +122 -0
  29. hatsuon-0.1.0/tests/test_audio.py +84 -0
  30. hatsuon-0.1.0/tests/test_calibration.py +36 -0
  31. hatsuon-0.1.0/tests/test_judges.py +58 -0
  32. hatsuon-0.1.0/tests/test_morae.py +44 -0
  33. hatsuon-0.1.0/tests/test_phonemes.py +53 -0
  34. hatsuon-0.1.0/tests/test_pipeline.py +53 -0
  35. hatsuon-0.1.0/tests/test_pitch_pattern.py +50 -0
  36. hatsuon-0.1.0/tests/test_smoke.py +6 -0
  37. hatsuon-0.1.0/tests/test_targets.py +55 -0
  38. hatsuon-0.1.0/tools/calibrate.py +398 -0
  39. hatsuon-0.1.0/tools/eval_accent.py +149 -0
  40. hatsuon-0.1.0/tools/fetch_data.sh +51 -0
@@ -0,0 +1,19 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .venv/
5
+ dist/
6
+ build/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+
10
+ # Never commit audio or downloaded corpora (licences forbid redistribution)
11
+ data/
12
+ *.wav
13
+ *.flac
14
+ *.mp3
15
+ *.m4a
16
+ *.onnx
17
+
18
+ # Claude
19
+ CLAUDE.md
@@ -0,0 +1,18 @@
1
+ # Data sources
2
+
3
+ Corpora used for calibration and evaluation (SPEC Appendix B). Nothing listed here
4
+ is redistributed by this repository: audio lives in the git-ignored `data/`
5
+ directory and is fetched by `tools/fetch_data.sh`. Licence summaries are
6
+ paraphrases for planning, not legal advice — re-read the official page before use.
7
+
8
+ | Source | Official page | Licence (summary) | Read on | Used for |
9
+ |---|---|---|---|---|
10
+ | JSUT v1.1 | https://sites.google.com/site/shinnosuketakamichi/publication/jsut | Text CC BY-SA 4.0. Audio: academic / non-commercial research (incl. inside companies) / personal use; no redistribution (small excerpts allowed); commercial use by contacting the authors. | 2026-11-04 | F0 and duration sanity checks, local regression fixtures |
11
+ | JVS v1 | https://sites.google.com/site/shinnosuketakamichi/research-topics/jvs_corpus | Tags CC BY-SA 4.0. Audio: same terms as JSUT (non-commercial research, no redistribution). | 2026-11-04 | Per-phone GOP calibration, duration norms, native false-alarm rate |
12
+ | jsut-label | https://github.com/sarulab-speech/jsut-label | CC BY-SA 4.0 | 2026-11-04 | Ground-truth accent nucleus for basic5000 (front-end accent accuracy) |
13
+
14
+ ## Models
15
+
16
+ | Model | Page | Licence | Read on | Notes |
17
+ |---|---|---|---|---|
18
+ | japanese-hubert-base-phoneme-ctc-v4 | https://huggingface.co/prj-beatrice/japanese-hubert-base-phoneme-ctc-v4 | Apache-2.0 | 2026-11-04 | Fine-tuned from rinna/japanese-hubert-base on ReazonSpeech (CDLA-Sharing-1.0, Art. 30-4 restricted — see SPEC B.2). Not redistributed; users export it locally with `hatsuon-export`. |
hatsuon-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Công Anh Dũng
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
hatsuon-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,121 @@
1
+ Metadata-Version: 2.5
2
+ Name: hatsuon
3
+ Version: 0.1.0
4
+ Summary: Japanese pronunciation scoring: mora-level accuracy, special morae and pitch accent.
5
+ Author: Công Anh Dũng
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: gop,japanese,mora,pitch-accent,pronunciation,speech
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Intended Audience :: Education
12
+ Classifier: Natural Language :: Japanese
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: numpy>=1.24
18
+ Provides-Extra: all
19
+ Requires-Dist: librosa>=0.10; extra == 'all'
20
+ Requires-Dist: onnxruntime>=1.17; extra == 'all'
21
+ Requires-Dist: pyopenjtalk>=0.3; extra == 'all'
22
+ Requires-Dist: soundfile>=0.12; extra == 'all'
23
+ Provides-Extra: audio
24
+ Requires-Dist: librosa>=0.10; extra == 'audio'
25
+ Requires-Dist: soundfile>=0.12; extra == 'audio'
26
+ Provides-Extra: dev
27
+ Requires-Dist: build>=1.2; extra == 'dev'
28
+ Requires-Dist: pytest>=8; extra == 'dev'
29
+ Requires-Dist: ruff>=0.5; extra == 'dev'
30
+ Requires-Dist: twine>=5; extra == 'dev'
31
+ Provides-Extra: export
32
+ Requires-Dist: onnx>=1.15; extra == 'export'
33
+ Requires-Dist: torch>=2.2; extra == 'export'
34
+ Requires-Dist: transformers>=4.40; extra == 'export'
35
+ Provides-Extra: frontend
36
+ Requires-Dist: pyopenjtalk>=0.3; extra == 'frontend'
37
+ Provides-Extra: onnx
38
+ Requires-Dist: onnxruntime>=1.17; extra == 'onnx'
39
+ Description-Content-Type: text/markdown
40
+
41
+ # hatsuon
42
+
43
+ Japanese pronunciation scoring for read-aloud speech, on the CPU. It scores
44
+ accuracy per mora, the special morae (っ, ん, long vowels) and Tokyo pitch accent.
45
+
46
+ > Status: **alpha (0.1)**. Thresholds were tuned on native speech only (JSUT/JVS),
47
+ > and no L2 learner data has been used yet. Treat the scores as feedback, not as a
48
+ > grade. Design and tuning records: [docs/SPEC.md](docs/SPEC.md) and
49
+ > [`calibration/default.json`](src/hatsuon/calibration/default.json).
50
+
51
+ ## Install
52
+
53
+ ```bash
54
+ pip install "hatsuon[all]"
55
+ ```
56
+
57
+ The acoustic model is **not** shipped in the package. Convert it once on your
58
+ machine. This step needs PyTorch and transformers only for the conversion itself:
59
+
60
+ ```bash
61
+ pip install "hatsuon[export]"
62
+ hatsuon-export # writes ~/.cache/hatsuon/models/... (ONNX, int8)
63
+ ```
64
+
65
+ `hatsuon-export --out DIR` writes the model elsewhere; set `HATSUON_MODEL_DIR=DIR`
66
+ to use it. `--no-quantize` keeps FP32 weights.
67
+
68
+ ## Use
69
+
70
+ ```python
71
+ import hatsuon
72
+
73
+ r = hatsuon.score("learner.wav", "東京に行きます。")
74
+ print(r.overall, r.accuracy, r.completeness, r.pitch, r.timing, r.confidence)
75
+ for w in r.words:
76
+ print(w.surface, w.reading, w.score, w.accent.value)
77
+ for m in w.morae:
78
+ print(" ", m.kana, m.status.value, round(m.score), m.duration, m.pitch_status)
79
+ print([x.value for x in r.warnings])
80
+ ```
81
+
82
+ - `audio` can be a path, encoded bytes, or a `(samples, sample_rate)` tuple.
83
+ - Ambiguous readings: `reading="きょう"` (whole text) or `reading={"今日": "きょう"}`.
84
+ - Accent overrides: `accent={"箸": 1}` (0 = heiban, n = fall after mora n).
85
+ - `pitch=False` or `timing=False` skips those stages.
86
+ - `debug=True` attaches F0, the free decode and per-phone GOP to `r.debug`.
87
+ - Soft problems such as `no_speech`, `content_mismatch` or `pitch_unreliable`
88
+ come back in `r.warnings` and lower `r.confidence`.
89
+ - Hard errors raise `hatsuon.AudioError` or `hatsuon.TextError`.
90
+
91
+ ## Known limitations (0.1)
92
+
93
+ - **Native-only calibration.** We have not yet measured mispronunciation recall
94
+ on learners. On 20 held-out JVS speakers, 0.6% of correct native morae fall
95
+ below the `mispronounced` threshold. Synthetic one-mora substitutions (the
96
+ text is changed, the audio is not) are caught 94% of the time: 98% for
97
+ consonants and 91% for vowels. Real learner errors are subtler than these.
98
+ - **Pitch accent:**
99
+ - Native speakers often place the F0 peak one mora late, so a fall up to one
100
+ mora after the nucleus is accepted. As a result, a learner who puts the
101
+ nucleus one mora too late is not caught.
102
+ - About 9% of native heiban phrases are flagged with a false fall.
103
+ - **Readings come from OpenJTalk.** When it misreads a word (proper nouns,
104
+ 命 → イノチ when the speaker says めい), a correct reading shows up as
105
+ `deleted` morae. Pass `reading={"命": "めい"}` in those cases.
106
+ - Read speech only. Not for spontaneous speech or singing.
107
+
108
+ ## Development
109
+
110
+ ```bash
111
+ pip install -e ".[all,dev]"
112
+ pytest && ruff check .
113
+ bash tools/fetch_data.sh # JSUT, JVS, jsut-label into data/ (see DATA_SOURCES.md)
114
+ python tools/eval_accent.py --n 300 # pitch-accent accuracy on JSUT
115
+ python tools/calibrate.py collect && python tools/calibrate.py fit --write
116
+ ```
117
+
118
+ ## License
119
+
120
+ MIT. Corpora and the acoustic model have their own licences and are never
121
+ redistributed. See [DATA_SOURCES.md](DATA_SOURCES.md).
@@ -0,0 +1,81 @@
1
+ # hatsuon
2
+
3
+ Japanese pronunciation scoring for read-aloud speech, on the CPU. It scores
4
+ accuracy per mora, the special morae (っ, ん, long vowels) and Tokyo pitch accent.
5
+
6
+ > Status: **alpha (0.1)**. Thresholds were tuned on native speech only (JSUT/JVS),
7
+ > and no L2 learner data has been used yet. Treat the scores as feedback, not as a
8
+ > grade. Design and tuning records: [docs/SPEC.md](docs/SPEC.md) and
9
+ > [`calibration/default.json`](src/hatsuon/calibration/default.json).
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pip install "hatsuon[all]"
15
+ ```
16
+
17
+ The acoustic model is **not** shipped in the package. Convert it once on your
18
+ machine. This step needs PyTorch and transformers only for the conversion itself:
19
+
20
+ ```bash
21
+ pip install "hatsuon[export]"
22
+ hatsuon-export # writes ~/.cache/hatsuon/models/... (ONNX, int8)
23
+ ```
24
+
25
+ `hatsuon-export --out DIR` writes the model elsewhere; set `HATSUON_MODEL_DIR=DIR`
26
+ to use it. `--no-quantize` keeps FP32 weights.
27
+
28
+ ## Use
29
+
30
+ ```python
31
+ import hatsuon
32
+
33
+ r = hatsuon.score("learner.wav", "東京に行きます。")
34
+ print(r.overall, r.accuracy, r.completeness, r.pitch, r.timing, r.confidence)
35
+ for w in r.words:
36
+ print(w.surface, w.reading, w.score, w.accent.value)
37
+ for m in w.morae:
38
+ print(" ", m.kana, m.status.value, round(m.score), m.duration, m.pitch_status)
39
+ print([x.value for x in r.warnings])
40
+ ```
41
+
42
+ - `audio` can be a path, encoded bytes, or a `(samples, sample_rate)` tuple.
43
+ - Ambiguous readings: `reading="きょう"` (whole text) or `reading={"今日": "きょう"}`.
44
+ - Accent overrides: `accent={"箸": 1}` (0 = heiban, n = fall after mora n).
45
+ - `pitch=False` or `timing=False` skips those stages.
46
+ - `debug=True` attaches F0, the free decode and per-phone GOP to `r.debug`.
47
+ - Soft problems such as `no_speech`, `content_mismatch` or `pitch_unreliable`
48
+ come back in `r.warnings` and lower `r.confidence`.
49
+ - Hard errors raise `hatsuon.AudioError` or `hatsuon.TextError`.
50
+
51
+ ## Known limitations (0.1)
52
+
53
+ - **Native-only calibration.** We have not yet measured mispronunciation recall
54
+ on learners. On 20 held-out JVS speakers, 0.6% of correct native morae fall
55
+ below the `mispronounced` threshold. Synthetic one-mora substitutions (the
56
+ text is changed, the audio is not) are caught 94% of the time: 98% for
57
+ consonants and 91% for vowels. Real learner errors are subtler than these.
58
+ - **Pitch accent:**
59
+ - Native speakers often place the F0 peak one mora late, so a fall up to one
60
+ mora after the nucleus is accepted. As a result, a learner who puts the
61
+ nucleus one mora too late is not caught.
62
+ - About 9% of native heiban phrases are flagged with a false fall.
63
+ - **Readings come from OpenJTalk.** When it misreads a word (proper nouns,
64
+ 命 → イノチ when the speaker says めい), a correct reading shows up as
65
+ `deleted` morae. Pass `reading={"命": "めい"}` in those cases.
66
+ - Read speech only. Not for spontaneous speech or singing.
67
+
68
+ ## Development
69
+
70
+ ```bash
71
+ pip install -e ".[all,dev]"
72
+ pytest && ruff check .
73
+ bash tools/fetch_data.sh # JSUT, JVS, jsut-label into data/ (see DATA_SOURCES.md)
74
+ python tools/eval_accent.py --n 300 # pitch-accent accuracy on JSUT
75
+ python tools/calibrate.py collect && python tools/calibrate.py fit --write
76
+ ```
77
+
78
+ ## License
79
+
80
+ MIT. Corpora and the acoustic model have their own licences and are never
81
+ redistributed. See [DATA_SOURCES.md](DATA_SOURCES.md).