foley 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- foley/__init__.py +292 -0
- foley/audio.py +424 -0
- foley/base.py +452 -0
- foley/index/__init__.py +78 -0
- foley/index/embedders.py +173 -0
- foley/index/indexes.py +595 -0
- foley/index/library.py +476 -0
- foley/index/protocols.py +134 -0
- foley/index/search.py +174 -0
- foley/index/taxonomy/__init__.py +48 -0
- foley/index/taxonomy/audioset.py +71 -0
- foley/index/taxonomy/model.py +103 -0
- foley/index/taxonomy/resolver.py +236 -0
- foley/index/taxonomy/seed.py +353 -0
- foley/index/taxonomy/ucs.py +102 -0
- foley/licensing.py +173 -0
- foley/qc.py +584 -0
- foley/stores.py +182 -0
- foley-0.0.2.dist-info/METADATA +119 -0
- foley-0.0.2.dist-info/RECORD +22 -0
- foley-0.0.2.dist-info/WHEEL +4 -0
- foley-0.0.2.dist-info/licenses/LICENSE +21 -0
foley/__init__.py
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"""foley — a retrieval-first façade for sound effects.
|
|
2
|
+
|
|
3
|
+
foley finds (or generates) the right sound effect for a moment of narration and
|
|
4
|
+
weaves it in. It is the SFX sibling of ``arioso`` (a unified façade over AI
|
|
5
|
+
music-generation backends): one simple surface over many sound *sources* (a
|
|
6
|
+
bring-your-own library, service APIs like Freesound, and generative-AI models),
|
|
7
|
+
a searchable *index* of every sound (by keyword *and* meaning, via CLAP
|
|
8
|
+
embeddings + hybrid search), an *agent* that selects the right sound for a
|
|
9
|
+
narrative context, and a *compositor* that places it under the voice.
|
|
10
|
+
|
|
11
|
+
Four stages::
|
|
12
|
+
|
|
13
|
+
SOURCE -> INDEX -> SELECT -> WEAVE
|
|
14
|
+
(get) (find) (choose) (compose)
|
|
15
|
+
|
|
16
|
+
Intended façade (design-stage — see ``misc/docs/design.md`` and
|
|
17
|
+
``misc/docs/roadmap.md`` for what is implemented)::
|
|
18
|
+
|
|
19
|
+
import foley
|
|
20
|
+
|
|
21
|
+
foley.find("She pushed open the heavy oak door; rain hammered outside.")
|
|
22
|
+
foley.search("distant thunder rumble", k=10)
|
|
23
|
+
foley.generate("a single wooden door creak", backend="stable_audio_open")
|
|
24
|
+
foley.ingest("~/my_sounds/")
|
|
25
|
+
|
|
26
|
+
The design is grounded in the research reports under ``misc/docs/research/``.
|
|
27
|
+
|
|
28
|
+
Foundation surface (implemented — the retrieval-agnostic base every later stage
|
|
29
|
+
stands on). This top-level namespace re-exports it:
|
|
30
|
+
|
|
31
|
+
* **Data models** (``foley.base``) — the SSOT dataclasses/enums shared across
|
|
32
|
+
layers (:class:`SoundRecord`, :class:`LicenseRecord`, :class:`Candidate`,
|
|
33
|
+
:class:`SoundEvent`, :class:`Verdict`, :class:`IntendedUse`), the two
|
|
34
|
+
affordance registries, and generic dict/JSON (de)serialization.
|
|
35
|
+
* **License policy** (``foley.licensing``) — the ``license_id`` -> flag-set
|
|
36
|
+
SSOT (:data:`LICENSE_FLAGS`), flag derivation, and the fail-closed
|
|
37
|
+
:func:`keep` gate.
|
|
38
|
+
* **Storage** (``foley.stores``) — content-addressed byte store + metadata
|
|
39
|
+
store built from ``dol``, and :func:`store_sound` (the by-value vs
|
|
40
|
+
by-reference gate driven by ``LicenseRecord.cache_bytes_ok``).
|
|
41
|
+
* **QC** (``foley.qc``) — Tier-0 deterministic audio checks
|
|
42
|
+
(:func:`run_qc` -> :class:`QCReport`, thresholds in :class:`QCThresholds`).
|
|
43
|
+
* **Audio** (``foley.audio``) — I/O + DSP primitives. Exposed as a submodule
|
|
44
|
+
(``foley.audio``) with the key functions also re-exported here.
|
|
45
|
+
|
|
46
|
+
Import cost: ``import foley`` pulls only ``dol`` (a light core dependency used by
|
|
47
|
+
``foley.stores``); ``numpy``/``soundfile``/``soxr``/``librosa``/``pyloudnorm`` are
|
|
48
|
+
lazy-imported inside the audio/QC functions that need them (install via the
|
|
49
|
+
``foley[audio]`` extra), so a bare install imports cleanly.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
from . import audio
|
|
53
|
+
from .audio import (
|
|
54
|
+
WORKING_SAMPLE_RATE,
|
|
55
|
+
encode,
|
|
56
|
+
ensure_channels,
|
|
57
|
+
fade,
|
|
58
|
+
load,
|
|
59
|
+
loudness_normalize,
|
|
60
|
+
resample,
|
|
61
|
+
save,
|
|
62
|
+
to_mono,
|
|
63
|
+
to_working,
|
|
64
|
+
trim_silence,
|
|
65
|
+
)
|
|
66
|
+
from .base import (
|
|
67
|
+
GENERATION_AFFORDANCES,
|
|
68
|
+
QUERY_AFFORDANCES,
|
|
69
|
+
SCHEMA_VERSION,
|
|
70
|
+
AcquisitionMethod,
|
|
71
|
+
Affordance,
|
|
72
|
+
Candidate,
|
|
73
|
+
CandidateOrigin,
|
|
74
|
+
IntendedUse,
|
|
75
|
+
Layer,
|
|
76
|
+
LicenseRecord,
|
|
77
|
+
Salience,
|
|
78
|
+
SerializableMixin,
|
|
79
|
+
SoundEvent,
|
|
80
|
+
SoundRecord,
|
|
81
|
+
StorageMode,
|
|
82
|
+
Verdict,
|
|
83
|
+
VerifyLevel,
|
|
84
|
+
)
|
|
85
|
+
from .licensing import (
|
|
86
|
+
LICENSE_FLAGS,
|
|
87
|
+
UNKNOWN_LICENSE_FLAGS,
|
|
88
|
+
LicenseFlags,
|
|
89
|
+
apply_license_flags,
|
|
90
|
+
derive_license_flags,
|
|
91
|
+
keep,
|
|
92
|
+
keep_sound,
|
|
93
|
+
)
|
|
94
|
+
from .qc import (
|
|
95
|
+
DEFAULT_QC_THRESHOLDS,
|
|
96
|
+
QCReport,
|
|
97
|
+
QCStatus,
|
|
98
|
+
QCThresholds,
|
|
99
|
+
dc_offset,
|
|
100
|
+
detect_clipping,
|
|
101
|
+
duration_s,
|
|
102
|
+
estimate_snr,
|
|
103
|
+
has_nan_inf,
|
|
104
|
+
is_silent,
|
|
105
|
+
measure_lufs,
|
|
106
|
+
needs_edge_fade,
|
|
107
|
+
run_qc,
|
|
108
|
+
true_peak_dbtp,
|
|
109
|
+
)
|
|
110
|
+
from .stores import (
|
|
111
|
+
DEFAULT_AUDIO_DIR,
|
|
112
|
+
DEFAULT_META_DIR,
|
|
113
|
+
FOLEY_DATA_DIR,
|
|
114
|
+
content_key,
|
|
115
|
+
make_byte_store,
|
|
116
|
+
make_meta_store,
|
|
117
|
+
store_sound,
|
|
118
|
+
)
|
|
119
|
+
from . import index
|
|
120
|
+
from .index import (
|
|
121
|
+
CLAP_SAMPLE_RATE,
|
|
122
|
+
DEFAULT_CANDIDATE_K,
|
|
123
|
+
DEFAULT_CLAP_DIM,
|
|
124
|
+
DEFAULT_CLAP_MODEL_ID,
|
|
125
|
+
RRF_K,
|
|
126
|
+
CatIdResolution,
|
|
127
|
+
ClapEmbedder,
|
|
128
|
+
Embedder,
|
|
129
|
+
FusedHit,
|
|
130
|
+
KeywordIndex,
|
|
131
|
+
LanceIndex,
|
|
132
|
+
MemoryIndex,
|
|
133
|
+
SoundLibrary,
|
|
134
|
+
SqliteVecIndex,
|
|
135
|
+
VectorIndex,
|
|
136
|
+
default_embedder,
|
|
137
|
+
default_index,
|
|
138
|
+
default_library,
|
|
139
|
+
fuse_hits,
|
|
140
|
+
hybrid_search,
|
|
141
|
+
lancedb_available,
|
|
142
|
+
parse_ucs_filename,
|
|
143
|
+
reciprocal_rank_fusion,
|
|
144
|
+
resolve_catid,
|
|
145
|
+
sqlite_vec_loadable,
|
|
146
|
+
vector_search,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
__all__ = [
|
|
150
|
+
# --- base: constants + enums ---------------------------------------------
|
|
151
|
+
"SCHEMA_VERSION",
|
|
152
|
+
"StorageMode",
|
|
153
|
+
"AcquisitionMethod",
|
|
154
|
+
"CandidateOrigin",
|
|
155
|
+
"Salience",
|
|
156
|
+
"Layer",
|
|
157
|
+
"VerifyLevel",
|
|
158
|
+
# --- base: affordances ---------------------------------------------------
|
|
159
|
+
"Affordance",
|
|
160
|
+
"QUERY_AFFORDANCES",
|
|
161
|
+
"GENERATION_AFFORDANCES",
|
|
162
|
+
# --- base: serialization + models ----------------------------------------
|
|
163
|
+
"SerializableMixin",
|
|
164
|
+
"LicenseRecord",
|
|
165
|
+
"SoundRecord",
|
|
166
|
+
"SoundEvent",
|
|
167
|
+
"Verdict",
|
|
168
|
+
"Candidate",
|
|
169
|
+
"IntendedUse",
|
|
170
|
+
# --- licensing: policy ---------------------------------------------------
|
|
171
|
+
"LicenseFlags",
|
|
172
|
+
"LICENSE_FLAGS",
|
|
173
|
+
"UNKNOWN_LICENSE_FLAGS",
|
|
174
|
+
"derive_license_flags",
|
|
175
|
+
"apply_license_flags",
|
|
176
|
+
"keep",
|
|
177
|
+
"keep_sound",
|
|
178
|
+
# --- stores: content-addressed storage + the storage gate ----------------
|
|
179
|
+
"content_key",
|
|
180
|
+
"make_byte_store",
|
|
181
|
+
"make_meta_store",
|
|
182
|
+
"store_sound",
|
|
183
|
+
"FOLEY_DATA_DIR",
|
|
184
|
+
"DEFAULT_AUDIO_DIR",
|
|
185
|
+
"DEFAULT_META_DIR",
|
|
186
|
+
# --- qc: Tier-0 deterministic audio QC -----------------------------------
|
|
187
|
+
"QCStatus",
|
|
188
|
+
"QCThresholds",
|
|
189
|
+
"DEFAULT_QC_THRESHOLDS",
|
|
190
|
+
"QCReport",
|
|
191
|
+
"run_qc",
|
|
192
|
+
"has_nan_inf",
|
|
193
|
+
"duration_s",
|
|
194
|
+
"dc_offset",
|
|
195
|
+
"is_silent",
|
|
196
|
+
"detect_clipping",
|
|
197
|
+
"true_peak_dbtp",
|
|
198
|
+
"estimate_snr",
|
|
199
|
+
"needs_edge_fade",
|
|
200
|
+
"measure_lufs",
|
|
201
|
+
# --- audio: I/O + DSP primitives -----------------------------------------
|
|
202
|
+
"audio",
|
|
203
|
+
"WORKING_SAMPLE_RATE",
|
|
204
|
+
"load",
|
|
205
|
+
"save",
|
|
206
|
+
"encode",
|
|
207
|
+
"resample",
|
|
208
|
+
"to_mono",
|
|
209
|
+
"ensure_channels",
|
|
210
|
+
"trim_silence",
|
|
211
|
+
"fade",
|
|
212
|
+
"loudness_normalize",
|
|
213
|
+
"to_working",
|
|
214
|
+
# --- index: embeddings, hybrid search, library façade, taxonomy ----------
|
|
215
|
+
"index",
|
|
216
|
+
"SoundLibrary",
|
|
217
|
+
"default_library",
|
|
218
|
+
"search",
|
|
219
|
+
"similar",
|
|
220
|
+
"Embedder",
|
|
221
|
+
"ClapEmbedder",
|
|
222
|
+
"default_embedder",
|
|
223
|
+
"VectorIndex",
|
|
224
|
+
"KeywordIndex",
|
|
225
|
+
"MemoryIndex",
|
|
226
|
+
"LanceIndex",
|
|
227
|
+
"SqliteVecIndex",
|
|
228
|
+
"default_index",
|
|
229
|
+
"lancedb_available",
|
|
230
|
+
"sqlite_vec_loadable",
|
|
231
|
+
"hybrid_search",
|
|
232
|
+
"vector_search",
|
|
233
|
+
"reciprocal_rank_fusion",
|
|
234
|
+
"fuse_hits",
|
|
235
|
+
"FusedHit",
|
|
236
|
+
"RRF_K",
|
|
237
|
+
"DEFAULT_CANDIDATE_K",
|
|
238
|
+
"DEFAULT_CLAP_MODEL_ID",
|
|
239
|
+
"DEFAULT_CLAP_DIM",
|
|
240
|
+
"CLAP_SAMPLE_RATE",
|
|
241
|
+
"resolve_catid",
|
|
242
|
+
"parse_ucs_filename",
|
|
243
|
+
"CatIdResolution",
|
|
244
|
+
"library",
|
|
245
|
+
]
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def search(
|
|
249
|
+
query: str,
|
|
250
|
+
*,
|
|
251
|
+
k: int = 10,
|
|
252
|
+
filters=None,
|
|
253
|
+
commercial_ok=None,
|
|
254
|
+
ucs_category=None,
|
|
255
|
+
min_snr=None,
|
|
256
|
+
duration_range=None,
|
|
257
|
+
rerank: bool = False,
|
|
258
|
+
):
|
|
259
|
+
"""Hybrid (CLAP vector ⊕ BM25) search of the default library.
|
|
260
|
+
|
|
261
|
+
Convenience wrapper over ``foley.library.search(...)`` — see
|
|
262
|
+
:meth:`foley.index.SoundLibrary.search`. Constructs the process-wide default
|
|
263
|
+
library (local stores + CLAP + best available index) on first use.
|
|
264
|
+
"""
|
|
265
|
+
return default_library().search(
|
|
266
|
+
query,
|
|
267
|
+
k=k,
|
|
268
|
+
filters=filters,
|
|
269
|
+
commercial_ok=commercial_ok,
|
|
270
|
+
ucs_category=ucs_category,
|
|
271
|
+
min_snr=min_snr,
|
|
272
|
+
duration_range=duration_range,
|
|
273
|
+
rerank=rerank,
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def similar(sound_id: str, *, k: int = 10):
|
|
278
|
+
"""Find sounds similar to a stored sound (audio<->audio) in the default library.
|
|
279
|
+
|
|
280
|
+
See :meth:`foley.index.SoundLibrary.similar`.
|
|
281
|
+
"""
|
|
282
|
+
return default_library().similar(sound_id, k=k)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def __getattr__(name: str):
|
|
286
|
+
"""Lazily expose ``foley.library`` (the default :class:`SoundLibrary`).
|
|
287
|
+
|
|
288
|
+
Kept lazy so ``import foley`` never constructs the CLAP model or the index.
|
|
289
|
+
"""
|
|
290
|
+
if name == "library":
|
|
291
|
+
return default_library()
|
|
292
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|