ninada 4.0.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.
ninada-4.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hemanth HM <hemanth@h3manth.com> (https://h3manth.com)
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.
ninada-4.0.0/PKG-INFO ADDED
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.4
2
+ Name: ninada
3
+ Version: 4.0.0
4
+ Summary: Ninada (निनाद) — Streaming 24 kHz Native Per-Language Studio VITS neural text-to-speech for Classical Sanskrit & 5 Indian languages (6 dedicated ~28 MB W8A32+FP16 ONNX specialists for Browser WASM SIMD, Node.js, and Python).
5
+ Author-email: Hemanth HM <hemanth@h3manth.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://hemanth.github.io/ninada/
8
+ Project-URL: Repository, https://github.com/hemanth/ninada
9
+ Project-URL: Model, https://huggingface.co/gnumanth/ninada
10
+ Project-URL: Dataset, https://huggingface.co/datasets/gnumanth/ninada-sanskrit-indic
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Provides-Extra: neural
15
+ Requires-Dist: onnxruntime>=1.18.0; extra == "neural"
16
+ Requires-Dist: numpy>=1.24.0; extra == "neural"
17
+ Requires-Dist: soundfile>=0.12.1; extra == "neural"
18
+ Provides-Extra: train
19
+ Requires-Dist: torch>=2.2.0; extra == "train"
20
+ Requires-Dist: torchaudio>=2.2.0; extra == "train"
21
+ Requires-Dist: transformers>=4.44.0; extra == "train"
22
+ Requires-Dist: safetensors>=0.4.3; extra == "train"
23
+ Requires-Dist: onnx>=1.16.0; extra == "train"
24
+ Requires-Dist: onnxruntime>=1.18.0; extra == "train"
25
+ Requires-Dist: huggingface_hub>=0.24.0; extra == "train"
26
+ Requires-Dist: pyarrow>=15.0.0; extra == "train"
27
+ Requires-Dist: scipy>=1.11.0; extra == "train"
28
+ Requires-Dist: soundfile>=0.12.1; extra == "train"
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # ninada
34
+
35
+ Stream 24,000 Hz studio speech for Classical Sanskrit and five Indian languages (`sa`, `kn`, `hi`, `ta`, `te`, `ml`) in the browser, Node.js, and Python using `27.9 MB` native per-language VITS ONNX specialists (Male & Female) with zero cross-language accent bleed.
36
+
37
+ ```bash
38
+ npm install ninada onnxruntime-web
39
+ ```
40
+
41
+ ```bash
42
+ pip install ninada
43
+ ```
44
+
45
+ ## Quick start
46
+
47
+ ```js
48
+ import ninada from 'ninada';
49
+
50
+ const voice = await ninada('kannada', {
51
+ models: {
52
+ kn: 'https://huggingface.co/gnumanth/ninada/resolve/main/onnx/kn.onnx',
53
+ sa: 'https://huggingface.co/gnumanth/ninada/resolve/main/onnx/sa.onnx',
54
+ },
55
+ cache: true,
56
+ });
57
+
58
+ for await (const chunk of voice.stream('ನಮಸ್ಕಾರ, ಇಂದು ಬೆಂಗಳೂರಿನಲ್ಲಿ ಹವಾಮಾನ ತುಂಬಾ ಚೆನ್ನಾಗಿದೆ.')) {
59
+ playPcm24k(chunk.pcm, chunk.sampleRate); // Float32Array @ 24,000 Hz
60
+ }
61
+
62
+ const wav = await voice.speak('ಕನ್ನಡವೇ ಸತ್ಯ ಕನ್ನಡವೇ ನಿತ್ಯ', { lang: 'kn', voice: 'female' });
63
+ await voice.dispose();
64
+ ```
65
+
66
+ `voice.stream()` yields `24,000 Hz` PCM clauses as they synthesize with `0` `AudioWorklet` underruns and `CacheStorage` + `IndexedDB` persistence (`0` refetches on reload). `voice.speak()` returns a complete `24 kHz` RIFF WAV buffer.
67
+
68
+ ## Python
69
+
70
+ ```python
71
+ from ninada import Ninada
72
+
73
+ tts = Ninada(lang="sa")
74
+ for chunk in tts.stream("प्रज्ञापूर्वकव्यापारवत्त्वं जीवत्वम् । यथार्थज्ञानं प्रमाणम् ॥"):
75
+ play(chunk["pcm"], chunk["sample_rate"]) # float32 @ 24,000 Hz (~0.197x CPU RTF)
76
+
77
+ wav_bytes = tts.speak("सत्यमेव जयते नानृतम्", lang="sa", voice="female")
78
+ open("satyam.wav", "wb").write(wav_bytes)
79
+ ```
80
+
81
+ `Ninada` loads dedicated `27.9 MB` W8A32+FP16 ONNX specialists (`onnx/{sa,kn,hi,ta,te,ml}.onnx` and `onnx/{sa,kn,hi,ta,te,ml}_female.onnx`), each trained exclusively on its own language's `ai4bharat/Rasa` single-speaker `24 kHz` studio recordings and native Unicode orthography.
82
+
83
+ ## CLI
84
+
85
+ ```bash
86
+ npx ninada "ಕನ್ನಡವೇ ಸತ್ಯ ಕನ್ನಡವೇ ನಿತ್ಯ" -l kn -o kannada.wav
87
+ ninada "सत्यमेव जयते नानृतम्" -l sa -o satyam.wav
88
+ ```
89
+
90
+ Runs `24 kHz` neural synthesis when ONNX weights are available and falls back automatically to a `0.0 MB` zero-dependency Cascade Klatt-Akṣara synthesizer offline.
91
+
92
+ ## Native Script Orthography & Prosody
93
+
94
+ ```js
95
+ import { studioTextToIds, textToIds } from 'ninada';
96
+
97
+ const { studioIds, lang } = studioTextToIds('ವಾಙ್ಮಯ ತಪಸ್ಸು ಮತ್ತು ಜ್ಞಾನ ವಿಕಾಸ ಅತ್ಯಂತ ಮುಖ್ಯವಾದವು.', 'kn');
98
+ const { aksharas } = textToIds('धर्मक्षेत्रे कुरुक्षेत्रे समवेता युयुत्सवः ।', 'sa');
99
+ ```
100
+
101
+ `studioTextToIds()` tokenizes directly in each language's native Unicode character table (`sa` 144 tokens, `kn` 85, `hi` 120, `ta` 61, `te` 110, `ml` 101) — preserving Classical Sanskrit vocalic `ṛ`/`ṝ`/`ḷ`, visarga sandhi, Kannada `ಙ`/`ಃ` allophony, Tamil `ழ`/`ற`/`ன`, and Malayalam atomic chillus (`ൺ ൻ ർ ൽ ൾ ൿ`) feeding a `24 kHz` `RelativePositionTransformer + StochasticDurationPredictor + HiFi-GAN v1` studio generator.
102
+
103
+ ## Benchmarks (`N = 240` Held-Out 24 kHz Studio Utterances, `B = 1,000` Bootstrap 95% CIs)
104
+
105
+ | System | Rate | Footprint (↓) | Coverage (↑) | TTFA p50 (↓) | MCD 0–8 kHz (dB, ↓) | 8–12 kHz HF Err (dB, ↓) | Dur MAE (↓) |
106
+ |---|---:|---:|---:|---:|---:|---:|---:|
107
+ | Base `facebook/mms-tts-hin` | 16 kHz | 138.8 MB | 35.0% | 1.0 ms* | `7.97 [7.69, 8.24]` | 66.24 dB | 3.21s |
108
+ | Meta MMS 5-Specialist Fleet (`5x` VITS) | 16 kHz | 694.0 MB | 100.0% | 60.2 ms | `5.09 [5.03, 5.15]` | 65.90 dB | 1.34s |
109
+ | `ninada` v4.0 Untuned Warm-Start (`step=0`) | 24 kHz | 112.0 MB | 100.0% | 189.2 ms | `4.60 [4.54, 4.65]` | 11.01 dB | 0.95s |
110
+ | **`ninada` v4.0 Native Studio FP32** | **24 kHz** | 112.0 MB | **100.0%** | **45.3 ms** | **`3.40 [3.37, 3.43]`** | **6.34 dB** | **0.57s** |
111
+ | **`ninada` v4.0 Native Browser ONNX** | **24 kHz** | **27.9 MB** | **100.0%** | **372.7 ms** | **`3.39 [3.36, 3.43]`** | **6.37 dB** | **0.56s** |
112
+ | `ninada` Tier-2 Klatt Fallback | 24 kHz | **0.0 MB** | **100.0%** | **104.0 ms** | `10.38 [10.26, 10.50]` | 41.94 dB | 0.98s |
113
+
114
+ Per-language held-out `MCD 0–8 kHz (dB, ↓)`: Sanskrit **`3.51`** (vs `5.32` MMS), Hindi **`3.37`** (vs `4.85` MMS), Kannada **`3.35`** (vs `5.04` MMS), Tamil **`3.21`** (vs `4.87` MMS), Telugu **`3.59`** (vs `5.57` MMS), Malayalam **`3.34`** (vs `4.88` MMS). Full bootstrap CIs and parity telemetry (`0.61 dB` parity MCD, `r = 0.9999`) in [`bench/SCIENCE_REPORT.md`](./bench/SCIENCE_REPORT.md) and [`bench/results.json`](./bench/results.json).
115
+
116
+ ## Reproduce & Verify
117
+
118
+ ```bash
119
+ PYTHONPATH=python/src:. python training/train_native_specialists_gcp.py --work-dir data/v4 --out-dir artifacts/ninada_v4
120
+ PYTHONPATH=python/src:. python bench/check_bench_thresholds.py
121
+ pytest -q && node verify-browser.mjs
122
+ ```
123
+
124
+ Trains all 12 native `24 kHz` Male/Female studio VITS specialists, evaluates `240` held-out studio clips, and verifies `0` `AudioWorklet` underruns and `0` cached network refetches in headless Chromium.
125
+
126
+ ## Links
127
+
128
+ - [Live Browser Voice Studio](https://hemanth.github.io/ninada/)
129
+ - [Hugging Face Model (`gnumanth/ninada`)](https://huggingface.co/gnumanth/ninada)
130
+ - [Hugging Face Dataset (`gnumanth/ninada-sanskrit-indic`)](https://huggingface.co/datasets/gnumanth/ninada-sanskrit-indic)
131
+
132
+ ## License
133
+
134
+ MIT © [Hemanth.HM](https://h3manth.com)
ninada-4.0.0/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # ninada
2
+
3
+ Stream 24,000 Hz studio speech for Classical Sanskrit and five Indian languages (`sa`, `kn`, `hi`, `ta`, `te`, `ml`) in the browser, Node.js, and Python using `27.9 MB` native per-language VITS ONNX specialists (Male & Female) with zero cross-language accent bleed.
4
+
5
+ ```bash
6
+ npm install ninada onnxruntime-web
7
+ ```
8
+
9
+ ```bash
10
+ pip install ninada
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ ```js
16
+ import ninada from 'ninada';
17
+
18
+ const voice = await ninada('kannada', {
19
+ models: {
20
+ kn: 'https://huggingface.co/gnumanth/ninada/resolve/main/onnx/kn.onnx',
21
+ sa: 'https://huggingface.co/gnumanth/ninada/resolve/main/onnx/sa.onnx',
22
+ },
23
+ cache: true,
24
+ });
25
+
26
+ for await (const chunk of voice.stream('ನಮಸ್ಕಾರ, ಇಂದು ಬೆಂಗಳೂರಿನಲ್ಲಿ ಹವಾಮಾನ ತುಂಬಾ ಚೆನ್ನಾಗಿದೆ.')) {
27
+ playPcm24k(chunk.pcm, chunk.sampleRate); // Float32Array @ 24,000 Hz
28
+ }
29
+
30
+ const wav = await voice.speak('ಕನ್ನಡವೇ ಸತ್ಯ ಕನ್ನಡವೇ ನಿತ್ಯ', { lang: 'kn', voice: 'female' });
31
+ await voice.dispose();
32
+ ```
33
+
34
+ `voice.stream()` yields `24,000 Hz` PCM clauses as they synthesize with `0` `AudioWorklet` underruns and `CacheStorage` + `IndexedDB` persistence (`0` refetches on reload). `voice.speak()` returns a complete `24 kHz` RIFF WAV buffer.
35
+
36
+ ## Python
37
+
38
+ ```python
39
+ from ninada import Ninada
40
+
41
+ tts = Ninada(lang="sa")
42
+ for chunk in tts.stream("प्रज्ञापूर्वकव्यापारवत्त्वं जीवत्वम् । यथार्थज्ञानं प्रमाणम् ॥"):
43
+ play(chunk["pcm"], chunk["sample_rate"]) # float32 @ 24,000 Hz (~0.197x CPU RTF)
44
+
45
+ wav_bytes = tts.speak("सत्यमेव जयते नानृतम्", lang="sa", voice="female")
46
+ open("satyam.wav", "wb").write(wav_bytes)
47
+ ```
48
+
49
+ `Ninada` loads dedicated `27.9 MB` W8A32+FP16 ONNX specialists (`onnx/{sa,kn,hi,ta,te,ml}.onnx` and `onnx/{sa,kn,hi,ta,te,ml}_female.onnx`), each trained exclusively on its own language's `ai4bharat/Rasa` single-speaker `24 kHz` studio recordings and native Unicode orthography.
50
+
51
+ ## CLI
52
+
53
+ ```bash
54
+ npx ninada "ಕನ್ನಡವೇ ಸತ್ಯ ಕನ್ನಡವೇ ನಿತ್ಯ" -l kn -o kannada.wav
55
+ ninada "सत्यमेव जयते नानृतम्" -l sa -o satyam.wav
56
+ ```
57
+
58
+ Runs `24 kHz` neural synthesis when ONNX weights are available and falls back automatically to a `0.0 MB` zero-dependency Cascade Klatt-Akṣara synthesizer offline.
59
+
60
+ ## Native Script Orthography & Prosody
61
+
62
+ ```js
63
+ import { studioTextToIds, textToIds } from 'ninada';
64
+
65
+ const { studioIds, lang } = studioTextToIds('ವಾಙ್ಮಯ ತಪಸ್ಸು ಮತ್ತು ಜ್ಞಾನ ವಿಕಾಸ ಅತ್ಯಂತ ಮುಖ್ಯವಾದವು.', 'kn');
66
+ const { aksharas } = textToIds('धर्मक्षेत्रे कुरुक्षेत्रे समवेता युयुत्सवः ।', 'sa');
67
+ ```
68
+
69
+ `studioTextToIds()` tokenizes directly in each language's native Unicode character table (`sa` 144 tokens, `kn` 85, `hi` 120, `ta` 61, `te` 110, `ml` 101) — preserving Classical Sanskrit vocalic `ṛ`/`ṝ`/`ḷ`, visarga sandhi, Kannada `ಙ`/`ಃ` allophony, Tamil `ழ`/`ற`/`ன`, and Malayalam atomic chillus (`ൺ ൻ ർ ൽ ൾ ൿ`) feeding a `24 kHz` `RelativePositionTransformer + StochasticDurationPredictor + HiFi-GAN v1` studio generator.
70
+
71
+ ## Benchmarks (`N = 240` Held-Out 24 kHz Studio Utterances, `B = 1,000` Bootstrap 95% CIs)
72
+
73
+ | System | Rate | Footprint (↓) | Coverage (↑) | TTFA p50 (↓) | MCD 0–8 kHz (dB, ↓) | 8–12 kHz HF Err (dB, ↓) | Dur MAE (↓) |
74
+ |---|---:|---:|---:|---:|---:|---:|---:|
75
+ | Base `facebook/mms-tts-hin` | 16 kHz | 138.8 MB | 35.0% | 1.0 ms* | `7.97 [7.69, 8.24]` | 66.24 dB | 3.21s |
76
+ | Meta MMS 5-Specialist Fleet (`5x` VITS) | 16 kHz | 694.0 MB | 100.0% | 60.2 ms | `5.09 [5.03, 5.15]` | 65.90 dB | 1.34s |
77
+ | `ninada` v4.0 Untuned Warm-Start (`step=0`) | 24 kHz | 112.0 MB | 100.0% | 189.2 ms | `4.60 [4.54, 4.65]` | 11.01 dB | 0.95s |
78
+ | **`ninada` v4.0 Native Studio FP32** | **24 kHz** | 112.0 MB | **100.0%** | **45.3 ms** | **`3.40 [3.37, 3.43]`** | **6.34 dB** | **0.57s** |
79
+ | **`ninada` v4.0 Native Browser ONNX** | **24 kHz** | **27.9 MB** | **100.0%** | **372.7 ms** | **`3.39 [3.36, 3.43]`** | **6.37 dB** | **0.56s** |
80
+ | `ninada` Tier-2 Klatt Fallback | 24 kHz | **0.0 MB** | **100.0%** | **104.0 ms** | `10.38 [10.26, 10.50]` | 41.94 dB | 0.98s |
81
+
82
+ Per-language held-out `MCD 0–8 kHz (dB, ↓)`: Sanskrit **`3.51`** (vs `5.32` MMS), Hindi **`3.37`** (vs `4.85` MMS), Kannada **`3.35`** (vs `5.04` MMS), Tamil **`3.21`** (vs `4.87` MMS), Telugu **`3.59`** (vs `5.57` MMS), Malayalam **`3.34`** (vs `4.88` MMS). Full bootstrap CIs and parity telemetry (`0.61 dB` parity MCD, `r = 0.9999`) in [`bench/SCIENCE_REPORT.md`](./bench/SCIENCE_REPORT.md) and [`bench/results.json`](./bench/results.json).
83
+
84
+ ## Reproduce & Verify
85
+
86
+ ```bash
87
+ PYTHONPATH=python/src:. python training/train_native_specialists_gcp.py --work-dir data/v4 --out-dir artifacts/ninada_v4
88
+ PYTHONPATH=python/src:. python bench/check_bench_thresholds.py
89
+ pytest -q && node verify-browser.mjs
90
+ ```
91
+
92
+ Trains all 12 native `24 kHz` Male/Female studio VITS specialists, evaluates `240` held-out studio clips, and verifies `0` `AudioWorklet` underruns and `0` cached network refetches in headless Chromium.
93
+
94
+ ## Links
95
+
96
+ - [Live Browser Voice Studio](https://hemanth.github.io/ninada/)
97
+ - [Hugging Face Model (`gnumanth/ninada`)](https://huggingface.co/gnumanth/ninada)
98
+ - [Hugging Face Dataset (`gnumanth/ninada-sanskrit-indic`)](https://huggingface.co/datasets/gnumanth/ninada-sanskrit-indic)
99
+
100
+ ## License
101
+
102
+ MIT © [Hemanth.HM](https://h3manth.com)
@@ -0,0 +1,53 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ninada"
7
+ version = "4.0.0"
8
+ description = "Ninada (निनाद) — Streaming 24 kHz Native Per-Language Studio VITS neural text-to-speech for Classical Sanskrit & 5 Indian languages (6 dedicated ~28 MB W8A32+FP16 ONNX specialists for Browser WASM SIMD, Node.js, and Python)."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ authors = [
12
+ { name = "Hemanth HM", email = "hemanth@h3manth.com" }
13
+ ]
14
+ requires-python = ">=3.10"
15
+ dependencies = []
16
+
17
+ [project.urls]
18
+ Homepage = "https://hemanth.github.io/ninada/"
19
+ Repository = "https://github.com/hemanth/ninada"
20
+ Model = "https://huggingface.co/gnumanth/ninada"
21
+ Dataset = "https://huggingface.co/datasets/gnumanth/ninada-sanskrit-indic"
22
+
23
+ [project.scripts]
24
+ ninada = "ninada.cli:main"
25
+
26
+ [project.optional-dependencies]
27
+ neural = [
28
+ "onnxruntime>=1.18.0",
29
+ "numpy>=1.24.0",
30
+ "soundfile>=0.12.1",
31
+ ]
32
+ train = [
33
+ "torch>=2.2.0",
34
+ "torchaudio>=2.2.0",
35
+ "transformers>=4.44.0",
36
+ "safetensors>=0.4.3",
37
+ "onnx>=1.16.0",
38
+ "onnxruntime>=1.18.0",
39
+ "huggingface_hub>=0.24.0",
40
+ "pyarrow>=15.0.0",
41
+ "scipy>=1.11.0",
42
+ "soundfile>=0.12.1",
43
+ ]
44
+ dev = [
45
+ "pytest>=8.0.0",
46
+ ]
47
+
48
+ [tool.setuptools.packages.find]
49
+ where = ["python/src"]
50
+
51
+ [tool.pytest.ini_options]
52
+ pythonpath = ["python/src"]
53
+ testpaths = ["tests"]
@@ -0,0 +1,76 @@
1
+ """ninada (निनाद): Streaming Pan-Indic & Classical Sanskrit Neural Text-to-Speech."""
2
+ from .engine import (
3
+ HOP_LENGTH,
4
+ SAMPLE_RATE,
5
+ Ninada,
6
+ encode_wav_bytes,
7
+ speak,
8
+ split_prosodic_clauses,
9
+ stream,
10
+ synthesize_klatt_pcm,
11
+ )
12
+ from .g2p import (
13
+ BLANK_ID,
14
+ ID_TO_LANGUAGE,
15
+ ID_TO_TOKEN,
16
+ IPA_ID_TO_TOKEN,
17
+ IPA_VOCAB,
18
+ LANGUAGE_IDS,
19
+ RETROFLEX_LATERAL_ID,
20
+ TOKEN_TO_ID,
21
+ UNK_ID,
22
+ VOCAB_TOKENS,
23
+ WARMSTART_DONOR_MAP,
24
+ apply_phonological_rules,
25
+ brahmic_to_devanagari,
26
+ detect_script_and_lang,
27
+ iast_to_devanagari,
28
+ ipa_to_ids,
29
+ segment_aksharas,
30
+ text_to_ids,
31
+ text_to_ipa,
32
+ )
33
+
34
+ from .studio_g2p import (
35
+ STUDIO_HOP_LENGTH,
36
+ STUDIO_VOCABS,
37
+ clean_studio_text,
38
+ studio_text_to_ids,
39
+ )
40
+
41
+ __version__ = "4.0.0"
42
+
43
+ __all__ = [
44
+ "__version__",
45
+ "SAMPLE_RATE",
46
+ "HOP_LENGTH",
47
+ "STUDIO_HOP_LENGTH",
48
+ "STUDIO_VOCABS",
49
+ "clean_studio_text",
50
+ "studio_text_to_ids",
51
+ "Ninada",
52
+ "speak",
53
+ "stream",
54
+ "split_prosodic_clauses",
55
+ "encode_wav_bytes",
56
+ "synthesize_klatt_pcm",
57
+ "VOCAB_TOKENS",
58
+ "TOKEN_TO_ID",
59
+ "ID_TO_TOKEN",
60
+ "IPA_VOCAB",
61
+ "IPA_ID_TO_TOKEN",
62
+ "RETROFLEX_LATERAL_ID",
63
+ "BLANK_ID",
64
+ "UNK_ID",
65
+ "LANGUAGE_IDS",
66
+ "ID_TO_LANGUAGE",
67
+ "WARMSTART_DONOR_MAP",
68
+ "detect_script_and_lang",
69
+ "iast_to_devanagari",
70
+ "brahmic_to_devanagari",
71
+ "apply_phonological_rules",
72
+ "segment_aksharas",
73
+ "text_to_ipa",
74
+ "ipa_to_ids",
75
+ "text_to_ids",
76
+ ]
@@ -0,0 +1,43 @@
1
+ """Command-line interface for Ninada (Pan-Indic & Classical Sanskrit TTS)."""
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import json
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ from .engine import SAMPLE_RATE, Ninada
10
+
11
+
12
+ def main() -> None:
13
+ parser = argparse.ArgumentParser(
14
+ prog="ninada",
15
+ description="Ninada — Pan-Indic & Classical Sanskrit Neural TTS (24 kHz Studio WAV)",
16
+ )
17
+ parser.add_argument("text", nargs="?", help="Input text in Devanagari, Kannada, Tamil, Telugu, Malayalam, or IAST")
18
+ parser.add_argument("-l", "--lang", default=None, help="Language code: sa | hi | kn | ta | te | ml")
19
+ parser.add_argument("-o", "--output", type=Path, default=Path("ninada_out.wav"), help="Output WAV file path")
20
+ parser.add_argument("-r", "--rate", type=float, default=1.0, help="Speaking rate multiplier (default: 1.0)")
21
+ parser.add_argument("--tier", choices=["auto", "neural", "klatt"], default="auto", help="Synthesis engine tier")
22
+ parser.add_argument("--inspect", action="store_true", help="Print Pan-Indic G2P & akshara prosody JSON")
23
+ args = parser.parse_args()
24
+
25
+ txt = args.text if args.text else sys.stdin.read().strip()
26
+ if not txt:
27
+ parser.error("Provide input text as an argument or via stdin.")
28
+
29
+ engine = Ninada(lang=args.lang or "sa")
30
+ pcm, meta = engine.synthesize(txt, lang=args.lang, rate=args.rate, tier=args.tier)
31
+ if args.inspect:
32
+ print(json.dumps({k: v for k, v in meta.items() if k != "durations"}, ensure_ascii=False, indent=2))
33
+ return
34
+
35
+ from .engine import encode_wav_bytes
36
+
37
+ wav = encode_wav_bytes(pcm, sr=SAMPLE_RATE)
38
+ args.output.write_bytes(wav)
39
+ print(f"Wrote {len(wav)} bytes ({len(pcm)/float(SAMPLE_RATE):.2f}s, tier={meta['tier']}, lang={meta['lang']}) -> {args.output}")
40
+
41
+
42
+ if __name__ == "__main__":
43
+ main()