The operations that change a sound's samples, as data: Reverse, Repeat, Add silence, Normalize, Pan, Dither, Filter, Stretch, Pitch, Speed and Repair, with Delete, Crop, Paste and Gain; applySoundOperation runs one on plain channels, on all of them or a stretch, soundOperationName names it as a step of the history.
pnpm dlx shadcn@latest add @audio-ui/sound-operations
import { REPAIR_NAMES, soundOperationName, SEAM, applySoundOperation, soundOperationTiming } from "@/lib/sound-operations";| Files | lib/sound-operations.ts |
|---|---|
| Depends on | Nothing |
| npm | @audio-ui/core, @audio-ui/engine |
| Used by | block-audio-editor, clip-panel, process-menu, use-bake |
| Export | Kind | What it is |
|---|---|---|
SoundSamples | interface | A sound as plain samples: what an operation reads and writes. |
SoundRange | type | A stretch of a sound, from where it starts to where it ends, in seconds. |
SoundOperation | type | One change to a sound's samples. |
REPAIR_NAMES | const | What each repair is called. |
soundOperationName | function | What an operation is called, as a step of the history: "Repeat ×2", "Pitch -5 st". |
SEAM | const | How long the seam between what an operation made and what it left is crossfaded, in seconds: no click at either end. |
applySoundOperation | function | The sound an operation makes, at the same rate: of the whole sound, or of range alone, spliced back in with its seams crossfaded. |
soundOperationTiming | function | How an operation moves the times in the stretch it changes: "scaled" by how much longer it makes it (Stretch, Speed), "cropped" to it alone (Crop), or "spliced", where what it made starts where the stretch did and what follows moves by as much as it grew or shrank (Delete, Paste, Repeat, Add silence, and the rest, which keep its length). |
Usage
An operation is data, { type: "stretch", factor: 1.5, method: "transient" }, so a menu, a key or an agent's tool can pick one and the code that holds the sound runs it. The Process menu lists the processes; Delete, Crop, Paste and Gain are an audio editor's edits.
import {
applySoundOperation,
soundOperationName,
soundOperationTiming,
} from "@/lib/sound-operations";
const operation = { semitones: -2, method: "formant", type: "shift" } as const;
const sound = { channels, sampleRate: 48_000 };
// Plain channels in, plain channels out, at the same rate.
const next = applySoundOperation(sound, operation);
// On a stretch alone, 1 s to 2.5 s, spliced back with each seam crossfaded.
const edited = applySoundOperation(sound, { db: 3, type: "gain" }, [1, 2.5]);
// The edits: take a stretch out, keep it alone, or put copied samples in its place.
applySoundOperation(sound, { type: "delete" }, [1, 2.5]);
applySoundOperation(sound, { type: "crop" }, [1, 2.5]);
applySoundOperation(sound, { channels: copied, type: "paste" }, [4, 4]); // at a point: inserted there
soundOperationName(operation); // "Pitch -2 st"
soundOperationTiming(operation); // "spliced": what follows the stretch moves by as much as it grewEach process is one of @audio-ui/engine/files (reverseChannels, repeatChannels, padChannels, normalizeChannels, panChannels, ditherChannels, filterChannels, stretchChannels, shiftChannels, speedChannels, gainChannels) or repairChannels of @audio-ui/engine/repair, whose methods the menu offers as a choice. Given a range, in seconds, the operation runs on that stretch alone, and each seam with the rest is crossfaded over SEAM (5 ms), so a cut, an insert or a stretch processed on its own makes no click. soundOperationTiming says how one moves the times in the stretch: "scaled" for Stretch and Speed, "cropped" for Crop, "spliced" for the rest; the clip panel's processedSettings reads it to keep a clip on what it played.