Spaces:
Running on Zero
Running on Zero
Upload folder using huggingface_hub
Browse files
README.md
CHANGED
|
@@ -26,20 +26,22 @@ The token stream is untouched, so the codec still runs at **0.1625 kbps**
|
|
| 26 |
|
| 27 |
| Tab | What it shows |
|
| 28 |
| --- | --- |
|
| 29 |
-
| **Compare** | One reconstructed clip + input/reconstruction spectrograms, side by side for all 8 levels |
|
| 30 |
-
| **Playground** | Encode → decode a single clip at one chosen
|
| 31 |
-
| **Benchmark** | SI-SDR, STOI, LSD, stored model size, bitrate and real-time factor for all
|
| 32 |
|
| 33 |
## Method
|
| 34 |
|
| 35 |
Post-training **fake quantization** of every floating-point tensor: per-output-channel
|
| 36 |
absmax scale, round-to-nearest in the target format, dequantize back to fp32, then run
|
| 37 |
-
the untouched
|
| 38 |
and `fp32` are exact casts. Nothing is fine-tuned or calibrated on data.
|
| 39 |
|
| 40 |
-
The
|
| 41 |
-
|
| 42 |
-
|
|
|
|
|
|
|
| 43 |
|
| 44 |
⚠️ **On SI-SDR:** it is deeply negative at every level, including `fp32`. That is
|
| 45 |
expected — at 0.16 kbps FocalCodec does not preserve waveform phase, and the
|
|
|
|
| 26 |
|
| 27 |
| Tab | What it shows |
|
| 28 |
| --- | --- |
|
| 29 |
+
| **Compare** | One reconstructed clip + input/reconstruction spectrograms, side by side for all 8 FocalCodec levels |
|
| 30 |
+
| **Playground** | Encode → decode a single clip at one chosen codec + weight format, with its metrics row |
|
| 31 |
+
| **Benchmark** | SI-SDR, STOI, LSD, stored model size, bitrate and real-time factor for all 16 levels — 8 FocalCodec + 8 LSCodec — plus a summary chart |
|
| 32 |
|
| 33 |
## Method
|
| 34 |
|
| 35 |
Post-training **fake quantization** of every floating-point tensor: per-output-channel
|
| 36 |
absmax scale, round-to-nearest in the target format, dequantize back to fp32, then run
|
| 37 |
+
the untouched codec forward pass. `fp4` is IEEE-style E2M1, `fp8` is E4M3, `fp16`
|
| 38 |
and `fp32` are exact casts. Nothing is fine-tuned or calibrated on data.
|
| 39 |
|
| 40 |
+
The same sweep runs on a second codec, [LSCodec-25 Hz](https://github.com/X-LANCE/LSCodec-Inference),
|
| 41 |
+
whose rows are prefixed `lscodec-`: its encoder, vocoder and codebook are quantized
|
| 42 |
+
identically, while the WavLM-Large features it self-prompts with are not. It is a
|
| 43 |
+
different model at a different bitrate (0.25 kbps vs 0.1625 kbps), so read it as a
|
| 44 |
+
floor, not a control.
|
| 45 |
|
| 46 |
⚠️ **On SI-SDR:** it is deeply negative at every level, including `fp32`. That is
|
| 47 |
expected — at 0.16 kbps FocalCodec does not preserve waveform phase, and the
|
app.py
CHANGED
|
@@ -16,9 +16,7 @@ from core import QUANT_LEVELS
|
|
| 16 |
MODEL_REPO = "lucadellalib/focalcodec_12_5hz"
|
| 17 |
HUB_REPO = "lucadellalib/focalcodec"
|
| 18 |
LS_REPO = "cantabile-kwok/lscodec_25hz"
|
| 19 |
-
|
| 20 |
-
LS_SIZE_MB = 196.3 # encoder 70.4 + vocoder 125.6 + codebook 0.3 MB
|
| 21 |
-
LS_BITRATE_KBPS = 25 * 10 / 1000 # 25 tokens/s x 10-bit codebook
|
| 22 |
MAX_SECONDS = 20
|
| 23 |
HEADERS = ["Level", "SI-SDR (dB)", "STOI", "LSD (dB)", "Model size (MB)", "Bitrate (kbps)", "RTF"]
|
| 24 |
DATATYPES = ["str", "number", "number", "number", "number", "number", "number"]
|
|
@@ -27,6 +25,7 @@ EXAMPLES = [
|
|
| 27 |
["assets/p226_006.wav"],
|
| 28 |
["assets/5_1812_20170628135856.wav"],
|
| 29 |
]
|
|
|
|
| 30 |
|
| 31 |
codec = torch.hub.load(HUB_REPO, "focalcodec", config=MODEL_REPO, trust_repo=True)
|
| 32 |
codec.eval().requires_grad_(False)
|
|
@@ -84,6 +83,9 @@ def _boot_lscodec() -> dict | None:
|
|
| 84 |
"dec": dec,
|
| 85 |
"books": books,
|
| 86 |
"wavlm": wavlm,
|
|
|
|
|
|
|
|
|
|
| 87 |
"repeat": bool(vocoder_config.get("repeat_input_tokens")),
|
| 88 |
"out_sr": int(vocoder_config["sampling_rate"]),
|
| 89 |
}
|
|
@@ -95,15 +97,20 @@ except Exception as exc: # noqa: BLE001 a third-party dep breaking must not ta
|
|
| 95 |
LS = None
|
| 96 |
print(f"[lscodec] baseline disabled: {exc!r}")
|
| 97 |
|
| 98 |
-
|
|
|
|
| 99 |
|
| 100 |
|
| 101 |
-
def
|
| 102 |
-
"""
|
| 103 |
-
audio = torch.from_numpy(ref).float().view(1, -1).cuda()
|
| 104 |
with torch.inference_mode():
|
| 105 |
prompt_input = torch.nn.functional.layer_norm(audio, audio.shape) # fairseq WavLM cfg.normalize
|
| 106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
_, _, index = LS["enc"].encode(audio.unsqueeze(0))
|
| 108 |
if LS["repeat"]:
|
| 109 |
index = index.repeat_interleave(2, dim=0)
|
|
@@ -116,13 +123,25 @@ def _lscodec_decode(ref: np.ndarray, sr: int) -> np.ndarray:
|
|
| 116 |
return rec
|
| 117 |
|
| 118 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
def _estimate_duration(audio_path: str, levels: tuple) -> float:
|
| 120 |
try:
|
| 121 |
seconds = min(sf.info(audio_path).duration, MAX_SECONDS)
|
| 122 |
except Exception: # noqa: BLE001 unreadable input falls back to the full cap
|
| 123 |
seconds = float(MAX_SECONDS)
|
| 124 |
# ZeroGPU rejects a request above the visitor's tier cap, so never ask for more than 60 s.
|
| 125 |
-
return min(60.0,
|
| 126 |
|
| 127 |
|
| 128 |
@spaces.GPU(duration=_estimate_duration)
|
|
@@ -132,6 +151,7 @@ def _encode_decode(audio_path: str, levels: tuple) -> dict:
|
|
| 132 |
seconds = len(ref) / sr
|
| 133 |
rows, reconstructed = [], {}
|
| 134 |
focal_levels = tuple(level for level in levels if level in QUANT_LEVELS)
|
|
|
|
| 135 |
if focal_levels:
|
| 136 |
sig = torch.from_numpy(ref).unsqueeze(0).cuda()
|
| 137 |
with torch.inference_mode(): # untimed warmup so the first row's RTF isn't inflated
|
|
@@ -147,15 +167,22 @@ def _encode_decode(audio_path: str, levels: tuple) -> dict:
|
|
| 147 |
rows.append(core.evaluate(ref, rec, sr, rtf, SIZES[level], level))
|
| 148 |
reconstructed[level] = (sr, rec)
|
| 149 |
codec.load_state_dict(BASE_STATE)
|
| 150 |
-
if
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
return {"input": (sr, ref), "rows": rows, "audio": reconstructed}
|
| 160 |
|
| 161 |
|
|
@@ -164,15 +191,10 @@ def _table(rows: list[dict]) -> list[list]:
|
|
| 164 |
|
| 165 |
|
| 166 |
_CACHE: dict[str, dict] = {}
|
| 167 |
-
_LS_CACHE: dict[str, dict] = {}
|
| 168 |
|
| 169 |
|
| 170 |
def run(audio_path: str, levels: list | tuple) -> dict:
|
| 171 |
-
"""Encode and decode the audio at every requested
|
| 172 |
-
|
| 173 |
-
Results are cached by audio content and level set, so the Compare and
|
| 174 |
-
Benchmark tabs share a single GPU pass.
|
| 175 |
-
"""
|
| 176 |
if not audio_path:
|
| 177 |
raise gr.Error("Provide audio first: upload, record, or pick an example.")
|
| 178 |
levels = tuple(levels)
|
|
@@ -207,22 +229,9 @@ def playground(audio_path: str, level: str):
|
|
| 207 |
)
|
| 208 |
|
| 209 |
|
| 210 |
-
def _lscodec_row(audio_path: str) -> dict:
|
| 211 |
-
"""LSCodec-25 Hz score for one input, cached separately from the quantization sweep."""
|
| 212 |
-
with open(audio_path, "rb") as fh:
|
| 213 |
-
key = hashlib.md5(fh.read()).hexdigest()
|
| 214 |
-
if key not in _LS_CACHE:
|
| 215 |
-
if len(_LS_CACHE) >= 6:
|
| 216 |
-
_LS_CACHE.clear()
|
| 217 |
-
_LS_CACHE[key] = _encode_decode(audio_path, (LS_LEVEL,))["rows"][0]
|
| 218 |
-
return _LS_CACHE[key]
|
| 219 |
-
|
| 220 |
-
|
| 221 |
def benchmark(audio_path: str):
|
| 222 |
-
"""Score every
|
| 223 |
-
rows = run(audio_path,
|
| 224 |
-
if LS_LEVEL in BENCH_LEVELS:
|
| 225 |
-
rows = rows + [_lscodec_row(audio_path)]
|
| 226 |
return _table(rows), core.metrics_figure(rows)
|
| 227 |
|
| 228 |
|
|
@@ -239,8 +248,9 @@ The bitrate never changes — **{core.BITRATE_KBPS:g} kbps** (12.5 tokens/s × 1
|
|
| 239 |
|
| 240 |
FOOTER = """Audio examples from the [FocalCodec repository](https://github.com/lucadellalib/focalcodec)
|
| 241 |
(LibriSpeech, VoiceBank, MagicData). Model and method by Luca Della Libera et al., Apache-2.0.
|
| 242 |
-
The **lscodec-
|
| 243 |
-
Yiwei Guo et al. (MIT), self-prompted with WavLM-Large from
|
|
|
|
| 244 |
|
| 245 |
with gr.Blocks(title="FocalCodec quantization lab") as demo:
|
| 246 |
gr.Markdown(HEADER)
|
|
@@ -278,7 +288,9 @@ with gr.Blocks(title="FocalCodec quantization lab") as demo:
|
|
| 278 |
)
|
| 279 |
gr.Examples(examples=EXAMPLES, inputs=pg_input, label="Examples")
|
| 280 |
pg_level = gr.Dropdown(
|
| 281 |
-
choices=list(QUANT_LEVELS)
|
|
|
|
|
|
|
| 282 |
)
|
| 283 |
pg_button = gr.Button("Encode + decode", variant="primary")
|
| 284 |
with gr.Column(scale=3):
|
|
@@ -303,12 +315,13 @@ with gr.Blocks(title="FocalCodec quantization lab") as demo:
|
|
| 303 |
"**RTF** = encode+decode time ÷ audio duration · size assumes "
|
| 304 |
"the stored weight format."
|
| 305 |
)
|
| 306 |
-
if
|
| 307 |
gr.Markdown(
|
| 308 |
-
f"
|
| 309 |
-
f"**{LS_BITRATE_KBPS:g} kbps** (25 tokens/s × 10 bits) versus
|
| 310 |
-
f"**{core.BITRATE_KBPS:g} kbps**, and its size
|
| 311 |
-
|
|
|
|
| 312 |
)
|
| 313 |
bm_table = gr.Dataframe(headers=HEADERS, datatype=DATATYPES, interactive=False)
|
| 314 |
bm_plot = gr.Plot(label="Quality and size per level")
|
|
|
|
| 16 |
MODEL_REPO = "lucadellalib/focalcodec_12_5hz"
|
| 17 |
HUB_REPO = "lucadellalib/focalcodec"
|
| 18 |
LS_REPO = "cantabile-kwok/lscodec_25hz"
|
| 19 |
+
LS_PREFIX = "lscodec-"
|
|
|
|
|
|
|
| 20 |
MAX_SECONDS = 20
|
| 21 |
HEADERS = ["Level", "SI-SDR (dB)", "STOI", "LSD (dB)", "Model size (MB)", "Bitrate (kbps)", "RTF"]
|
| 22 |
DATATYPES = ["str", "number", "number", "number", "number", "number", "number"]
|
|
|
|
| 25 |
["assets/p226_006.wav"],
|
| 26 |
["assets/5_1812_20170628135856.wav"],
|
| 27 |
]
|
| 28 |
+
LS_BITRATE_KBPS = 25 * 10 / 1000 # 25 tokens/s x 10-bit codebook
|
| 29 |
|
| 30 |
codec = torch.hub.load(HUB_REPO, "focalcodec", config=MODEL_REPO, trust_repo=True)
|
| 31 |
codec.eval().requires_grad_(False)
|
|
|
|
| 83 |
"dec": dec,
|
| 84 |
"books": books,
|
| 85 |
"wavlm": wavlm,
|
| 86 |
+
"enc_state": {k: v.detach().cpu().clone() for k, v in enc.state_dict().items()},
|
| 87 |
+
"dec_state": {k: v.detach().cpu().clone() for k, v in dec.state_dict().items()},
|
| 88 |
+
"books_state": {k: v.detach().cpu().clone() for k, v in books.state_dict().items()},
|
| 89 |
"repeat": bool(vocoder_config.get("repeat_input_tokens")),
|
| 90 |
"out_sr": int(vocoder_config["sampling_rate"]),
|
| 91 |
}
|
|
|
|
| 97 |
LS = None
|
| 98 |
print(f"[lscodec] baseline disabled: {exc!r}")
|
| 99 |
|
| 100 |
+
LS_LEVELS = tuple(LS_PREFIX + level for level in QUANT_LEVELS) if LS is not None else ()
|
| 101 |
+
BENCH_LEVELS = QUANT_LEVELS + LS_LEVELS
|
| 102 |
|
| 103 |
|
| 104 |
+
def _lscodec_prompt(audio: torch.Tensor) -> torch.Tensor:
|
| 105 |
+
"""WavLM-Large layers 0..5 features: a function of the input only, so compute it once per clip."""
|
|
|
|
| 106 |
with torch.inference_mode():
|
| 107 |
prompt_input = torch.nn.functional.layer_norm(audio, audio.shape) # fairseq WavLM cfg.normalize
|
| 108 |
+
return LS["wavlm"](prompt_input, output_hidden_states=True).hidden_states[6]
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
def _lscodec_decode(prompt: torch.Tensor, audio: torch.Tensor, sr: int) -> np.ndarray:
|
| 112 |
+
"""Reconstruct `audio` with LSCodec at the currently loaded weight level, resampled back to `sr`."""
|
| 113 |
+
with torch.inference_mode():
|
| 114 |
_, _, index = LS["enc"].encode(audio.unsqueeze(0))
|
| 115 |
if LS["repeat"]:
|
| 116 |
index = index.repeat_interleave(2, dim=0)
|
|
|
|
| 123 |
return rec
|
| 124 |
|
| 125 |
|
| 126 |
+
def _load_lscodec(level: str) -> None:
|
| 127 |
+
"""Swap the LSCodec encoder, vocoder and codebook onto `level` (any QUANT_LEVELS entry)."""
|
| 128 |
+
for key in ("enc", "dec", "books"):
|
| 129 |
+
state = LS[key + "_state"]
|
| 130 |
+
LS[key].load_state_dict(state if level == "fp32" else core.quantize_state(state, level))
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def _lscodec_size_mb(level: str) -> float:
|
| 134 |
+
"""Stored size of the codec at `level`; the WavLM prompt encoder is excluded (see the tab note)."""
|
| 135 |
+
return sum(core.model_size_mb(LS[key + "_state"], level) for key in ("enc", "dec", "books"))
|
| 136 |
+
|
| 137 |
+
|
| 138 |
def _estimate_duration(audio_path: str, levels: tuple) -> float:
|
| 139 |
try:
|
| 140 |
seconds = min(sf.info(audio_path).duration, MAX_SECONDS)
|
| 141 |
except Exception: # noqa: BLE001 unreadable input falls back to the full cap
|
| 142 |
seconds = float(MAX_SECONDS)
|
| 143 |
# ZeroGPU rejects a request above the visitor's tier cap, so never ask for more than 60 s.
|
| 144 |
+
return min(60.0, 3.0 + len(levels) + 1.5 * seconds)
|
| 145 |
|
| 146 |
|
| 147 |
@spaces.GPU(duration=_estimate_duration)
|
|
|
|
| 151 |
seconds = len(ref) / sr
|
| 152 |
rows, reconstructed = [], {}
|
| 153 |
focal_levels = tuple(level for level in levels if level in QUANT_LEVELS)
|
| 154 |
+
ls_levels = tuple(level for level in levels if level.startswith(LS_PREFIX))
|
| 155 |
if focal_levels:
|
| 156 |
sig = torch.from_numpy(ref).unsqueeze(0).cuda()
|
| 157 |
with torch.inference_mode(): # untimed warmup so the first row's RTF isn't inflated
|
|
|
|
| 167 |
rows.append(core.evaluate(ref, rec, sr, rtf, SIZES[level], level))
|
| 168 |
reconstructed[level] = (sr, rec)
|
| 169 |
codec.load_state_dict(BASE_STATE)
|
| 170 |
+
if ls_levels:
|
| 171 |
+
audio = torch.from_numpy(ref).float().view(1, -1).cuda()
|
| 172 |
+
with torch.inference_mode(): # one prompt for every level, plus an untimed warmup pass
|
| 173 |
+
prompt = _lscodec_prompt(audio)
|
| 174 |
+
_lscodec_decode(prompt, audio, sr)
|
| 175 |
+
for level in ls_levels:
|
| 176 |
+
_load_lscodec(level[len(LS_PREFIX) :])
|
| 177 |
+
torch.cuda.synchronize()
|
| 178 |
+
start = time.perf_counter()
|
| 179 |
+
rec = _lscodec_decode(prompt, audio, sr)
|
| 180 |
+
torch.cuda.synchronize()
|
| 181 |
+
rtf = (time.perf_counter() - start) / seconds
|
| 182 |
+
base = level[len(LS_PREFIX) :]
|
| 183 |
+
rows.append(core.evaluate(ref, rec, sr, rtf, _lscodec_size_mb(base), level, LS_BITRATE_KBPS))
|
| 184 |
+
reconstructed[level] = (sr, rec)
|
| 185 |
+
_load_lscodec("fp32") # leave the baseline weights in place for the next request
|
| 186 |
return {"input": (sr, ref), "rows": rows, "audio": reconstructed}
|
| 187 |
|
| 188 |
|
|
|
|
| 191 |
|
| 192 |
|
| 193 |
_CACHE: dict[str, dict] = {}
|
|
|
|
| 194 |
|
| 195 |
|
| 196 |
def run(audio_path: str, levels: list | tuple) -> dict:
|
| 197 |
+
"""Encode and decode the audio at every requested level (either codec), cached per level set."""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
if not audio_path:
|
| 199 |
raise gr.Error("Provide audio first: upload, record, or pick an example.")
|
| 200 |
levels = tuple(levels)
|
|
|
|
| 229 |
)
|
| 230 |
|
| 231 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 232 |
def benchmark(audio_path: str):
|
| 233 |
+
"""Score every level of both codecs on one input: metrics table plus summary chart."""
|
| 234 |
+
rows = run(audio_path, BENCH_LEVELS)["rows"]
|
|
|
|
|
|
|
| 235 |
return _table(rows), core.metrics_figure(rows)
|
| 236 |
|
| 237 |
|
|
|
|
| 248 |
|
| 249 |
FOOTER = """Audio examples from the [FocalCodec repository](https://github.com/lucadellalib/focalcodec)
|
| 250 |
(LibriSpeech, VoiceBank, MagicData). Model and method by Luca Della Libera et al., Apache-2.0.
|
| 251 |
+
The **`lscodec-…`** rows are [LSCodec](https://github.com/X-LANCE/LSCodec-Inference) by
|
| 252 |
+
Yiwei Guo et al. (MIT), quantized identically and self-prompted with WavLM-Large from
|
| 253 |
+
[`microsoft/wavlm-large`](https://huggingface.co/microsoft/wavlm-large)."""
|
| 254 |
|
| 255 |
with gr.Blocks(title="FocalCodec quantization lab") as demo:
|
| 256 |
gr.Markdown(HEADER)
|
|
|
|
| 288 |
)
|
| 289 |
gr.Examples(examples=EXAMPLES, inputs=pg_input, label="Examples")
|
| 290 |
pg_level = gr.Dropdown(
|
| 291 |
+
choices=list(QUANT_LEVELS) + list(LS_LEVELS),
|
| 292 |
+
value="int8",
|
| 293 |
+
label="Codec / weight format",
|
| 294 |
)
|
| 295 |
pg_button = gr.Button("Encode + decode", variant="primary")
|
| 296 |
with gr.Column(scale=3):
|
|
|
|
| 315 |
"**RTF** = encode+decode time ÷ audio duration · size assumes "
|
| 316 |
"the stored weight format."
|
| 317 |
)
|
| 318 |
+
if LS_LEVELS:
|
| 319 |
gr.Markdown(
|
| 320 |
+
f"Rows prefixed `lscodec-` are the second codec, quantized the same way: "
|
| 321 |
+
f"it runs at **{LS_BITRATE_KBPS:g} kbps** (25 tokens/s × 10 bits) versus "
|
| 322 |
+
f"FocalCodec's **{core.BITRATE_KBPS:g} kbps**, and its size covers the encoder, "
|
| 323 |
+
"vocoder and codebook only — the WavLM-Large prompt encoder it needs is 1.2 GB "
|
| 324 |
+
"and stays excluded."
|
| 325 |
)
|
| 326 |
bm_table = gr.Dataframe(headers=HEADERS, datatype=DATATYPES, interactive=False)
|
| 327 |
bm_plot = gr.Plot(label="Quality and size per level")
|
core.py
CHANGED
|
@@ -88,7 +88,11 @@ def quantize_state(state: dict, level: str) -> dict:
|
|
| 88 |
|
| 89 |
|
| 90 |
def model_size_mb(state: dict, level: str) -> float:
|
| 91 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
|
| 93 |
|
| 94 |
def load_audio(path: str, target_sr: int, max_seconds: float | None = None) -> tuple[np.ndarray, int]:
|
|
@@ -180,6 +184,8 @@ if __name__ == "__main__":
|
|
| 180 |
assert torch.equal(grid8.to(torch.float8_e4m3fn).float(), grid8), "fp8 grid escapes E4M3-FN"
|
| 181 |
grid4 = fp_levels(w, "fp4")
|
| 182 |
assert grid4.abs().max() <= _FP_MAX_NORM["fp4"] * 1.0000001, "fp4 grid escapes E2M1"
|
|
|
|
|
|
|
| 183 |
x = np.random.randn(16000).astype(np.float32)
|
| 184 |
assert si_sdr(x, x) > 60, "SI-SDR of identical signals should be large"
|
| 185 |
assert si_sdr(x, 3 * x) > 60, "SI-SDR must be scale invariant"
|
|
|
|
| 88 |
|
| 89 |
|
| 90 |
def model_size_mb(state: dict, level: str) -> float:
|
| 91 |
+
"""Stored size of `state` at `level`; non-float buffers keep their own width."""
|
| 92 |
+
return sum(
|
| 93 |
+
v.numel() * (v.element_size() if not v.is_floating_point() else _BITS[level] / 8)
|
| 94 |
+
for v in state.values()
|
| 95 |
+
) / 1e6
|
| 96 |
|
| 97 |
|
| 98 |
def load_audio(path: str, target_sr: int, max_seconds: float | None = None) -> tuple[np.ndarray, int]:
|
|
|
|
| 184 |
assert torch.equal(grid8.to(torch.float8_e4m3fn).float(), grid8), "fp8 grid escapes E4M3-FN"
|
| 185 |
grid4 = fp_levels(w, "fp4")
|
| 186 |
assert grid4.abs().max() <= _FP_MAX_NORM["fp4"] * 1.0000001, "fp4 grid escapes E2M1"
|
| 187 |
+
assert model_size_mb({"w": w}, "fp32") == w.numel() * 4 / 1e6
|
| 188 |
+
assert model_size_mb({"i": torch.zeros(8, dtype=torch.int64)}, "int4") == 8 * 8 / 1e6 # buffers keep 8 bytes
|
| 189 |
x = np.random.randn(16000).astype(np.float32)
|
| 190 |
assert si_sdr(x, x) > 60, "SI-SDR of identical signals should be large"
|
| 191 |
assert si_sdr(x, 3 * x) > 60, "SI-SDR must be scale invariant"
|