first commit
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
# `chorus/schemas`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Zod schemas validating the construction-time options and preset payload of `ChorusPlugin`. These run on the public boundary between user code and the plugin: any malformed object hitting the constructor or `applyPreset` is rejected with `AUDIO_FX.INVALID_OPTIONS` / `AUDIO_FX.INVALID_PRESET` before it can corrupt runtime state.
|
||||
|
||||
Separating schemas from the plugin module lets `index.ts` re-export them so callers can introspect the option surface (for forms, editors, RPC validation) without importing the audio implementation.
|
||||
|
||||
## Features
|
||||
|
||||
- `ChorusPluginOptionsSchema` — validates all five optional construction fields with their documented ranges (`rate` 0.05..10 Hz, `depth` 0..20 ms, `feedback` 0..0.95, `wet` 0..1, `baseDelay` 5..30 ms).
|
||||
- `ChorusPresetDataSchema` — empty strict object: the chorus has no plugin-specific preset payload, so any extra keys are rejected by `.strict()`.
|
||||
- Both schemas use `z.number().finite()` so `NaN` and `Infinity` cannot sneak through.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { ChorusPluginOptionsSchema } from "@suaveplan/audio-fx-plugin-chorus";
|
||||
|
||||
const parsed = ChorusPluginOptionsSchema.parse({ initialWet: 0.4 });
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
ChorusPluginOptionsSchema,
|
||||
ChorusPresetDataSchema,
|
||||
} from "@suaveplan/audio-fx-plugin-chorus";
|
||||
|
||||
// Build a form from the schema's shape keys.
|
||||
const fields = ChorusPluginOptionsSchema.keyof().options;
|
||||
for (const field of fields) {
|
||||
form.addRow(field);
|
||||
}
|
||||
|
||||
// Reject foreign preset payloads at the IPC boundary before they
|
||||
// reach the plugin.
|
||||
function validateChorusPreset(blob: unknown): boolean {
|
||||
return ChorusPresetDataSchema.safeParse(blob).success;
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `ChorusPluginOptionsSchema: z.ZodObject<{ initialRateHz?, initialDepthMs?, initialFeedback?, initialWet?, initialBaseDelayMs? }>`
|
||||
- `ChorusPresetDataSchema: z.ZodObject<{}, "strict">`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The maximum feedback is `0.95`, not `1.0`. Allowing feedback at unity would create a marginally stable system whose output diverges for any non-zero input; clamping at 0.95 leaves enough headroom that even a noise-floor leak stays bounded over arbitrarily long renders. The test "max feedback over a long sine never produces non-finite samples" exercises this boundary.
|
||||
|
||||
`ChorusPresetDataSchema` is `.strict()` for the same reason as the other plugins: unknown fields almost always indicate a payload from a sibling plugin or a forwards-incompatible schema. Silent rejection at the boundary is much less harmful than partial application, which can leave the plugin in a half-restored state.
|
||||
Reference in New Issue
Block a user