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 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}")