Merge minieq/main: Apache-2.0 LICENSE, NOTICE and SPDX headers
The remote had one commit this branch did not (03f8a85), which adds the
Apache-2.0 LICENSE, the NOTICE and SPDX headers to every .py and .sh
file. The merge was clean - the headers sit at the top of each file and
my changes are further down.
The new files this branch added (languages.py, translations.py, the
cluster package, the new tests and scripts) were written after the
merge base, so the licence commit never saw them. They now carry the
same header, so the convention holds across the whole tree.
Nothing else changed. 883 tests passed / 8 failed - the same 8
pre-existing failures.
This commit is contained in:
202
LICENSE
Normal file
202
LICENSE
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
2
NOTICE
Normal file
2
NOTICE
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Umbra Tools (https://umbratools.com)
|
||||||
|
Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# Restore an UmbraAudio full backup and rebuild a portable runtime.
|
# Restore an UmbraAudio full backup and rebuild a portable runtime.
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Analyse the lab: variance vs separation, and verify a suspicious F0 reading."""
|
"""Analyse the lab: variance vs separation, and verify a suspicious F0 reading."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -88,4 +91,4 @@ lo = min(st(r["f0_median"], REF_F0) for r in usable)
|
|||||||
hi = max(st(r["f0_median"], REF_F0) for r in usable)
|
hi = max(st(r["f0_median"], REF_F0) for r in usable)
|
||||||
step = 2 * F0_SD_ST
|
step = 2 * F0_SD_ST
|
||||||
print(f" span {lo:+.1f}..{hi:+.1f} st / {step:.1f} st per voice => "
|
print(f" span {lo:+.1f}..{hi:+.1f} st / {step:.1f} st per voice => "
|
||||||
f"~{int((hi-lo)//step)+1} reliably distinct voices on ONE axis")
|
f"~{int((hi-lo)//step)+1} reliably distinct voices on ONE axis")
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Durable backup of the Author voice matrix (vmatrix) + its reference chain.
|
"""Durable backup of the Author voice matrix (vmatrix) + its reference chain.
|
||||||
|
|
||||||
The live matrix lives in a git-ignored project cache and the previous version's
|
The live matrix lives in a git-ignored project cache and the previous version's
|
||||||
@@ -236,4 +239,4 @@ To confirm a matrix still renders the right speaker, generate from
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Phase-insensitive fidelity: how faithfully does the matrix reproduce the reference?
|
"""Phase-insensitive fidelity: how faithfully does the matrix reproduce the reference?
|
||||||
|
|
||||||
Frame-wise waveform correlation and LSD are dominated by phase, which a 12 Hz
|
Frame-wise waveform correlation and LSD are dominated by phase, which a 12 Hz
|
||||||
@@ -71,4 +74,4 @@ print(f"voiced frames: decoded {len(va)} reference {len(vb)}")
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
sys.path.insert(0, "/Volumes/1TB_APL_Storage/UmbraAudio")
|
sys.path.insert(0, "/Volumes/1TB_APL_Storage/UmbraAudio")
|
||||||
print("\n(note: full re-encode check runs in matrix_roundtrip.py)")
|
print("\n(note: full re-encode check runs in matrix_roundtrip.py)")
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Install the matrix-derived Author reference into the project.
|
"""Install the matrix-derived Author reference into the project.
|
||||||
|
|
||||||
The matrix is the source of truth; this writes the WAV *decoded from that matrix*
|
The matrix is the source of truth; this writes the WAV *decoded from that matrix*
|
||||||
@@ -44,4 +47,4 @@ info = {
|
|||||||
}
|
}
|
||||||
side = dest.with_suffix(".json")
|
side = dest.with_suffix(".json")
|
||||||
side.write_text(json.dumps(info, indent=2) + "\n")
|
side.write_text(json.dumps(info, indent=2) + "\n")
|
||||||
print(json.dumps(info, indent=2))
|
print(json.dumps(info, indent=2))
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Prove: the vmatrix alone can reproduce the reference WAV — and verify its provenance.
|
"""Prove: the vmatrix alone can reproduce the reference WAV — and verify its provenance.
|
||||||
|
|
||||||
1. DECODE author.pt ref_code -> waveform (matrix -> audio; the user's requirement)
|
1. DECODE author.pt ref_code -> waveform (matrix -> audio; the user's requirement)
|
||||||
@@ -126,4 +129,4 @@ def main() -> None:
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Probe 2: DSP axis limits. What does pitch_shift_pv actually move?"""
|
"""Probe 2: DSP axis limits. What does pitch_shift_pv actually move?"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -53,4 +56,4 @@ for st in (-12, -8, -4, 0, 4, 8, 12):
|
|||||||
print(f"{st:>6} {f0:>8.1f} {d_f0:>8.1f} {cen:>9.0f} {d_cen:>8.1f} {ftr:>8.0f} {d_ftr:>9.1f}")
|
print(f"{st:>6} {f0:>8.1f} {d_f0:>8.1f} {cen:>9.0f} {d_cen:>8.1f} {ftr:>8.0f} {d_ftr:>9.1f}")
|
||||||
|
|
||||||
print("\nInterpretation: d_cen ~= d_f0 => full-spectrum shift => formants move WITH pitch.")
|
print("\nInterpretation: d_cen ~= d_f0 => full-spectrum shift => formants move WITH pitch.")
|
||||||
print("A true male->female conversion needs d_cen/d_F0 ~= +2.5 to +3 st, d_F0 ~= +9 to +12 st.")
|
print("A true male->female conversion needs d_cen/d_F0 ~= +2.5 to +3 st, d_F0 ~= +9 to +12 st.")
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Probe 3: prove the missing primitive is an INDEPENDENT FORMANT SHIFTER.
|
"""Probe 3: prove the missing primitive is an INDEPENDENT FORMANT SHIFTER.
|
||||||
|
|
||||||
pitch_shift_pv is a phase vocoder -> it moves F0 and the spectral envelope by
|
pitch_shift_pv is a phase vocoder -> it moves F0 and the spectral envelope by
|
||||||
@@ -66,4 +69,4 @@ o = formant_shift(_pv(y, sr, semitones=-10.0), sr, -8.0)
|
|||||||
f0, ftr = m(o, sr)
|
f0, ftr = m(o, sr)
|
||||||
print(f" F0={f0:.1f}Hz ({12*np.log2(f0/b_f0):+.1f} st) LTAS4k={ftr:.0f}Hz "
|
print(f" F0={f0:.1f}Hz ({12*np.log2(f0/b_f0):+.1f} st) LTAS4k={ftr:.0f}Hz "
|
||||||
f"({12*np.log2(ftr/b_ftr):+.1f} st)")
|
f"({12*np.log2(ftr/b_ftr):+.1f} st)")
|
||||||
sf.write(OUT / "dragon_recipe.wav", o, sr)
|
sf.write(OUT / "dragon_recipe.wav", o, sr)
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Probe: can the narrator vmatrix be morphed (gender / creature) via instruct?
|
"""Probe: can the narrator vmatrix be morphed (gender / creature) via instruct?
|
||||||
|
|
||||||
Read-only against the project; writes WAVs + measurements to an off-volume temp dir.
|
Read-only against the project; writes WAVs + measurements to an off-volume temp dir.
|
||||||
@@ -88,4 +91,4 @@ CASES = [
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
results = [gen(label, instruct=instr) for label, instr in CASES]
|
results = [gen(label, instruct=instr) for label, instr in CASES]
|
||||||
(OUT / "probe_results.json").write_text(json.dumps(results, indent=2))
|
(OUT / "probe_results.json").write_text(json.dumps(results, indent=2))
|
||||||
print("WROTE", OUT / "probe_results.json")
|
print("WROTE", OUT / "probe_results.json")
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Verify the downward-pitch intelligibility cliff on a LONGER text, 2 seeds.
|
"""Verify the downward-pitch intelligibility cliff on a LONGER text, 2 seeds.
|
||||||
|
|
||||||
The 25-word probe suggested WER collapses below ~0 st. WER on 25 words is coarse
|
The 25-word probe suggested WER collapses below ~0 st. WER on 25 words is coarse
|
||||||
@@ -83,4 +86,4 @@ for st in (0, -2, -4, -6, +2):
|
|||||||
print("\n--- mean WER by shift ---")
|
print("\n--- mean WER by shift ---")
|
||||||
for st in (0, -2, -4, -6, +2):
|
for st in (0, -2, -4, -6, +2):
|
||||||
ws = [r["wer"] for r in rows if r["shift_st"] == st]
|
ws = [r["wer"] for r in rows if r["shift_st"] == st]
|
||||||
print(f" {st:+3d} st: mean WER {sum(ws)/len(ws):.3f} {ws}")
|
print(f" {st:+3d} st: mean WER {sum(ws)/len(ws):.3f} {ws}")
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""voice_lab — measure what the Author voice matrix can become.
|
"""voice_lab — measure what the Author voice matrix can become.
|
||||||
|
|
||||||
One fixed text for every sample (comparisons are only valid at constant text).
|
One fixed text for every sample (comparisons are only valid at constant text).
|
||||||
@@ -217,4 +220,4 @@ REF_ENV = None
|
|||||||
REF_WORDS: list[str] = []
|
REF_WORDS: list[str] = []
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# Create a complete, restorable UmbraAudio snapshot on a mounted filesystem/NAS.
|
# Create a complete, restorable UmbraAudio snapshot on a mounted filesystem/NAS.
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Portable backup/restore support helpers for UmbraAudio.
|
"""Portable backup/restore support helpers for UmbraAudio.
|
||||||
|
|
||||||
This module uses only the Python standard library. It snapshots global Umbra
|
This module uses only the Python standard library. It snapshots global Umbra
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Temporary browser-to-agent bridge for UmbraTrans."""
|
"""Temporary browser-to-agent bridge for UmbraTrans."""
|
||||||
|
|
||||||
__all__: list[str] = []
|
__all__: list[str] = []
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from .server import main
|
from .server import main
|
||||||
|
|
||||||
raise SystemExit(main())
|
raise SystemExit(main())
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# Phase-one enterprise control-plane bootstrap for Linux Mint 22.x.
|
# Phase-one enterprise control-plane bootstrap for Linux Mint 22.x.
|
||||||
# This provisions PostgreSQL, database roles, core tenancy/identity tables,
|
# This provisions PostgreSQL, database roles, core tenancy/identity tables,
|
||||||
# and least-privilege service accounts. It does not install application code,
|
# and least-privilege service accounts. It does not install application code,
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# Database-only bootstrap for the UmbraTrans control plane.
|
# Database-only bootstrap for the UmbraTrans control plane.
|
||||||
# This intentionally does not install packages, create application directories,
|
# This intentionally does not install packages, create application directories,
|
||||||
# install application services, or modify Qwen/Docker/firewall settings.
|
# install application services, or modify Qwen/Docker/firewall settings.
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Local, stdio MCP broker for controlled remote operations.
|
"""Local, stdio MCP broker for controlled remote operations.
|
||||||
|
|
||||||
The broker keeps passwords in the macOS Keychain and exposes only operations,
|
The broker keeps passwords in the macOS Keychain and exposes only operations,
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from .broker import main
|
from .broker import main
|
||||||
|
|
||||||
raise SystemExit(main())
|
raise SystemExit(main())
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import ctypes
|
import ctypes
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Controller alignment reports (spec 21 §6.6) - read-only, never guesses.
|
"""Controller alignment reports (spec 21 §6.6) - read-only, never guesses.
|
||||||
|
|
||||||
Emits the envelope the controller diffs mechanically:
|
Emits the envelope the controller diffs mechanically:
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Run LLM emotion/tone analysis on existing utterances without re-segmenting."""
|
"""Run LLM emotion/tone analysis on existing utterances without re-segmenting."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Assign unique Edge-TTS voices to all speakers."""
|
"""Assign unique Edge-TTS voices to all speakers."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Backfill content-addressed ``source_unit_key`` values (spec 21 §9.1 M4-04).
|
"""Backfill content-addressed ``source_unit_key`` values (spec 21 §9.1 M4-04).
|
||||||
|
|
||||||
The key is derived from the chapter's source text and the utterance's own text, so
|
The key is derived from the chapter's source text and the utterance's own text, so
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/bin/zsh
|
#!/bin/zsh
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# backup_system.sh - Complete UmbraAudio system backup
|
# backup_system.sh - Complete UmbraAudio system backup
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Generate the Deal Hunter sample chapter in every language Qwen3-TTS produces.
|
"""Generate the Deal Hunter sample chapter in every language Qwen3-TTS produces.
|
||||||
|
|
||||||
IMPORTANT - what this is and is not
|
IMPORTANT - what this is and is not
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""UmbraAudio cluster worker entry point.
|
"""UmbraAudio cluster worker entry point.
|
||||||
|
|
||||||
Registers this node with UmbraTrans and polls for jobs.
|
Registers this node with UmbraTrans and polls for jobs.
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
#
|
#
|
||||||
# commit_check.sh — warn when the working tree has been dirty too long.
|
# commit_check.sh — warn when the working tree has been dirty too long.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Weekly commit reminder for the UmbraAudio working tree.
|
"""Weekly commit reminder for the UmbraAudio working tree.
|
||||||
|
|
||||||
Invoked by ``~/.umbraaudio/umbra_commit_check.sh`` from the launchd job
|
Invoked by ``~/.umbraaudio/umbra_commit_check.sh`` from the launchd job
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Create the standalone "Vocals" example-vocals project (no upload needed).
|
"""Create the standalone "Vocals" example-vocals project (no upload needed).
|
||||||
|
|
||||||
The project has a single chapter that speaks the Rainbow Passage once per
|
The project has a single chapter that speaks the Rainbow Passage once per
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# Downloads the Qwen3-TTS model weights required by UmbraAudio.
|
# Downloads the Qwen3-TTS model weights required by UmbraAudio.
|
||||||
#
|
#
|
||||||
# These models are stock HuggingFace downloads (~9 GB). They are NOT tracked
|
# These models are stock HuggingFace downloads (~9 GB). They are NOT tracked
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Extract Qwen TTS speaker embeddings from existing voice reference WAVs.
|
"""Extract Qwen TTS speaker embeddings from existing voice reference WAVs.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Fix Chapter 6 (Salvage) utterance issues:
|
"""Fix Chapter 6 (Salvage) utterance issues:
|
||||||
1. Split utterance 56 into 3 utterances with correct speakers
|
1. Split utterance 56 into 3 utterances with correct speakers
|
||||||
2. Fix utterance 145 - Kainda with pleading tone
|
2. Fix utterance 145 - Kainda with pleading tone
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Background chapter audio generation with Qwen3-TTS.
|
"""Background chapter audio generation with Qwen3-TTS.
|
||||||
Run as: nohup python scripts/generate_all_audio.py [--project NAME] > generation.log 2>&1 &
|
Run as: nohup python scripts/generate_all_audio.py [--project NAME] > generation.log 2>&1 &
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Generate audio for chapters using Qwen3-TTS with voice cloning from references."""
|
"""Generate audio for chapters using Qwen3-TTS with voice cloning from references."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Generate longer voice references (30+ seconds) for speakers using VoiceDesign."""
|
"""Generate longer voice references (30+ seconds) for speakers using VoiceDesign."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Generate a narrator reference voice for each target language.
|
"""Generate a narrator reference voice for each target language.
|
||||||
|
|
||||||
Specification change (2026-10-13):
|
Specification change (2026-10-13):
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Generate test samples for all speakers using Edge-TTS with speaker attributes."""
|
"""Generate test samples for all speakers using Edge-TTS with speaker attributes."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Generate Rainbow Passage samples from cached speaker embeddings.
|
"""Generate Rainbow Passage samples from cached speaker embeddings.
|
||||||
|
|
||||||
For each speaker in the given chapter, generates a WAV file of the Rainbow Passage
|
For each speaker in the given chapter, generates a WAV file of the Rainbow Passage
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""LM Studio model control script for UmbraAudio.
|
"""LM Studio model control script for UmbraAudio.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Merge mechanically-detected speaker designations into speakers.json.
|
"""Merge mechanically-detected speaker designations into speakers.json.
|
||||||
|
|
||||||
Discovery is LLM-driven and will always miss *some* characters — on Last Dwarf
|
Discovery is LLM-driven and will always miss *some* characters — on Last Dwarf
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""CLI for the model coordinator.
|
"""CLI for the model coordinator.
|
||||||
|
|
||||||
Ensures only the model needed by the current pipeline stage is resident in
|
Ensures only the model needed by the current pipeline stage is resident in
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""NAS sync + local prune lifecycle for UmbraAudio.
|
"""NAS sync + local prune lifecycle for UmbraAudio.
|
||||||
|
|
||||||
Primary store: local SSD. Secondary: NAS mirror. On each run:
|
Primary store: local SSD. Secondary: NAS mirror. On each run:
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Publish a release: author a comment, approve it, then pin what shipped (spec 22).
|
"""Publish a release: author a comment, approve it, then pin what shipped (spec 22).
|
||||||
|
|
||||||
A release is a pinned set of artifacts plus an authored comment. The comment is a step, not
|
A release is a pinned set of artifacts plus an authored comment. The comment is a step, not
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Mechanical QA cross-check of speaker attribution against speech tags.
|
"""Mechanical QA cross-check of speaker attribution against speech tags.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Qwen3-TTS FastAPI Server for UmbraAudio.
|
"""Qwen3-TTS FastAPI Server for UmbraAudio.
|
||||||
|
|
||||||
Provides REST endpoints for voice design and voice cloning.
|
Provides REST endpoints for voice design and voice cloning.
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Re-run LLM speaker attribution on existing utterances without re-segmenting.
|
"""Re-run LLM speaker attribution on existing utterances without re-segmenting.
|
||||||
|
|
||||||
Preserves utterance IDs and mechanical segmentation; only updates speaker_name.
|
Preserves utterance IDs and mechanical segmentation; only updates speaker_name.
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Re-index utterance_index values and fix remaining issues for Chapter 6."""
|
"""Re-index utterance_index values and fix remaining issues for Chapter 6."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Deterministic re-merge of existing discovery chapter data with fixed logic.
|
"""Deterministic re-merge of existing discovery chapter data with fixed logic.
|
||||||
|
|
||||||
Regenerates .umbra/speakers.json from .umbra/discovery/discovery_pass1.json
|
Regenerates .umbra/speakers.json from .umbra/discovery/discovery_pass1.json
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Render the sample chapter in every language Qwen3-TTS supports.
|
"""Render the sample chapter in every language Qwen3-TTS supports.
|
||||||
|
|
||||||
Reads the translation JSONs produced by ``build_sample_translations.py`` and
|
Reads the translation JSONs produced by ``build_sample_translations.py`` and
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Report mechanical speech-evidence support over a project's dialogue lines.
|
"""Report mechanical speech-evidence support over a project's dialogue lines.
|
||||||
|
|
||||||
Read-only. Prints the verdict mix, then every contradicted line with the narration the
|
Read-only. Prints the verdict mix, then every contradicted line with the narration the
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Re-segment all chapters using mechanical splitter + LLM attribution."""
|
"""Re-segment all chapters using mechanical splitter + LLM attribution."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Non-destructive chapter re-segmentation.
|
"""Non-destructive chapter re-segmentation.
|
||||||
|
|
||||||
Re-runs the *current* Segmenter over selected chapters and merges the result
|
Re-runs the *current* Segmenter over selected chapters and merges the result
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Run character discovery to a SEPARATE output file (never overwrites speakers.json).
|
"""Run character discovery to a SEPARATE output file (never overwrites speakers.json).
|
||||||
|
|
||||||
Discovery is slow (4 LLM passes/chapter). This runner lets you validate the
|
Discovery is slow (4 LLM passes/chapter). This runner lets you validate the
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Scan the manuscript for orphan name tokens (unresolved speaker identities).
|
"""Scan the manuscript for orphan name tokens (unresolved speaker identities).
|
||||||
|
|
||||||
Walks every chapter's utterances, collects proper-noun tokens used as speaker
|
Walks every chapter's utterances, collects proper-noun tokens used as speaker
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Scan for duplicate speakers and report them ranked by how safe the merge is.
|
"""Scan for duplicate speakers and report them ranked by how safe the merge is.
|
||||||
|
|
||||||
Read-only by default. Nothing is merged without ``--apply`` and an explicit group choice.
|
Read-only by default. Nothing is merged without ``--apply`` and an explicit group choice.
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Speaker-review audit: is the attribution data fit to hand to the next stage?
|
"""Speaker-review audit: is the attribution data fit to hand to the next stage?
|
||||||
|
|
||||||
Answers the two questions asked after a speaker review completes:
|
Answers the two questions asked after a speaker review completes:
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# UmbraAudio Startup Script
|
# UmbraAudio Startup Script
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#!/bin/zsh
|
#!/bin/zsh
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
PROJ=/Volumes/1TB_APL_Storage/UmbraAudio
|
PROJ=/Volumes/1TB_APL_Storage/UmbraAudio
|
||||||
exec >> "$PROJ/logs/web_server.log" 2>&1
|
exec >> "$PROJ/logs/web_server.log" 2>&1
|
||||||
echo "[$(date '+%F %T')] web server starting (wrapper pid $$)"
|
echo "[$(date '+%F %T')] web server starting (wrapper pid $$)"
|
||||||
cd "$PROJ"
|
cd "$PROJ"
|
||||||
exec "$PROJ/.venv/bin/python" -c "from pathlib import Path; from umbraaudio.web import create_app; from umbraaudio.config import load_config; import uvicorn; c = load_config(Path('/Volumes/1TB_APL_Storage/UmbraAudio')); uvicorn.run(create_app(c), host='0.0.0.0', port=8420, log_level='info')"
|
exec "$PROJ/.venv/bin/python" -c "from pathlib import Path; from umbraaudio.web import create_app; from umbraaudio.config import load_config; import uvicorn; c = load_config(Path('/Volumes/1TB_APL_Storage/UmbraAudio')); uvicorn.run(create_app(c), host='0.0.0.0', port=8420, log_level='info')"
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Test script for document parser and entity extraction.
|
Test script for document parser and entity extraction.
|
||||||
Tests the parsing of DealHunterShip manuscript.
|
Tests the parsing of DealHunterShip manuscript.
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Test a Scottish voice for a given speaker once project discovery completes.
|
"""Test a Scottish voice for a given speaker once project discovery completes.
|
||||||
|
|
||||||
Waits for ``analysis_status.json`` to reach ``complete`` (or ``error``), then:
|
Waits for ``analysis_status.json`` to reach ``complete`` (or ``error``), then:
|
||||||
@@ -246,4 +249,4 @@ if __name__ == "__main__":
|
|||||||
main()
|
main()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"HALLR SCOTTISH TEST FAILED: {e}")
|
log(f"HALLR SCOTTISH TEST FAILED: {e}")
|
||||||
raise
|
raise
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Test script for Qwen3-TTS voice synthesis.
|
Test script for Qwen3-TTS voice synthesis.
|
||||||
Tests the TTS server with character voice prompts.
|
Tests the TTS server with character voice prompts.
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Read-only Umbra node report: the facts another machine needs to align with.
|
"""Read-only Umbra node report: the facts another machine needs to align with.
|
||||||
|
|
||||||
Every Umbra machine is a *node* in the Umbra system (spec 21). Before any data
|
Every Umbra machine is a *node* in the Umbra system (spec 21). Before any data
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/bin/zsh
|
#!/bin/zsh
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# verify_backup.sh - Verify UmbraAudio backup integrity
|
# verify_backup.sh - Verify UmbraAudio backup integrity
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""verify_nas.py — NAS mirror consistency verifier (Phase D2).
|
"""verify_nas.py — NAS mirror consistency verifier (Phase D2).
|
||||||
|
|
||||||
Idempotent, safe to run anytime. After a sync to the NAS mirror it asserts, for
|
Idempotent, safe to run anytime. After a sync to the NAS mirror it asserts, for
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""verify_projects.py — multi-project integrity verifier (Phase D1).
|
"""verify_projects.py — multi-project integrity verifier (Phase D1).
|
||||||
|
|
||||||
Idempotent, safe to run anytime. For every project under PROJECT_BASE it:
|
Idempotent, safe to run anytime. For every project under PROJECT_BASE it:
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# Qwen3-TTS 1.7B-Base Gradio server launcher (all paths on the 1TB drive)
|
# Qwen3-TTS 1.7B-Base Gradio server launcher (all paths on the 1TB drive)
|
||||||
export HF_HOME=/Volumes/1TB_APL_Storage/UmbraAudio/.hf_home
|
export HF_HOME=/Volumes/1TB_APL_Storage/UmbraAudio/.hf_home
|
||||||
export PATH=/Volumes/1TB_APL_Storage/UmbraAudio/.venv/bin:$PATH
|
export PATH=/Volumes/1TB_APL_Storage/UmbraAudio/.venv/bin:$PATH
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import torch
|
import torch
|
||||||
import soundfile as sf
|
import soundfile as sf
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from umbraaudio.analysis.attribution_qa import (
|
from umbraaudio.analysis.attribution_qa import (
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Tests for the single-user auth gate.
|
"""Tests for the single-user auth gate.
|
||||||
|
|
||||||
The review UI previously had no authentication at all, reachable by anything
|
The review UI previously had no authentication at all, reachable by anything
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from umbraaudio.analysis.character_discovery import (
|
from umbraaudio.analysis.character_discovery import (
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from umbraaudio.analysis.clarity import (
|
from umbraaudio.analysis.clarity import (
|
||||||
@@ -296,4 +299,4 @@ class TestAssessUtteranceClarity:
|
|||||||
]
|
]
|
||||||
out = assess_utterance_clarity(utts, 6, ALIAS_MAP, PROFILES)
|
out = assess_utterance_clarity(utts, 6, ALIAS_MAP, PROFILES)
|
||||||
assert "needs_review" not in out[2]
|
assert "needs_review" not in out[2]
|
||||||
assert out[2]["type"] == "scene_break"
|
assert out[2]["type"] == "scene_break"
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Tests for speaker deletion.
|
"""Tests for speaker deletion.
|
||||||
|
|
||||||
The speakers page has offered a Delete button for a long time. The endpoint
|
The speakers page has offered a Delete button for a long time. The endpoint
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from umbraaudio.analysis.designation_scan import (
|
from umbraaudio.analysis.designation_scan import (
|
||||||
@@ -110,4 +113,4 @@ class TestBookScan:
|
|||||||
]
|
]
|
||||||
out = scan_book_designations(chapters)
|
out = scan_book_designations(chapters)
|
||||||
assert len(out) == 1
|
assert len(out) == 1
|
||||||
assert out["the guard"].chapter_id == 1
|
assert out["the guard"].chapter_id == 1
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Guard tests for the character-discovery prompt's over-detection rules.
|
"""Guard tests for the character-discovery prompt's over-detection rules.
|
||||||
|
|
||||||
These rules exist because discovery was missing obvious speakers (characters
|
These rules exist because discovery was missing obvious speakers (characters
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""The m4b must ship the same audio spec as the AR MP3 package.
|
"""The m4b must ship the same audio spec as the AR MP3 package.
|
||||||
|
|
||||||
Previously the m4b path had no sample-rate flag, no channel layout, and no
|
Previously the m4b path had no sample-rate flag, no channel layout, and no
|
||||||
@@ -119,4 +122,4 @@ def test_concat_resamples_to_the_delivery_rate(tmp_path: Path) -> None:
|
|||||||
out = tmp_path / "concat.wav"
|
out = tmp_path / "concat.wav"
|
||||||
exporter._concat_wavs_with_silence(files, out, gap_ms=100)
|
exporter._concat_wavs_with_silence(files, out, gap_ms=100)
|
||||||
info = sf.info(str(out))
|
info = sf.info(str(out))
|
||||||
assert info.samplerate == TARGET_SAMPLE_RATE
|
assert info.samplerate == TARGET_SAMPLE_RATE
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Tests for umbraaudio.generation.audio_effects."""
|
"""Tests for umbraaudio.generation.audio_effects."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""The per-utterance language tag must reach the TTS engine and the marker.
|
"""The per-utterance language tag must reach the TTS engine and the marker.
|
||||||
|
|
||||||
Spec 31's source axis: an utterance tagged with the language it is *written in*
|
Spec 31's source axis: an utterance tagged with the language it is *written in*
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Tests for the language registry (spec 31 section 5).
|
"""Tests for the language registry (spec 31 section 5).
|
||||||
|
|
||||||
The registry is the single source of truth for what this system can speak, so
|
The registry is the single source of truth for what this system can speak, so
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from umbraaudio.analysis.llm_attributor import LLMAttributor
|
from umbraaudio.analysis.llm_attributor import LLMAttributor
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
# Copyright 2026 Umbra Tools (umbratools.com)
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
"""Tests for multi-project readiness (Phase C2 of MULTI_PROJECT_PLAN.md).
|
"""Tests for multi-project readiness (Phase C2 of MULTI_PROJECT_PLAN.md).
|
||||||
|
|
||||||
Covers:
|
Covers:
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user