@glissade/sfx 0.5.0-pre.2 → 0.5.0-pre.3
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.
- package/dist/index.d.ts +35 -1
- package/dist/index.js +29 -1
- package/package.json +5 -2
package/dist/index.d.ts
CHANGED
|
@@ -118,5 +118,39 @@ interface SfxClipOptions {
|
|
|
118
118
|
* re-evaluation out of order never drifts. Mirrors buildNarrationClips.
|
|
119
119
|
*/
|
|
120
120
|
declare function buildSfxClips(hits: readonly SfxHit[], source: SfxSource, opts?: SfxClipOptions): AudioClip[];
|
|
121
|
+
/** One keystroke to sonify — the structural shape both the typewriter's
|
|
122
|
+
* `EditMark` and a monotonic `RevealMark` satisfy. `kind` lets a backspace
|
|
123
|
+
* take a different sample; absent, it's treated as an insert. */
|
|
124
|
+
interface KeystrokeMark {
|
|
125
|
+
time: number;
|
|
126
|
+
grapheme: string;
|
|
127
|
+
kind?: 'insert' | 'delete';
|
|
128
|
+
}
|
|
129
|
+
interface KeystrokeOptions extends SfxClipOptions {
|
|
130
|
+
/** voice for inserts (a typed char); default 'type' */
|
|
131
|
+
insertVoice?: string;
|
|
132
|
+
/** voice for deletes (a backspace); default = insertVoice */
|
|
133
|
+
deleteVoice?: string;
|
|
134
|
+
/**
|
|
135
|
+
* Round-robin pool for inserts (overrides insertVoice) — a real keyboard
|
|
136
|
+
* foley pack rotates several keypress recordings so the typing doesn't sound
|
|
137
|
+
* looped. The per-keystroke pick is index-seeded (deterministic).
|
|
138
|
+
*/
|
|
139
|
+
insertVoices?: readonly string[];
|
|
140
|
+
/** round-robin pool for deletes (overrides deleteVoice; default = the insert pool) */
|
|
141
|
+
deleteVoices?: readonly string[];
|
|
142
|
+
/** graphemes to NOT click; default whitespace (space, tab, newline) */
|
|
143
|
+
skip?: (grapheme: string) => boolean;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* One AudioClip per keystroke, placed at its time — the SFX side of the
|
|
147
|
+
* typewriter, the analogue of buildNarrationClips. Consumes the typewriter's
|
|
148
|
+
* `marks` (insert + delete) or a monotonic `revealSchedule` (inserts only).
|
|
149
|
+
* Char-class policy lives HERE: whitespace is skipped by default, a backspace
|
|
150
|
+
* can take a distinct voice, and a multi-sample pool round-robins (index-seeded)
|
|
151
|
+
* for non-looping foley. The marks stay neutral data; everything is a pure
|
|
152
|
+
* function of position.
|
|
153
|
+
*/
|
|
154
|
+
declare function keystrokeClips(marks: readonly KeystrokeMark[], source: SfxSource, opts?: KeystrokeOptions): AudioClip[];
|
|
121
155
|
//#endregion
|
|
122
|
-
export { PRESETS, SFX_PRESETS, SfxClipOptions, SfxError, SfxHit, SfxPreset, SfxSamplePack, SfxSource, SfxVoiceRef, SfxWaveform, SfxrParams, buildSfxClips, encodeWavMono, hashStr, renderSfxAssets, renderSfxr, samplePackSource, sfxFileName, sfxrSource };
|
|
156
|
+
export { KeystrokeMark, KeystrokeOptions, PRESETS, SFX_PRESETS, SfxClipOptions, SfxError, SfxHit, SfxPreset, SfxSamplePack, SfxSource, SfxVoiceRef, SfxWaveform, SfxrParams, buildSfxClips, encodeWavMono, hashStr, keystrokeClips, renderSfxAssets, renderSfxr, samplePackSource, sfxFileName, sfxrSource };
|
package/dist/index.js
CHANGED
|
@@ -289,5 +289,33 @@ function buildSfxClips(hits, source, opts = {}) {
|
|
|
289
289
|
return clip;
|
|
290
290
|
});
|
|
291
291
|
}
|
|
292
|
+
const isWhitespace = (g) => /^\s+$/.test(g);
|
|
293
|
+
/**
|
|
294
|
+
* One AudioClip per keystroke, placed at its time — the SFX side of the
|
|
295
|
+
* typewriter, the analogue of buildNarrationClips. Consumes the typewriter's
|
|
296
|
+
* `marks` (insert + delete) or a monotonic `revealSchedule` (inserts only).
|
|
297
|
+
* Char-class policy lives HERE: whitespace is skipped by default, a backspace
|
|
298
|
+
* can take a distinct voice, and a multi-sample pool round-robins (index-seeded)
|
|
299
|
+
* for non-looping foley. The marks stay neutral data; everything is a pure
|
|
300
|
+
* function of position.
|
|
301
|
+
*/
|
|
302
|
+
function keystrokeClips(marks, source, opts = {}) {
|
|
303
|
+
const insertPool = opts.insertVoices ?? [opts.insertVoice ?? "type"];
|
|
304
|
+
const deletePool = opts.deleteVoices ?? (opts.deleteVoice ? [opts.deleteVoice] : insertPool);
|
|
305
|
+
const skip = opts.skip ?? isWhitespace;
|
|
306
|
+
const seed = opts.seed ?? 0;
|
|
307
|
+
return buildSfxClips(marks.filter((m) => !skip(m.grapheme)).map((m, index) => {
|
|
308
|
+
const pool = m.kind === "delete" ? deletePool : insertPool;
|
|
309
|
+
let voice = pool[0];
|
|
310
|
+
if (pool.length > 1) {
|
|
311
|
+
const r = random((seed ^ hashStr("keystroke") ^ Math.imul(index + 1, 2246822507)) >>> 0)();
|
|
312
|
+
voice = pool[Math.min(pool.length - 1, Math.floor(r * pool.length))];
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
voice,
|
|
316
|
+
at: m.time
|
|
317
|
+
};
|
|
318
|
+
}), source, opts);
|
|
319
|
+
}
|
|
292
320
|
//#endregion
|
|
293
|
-
export { PRESETS, SFX_PRESETS, SfxError, buildSfxClips, encodeWavMono, hashStr, renderSfxAssets, renderSfxr, samplePackSource, sfxFileName, sfxrSource };
|
|
321
|
+
export { PRESETS, SFX_PRESETS, SfxError, buildSfxClips, encodeWavMono, hashStr, keystrokeClips, renderSfxAssets, renderSfxr, samplePackSource, sfxFileName, sfxrSource };
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glissade/sfx",
|
|
3
|
-
"version": "0.5.0-pre.
|
|
3
|
+
"version": "0.5.0-pre.3",
|
|
4
4
|
"description": "glissade sound effects: a clean-room procedural (sfxr-style) synth, license-checked sample packs, and deterministic index-seeded variation — committed WAVs feed the same offline FFmpeg mix as narration and music.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
8
11
|
"exports": {
|
|
9
12
|
".": {
|
|
10
13
|
"types": "./dist/index.d.ts",
|
|
@@ -15,7 +18,7 @@
|
|
|
15
18
|
"dist"
|
|
16
19
|
],
|
|
17
20
|
"dependencies": {
|
|
18
|
-
"@glissade/core": "0.5.0-pre.
|
|
21
|
+
"@glissade/core": "0.5.0-pre.3"
|
|
19
22
|
},
|
|
20
23
|
"repository": {
|
|
21
24
|
"type": "git",
|