Yoni commited on
Commit
3f8595e
·
1 Parent(s): ce63d92

no message

Browse files
app.py CHANGED
@@ -12,7 +12,7 @@ import sys
12
  if not os.path.exists("israwave-main"):
13
  with zipfile.ZipFile("israwave-clean.zip", "r") as zip_ref:
14
  zip_ref.extractall(".")
15
- subprocess.check_call([sys.executable, "-m", "pip", "install", "./israwave-clean"])
16
 
17
  # Only after install, import israwave
18
  from israwave import IsrawaveTTS
 
12
  if not os.path.exists("israwave-main"):
13
  with zipfile.ZipFile("israwave-clean.zip", "r") as zip_ref:
14
  zip_ref.extractall(".")
15
+ # subprocess.check_call([sys.executable, "-m", "pip", "install", "./israwave-clean"])
16
 
17
  # Only after install, import israwave
18
  from israwave import IsrawaveTTS
israwave/.python-version ADDED
@@ -0,0 +1 @@
 
 
1
+ 3.12
israwave/README.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # israwave
2
+
3
+ Mission to create a Hebrew TTS model as powerful and user-friendly as WaveNet
4
+
5
+ ## Install
6
+
7
+ ```console
8
+ pip install israwave
9
+ ```
10
+
11
+ See https://github.com/thewh1teagle/israwave
israwave/pyproject.toml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "israwave"
3
+ version = "0.1.8"
4
+ description = "Hebrew text to speech on the edge"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "thewh1teagle", email = "[email protected]" }
8
+ ]
9
+ requires-python = ">=3.9"
10
+ dependencies = [
11
+ "onnxruntime>=1.19.2",
12
+ "numpy>=2.1.1",
13
+ "soundfile>=0.12.1",
14
+ "sounddevice>=0.5.0",
15
+ "nakdimon-ort>=0.1.5",
16
+ "espeakng-loader==0.1.2",
17
+ "phonemizer-fork==3.3.1", # TODO: remove once https://github.com/thewh1teagle/espeakng-loader/issues/2 merged and change dependency from git to stable!
18
+ ]
19
+
20
+ [build-system]
21
+ requires = ["hatchling"]
22
+ build-backend = "hatchling.build"
israwave/src/israwave/__init__.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from israwave.tensors import FloatArray
2
+ from .model import Model
3
+ import soundfile as sf
4
+ import os
5
+ from pathlib import Path
6
+
7
+ class WaveForm:
8
+ def __init__(self, samples: FloatArray, sample_rate: int) -> None:
9
+ self.samples = samples
10
+ self.sample_rate = sample_rate
11
+
12
+ def save(self, path: str):
13
+ if os.path.exists(path):
14
+ os.remove(path)
15
+ sf.write(path, self.samples, self.sample_rate)
16
+
17
+
18
+ class IsraWave:
19
+ def __init__(self, model_path: str, espeak_data_path: str) -> None:
20
+ # Check if the speech model exists
21
+ if not Path(model_path).exists():
22
+ raise FileNotFoundError(
23
+ f"Speech model not found at {model_path}\n"
24
+ "Please download and prepare the model using the following commands:\n"
25
+ "wget https://github.com/thewh1teagle/israwave/releases/download/v0.1.0/israwave.onnx"
26
+ )
27
+
28
+ # Check if the espeak data folder exists
29
+ if not Path(espeak_data_path).exists():
30
+ raise FileNotFoundError(
31
+ f"Espeak data folder not found at {espeak_data_path}\n"
32
+ "Please download and extract the espeak data using the following commands:\n"
33
+ "wget https://github.com/thewh1teagle/israwave/releases/download/v0.1.0/espeak-ng-data.tar.gz\n"
34
+ "tar xf espeak-ng-data.tar.gz"
35
+ )
36
+
37
+ self.model = Model(model_path, espeak_data_path)
38
+ self.sample_rate = self.model.sample_rate
39
+
40
+ def create(self, text, rate = 1.0, pitch = 1.0, energy = 1.0):
41
+ """create speech waveform
42
+
43
+ Args:
44
+ text str: _description_
45
+ rate (float, optional): Control rate. Defaults to 1.0.
46
+ pitch (float, optional): Control pitch. Defaults to 1.0.
47
+ energy (float, optional): Control energy. Defaults to 1.0.
48
+
49
+ Returns:
50
+ _type_: _description_
51
+ """
52
+ inputs = self.model.prepare_input(
53
+ text,
54
+ d_factor=rate,
55
+ p_factor=pitch,
56
+ e_factor=energy,
57
+ lang='he'
58
+ )
59
+ outputs = self.model.synthesise(inputs)
60
+ wav = outputs.unbatched_wavs()[0]
61
+ waveform = WaveForm(wav, self.model.sample_rate)
62
+ return waveform
63
+
64
+
israwave/src/israwave/config.json ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "symbols": [
3
+ "_",
4
+ "^",
5
+ "$",
6
+ " ",
7
+ "!",
8
+ "\"",
9
+ "#",
10
+ "'",
11
+ "(",
12
+ ")",
13
+ ",",
14
+ "-",
15
+ ".",
16
+ "0",
17
+ "1",
18
+ "2",
19
+ "3",
20
+ "4",
21
+ "5",
22
+ "6",
23
+ "7",
24
+ "8",
25
+ "9",
26
+ ":",
27
+ ";",
28
+ "?",
29
+ "X",
30
+ "a",
31
+ "b",
32
+ "c",
33
+ "d",
34
+ "e",
35
+ "f",
36
+ "g",
37
+ "h",
38
+ "i",
39
+ "j",
40
+ "k",
41
+ "l",
42
+ "m",
43
+ "n",
44
+ "o",
45
+ "p",
46
+ "q",
47
+ "r",
48
+ "s",
49
+ "t",
50
+ "u",
51
+ "v",
52
+ "w",
53
+ "x",
54
+ "y",
55
+ "z",
56
+ "æ",
57
+ "ç",
58
+ "ð",
59
+ "ø",
60
+ "ħ",
61
+ "ŋ",
62
+ "œ",
63
+ "ǀ",
64
+ "ǁ",
65
+ "ǂ",
66
+ "ǃ",
67
+ "ɐ",
68
+ "ɑ",
69
+ "ɒ",
70
+ "ɓ",
71
+ "ɔ",
72
+ "ɕ",
73
+ "ɖ",
74
+ "ɗ",
75
+ "ɘ",
76
+ "ə",
77
+ "ɚ",
78
+ "ɛ",
79
+ "ɜ",
80
+ "ɞ",
81
+ "ɟ",
82
+ "ɠ",
83
+ "ɡ",
84
+ "ɢ",
85
+ "ɣ",
86
+ "ɤ",
87
+ "ɥ",
88
+ "ɦ",
89
+ "ɧ",
90
+ "ɨ",
91
+ "ɪ",
92
+ "ɫ",
93
+ "ɬ",
94
+ "ɭ",
95
+ "ɮ",
96
+ "ɯ",
97
+ "ɰ",
98
+ "ɱ",
99
+ "ɲ",
100
+ "ɳ",
101
+ "ɴ",
102
+ "ɵ",
103
+ "ɶ",
104
+ "ɸ",
105
+ "ɹ",
106
+ "ɺ",
107
+ "ɻ",
108
+ "ɽ",
109
+ "ɾ",
110
+ "ʀ",
111
+ "ʁ",
112
+ "ʂ",
113
+ "ʃ",
114
+ "ʄ",
115
+ "ʈ",
116
+ "ʉ",
117
+ "ʊ",
118
+ "ʋ",
119
+ "ʌ",
120
+ "ʍ",
121
+ "ʎ",
122
+ "ʏ",
123
+ "ʐ",
124
+ "ʑ",
125
+ "ʒ",
126
+ "ʔ",
127
+ "ʕ",
128
+ "ʘ",
129
+ "ʙ",
130
+ "ʛ",
131
+ "ʜ",
132
+ "ʝ",
133
+ "ʟ",
134
+ "ʡ",
135
+ "ʢ",
136
+ "ʦ",
137
+ "ʰ",
138
+ "ʲ",
139
+ "ˈ",
140
+ "ˌ",
141
+ "ː",
142
+ "ˑ",
143
+ "˞",
144
+ "ˤ",
145
+ "̃",
146
+ "̊",
147
+ "̝",
148
+ "̧",
149
+ "̩",
150
+ "̪",
151
+ "̯",
152
+ "̺",
153
+ "̻",
154
+ "β",
155
+ "ε",
156
+ "θ",
157
+ "χ",
158
+ "ᵻ",
159
+ "↑",
160
+ "↓",
161
+ "ⱱ"
162
+ ],
163
+ "PAD": "_",
164
+ "BOS": "^",
165
+ "EOS": "$"
166
+ }
israwave/src/israwave/helpers.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import soundfile as sf
3
+ import io
4
+
5
+ def text_has_niqqud(text: str) -> bool:
6
+ return any("\u0591" <= char <= "\u05C7" for char in text)
7
+
8
+ def text_has_ipa(text: str) -> bool:
9
+ return any("\u0250" <= char <= "\u02AF" for char in text)
10
+
11
+ def float_to_int16(samples: np.floating) -> np.int16:
12
+ """
13
+ Normalize audio_array if it's floating-point
14
+ """
15
+ if np.issubdtype(samples.dtype, np.floating):
16
+ max_val = np.max(np.abs(samples))
17
+ samples = (samples / max_val) * 32767 # Normalize to 16-bit range
18
+ samples = samples.astype(np.int16)
19
+ return samples
20
+
21
+ def to_ogg(samples: np.array, sample_rate: int):
22
+ # Normalize audio_array if it's floating-point
23
+ samples = float_to_int16(samples)
24
+ # Create in memory buffer of ogg
25
+ buf = io.BytesIO()
26
+ buf.name = 'audio.ogg'
27
+ sf.write(buf, samples, sample_rate, format="ogg")
28
+ buf.seek(0)
29
+ return buf
israwave/src/israwave/logging.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Provide a way to enable logging by setting LOG_LEVEL environment variable
3
+ """
4
+ import logging
5
+ import os
6
+
7
+ # Set default logging level to WARNING if LOG_LEVEL is not set
8
+ log_level = os.getenv("LOG_LEVEL", "WARNING").upper()
9
+ logger = logging.getLogger(__package__)
10
+ logger.setLevel(level=getattr(logging, log_level, logging.WARNING))
11
+ # Setup logging to stdout
12
+ logging.basicConfig(format='%(levelname)s [%(filename)s:%(lineno)d] %(message)s')
13
+
14
+ log = logging.getLogger(__package__)
israwave/src/israwave/model.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from time import perf_counter
3
+ import numpy as np
4
+ import onnxruntime
5
+ from israwave.tokenizer import IPATokenizer
6
+ from .tensors import InferenceInputs, InferenceOutputs
7
+
8
+ class Model:
9
+
10
+ def __init__(self, onnx_path: str, espeak_data_path: str, onnx_providers: list[str] = ["CPUExecutionProvider"]):
11
+ session = onnxruntime.InferenceSession(onnx_path, providers=onnx_providers)
12
+ meta = session.get_modelmeta()
13
+ infer_params = json.loads(meta.custom_metadata_map["inference"])
14
+ self.tokenizer=IPATokenizer(espeak_data_path)
15
+ self.session=session
16
+ self.name=infer_params["name"]
17
+ self.sample_rate=infer_params["sample_rate"]
18
+ self.inference_args=infer_params["inference_args"]
19
+ self.speakers=infer_params["speakers"]
20
+ self.languages=infer_params["languages"]
21
+
22
+ def __post_init__(self):
23
+ self.is_multispeaker = len(self.speakers) > 1
24
+ self.is_multilanguage = len(self.languages) > 1
25
+
26
+ def prepare_input(
27
+ self,
28
+ text: str,
29
+ lang: str | None = None,
30
+ speaker: str | int | None = None,
31
+ d_factor: float|None=None,
32
+ p_factor: float|None=None,
33
+ e_factor: float|None=None,
34
+ ) -> InferenceInputs:
35
+ sid = None
36
+ lid = None
37
+ phids, clean_text = self.tokenizer.tokenize(text=text, language=lang)
38
+
39
+ phids = [phids]
40
+ input_ids = []
41
+ lengths = []
42
+ for phid in phids:
43
+ input_ids.append(phid)
44
+ lengths.append(len(phid))
45
+ sids = [sid] * len(input_ids) if sid is not None else None
46
+ lids = [lid] * len(input_ids) if lid is not None else None
47
+ return InferenceInputs.from_ids_and_lengths(
48
+ ids=input_ids,
49
+ lengths=lengths,
50
+ clean_text=clean_text,
51
+ sids=sids,
52
+ lids=lids,
53
+ d_factor=d_factor or self.inference_args["d_factor"],
54
+ p_factor=p_factor or self.inference_args["p_factor"],
55
+ e_factor=e_factor or self.inference_args["e_factor"],
56
+ )
57
+
58
+ def synthesise(self, inference_inputs: InferenceInputs) -> InferenceOutputs:
59
+ inference_inputs = inference_inputs.as_numpy()
60
+ synth_outs = self.synthesise_with_values(
61
+ x=inference_inputs.x,
62
+ x_lengths=inference_inputs.x_lengths,
63
+ sids=inference_inputs.sids,
64
+ lids=inference_inputs.lids,
65
+ d_factor=inference_inputs.d_factor,
66
+ p_factor=inference_inputs.p_factor,
67
+ e_factor=inference_inputs.e_factor
68
+ )
69
+ return InferenceOutputs(
70
+ wav=synth_outs["wav"],
71
+ wav_lengths=synth_outs["wav_lengths"],
72
+ latency=synth_outs["latency"],
73
+ rtf=synth_outs["rtf"],
74
+ )
75
+
76
+ def synthesise_with_values(self, x, x_lengths, sids, lids, d_factor, p_factor, e_factor):
77
+ inputs = dict(
78
+ x=x,
79
+ x_lengths=x_lengths,
80
+ scales=np.array([d_factor, p_factor, e_factor], dtype=np.float32),
81
+ )
82
+ t0 = perf_counter()
83
+ wav, wav_lengths, durations = self.session.run(None, inputs)
84
+ t_infer = perf_counter() - t0
85
+ t_audio = wav_lengths.sum() / self.sample_rate
86
+ rtf = t_infer / t_audio
87
+ latency = t_infer * 1000
88
+ return dict(wav=wav, wav_lengths=wav_lengths, rtf=rtf, latency=latency)
89
+
90
+
israwave/src/israwave/segment.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from dataclasses import dataclass
3
+ import numpy as np
4
+ from israwave.logging import log
5
+
6
+ @dataclass
7
+ class Segment:
8
+ text: str
9
+ next_pause: float
10
+
11
+ def create_pause(self, sample_rate: int):
12
+ """
13
+ Return array of zeros (silence) with size of the next_pause
14
+ """
15
+ num_samples = int(self.next_pause * sample_rate)
16
+ return np.zeros(num_samples, dtype=np.float32)
17
+
18
+ class SegmentExtractor:
19
+ def __init__(self, default_pause: float = 0.05, question_pause: float = 0.05, dot_pause: float = 0.05, new_line_pause = 0.05, hyphen_pause = 0.01):
20
+ self.default_pause = default_pause
21
+ self.question_pause = question_pause
22
+ self.period_pause = dot_pause
23
+ self.new_line_pause = new_line_pause
24
+ self.hyphen_pause = hyphen_pause
25
+
26
+ def extract_segments(self, text: str):
27
+ """
28
+ Break the text into segment items. eg. on '?' or '.' or '!' or '\n'
29
+ Used later to add pauses when speaking
30
+ """
31
+ log.debug(f'extract segments from {text}')
32
+ sentences = re.split(r'([•.?!:–\n\-])', text)
33
+ for i in range(0, len(sentences) - 1, 2):
34
+ sentence = sentences[i].strip()
35
+ punctuation = sentences[i + 1]
36
+ if sentence: # Ensure the sentence is not empty
37
+ if punctuation == '.':
38
+ yield Segment(text=f"{sentence}{punctuation}", next_pause=self.period_pause)
39
+ elif punctuation == '?':
40
+ yield Segment(text=f"{sentence}{punctuation}", next_pause=self.question_pause)
41
+ elif punctuation == '\n':
42
+ yield Segment(text=f"{sentence}{punctuation}.", next_pause=self.new_line_pause)
43
+ elif punctuation == '-':
44
+ yield Segment(text=f"{sentence}{punctuation}", next_pause=self.hyphen_pause)
45
+ elif punctuation == '•':
46
+ yield Segment(text=f"{sentence}{punctuation}.", next_pause=self.new_line_pause)
47
+ else:
48
+ yield Segment(text=f"{sentence}{punctuation}", next_pause=self.default_pause)
49
+ last_sentence = sentences[-1].strip()
50
+ if last_sentence:
51
+ yield Segment(text=f"{last_sentence}.", next_pause=self.default_pause)
israwave/src/israwave/symbols.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ import json
3
+
4
+ CONFIG_PATH = Path(__file__).parent / 'config.json'
5
+ with open(CONFIG_PATH, encoding='utf-8') as f:
6
+ CONFIG = json.load(f)
7
+ SYMBOLS = CONFIG['symbols']
8
+
9
+ # Special symbols
10
+ PAD = CONFIG['PAD']
11
+ BOS = CONFIG['BOS']
12
+ EOS = CONFIG['EOS']
13
+
14
+ # Special symbol ids
15
+ PAD_ID = SYMBOLS.index(PAD)
16
+ BOS_ID = SYMBOLS.index(BOS)
17
+ EOS_ID = SYMBOLS.index(EOS)
18
+ SPACE_ID = SYMBOLS.index(" ")
19
+
20
+ # Mappings from symbol to numeric ID and vice versa:
21
+ SYMBOL_TO_ID = {s: i for i, s in enumerate(SYMBOLS)}
22
+ ID_TO_SYMBOL = {i: s for i, s in enumerate(SYMBOLS)} # pylint: disable=unnecessary-comprehension
23
+
24
+
25
+ def phonemes_to_ids(text):
26
+ """Converts a string of text to a sequence of IDs corresponding to the symbols in the text.
27
+ Args:
28
+ text: string to convert to a sequence
29
+ Returns:
30
+ List of integers corresponding to the symbols in the text
31
+ """
32
+ sequence = []
33
+ for symbol in text:
34
+ symbol_id = SYMBOL_TO_ID[symbol]
35
+ sequence.append(symbol_id)
36
+ return sequence
37
+
38
+
39
+ def ids_to_phonemes(sequence):
40
+ """Converts a sequence of IDs back to a string"""
41
+ result = ""
42
+ for symbol_id in sequence:
43
+ s = ID_TO_SYMBOL[symbol_id]
44
+ result += s
45
+ return result
israwave/src/israwave/tensors.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import dataclasses
2
+ from dataclasses import dataclass
3
+ from typing import TypeAlias
4
+ import numpy as np
5
+
6
+ FloatArray: TypeAlias = np.ndarray[np.float32]
7
+ IntArray: TypeAlias = np.ndarray[np.int64]
8
+
9
+
10
+ @dataclass
11
+ class BaseTensorContainer:
12
+
13
+ def as_tuple(self):
14
+ return dataclasses.astuple(self)
15
+
16
+ def as_dict(self):
17
+ return dataclasses.asdict(self)
18
+
19
+ def as_numpy(self):
20
+ data = self.as_dict()
21
+ kwargs = {}
22
+ for name, value in self.as_dict().items():
23
+ if isinstance(value, np.ndarray):
24
+ kwargs[name] = np.asarray(value)
25
+ else:
26
+ kwargs[name] = value
27
+ cls = type(self)
28
+ return cls(**kwargs)
29
+
30
+
31
+ @dataclass(kw_only=True)
32
+ class InferenceInputs(BaseTensorContainer):
33
+ clean_text: str
34
+ x: IntArray
35
+ x_lengths: IntArray
36
+ sids: IntArray|None = None
37
+ lids: IntArray|None = None
38
+ d_factor: float = 1.0
39
+ p_factor: float = 1.0
40
+ e_factor: float = 1.0
41
+
42
+ @classmethod
43
+ def from_ids_and_lengths(cls, ids: list[int], lengths: list[int], **kwargs) -> "Self":
44
+ x = numpy_pad_sequences(ids).astype(np.int64)
45
+ x_lengths = np.array(lengths, dtype=np.int64)
46
+ instance = cls(x=x, x_lengths=x_lengths, **kwargs)
47
+ return instance.as_numpy()
48
+
49
+
50
+ @dataclass(kw_only=True)
51
+ class InferenceOutputs(BaseTensorContainer):
52
+ wav: FloatArray
53
+ wav_lengths: FloatArray
54
+ latency: int
55
+ rtf: float
56
+ durations: FloatArray|None = None
57
+ pitch: FloatArray|None = None
58
+ energy: FloatArray|None = None
59
+ am_rtf: float|None = None
60
+ v_rtf: float|None = None
61
+
62
+ def __iter__(self):
63
+ return iter(self.unbatched_wavs())
64
+
65
+ def unbatched_wavs(self) -> list[FloatArray]:
66
+ if isinstance(self.wav, np.ndarray):
67
+ return numpy_unpad_sequences(self.wav, self.wav_lengths)
68
+ else:
69
+ raise RuntimeError("Unsupported operation")
70
+
71
+
72
+ def numpy_pad_sequences(sequences, maxlen=None, value=0):
73
+ """Pads a list of sequences to the same length using broadcasting.
74
+
75
+ Args:
76
+ sequences: A list of Python lists with variable lengths.
77
+ maxlen: The maximum length to pad the sequences to. If not specified,
78
+ the maximum length of all sequences in the list will be used.
79
+ value: The value to use for padding (default 0).
80
+
81
+ Returns:
82
+ A numpy array with shape [batch_size, maxlen] where the sequences are padded
83
+ with the specified value.
84
+ """
85
+
86
+ # Get the maximum length if not specified
87
+ if maxlen is None:
88
+ maxlen = max(len(seq) for seq in sequences)
89
+
90
+ # Create a numpy array with the specified value and broadcast
91
+ padded_seqs = np.full((len(sequences), maxlen), value)
92
+ for i, seq in enumerate(sequences):
93
+ padded_seqs[i, : len(seq)] = seq
94
+
95
+ return padded_seqs
96
+
97
+
98
+ def numpy_unpad_sequences(sequences, lengths):
99
+ """Unpads a list of sequences based on a list of lengths.
100
+
101
+ Args:
102
+ sequences: A numpy array with shape [batch_size, feature_dim, max_len].
103
+ lengths: A numpy array with shape [batch_size] representing the lengths
104
+ of each sequence in the batch.
105
+
106
+ Returns:
107
+ A list of unpadded sequences. The i-th element of the list corresponds
108
+ to the i-th sequence in the batch. Each sequence is a numpy array with
109
+ variable length.
110
+ """
111
+
112
+ # Check if lengths argument is a list or 1D numpy array
113
+ if not isinstance(lengths, np.ndarray) or len(lengths.shape) != 1:
114
+ raise ValueError("lengths must be a 1D numpy array")
115
+
116
+ # Check if sequence lengths are within bounds
117
+ if np.any(lengths < 0) or np.any(lengths > sequences.shape[-1]):
118
+ raise ValueError("lengths must be between 0 and max_len")
119
+
120
+ # Get the batch size
121
+ batch_size = sequences.shape[0]
122
+
123
+ # Extract unpadded sequences
124
+ unpadded_seqs = []
125
+ for i in range(batch_size):
126
+ unpadded_seqs.append(sequences[i, : lengths[i]])
127
+
128
+ return unpadded_seqs
129
+
israwave/src/israwave/tokenizer.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from .symbols import phonemes_to_ids
3
+ from israwave.logging import log
4
+ from phonemizer.backend.espeak.wrapper import EspeakWrapper
5
+ import phonemizer
6
+ import espeakng_loader
7
+
8
+ WHITESPACE_RE = re.compile(r"\s+")
9
+
10
+ class IPATokenizer:
11
+ def __init__(self, espeak_data_path = None) -> None:
12
+ EspeakWrapper.set_library(espeakng_loader.get_library_path())
13
+ EspeakWrapper.set_data_path(espeak_data_path or espeakng_loader.get_data_path())
14
+
15
+ def preprocess_text(self, text, _language):
16
+ return self.collapse_whitespace(text)
17
+
18
+ def collapse_whitespace(self, text):
19
+ text = re.sub(WHITESPACE_RE, " ", text)
20
+ return text
21
+
22
+ def phonemize_text(self, text: str, language: str) -> str:
23
+ # Preprocess
24
+ text = self.preprocess_text(text, language)
25
+ # Phonemize
26
+ phonemes = phonemizer.phonemize(text, language, preserve_punctuation=True, with_stress=True)
27
+ return phonemes, text
28
+
29
+ def tokenize(self, text, language):
30
+ try:
31
+ # Accept phonemes directly
32
+ phoneme_ids, normalized_text = phonemes_to_ids(text), self.preprocess_text(text, 'he')
33
+ except:
34
+ # Create phoenems
35
+ phonemes, normalized_text = self.phonemize_text(text, language)
36
+ phonemes = [phoneme for sentence_phonemes in phonemes for phoneme in sentence_phonemes]
37
+ phonemes = list(self.collapse_whitespace("".join(phonemes)))
38
+ phoneme_ids = phonemes_to_ids(phonemes)
39
+ log.debug(f"phonemes: {''.join(phonemes)} text: {text}")
40
+ return phoneme_ids, normalized_text
israwave/uv.lock ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version = 1
2
+ requires-python = ">=3.12"
3
+
4
+ [[package]]
5
+ name = "cffi"
6
+ version = "1.17.1"
7
+ source = { registry = "https://pypi.org/simple" }
8
+ dependencies = [
9
+ { name = "pycparser" },
10
+ ]
11
+ sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 }
12
+ wheels = [
13
+ { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 },
14
+ { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 },
15
+ { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 },
16
+ { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 },
17
+ { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 },
18
+ { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 },
19
+ { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 },
20
+ { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 },
21
+ { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 },
22
+ { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 },
23
+ { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 },
24
+ { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 },
25
+ { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 },
26
+ { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 },
27
+ { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 },
28
+ { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 },
29
+ { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 },
30
+ { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 },
31
+ { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 },
32
+ { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 },
33
+ { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 },
34
+ { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 },
35
+ ]
36
+
37
+ [[package]]
38
+ name = "coloredlogs"
39
+ version = "15.0.1"
40
+ source = { registry = "https://pypi.org/simple" }
41
+ dependencies = [
42
+ { name = "humanfriendly" },
43
+ ]
44
+ sdist = { url = "https://files.pythonhosted.org/packages/cc/c7/eed8f27100517e8c0e6b923d5f0845d0cb99763da6fdee00478f91db7325/coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0", size = 278520 }
45
+ wheels = [
46
+ { url = "https://files.pythonhosted.org/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934", size = 46018 },
47
+ ]
48
+
49
+ [[package]]
50
+ name = "flatbuffers"
51
+ version = "24.3.25"
52
+ source = { registry = "https://pypi.org/simple" }
53
+ sdist = { url = "https://files.pythonhosted.org/packages/a9/74/2df95ef84b214d2bee0886d572775a6f38793f5ca6d7630c3239c91104ac/flatbuffers-24.3.25.tar.gz", hash = "sha256:de2ec5b203f21441716617f38443e0a8ebf3d25bf0d9c0bb0ce68fa00ad546a4", size = 22139 }
54
+ wheels = [
55
+ { url = "https://files.pythonhosted.org/packages/41/f0/7e988a019bc54b2dbd0ad4182ef2d53488bb02e58694cd79d61369e85900/flatbuffers-24.3.25-py2.py3-none-any.whl", hash = "sha256:8dbdec58f935f3765e4f7f3cf635ac3a77f83568138d6a2311f524ec96364812", size = 26784 },
56
+ ]
57
+
58
+ [[package]]
59
+ name = "humanfriendly"
60
+ version = "10.0"
61
+ source = { registry = "https://pypi.org/simple" }
62
+ dependencies = [
63
+ { name = "pyreadline3", marker = "sys_platform == 'win32'" },
64
+ ]
65
+ sdist = { url = "https://files.pythonhosted.org/packages/cc/3f/2c29224acb2e2df4d2046e4c73ee2662023c58ff5b113c4c1adac0886c43/humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc", size = 360702 }
66
+ wheels = [
67
+ { url = "https://files.pythonhosted.org/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477", size = 86794 },
68
+ ]
69
+
70
+ [[package]]
71
+ name = "israwave"
72
+ version = "0.1.7"
73
+ source = { editable = "." }
74
+ dependencies = [
75
+ { name = "nakdimon-ort" },
76
+ { name = "numpy" },
77
+ { name = "onnxruntime" },
78
+ { name = "piper-phonemize-cross", marker = "platform_system == 'Linux'" },
79
+ { name = "piper-phonemize-fork", marker = "platform_system != 'Linux'" },
80
+ { name = "sounddevice" },
81
+ { name = "soundfile" },
82
+ ]
83
+
84
+ [package.metadata]
85
+ requires-dist = [
86
+ { name = "nakdimon-ort", specifier = ">=0.1.5" },
87
+ { name = "numpy", specifier = ">=2.1.1" },
88
+ { name = "onnxruntime", specifier = ">=1.19.2" },
89
+ { name = "piper-phonemize-cross", marker = "platform_system == 'Linux'", specifier = ">=1.2.1" },
90
+ { name = "piper-phonemize-fork", marker = "platform_system != 'Linux'", specifier = ">=1.2.0" },
91
+ { name = "sounddevice", specifier = ">=0.5.0" },
92
+ { name = "soundfile", specifier = ">=0.12.1" },
93
+ ]
94
+
95
+ [[package]]
96
+ name = "mpmath"
97
+ version = "1.3.0"
98
+ source = { registry = "https://pypi.org/simple" }
99
+ sdist = { url = "https://files.pythonhosted.org/packages/e0/47/dd32fa426cc72114383ac549964eecb20ecfd886d1e5ccf5340b55b02f57/mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f", size = 508106 }
100
+ wheels = [
101
+ { url = "https://files.pythonhosted.org/packages/43/e3/7d92a15f894aa0c9c4b49b8ee9ac9850d6e63b03c9c32c0367a13ae62209/mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c", size = 536198 },
102
+ ]
103
+
104
+ [[package]]
105
+ name = "nakdimon-ort"
106
+ version = "0.1.5"
107
+ source = { registry = "https://pypi.org/simple" }
108
+ dependencies = [
109
+ { name = "onnxruntime" },
110
+ ]
111
+ sdist = { url = "https://files.pythonhosted.org/packages/89/81/d4627b4fe4871984ba2f6031f6c7601065081d1cbfd831afc54246a771bc/nakdimon_ort-0.1.5.tar.gz", hash = "sha256:08f2627d2ce45f4a6ec4bf6ef20d38c8ecb70e19a627e0d151770b843c9a4c58", size = 3085 }
112
+ wheels = [
113
+ { url = "https://files.pythonhosted.org/packages/7c/2f/21ab47e2bc163d4f04e1c0a2b6efde951b1307d1e57452b740be671ca0ac/nakdimon_ort-0.1.5-py2.py3-none-any.whl", hash = "sha256:d471b66b038169c4538e99fa3df3268a9661512c8112362f55eb395d2d6ffded", size = 3931 },
114
+ ]
115
+
116
+ [[package]]
117
+ name = "numpy"
118
+ version = "2.2.0"
119
+ source = { registry = "https://pypi.org/simple" }
120
+ sdist = { url = "https://files.pythonhosted.org/packages/47/1b/1d565e0f6e156e1522ab564176b8b29d71e13d8caf003a08768df3d5cec5/numpy-2.2.0.tar.gz", hash = "sha256:140dd80ff8981a583a60980be1a655068f8adebf7a45a06a6858c873fcdcd4a0", size = 20225497 }
121
+ wheels = [
122
+ { url = "https://files.pythonhosted.org/packages/7f/bc/a20dc4e1d051149052762e7647455311865d11c603170c476d1e910a353e/numpy-2.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cff210198bb4cae3f3c100444c5eaa573a823f05c253e7188e1362a5555235b3", size = 20909153 },
123
+ { url = "https://files.pythonhosted.org/packages/60/3d/ac4fb63f36db94f4c7db05b45e3ecb3f88f778ca71850664460c78cfde41/numpy-2.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:58b92a5828bd4d9aa0952492b7de803135038de47343b2aa3cc23f3b71a3dc4e", size = 14095021 },
124
+ { url = "https://files.pythonhosted.org/packages/41/6d/a654d519d24e4fcc7a83d4a51209cda086f26cf30722b3d8ffc1aa9b775e/numpy-2.2.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:ebe5e59545401fbb1b24da76f006ab19734ae71e703cdb4a8b347e84a0cece67", size = 5125491 },
125
+ { url = "https://files.pythonhosted.org/packages/e6/22/fab7e1510a62e5092f4e6507a279020052b89f11d9cfe52af7f52c243b04/numpy-2.2.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e2b8cd48a9942ed3f85b95ca4105c45758438c7ed28fff1e4ce3e57c3b589d8e", size = 6658534 },
126
+ { url = "https://files.pythonhosted.org/packages/fc/29/a3d938ddc5a534cd53df7ab79d20a68db8c67578de1df0ae0118230f5f54/numpy-2.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57fcc997ffc0bef234b8875a54d4058afa92b0b0c4223fc1f62f24b3b5e86038", size = 14046306 },
127
+ { url = "https://files.pythonhosted.org/packages/90/24/d0bbb56abdd8934f30384632e3c2ca1ebfeb5d17e150c6e366ba291de36b/numpy-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ad7d11b309bd132d74397fcf2920933c9d1dc865487128f5c03d580f2c3d03", size = 16095819 },
128
+ { url = "https://files.pythonhosted.org/packages/99/9c/58a673faa9e8a0e77248e782f7a17410cf7259b326265646fd50ed49c4e1/numpy-2.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cb24cca1968b21355cc6f3da1a20cd1cebd8a023e3c5b09b432444617949085a", size = 15243215 },
129
+ { url = "https://files.pythonhosted.org/packages/9c/61/f311693f78cbf635cfb69ce9e1e857ff83937a27d93c96ac5932fd33e330/numpy-2.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0798b138c291d792f8ea40fe3768610f3c7dd2574389e37c3f26573757c8f7ef", size = 17860175 },
130
+ { url = "https://files.pythonhosted.org/packages/11/3e/491c34262cb1fc9dd13a00beb80d755ee0517b17db20e54cac7aa524533e/numpy-2.2.0-cp312-cp312-win32.whl", hash = "sha256:afe8fb968743d40435c3827632fd36c5fbde633b0423da7692e426529b1759b1", size = 6273281 },
131
+ { url = "https://files.pythonhosted.org/packages/89/ea/00537f599eb230771157bc509f6ea5b2dddf05d4b09f9d2f1d7096a18781/numpy-2.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:3a4199f519e57d517ebd48cb76b36c82da0360781c6a0353e64c0cac30ecaad3", size = 12613227 },
132
+ { url = "https://files.pythonhosted.org/packages/bd/4c/0d1eef206545c994289e7a9de21b642880a11e0ed47a2b0c407c688c4f69/numpy-2.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f8c8b141ef9699ae777c6278b52c706b653bf15d135d302754f6b2e90eb30367", size = 20895707 },
133
+ { url = "https://files.pythonhosted.org/packages/16/cb/88f6c1e6df83002c421d5f854ccf134aa088aa997af786a5dac3f32ec99b/numpy-2.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0f0986e917aca18f7a567b812ef7ca9391288e2acb7a4308aa9d265bd724bdae", size = 14110592 },
134
+ { url = "https://files.pythonhosted.org/packages/b4/54/817e6894168a43f33dca74199ba0dd0f1acd99aa6323ed6d323d63d640a2/numpy-2.2.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:1c92113619f7b272838b8d6702a7f8ebe5edea0df48166c47929611d0b4dea69", size = 5110858 },
135
+ { url = "https://files.pythonhosted.org/packages/c7/99/00d8a1a8eb70425bba7880257ed73fed08d3e8d05da4202fb6b9a81d5ee4/numpy-2.2.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5a145e956b374e72ad1dff82779177d4a3c62bc8248f41b80cb5122e68f22d13", size = 6645143 },
136
+ { url = "https://files.pythonhosted.org/packages/34/86/5b9c2b7c56e7a9d9297a0a4be0b8433f498eba52a8f5892d9132b0f64627/numpy-2.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18142b497d70a34b01642b9feabb70156311b326fdddd875a9981f34a369b671", size = 14042812 },
137
+ { url = "https://files.pythonhosted.org/packages/df/54/13535f74391dbe5f479ceed96f1403267be302c840040700d4fd66688089/numpy-2.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7d41d1612c1a82b64697e894b75db6758d4f21c3ec069d841e60ebe54b5b571", size = 16093419 },
138
+ { url = "https://files.pythonhosted.org/packages/dd/37/dfb2056842ac61315f225aa56f455da369f5223e4c5a38b91d20da1b628b/numpy-2.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a98f6f20465e7618c83252c02041517bd2f7ea29be5378f09667a8f654a5918d", size = 15238969 },
139
+ { url = "https://files.pythonhosted.org/packages/5a/3d/d20d24ee313992f0b7e7b9d9eef642d9b545d39d5b91c4a2cc8c98776328/numpy-2.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e09d40edfdb4e260cb1567d8ae770ccf3b8b7e9f0d9b5c2a9992696b30ce2742", size = 17855705 },
140
+ { url = "https://files.pythonhosted.org/packages/5b/40/944c9ee264f875a2db6f79380944fd2b5bb9d712bb4a134d11f45ad5b693/numpy-2.2.0-cp313-cp313-win32.whl", hash = "sha256:3905a5fffcc23e597ee4d9fb3fcd209bd658c352657548db7316e810ca80458e", size = 6270078 },
141
+ { url = "https://files.pythonhosted.org/packages/30/04/e1ee6f8b22034302d4c5c24e15782bdedf76d90b90f3874ed0b48525def0/numpy-2.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:a184288538e6ad699cbe6b24859206e38ce5fba28f3bcfa51c90d0502c1582b2", size = 12605791 },
142
+ { url = "https://files.pythonhosted.org/packages/ef/fb/51d458625cd6134d60ac15180ae50995d7d21b0f2f92a6286ae7b0792d19/numpy-2.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7832f9e8eb00be32f15fdfb9a981d6955ea9adc8574c521d48710171b6c55e95", size = 20920160 },
143
+ { url = "https://files.pythonhosted.org/packages/b4/34/162ae0c5d2536ea4be98c813b5161c980f0443cd5765fde16ddfe3450140/numpy-2.2.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f0dd071b95bbca244f4cb7f70b77d2ff3aaaba7fa16dc41f58d14854a6204e6c", size = 14119064 },
144
+ { url = "https://files.pythonhosted.org/packages/17/6c/4195dd0e1c41c55f466d516e17e9e28510f32af76d23061ea3da67438e3c/numpy-2.2.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:b0b227dcff8cdc3efbce66d4e50891f04d0a387cce282fe1e66199146a6a8fca", size = 5152778 },
145
+ { url = "https://files.pythonhosted.org/packages/2f/47/ea804ae525832c8d05ed85b560dfd242d34e4bb0962bc269ccaa720fb934/numpy-2.2.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:6ab153263a7c5ccaf6dfe7e53447b74f77789f28ecb278c3b5d49db7ece10d6d", size = 6667605 },
146
+ { url = "https://files.pythonhosted.org/packages/76/99/34d20e50b3d894bb16b5374bfbee399ab8ff3a33bf1e1f0b8acfe7bbd70d/numpy-2.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e500aba968a48e9019e42c0c199b7ec0696a97fa69037bea163b55398e390529", size = 14013275 },
147
+ { url = "https://files.pythonhosted.org/packages/69/8f/a1df7bd02d434ab82539517d1b98028985700cfc4300bc5496fb140ca648/numpy-2.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:440cfb3db4c5029775803794f8638fbdbf71ec702caf32735f53b008e1eaece3", size = 16074900 },
148
+ { url = "https://files.pythonhosted.org/packages/04/94/b419e7a76bf21a00fcb03c613583f10e389fdc8dfe420412ff5710c8ad3d/numpy-2.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a55dc7a7f0b6198b07ec0cd445fbb98b05234e8b00c5ac4874a63372ba98d4ab", size = 15219122 },
149
+ { url = "https://files.pythonhosted.org/packages/65/d9/dddf398b2b6c5d750892a207a469c2854a8db0f033edaf72103af8cf05aa/numpy-2.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4bddbaa30d78c86329b26bd6aaaea06b1e47444da99eddac7bf1e2fab717bd72", size = 17851668 },
150
+ { url = "https://files.pythonhosted.org/packages/d4/dc/09a4e5819a9782a213c0eb4eecacdc1cd75ad8dac99279b04cfccb7eeb0a/numpy-2.2.0-cp313-cp313t-win32.whl", hash = "sha256:30bf971c12e4365153afb31fc73f441d4da157153f3400b82db32d04de1e4066", size = 6325288 },
151
+ { url = "https://files.pythonhosted.org/packages/ce/e1/e0d06ec34036c92b43aef206efe99a5f5f04e12c776eab82a36e00c40afc/numpy-2.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:d35717333b39d1b6bb8433fa758a55f1081543de527171543a2b710551d40881", size = 12692303 },
152
+ ]
153
+
154
+ [[package]]
155
+ name = "onnxruntime"
156
+ version = "1.20.1"
157
+ source = { registry = "https://pypi.org/simple" }
158
+ dependencies = [
159
+ { name = "coloredlogs" },
160
+ { name = "flatbuffers" },
161
+ { name = "numpy" },
162
+ { name = "packaging" },
163
+ { name = "protobuf" },
164
+ { name = "sympy" },
165
+ ]
166
+ wheels = [
167
+ { url = "https://files.pythonhosted.org/packages/e5/39/9335e0874f68f7d27103cbffc0e235e32e26759202df6085716375c078bb/onnxruntime-1.20.1-cp312-cp312-macosx_13_0_universal2.whl", hash = "sha256:22b0655e2bf4f2161d52706e31f517a0e54939dc393e92577df51808a7edc8c9", size = 31007580 },
168
+ { url = "https://files.pythonhosted.org/packages/c5/9d/a42a84e10f1744dd27c6f2f9280cc3fb98f869dd19b7cd042e391ee2ab61/onnxruntime-1.20.1-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f1f56e898815963d6dc4ee1c35fc6c36506466eff6d16f3cb9848cea4e8c8172", size = 11952833 },
169
+ { url = "https://files.pythonhosted.org/packages/47/42/2f71f5680834688a9c81becbe5c5bb996fd33eaed5c66ae0606c3b1d6a02/onnxruntime-1.20.1-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bb71a814f66517a65628c9e4a2bb530a6edd2cd5d87ffa0af0f6f773a027d99e", size = 13333903 },
170
+ { url = "https://files.pythonhosted.org/packages/c8/f1/aabfdf91d013320aa2fc46cf43c88ca0182860ff15df872b4552254a9680/onnxruntime-1.20.1-cp312-cp312-win32.whl", hash = "sha256:bd386cc9ee5f686ee8a75ba74037750aca55183085bf1941da8efcfe12d5b120", size = 9814562 },
171
+ { url = "https://files.pythonhosted.org/packages/dd/80/76979e0b744307d488c79e41051117634b956612cc731f1028eb17ee7294/onnxruntime-1.20.1-cp312-cp312-win_amd64.whl", hash = "sha256:19c2d843eb074f385e8bbb753a40df780511061a63f9def1b216bf53860223fb", size = 11331482 },
172
+ { url = "https://files.pythonhosted.org/packages/f7/71/c5d980ac4189589267a06f758bd6c5667d07e55656bed6c6c0580733ad07/onnxruntime-1.20.1-cp313-cp313-macosx_13_0_universal2.whl", hash = "sha256:cc01437a32d0042b606f462245c8bbae269e5442797f6213e36ce61d5abdd8cc", size = 31007574 },
173
+ { url = "https://files.pythonhosted.org/packages/81/0d/13bbd9489be2a6944f4a940084bfe388f1100472f38c07080a46fbd4ab96/onnxruntime-1.20.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb44b08e017a648924dbe91b82d89b0c105b1adcfe31e90d1dc06b8677ad37be", size = 11951459 },
174
+ { url = "https://files.pythonhosted.org/packages/c0/ea/4454ae122874fd52bbb8a961262de81c5f932edeb1b72217f594c700d6ef/onnxruntime-1.20.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bda6aebdf7917c1d811f21d41633df00c58aff2bef2f598f69289c1f1dabc4b3", size = 13331620 },
175
+ { url = "https://files.pythonhosted.org/packages/d8/e0/50db43188ca1c945decaa8fc2a024c33446d31afed40149897d4f9de505f/onnxruntime-1.20.1-cp313-cp313-win_amd64.whl", hash = "sha256:d30367df7e70f1d9fc5a6a68106f5961686d39b54d3221f760085524e8d38e16", size = 11331758 },
176
+ { url = "https://files.pythonhosted.org/packages/d8/55/3821c5fd60b52a6c82a00bba18531793c93c4addfe64fbf061e235c5617a/onnxruntime-1.20.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9158465745423b2b5d97ed25aa7740c7d38d2993ee2e5c3bfacb0c4145c49d8", size = 11950342 },
177
+ { url = "https://files.pythonhosted.org/packages/14/56/fd990ca222cef4f9f4a9400567b9a15b220dee2eafffb16b2adbc55c8281/onnxruntime-1.20.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0df6f2df83d61f46e842dbcde610ede27218947c33e994545a22333491e72a3b", size = 13337040 },
178
+ ]
179
+
180
+ [[package]]
181
+ name = "packaging"
182
+ version = "24.2"
183
+ source = { registry = "https://pypi.org/simple" }
184
+ sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 }
185
+ wheels = [
186
+ { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 },
187
+ ]
188
+
189
+ [[package]]
190
+ name = "piper-phonemize-cross"
191
+ version = "1.2.1"
192
+ source = { registry = "https://pypi.org/simple" }
193
+ wheels = [
194
+ { url = "https://files.pythonhosted.org/packages/f0/f4/8f16aa5c2322495c920ae330beb6d2ac666e52c2a18380bf0e8fb6b0426a/piper_phonemize_cross-1.2.1-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:2d64cbbc8ceec7614032cd0d86eeb49a678fd430f02833d43914108a384034ea", size = 15127861 },
195
+ { url = "https://files.pythonhosted.org/packages/76/3f/f3d1e2d5ef7005abf6f7812d06b471788346dda2b82de285ae87ab45a9fa/piper_phonemize_cross-1.2.1-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f171d5bd5a7e19871c9ef6b5a21390020587034ad140bc678d9360bc1627df1d", size = 15575585 },
196
+ ]
197
+
198
+ [[package]]
199
+ name = "piper-phonemize-fork"
200
+ version = "1.2.0"
201
+ source = { registry = "https://pypi.org/simple" }
202
+ wheels = [
203
+ { url = "https://files.pythonhosted.org/packages/7c/c2/31df52c152be3ac759c3033a3aa43f068f659f0ba04693f3a7a9d140f317/piper_phonemize_fork-1.2.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:575ee14d1624cd3ead3de8ccd9e19176997b32ec091982c13c2bc7db208849ed", size = 15071519 },
204
+ { url = "https://files.pythonhosted.org/packages/9e/75/b9036c6950eecfa7b2648f3d29e99b9ec4edcb370fbdd17f1a3db8d923bd/piper_phonemize_fork-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:7445ac1fd72db91ec9ba5bde5c0c4a367ab38db86bf1e1da944631e205bdfbad", size = 12951593 },
205
+ ]
206
+
207
+ [[package]]
208
+ name = "protobuf"
209
+ version = "5.29.1"
210
+ source = { registry = "https://pypi.org/simple" }
211
+ sdist = { url = "https://files.pythonhosted.org/packages/d2/4f/1639b7b1633d8fd55f216ba01e21bf2c43384ab25ef3ddb35d85a52033e8/protobuf-5.29.1.tar.gz", hash = "sha256:683be02ca21a6ffe80db6dd02c0b5b2892322c59ca57fd6c872d652cb80549cb", size = 424965 }
212
+ wheels = [
213
+ { url = "https://files.pythonhosted.org/packages/50/c7/28669b04691a376cf7d0617d612f126aa0fff763d57df0142f9bf474c5b8/protobuf-5.29.1-cp310-abi3-win32.whl", hash = "sha256:22c1f539024241ee545cbcb00ee160ad1877975690b16656ff87dde107b5f110", size = 422706 },
214
+ { url = "https://files.pythonhosted.org/packages/e3/33/dc7a7712f457456b7e0b16420ab8ba1cc8686751d3f28392eb43d0029ab9/protobuf-5.29.1-cp310-abi3-win_amd64.whl", hash = "sha256:1fc55267f086dd4050d18ef839d7bd69300d0d08c2a53ca7df3920cc271a3c34", size = 434505 },
215
+ { url = "https://files.pythonhosted.org/packages/e5/39/44239fb1c6ec557e1731d996a5de89a9eb1ada7a92491fcf9c5d714052ed/protobuf-5.29.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:d473655e29c0c4bbf8b69e9a8fb54645bc289dead6d753b952e7aa660254ae18", size = 417822 },
216
+ { url = "https://files.pythonhosted.org/packages/fb/4a/ec56f101d38d4bef2959a9750209809242d86cf8b897db00f2f98bfa360e/protobuf-5.29.1-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:b5ba1d0e4c8a40ae0496d0e2ecfdbb82e1776928a205106d14ad6985a09ec155", size = 319572 },
217
+ { url = "https://files.pythonhosted.org/packages/04/52/c97c58a33b3d6c89a8138788576d372a90a6556f354799971c6b4d16d871/protobuf-5.29.1-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:8ee1461b3af56145aca2800e6a3e2f928108c749ba8feccc6f5dd0062c410c0d", size = 319671 },
218
+ { url = "https://files.pythonhosted.org/packages/3b/24/c8c49df8f6587719e1d400109b16c10c6902d0c9adddc8fff82840146f99/protobuf-5.29.1-py3-none-any.whl", hash = "sha256:32600ddb9c2a53dedc25b8581ea0f1fd8ea04956373c0c07577ce58d312522e0", size = 172547 },
219
+ ]
220
+
221
+ [[package]]
222
+ name = "pycparser"
223
+ version = "2.22"
224
+ source = { registry = "https://pypi.org/simple" }
225
+ sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 }
226
+ wheels = [
227
+ { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 },
228
+ ]
229
+
230
+ [[package]]
231
+ name = "pyreadline3"
232
+ version = "3.5.4"
233
+ source = { registry = "https://pypi.org/simple" }
234
+ sdist = { url = "https://files.pythonhosted.org/packages/0f/49/4cea918a08f02817aabae639e3d0ac046fef9f9180518a3ad394e22da148/pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7", size = 99839 }
235
+ wheels = [
236
+ { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178 },
237
+ ]
238
+
239
+ [[package]]
240
+ name = "sounddevice"
241
+ version = "0.5.1"
242
+ source = { registry = "https://pypi.org/simple" }
243
+ dependencies = [
244
+ { name = "cffi" },
245
+ ]
246
+ sdist = { url = "https://files.pythonhosted.org/packages/80/2d/b04ae180312b81dbb694504bee170eada5372242e186f6298139fd3a0513/sounddevice-0.5.1.tar.gz", hash = "sha256:09ca991daeda8ce4be9ac91e15a9a81c8f81efa6b695a348c9171ea0c16cb041", size = 52896 }
247
+ wheels = [
248
+ { url = "https://files.pythonhosted.org/packages/06/d1/464b5fca3decdd0cfec8c47f7b4161a0b12972453201c1bf03811f367c5e/sounddevice-0.5.1-py3-none-any.whl", hash = "sha256:e2017f182888c3f3c280d9fbac92e5dbddac024a7e3442f6e6116bd79dab8a9c", size = 32276 },
249
+ { url = "https://files.pythonhosted.org/packages/6f/f6/6703fe7cf3d7b7279040c792aeec6334e7305956aba4a80f23e62c8fdc44/sounddevice-0.5.1-py3-none-macosx_10_6_x86_64.macosx_10_6_universal2.whl", hash = "sha256:d16cb23d92322526a86a9490c427bf8d49e273d9ccc0bd096feecd229cde6031", size = 107916 },
250
+ { url = "https://files.pythonhosted.org/packages/57/a5/78a5e71f5ec0faedc54f4053775d61407bfbd7d0c18228c7f3d4252fd276/sounddevice-0.5.1-py3-none-win32.whl", hash = "sha256:d84cc6231526e7a08e89beff229c37f762baefe5e0cc2747cbe8e3a565470055", size = 312494 },
251
+ { url = "https://files.pythonhosted.org/packages/af/9b/15217b04f3b36d30de55fef542389d722de63f1ad81f9c72d8afc98cb6ab/sounddevice-0.5.1-py3-none-win_amd64.whl", hash = "sha256:4313b63f2076552b23ac3e0abd3bcfc0c1c6a696fc356759a13bd113c9df90f1", size = 363634 },
252
+ ]
253
+
254
+ [[package]]
255
+ name = "soundfile"
256
+ version = "0.12.1"
257
+ source = { registry = "https://pypi.org/simple" }
258
+ dependencies = [
259
+ { name = "cffi" },
260
+ ]
261
+ sdist = { url = "https://files.pythonhosted.org/packages/6f/96/5ff33900998bad58d5381fd1acfcdac11cbea4f08fc72ac1dc25ffb13f6a/soundfile-0.12.1.tar.gz", hash = "sha256:e8e1017b2cf1dda767aef19d2fd9ee5ebe07e050d430f77a0a7c66ba08b8cdae", size = 43184 }
262
+ wheels = [
263
+ { url = "https://files.pythonhosted.org/packages/04/bc/cd845c2dbb4d257c744cd58a5bcdd9f6d235ca317e7e22e49564ec88dcd9/soundfile-0.12.1-py2.py3-none-any.whl", hash = "sha256:828a79c2e75abab5359f780c81dccd4953c45a2c4cd4f05ba3e233ddf984b882", size = 24030 },
264
+ { url = "https://files.pythonhosted.org/packages/c8/73/059c84343be6509b480013bf1eeb11b96c5f9eb48deff8f83638011f6b2c/soundfile-0.12.1-py2.py3-none-macosx_10_9_x86_64.whl", hash = "sha256:d922be1563ce17a69582a352a86f28ed8c9f6a8bc951df63476ffc310c064bfa", size = 1213305 },
265
+ { url = "https://files.pythonhosted.org/packages/71/87/31d2b9ed58975cec081858c01afaa3c43718eb0f62b5698a876d94739ad0/soundfile-0.12.1-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:bceaab5c4febb11ea0554566784bcf4bc2e3977b53946dda2b12804b4fe524a8", size = 1075977 },
266
+ { url = "https://files.pythonhosted.org/packages/ad/bd/0602167a213d9184fc688b1086dc6d374b7ae8c33eccf169f9b50ce6568c/soundfile-0.12.1-py2.py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:2dc3685bed7187c072a46ab4ffddd38cef7de9ae5eb05c03df2ad569cf4dacbc", size = 1257765 },
267
+ { url = "https://files.pythonhosted.org/packages/c1/07/7591f4efd29e65071c3a61b53725036ea8f73366a4920a481ebddaf8d0ca/soundfile-0.12.1-py2.py3-none-manylinux_2_31_x86_64.whl", hash = "sha256:074247b771a181859d2bc1f98b5ebf6d5153d2c397b86ee9e29ba602a8dfe2a6", size = 1174746 },
268
+ { url = "https://files.pythonhosted.org/packages/03/0f/49941ed8a2d94e5b36ea94346fb1d2b22e847fede902e05be4c96f26be7d/soundfile-0.12.1-py2.py3-none-win32.whl", hash = "sha256:59dfd88c79b48f441bbf6994142a19ab1de3b9bb7c12863402c2bc621e49091a", size = 888234 },
269
+ { url = "https://files.pythonhosted.org/packages/50/ff/26a4ee48d0b66625a4e4028a055b9f25bc9d7c7b2d17d21a45137621a50d/soundfile-0.12.1-py2.py3-none-win_amd64.whl", hash = "sha256:0d86924c00b62552b650ddd28af426e3ff2d4dc2e9047dae5b3d8452e0a49a77", size = 1009109 },
270
+ ]
271
+
272
+ [[package]]
273
+ name = "sympy"
274
+ version = "1.13.3"
275
+ source = { registry = "https://pypi.org/simple" }
276
+ dependencies = [
277
+ { name = "mpmath" },
278
+ ]
279
+ sdist = { url = "https://files.pythonhosted.org/packages/11/8a/5a7fd6284fa8caac23a26c9ddf9c30485a48169344b4bd3b0f02fef1890f/sympy-1.13.3.tar.gz", hash = "sha256:b27fd2c6530e0ab39e275fc9b683895367e51d5da91baa8d3d64db2565fec4d9", size = 7533196 }
280
+ wheels = [
281
+ { url = "https://files.pythonhosted.org/packages/99/ff/c87e0622b1dadea79d2fb0b25ade9ed98954c9033722eb707053d310d4f3/sympy-1.13.3-py3-none-any.whl", hash = "sha256:54612cf55a62755ee71824ce692986f23c88ffa77207b30c1368eda4a7060f73", size = 6189483 },
282
+ ]