@denaudio/den 0.0.0-stage → 0.2.0
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/CHANGELOG.md +63 -0
- package/LICENSE-APACHE +202 -0
- package/LICENSE-MIT +21 -0
- package/README.md +107 -2
- package/dist/biquad-eq.d.ts +11 -0
- package/dist/biquad-eq.js +35 -0
- package/dist/catalog-filter-math.d.ts +4 -0
- package/dist/catalog-filter-math.js +30 -0
- package/dist/character-filter.d.ts +13 -0
- package/dist/character-filter.js +53 -0
- package/dist/convolution-spectrum.d.ts +25 -0
- package/dist/convolution-spectrum.js +82 -0
- package/dist/convolution.d.ts +17 -0
- package/dist/convolution.js +87 -0
- package/dist/crossover.d.ts +11 -0
- package/dist/crossover.js +17 -0
- package/dist/curve-shaper.d.ts +26 -0
- package/dist/curve-shaper.js +73 -0
- package/dist/delay-fx.d.ts +37 -0
- package/dist/delay-fx.js +84 -0
- package/dist/delay-readhead.d.ts +19 -0
- package/dist/delay-readhead.js +54 -0
- package/dist/delay-settings.d.ts +55 -0
- package/dist/delay-settings.js +20 -0
- package/dist/drive.d.ts +24 -0
- package/dist/drive.js +116 -0
- package/dist/dual-head-delay.d.ts +28 -0
- package/dist/dual-head-delay.js +77 -0
- package/dist/dynamics.d.ts +61 -0
- package/dist/dynamics.js +130 -0
- package/dist/envelope.d.ts +34 -0
- package/dist/envelope.js +62 -0
- package/dist/filter.d.ts +9 -0
- package/dist/filter.js +34 -0
- package/dist/filterbank-vocoder.d.ts +35 -0
- package/dist/filterbank-vocoder.js +52 -0
- package/dist/formant-bank.d.ts +15 -0
- package/dist/formant-bank.js +28 -0
- package/dist/freeze-reverb.d.ts +35 -0
- package/dist/freeze-reverb.js +61 -0
- package/dist/frequency-shifter.d.ts +24 -0
- package/dist/frequency-shifter.js +57 -0
- package/dist/gate.d.ts +2 -0
- package/dist/gate.js +12 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +12 -0
- package/dist/instrument-example.d.ts +12 -0
- package/dist/instrument-example.js +29 -0
- package/dist/instrument-settings.d.ts +95 -0
- package/dist/instrument-settings.js +36 -0
- package/dist/instrument.d.ts +42 -0
- package/dist/instrument.js +166 -0
- package/dist/lfo.d.ts +19 -0
- package/dist/lfo.js +55 -0
- package/dist/live-buffer.d.ts +39 -0
- package/dist/live-buffer.js +52 -0
- package/dist/live-granular.d.ts +41 -0
- package/dist/live-granular.js +64 -0
- package/dist/lookahead-limiter.d.ts +31 -0
- package/dist/lookahead-limiter.js +67 -0
- package/dist/loop-crossfade.d.ts +28 -0
- package/dist/loop-crossfade.js +72 -0
- package/dist/modulation-fx.d.ts +47 -0
- package/dist/modulation-fx.js +58 -0
- package/dist/modulation.d.ts +132 -0
- package/dist/modulation.js +228 -0
- package/dist/mpe-expression.d.ts +36 -0
- package/dist/mpe-expression.js +73 -0
- package/dist/multiband-dynamics.d.ts +50 -0
- package/dist/multiband-dynamics.js +60 -0
- package/dist/musical-controls.d.ts +76 -0
- package/dist/musical-controls.js +125 -0
- package/dist/musical-examples.d.ts +21 -0
- package/dist/musical-examples.js +142 -0
- package/dist/musical-materials.d.ts +110 -0
- package/dist/musical-materials.js +56 -0
- package/dist/oscillator.d.ts +10 -0
- package/dist/oscillator.js +35 -0
- package/dist/oversampled-drive.d.ts +19 -0
- package/dist/oversampled-drive.js +99 -0
- package/dist/performance.d.ts +61 -0
- package/dist/performance.js +241 -0
- package/dist/pitch-quantizer.d.ts +26 -0
- package/dist/pitch-quantizer.js +88 -0
- package/dist/prepared-convolution.d.ts +26 -0
- package/dist/prepared-convolution.js +104 -0
- package/dist/resident-recorder.d.ts +28 -0
- package/dist/resident-recorder.js +68 -0
- package/dist/resident-time-stretch.d.ts +46 -0
- package/dist/resident-time-stretch.js +136 -0
- package/dist/resonator.d.ts +32 -0
- package/dist/resonator.js +63 -0
- package/dist/reverb.d.ts +27 -0
- package/dist/reverb.js +52 -0
- package/dist/sample.d.ts +113 -0
- package/dist/sample.js +212 -0
- package/dist/source.d.ts +58 -0
- package/dist/source.js +113 -0
- package/dist/spatial-chains.d.ts +50 -0
- package/dist/spatial-chains.js +76 -0
- package/dist/spectral-fft.d.ts +27 -0
- package/dist/spectral-fft.js +84 -0
- package/dist/spectral-freeze.d.ts +24 -0
- package/dist/spectral-freeze.js +74 -0
- package/dist/spectral-gate.d.ts +23 -0
- package/dist/spectral-gate.js +58 -0
- package/dist/spectral-stft.d.ts +14 -0
- package/dist/spectral-stft.js +70 -0
- package/dist/spectral-texture.d.ts +46 -0
- package/dist/spectral-texture.js +141 -0
- package/dist/spectral.d.ts +18 -0
- package/dist/spectral.js +10 -0
- package/dist/state-variable-filter.d.ts +17 -0
- package/dist/state-variable-filter.js +25 -0
- package/dist/stereo-delay.d.ts +45 -0
- package/dist/stereo-delay.js +70 -0
- package/dist/virtual-analog.d.ts +26 -0
- package/dist/virtual-analog.js +66 -0
- package/dist/voice-policy.d.ts +37 -0
- package/dist/voice-policy.js +245 -0
- package/dist/wavetable-bands.d.ts +37 -0
- package/dist/wavetable-bands.js +145 -0
- package/dist/wavetable-read.d.ts +6 -0
- package/dist/wavetable-read.js +11 -0
- package/dist/wavetable.d.ts +29 -0
- package/dist/wavetable.js +49 -0
- package/dist/windowed-pitch-shift.d.ts +34 -0
- package/dist/windowed-pitch-shift.js +51 -0
- package/docs/catalog-audition.md +76 -0
- package/docs/catalog-filters.md +125 -0
- package/docs/catalog-modulation-fx.md +220 -0
- package/docs/catalog-status.md +433 -0
- package/docs/character-filter.md +139 -0
- package/docs/contracts.md +141 -0
- package/docs/control-modulation.md +194 -0
- package/docs/convolution.md +50 -0
- package/docs/curve-shaper.md +117 -0
- package/docs/delay-fx-capture-findings.json +134 -0
- package/docs/delay-fx.md +202 -0
- package/docs/delay-readhead.md +121 -0
- package/docs/delay-settings-candidate.json +333 -0
- package/docs/delay-settings.md +111 -0
- package/docs/dependency-findings.md +58 -0
- package/docs/deployment-status.md +37 -0
- package/docs/drive.md +152 -0
- package/docs/dual-head-delay.md +131 -0
- package/docs/dynamics.md +180 -0
- package/docs/envelope-integer-staging.md +64 -0
- package/docs/filter-materialization-results.json +71 -0
- package/docs/filter-materialization.md +135 -0
- package/docs/filter-oscillator.md +126 -0
- package/docs/filterbank-vocoder-entry.md +58 -0
- package/docs/freeze-reverb.md +179 -0
- package/docs/frequency-shifter.md +133 -0
- package/docs/frontend-audition.md +22 -0
- package/docs/gain-schedule-verification.md +53 -0
- package/docs/initial-acceptance.md +79 -0
- package/docs/instrument-performance.md +191 -0
- package/docs/instrument-settings.md +130 -0
- package/docs/instrument.md +204 -0
- package/docs/integration-candidate.md +114 -0
- package/docs/live-buffer.md +163 -0
- package/docs/live-granular.md +179 -0
- package/docs/lookahead-multiband.md +183 -0
- package/docs/loop-crossfade.md +99 -0
- package/docs/mpe-expression.md +65 -0
- package/docs/musical-clock-seek-boundary.md +31 -0
- package/docs/musical-controls-contract.md +144 -0
- package/docs/musical-examples.md +255 -0
- package/docs/oversampled-drive.md +153 -0
- package/docs/performance.md +53 -0
- package/docs/pitch-quantizer.md +55 -0
- package/docs/prepared-convolution.md +197 -0
- package/docs/realtime-audition.md +63 -0
- package/docs/resident-recorder.md +151 -0
- package/docs/resident-time-stretch.md +196 -0
- package/docs/sample.md +191 -0
- package/docs/sound-audition-headroom.md +103 -0
- package/docs/sources.md +81 -0
- package/docs/spatial-chains-entry.md +251 -0
- package/docs/spectral-freeze-entry.md +132 -0
- package/docs/spectral-gate-entry.md +134 -0
- package/docs/spectral-large-candidate.md +81 -0
- package/docs/spectral-texture-entry.md +178 -0
- package/docs/spectral.md +127 -0
- package/docs/virtual-analog.md +77 -0
- package/docs/voice-policy.md +38 -0
- package/docs/wavetable-bands.md +138 -0
- package/docs/wavetable.md +101 -0
- package/docs/windowed-pitch-shift.md +112 -0
- package/package.json +269 -4
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Bounded resident wavetable candidate
|
|
2
|
+
|
|
3
|
+
`@denaudio/den/wavetable` exports `wavetableSource`, `WavetableConfig` and
|
|
4
|
+
`WavetableControls`. This is a candidate source, not an approved sound or a
|
|
5
|
+
bandlimited wavetable engine. Existing oscillator, instrument and sounds are unchanged.
|
|
6
|
+
|
|
7
|
+
## Layout and ingress
|
|
8
|
+
|
|
9
|
+
Instantiate one `residentSample` from `@denaudio/den/sample`, then pass that shared
|
|
10
|
+
resident to `wavetableSource`. The source does not create an asset loader or a
|
|
11
|
+
second PCM buffer. Use the resident's existing native `event<{data:Float32Array}>`
|
|
12
|
+
and `sample.load(data)` ingress, outside audible playback when practical. Native
|
|
13
|
+
dispatch copies PCM at a block boundary; this is not callback-free streaming.
|
|
14
|
+
|
|
15
|
+
PCM is frame-major mono: concatenate complete cycles of equal length. Do not
|
|
16
|
+
duplicate the first sample at the end. `frameLength` is an integer 4..4096;
|
|
17
|
+
`frameCount` is an integer 1..16. Their product must fit `sample.capacity`, which
|
|
18
|
+
must be 4..65536. Construction rejects invalid layouts. Extra loaded PCM after the
|
|
19
|
+
required product is ignored. A shorter or empty asset produces zero with
|
|
20
|
+
`missing=true` for the whole source, rather than playing a partial table.
|
|
21
|
+
|
|
22
|
+
The maximum layout holds 16 × 4096 = 65536 float32 samples (256 KiB). With the
|
|
23
|
+
sample lane's explicit CAPACITY_16 ingress and 262144-byte payload capacity,
|
|
24
|
+
the event payload arena contributes another 4 MiB, plus native metadata and
|
|
25
|
+
I/O/state. Ingress belongs to the shared resident, not to each oscillator. A
|
|
26
|
+
source has two cycle interpolations/four integer resident reads (eight bounded
|
|
27
|
+
PCM taps) regardless of frame count,
|
|
28
|
+
plus 36 bytes of declared scalar values before native layout/alignment. There is
|
|
29
|
+
no unrolled table bank, mipmap builder, FFT, dynamic allocation or JS DSP callback.
|
|
30
|
+
|
|
31
|
+
## Controls and sound
|
|
32
|
+
|
|
33
|
+
- `sampleRate`: finite 8000..192000 Hz, fixed at construction.
|
|
34
|
+
- `phaseCycles`: initial/reset phase in [0,1), default0.
|
|
35
|
+
- `frequencyHz`: float32 signal, clipped to [0,.45 × host sample rate]. Negative
|
|
36
|
+
values and NaN become0; positive infinity saturates. At zero Hz phase holds.
|
|
37
|
+
- `frame`: fractional frame index, clipped to [0,frameCount−1]. NaN becomes0.
|
|
38
|
+
Frame interpolation is linear without smoothing or wrap of the frame selector.
|
|
39
|
+
- `reset`: level-sensitive. True emits the configured phase on that sample,
|
|
40
|
+
then advances. A held reset repeats the same phase, though morph can change.
|
|
41
|
+
- Return: `{output, missing}`. Output is not peak-normalized or hard-clipped.
|
|
42
|
+
|
|
43
|
+
Cycle-local integer positions and fractions are split before adding a frame
|
|
44
|
+
offset, preserving tiny fractional contributions against large finite PCM. Each
|
|
45
|
+
cycle uses two integer resident reads and a convex linear mix. Both selected
|
|
46
|
+
cycles wrap independently from their last PCM sample back to their
|
|
47
|
+
own first sample, then their outputs are mixed. A cycle never interpolates into
|
|
48
|
+
the next morph frame. `sourceSampleRate` metadata is intentionally irrelevant:
|
|
49
|
+
each frame is one cycle, so frequency is controlled in host Hz, not playback-rate
|
|
50
|
+
conversion. The resident reader substitutes zero for NaN/infinite PCM taps;
|
|
51
|
+
arbitrary finite PCM amplitude is retained. Interpolated values are not stored in
|
|
52
|
+
float scalar scratch states, preserving tiny/subnormal samples.
|
|
53
|
+
|
|
54
|
+
Every resident revision, including equal-length replacement and revision integer
|
|
55
|
+
wrap, restarts the configured phase. Phase still advances while the asset is
|
|
56
|
+
missing. Replacement restarts it again when data arrives. There is no replacement
|
|
57
|
+
crossfade. No note/gate policy, envelope, gain stage or automatic unison is added.
|
|
58
|
+
|
|
59
|
+
Phase and frame materialization use exact power-of-two-scaled f64 native state to
|
|
60
|
+
avoid the upstream scalar flush below 1e-30. Tiny positive float32 frequencies
|
|
61
|
+
therefore accumulate from zero, subject to ordinary f64 rounding once added to a
|
|
62
|
+
nonzero phase. No artificial minimum musical frequency is imposed. State uses
|
|
63
|
+
the existing native snapshot mechanism. Only identical graph/config/sample-rate
|
|
64
|
+
continuation is tested; PCM contents and the shared resident revision are part
|
|
65
|
+
of that snapshot. No new serialization or cross-schema migration guarantee.
|
|
66
|
+
|
|
67
|
+
The phase scale is 2^1020 so even f64 `Number.MIN_VALUE` initialization survives
|
|
68
|
+
the native guard. Phase is always wrapped below 1 before scaling, leaving over
|
|
69
|
+
16× finite headroom; advance/multiply/read arithmetic occurs only after unscaling.
|
|
70
|
+
Morph is a float32 control, so its separate 2^128 scale is sufficient and remains
|
|
71
|
+
far from f64 overflow at frame 15. Scaled state is never multiplied by PCM.
|
|
72
|
+
|
|
73
|
+
## Quality boundaries
|
|
74
|
+
|
|
75
|
+
Linear cycle interpolation attenuates high harmonics but is not antialiasing.
|
|
76
|
+
High table harmonics fold even with legal fundamental frequency. Morph scanning,
|
|
77
|
+
abrupt replacement, reset and frequency modulation can add bandwidth. There are
|
|
78
|
+
no pitch bands or runtime harmonic rejection in this candidate. Pre-bandlimited
|
|
79
|
+
assets may help static playback; they do not prove modulation is alias-free.
|
|
80
|
+
|
|
81
|
+
Tests cover 44.1/48/96 kHz, independent periodic interpolation and sine-frequency
|
|
82
|
+
oracles, exact phase/reset/hold, frame 1/length4, wrapped endpoints, missing/short
|
|
83
|
+
assets, revision wrap, max resident, full finite/subnormal/nonfinite PCM and exact
|
|
84
|
+
snapshot continuation. An explicit high-harmonic test preserves the known folded
|
|
85
|
+
alias instead of labeling the source bandlimited. Packed consumer evidence is
|
|
86
|
+
separate from human listening, browser scheduling and hardware real-time proof.
|
|
87
|
+
|
|
88
|
+
## Optional prepared pitch bands
|
|
89
|
+
|
|
90
|
+
The same public subpath also exposes an additive host-preparation/native-reader
|
|
91
|
+
candidate. See [prepared pitch bands](./wavetable-bands.md) for its separate layout,
|
|
92
|
+
capacity, transition and quality contracts. The unbanded reader retains the
|
|
93
|
+
separate layout and control contract described above.
|
|
94
|
+
|
|
95
|
+
The cycle-local interpolation correction also fixes the former loss of tiny phase
|
|
96
|
+
at nonzero frame offsets. A frozen pre-fix fixture records the failing case
|
|
97
|
+
(phase 1e-40, a 0→3e38 ramp, expected 0.48 but formerly 0 in frame 1). Ordinary coherent
|
|
98
|
+
quarter-sample reads remain bit-identical to that fixture; general ordinary-rate
|
|
99
|
+
reads stay within the independent interpolation tolerance. Endpoint-safe convex
|
|
100
|
+
weighting can legitimately improve previous rounding/cancellation at extreme
|
|
101
|
+
PCM. Initial instrument/FX settings are untouched.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Bounded moving-window pitch effect
|
|
2
|
+
|
|
3
|
+
`windowedPitchShift` from `@denaudio/den/windowed-pitch-shift` is a CANDIDATE
|
|
4
|
+
mono input pitch effect made entirely from the existing unworklet 0.4.1 graph,
|
|
5
|
+
native controls, fixed buffers and snapshots. It changes the read speed of a
|
|
6
|
+
continuously arriving input. It does not reuse or change `dualHeadDelay`.
|
|
7
|
+
|
|
8
|
+
## Entry and allocation
|
|
9
|
+
|
|
10
|
+
Instantiate with `sampleRate: ctx.sampleRate` (integer 8000..192000) and optional
|
|
11
|
+
`windowSamples` (even integer 32..16384, default 2048). This fixes the delay-sweep
|
|
12
|
+
width W and allocates W+3 f64 history values, or 8(W+3) bytes excluding native
|
|
13
|
+
driver overhead. No resizing, runtime asset load, FFT or second audio runtime.
|
|
14
|
+
|
|
15
|
+
Call `tick(input, { ratio, retrigger, reset })` exactly once per sample. It returns
|
|
16
|
+
`{ output, ratioRejected }`. Input must be finite f32; all finite magnitudes,
|
|
17
|
+
including subnormals, are supported through exact binary internal scaling.
|
|
18
|
+
`ratio` is an audio-rate f32 input-time speed in [0.5,2], corresponding to one
|
|
19
|
+
octave down/up. NaN, infinities and adjacent out-of-range f32 values are rejected,
|
|
20
|
+
leaving the last valid ratio unchanged. Initial ratio is 1. There is no implicit
|
|
21
|
+
smoothing or semitone conversion; hosts may compose those explicitly.
|
|
22
|
+
|
|
23
|
+
## Exact sample law, latency and gain
|
|
24
|
+
|
|
25
|
+
Before consuming input x[n], let p be the stored phase in [0,1). Read the existing
|
|
26
|
+
history at delays dA=1+Wp and dB=1+W frac(p+1/2), using linear interpolation and
|
|
27
|
+
zero for unavailable history. The A weight is 1-|2p-1|; B uses its exact complement.
|
|
28
|
+
The emitted sample is their weighted sum. Store x[n] after reading, then advance
|
|
29
|
+
p by (1-ratio)/W modulo one. Between head wraps, input time therefore advances
|
|
30
|
+
by `ratio` samples per output sample. A head wraps only at its zero-weight point;
|
|
31
|
+
this does not make arbitrary input, retrigger or parameter edits click-free.
|
|
32
|
+
|
|
33
|
+
W denotes delay excursion, not a fixed-duration grain or STFT frame. At constant
|
|
34
|
+
nonunity ratio, one head cycle lasts W/|1-ratio| output samples; the other is a
|
|
35
|
+
half-cycle away. A large W lowers that window modulation rate and raises delay.
|
|
36
|
+
Ratio 1 stops phase movement rather than resetting it.
|
|
37
|
+
|
|
38
|
+
All reads have ages between 1 and W+1 samples. There is no single fixed latency
|
|
39
|
+
for pitch-shifted audio. Initially (or after a phase retrigger), ratio 1 gives an
|
|
40
|
+
exact 1+W/2-sample delay: at default W=2048 this is 1025 samples, about 21.35 ms
|
|
41
|
+
at 48 kHz. Returning to ratio 1 after arbitrary modulation freezes two weighted
|
|
42
|
+
different delays, which can comb-filter or cancel; it is not transparent bypass.
|
|
43
|
+
Mixing with dry audio adds phase coloration. The caller owns mixing and any
|
|
44
|
+
alignment decision; neither a dry tap nor automatic level compensation is hidden.
|
|
45
|
+
|
|
46
|
+
Both the interpolation and crossfade are convex. Output peak cannot exceed the
|
|
47
|
+
largest absolute retained input sample (up to floating rounding). Once history
|
|
48
|
+
is full, constant input passes at exactly unity gain. There is no feedback. If
|
|
49
|
+
the final nonzero input is at n, output is zero from n+W+2 onward, under every
|
|
50
|
+
ratio/retrigger sequence. An impulse may be repeated, attenuated or skipped.
|
|
51
|
+
|
|
52
|
+
## Reset, retrigger and state
|
|
53
|
+
|
|
54
|
+
`reset` has priority. It silences the current sample, discards that input,
|
|
55
|
+
invalidates history without clearing the entire allocation, and holds phase and
|
|
56
|
+
write cursor at zero. Held reset remains silent. The first sample after release
|
|
57
|
+
starts at phase zero with empty history. During reset a valid ratio is accepted;
|
|
58
|
+
an invalid ratio falls back to 1 instead of preserving the pre-reset value.
|
|
59
|
+
|
|
60
|
+
`retrigger` rephases the current read to zero while retaining existing history
|
|
61
|
+
and the current valid ratio. The sample then advances normally. A held retrigger
|
|
62
|
+
uses the initial midpoint delay every sample, even when ratio is not 1. An
|
|
63
|
+
instantaneous rephase can click; this is an explicit articulation control, not a
|
|
64
|
+
crossfade or automatic note policy.
|
|
65
|
+
|
|
66
|
+
History, cursor, valid age, phase and last valid ratio are native persistent
|
|
67
|
+
state. The output temporary is transient. Restoration is supported only for the
|
|
68
|
+
same processor, schema, configuration and sample rate; no cross-schema migration
|
|
69
|
+
is provided. Capture rendered native controls, not pending suspended edits.
|
|
70
|
+
|
|
71
|
+
## Audible limits and verification boundary
|
|
72
|
+
|
|
73
|
+
Linear interpolation is not a bandlimited resampler. Upward transposition of
|
|
74
|
+
content above sampleRate/(2*ratio) folds across Nyquist; even lower inputs can
|
|
75
|
+
show interpolation images and window sidebands. The two windows can color,
|
|
76
|
+
amplitude-modulate, smear, repeat, skip or cancel material, especially transients
|
|
77
|
+
and tones whose periods do not fit W. Window size and ratio are audible design
|
|
78
|
+
choices, not quality guarantees. There is no formant preservation, transient
|
|
79
|
+
alignment, WSOLA, phase vocoder or general independent duration/time stretching.
|
|
80
|
+
|
|
81
|
+
The dominant output pitch need not equal ratio times input pitch for undersized
|
|
82
|
+
or noncoherent windows. For example, W=64, ratio=2 and input
|
|
83
|
+
`0.75*cos(2*pi*n/128)` cancel the desired doubled-frequency bin (1/64 cycles per
|
|
84
|
+
sample, measured amplitude about 1.1e-16), while the original-frequency bin
|
|
85
|
+
(1/128 cycles per sample) remains at about 0.608049 amplitude. This measured
|
|
86
|
+
window limitation also means a larger/default W is not a pitch-quality guarantee.
|
|
87
|
+
|
|
88
|
+
Tests use an independent unbounded absolute-input timeline, analytic coherent
|
|
89
|
+
sinusoid frequency/phase checks, retained cancellation and alias counterexamples,
|
|
90
|
+
endpoint and gain bounds, reset/retrigger and in-flight same-schema continuation
|
|
91
|
+
at 44.1/48/96 kHz offline. The isolated packed consumer checks public declarations,
|
|
92
|
+
native per-sample ratio controls and fixed maximum allocation. Local timing is
|
|
93
|
+
diagnostic only. No browser/hardware realtime deadline, human listening approval
|
|
94
|
+
or golden-audio status follows from these tests.
|
|
95
|
+
|
|
96
|
+
## Live state and control restoration
|
|
97
|
+
|
|
98
|
+
Pinned core 0.4.1 copies worklet state before the host restores AudioParam values.
|
|
99
|
+
Restoring saved phase while an old ratio is still rendering can advance that
|
|
100
|
+
phase before unity ratio arrives; unity then holds the changed phase indefinitely.
|
|
101
|
+
For W2048 and an old ratio .5, one 128-sample quantum changes phase by 1/32 and
|
|
102
|
+
read age by 64 samples. A coherent 375 Hz input at 48 kHz therefore changes sign.
|
|
103
|
+
An even gap can coincidentally preserve that particular tone's phase; a passing
|
|
104
|
+
window is not proof of an atomic operation.
|
|
105
|
+
|
|
106
|
+
The tested browser composition first sets every saved control and confirms it
|
|
107
|
+
rendered, then restores without reset or retrigger. Native telemetry is checked
|
|
108
|
+
exactly and the original complex-phase assertion remains. This caller protocol
|
|
109
|
+
uses the existing native API, not an upstream fix or a general live-restore
|
|
110
|
+
guarantee for arbitrary changing automation/input. Exact same-schema offline
|
|
111
|
+
continuation and the deterministic stale-gap counterexample remain separate
|
|
112
|
+
evidence. See [shared contracts](contracts.md).
|
package/package.json
CHANGED
|
@@ -1,6 +1,271 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@denaudio/den",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Composable DSP modules and instrument/delay engines for unworklet",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT OR Apache-2.0",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/yuichkun/den.git"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"README.md",
|
|
14
|
+
"CHANGELOG.md",
|
|
15
|
+
"LICENSE-MIT",
|
|
16
|
+
"LICENSE-APACHE",
|
|
17
|
+
"docs"
|
|
18
|
+
],
|
|
19
|
+
"exports": {
|
|
20
|
+
"./character-filter": {
|
|
21
|
+
"types": "./dist/character-filter.d.ts",
|
|
22
|
+
"import": "./dist/character-filter.js"
|
|
23
|
+
},
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"import": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./gate": {
|
|
29
|
+
"types": "./dist/gate.d.ts",
|
|
30
|
+
"import": "./dist/gate.js"
|
|
31
|
+
},
|
|
32
|
+
"./envelope": {
|
|
33
|
+
"types": "./dist/envelope.d.ts",
|
|
34
|
+
"import": "./dist/envelope.js"
|
|
35
|
+
},
|
|
36
|
+
"./lfo": {
|
|
37
|
+
"types": "./dist/lfo.d.ts",
|
|
38
|
+
"import": "./dist/lfo.js"
|
|
39
|
+
},
|
|
40
|
+
"./oscillator": {
|
|
41
|
+
"types": "./dist/oscillator.d.ts",
|
|
42
|
+
"import": "./dist/oscillator.js"
|
|
43
|
+
},
|
|
44
|
+
"./instrument": {
|
|
45
|
+
"types": "./dist/instrument.d.ts",
|
|
46
|
+
"import": "./dist/instrument.js"
|
|
47
|
+
},
|
|
48
|
+
"./delay-fx": {
|
|
49
|
+
"types": "./dist/delay-fx.d.ts",
|
|
50
|
+
"import": "./dist/delay-fx.js"
|
|
51
|
+
},
|
|
52
|
+
"./delay-settings": {
|
|
53
|
+
"types": "./dist/delay-settings.d.ts",
|
|
54
|
+
"import": "./dist/delay-settings.js"
|
|
55
|
+
},
|
|
56
|
+
"./filter": {
|
|
57
|
+
"types": "./dist/filter.d.ts",
|
|
58
|
+
"import": "./dist/filter.js"
|
|
59
|
+
},
|
|
60
|
+
"./voice-policy": {
|
|
61
|
+
"types": "./dist/voice-policy.d.ts",
|
|
62
|
+
"import": "./dist/voice-policy.js"
|
|
63
|
+
},
|
|
64
|
+
"./delay-readhead": {
|
|
65
|
+
"types": "./dist/delay-readhead.d.ts",
|
|
66
|
+
"import": "./dist/delay-readhead.js"
|
|
67
|
+
},
|
|
68
|
+
"./instrument-example": {
|
|
69
|
+
"types": "./dist/instrument-example.d.ts",
|
|
70
|
+
"import": "./dist/instrument-example.js"
|
|
71
|
+
},
|
|
72
|
+
"./state-variable-filter": {
|
|
73
|
+
"types": "./dist/state-variable-filter.d.ts",
|
|
74
|
+
"import": "./dist/state-variable-filter.js"
|
|
75
|
+
},
|
|
76
|
+
"./biquad-eq": {
|
|
77
|
+
"types": "./dist/biquad-eq.d.ts",
|
|
78
|
+
"import": "./dist/biquad-eq.js"
|
|
79
|
+
},
|
|
80
|
+
"./crossover": {
|
|
81
|
+
"types": "./dist/crossover.d.ts",
|
|
82
|
+
"import": "./dist/crossover.js"
|
|
83
|
+
},
|
|
84
|
+
"./formant-bank": {
|
|
85
|
+
"types": "./dist/formant-bank.d.ts",
|
|
86
|
+
"import": "./dist/formant-bank.js"
|
|
87
|
+
},
|
|
88
|
+
"./dynamics": {
|
|
89
|
+
"types": "./dist/dynamics.d.ts",
|
|
90
|
+
"import": "./dist/dynamics.js"
|
|
91
|
+
},
|
|
92
|
+
"./drive": {
|
|
93
|
+
"types": "./dist/drive.d.ts",
|
|
94
|
+
"import": "./dist/drive.js"
|
|
95
|
+
},
|
|
96
|
+
"./modulation-fx": {
|
|
97
|
+
"types": "./dist/modulation-fx.d.ts",
|
|
98
|
+
"import": "./dist/modulation-fx.js"
|
|
99
|
+
},
|
|
100
|
+
"./stereo-delay": {
|
|
101
|
+
"types": "./dist/stereo-delay.d.ts",
|
|
102
|
+
"import": "./dist/stereo-delay.js"
|
|
103
|
+
},
|
|
104
|
+
"./reverb": {
|
|
105
|
+
"types": "./dist/reverb.d.ts",
|
|
106
|
+
"import": "./dist/reverb.js"
|
|
107
|
+
},
|
|
108
|
+
"./source": {
|
|
109
|
+
"types": "./dist/source.d.ts",
|
|
110
|
+
"import": "./dist/source.js"
|
|
111
|
+
},
|
|
112
|
+
"./resonator": {
|
|
113
|
+
"types": "./dist/resonator.d.ts",
|
|
114
|
+
"import": "./dist/resonator.js"
|
|
115
|
+
},
|
|
116
|
+
"./modulation": {
|
|
117
|
+
"types": "./dist/modulation.d.ts",
|
|
118
|
+
"import": "./dist/modulation.js"
|
|
119
|
+
},
|
|
120
|
+
"./performance": {
|
|
121
|
+
"types": "./dist/performance.d.ts",
|
|
122
|
+
"import": "./dist/performance.js"
|
|
123
|
+
},
|
|
124
|
+
"./sample": {
|
|
125
|
+
"types": "./dist/sample.d.ts",
|
|
126
|
+
"import": "./dist/sample.js"
|
|
127
|
+
},
|
|
128
|
+
"./wavetable": {
|
|
129
|
+
"types": "./dist/wavetable.d.ts",
|
|
130
|
+
"import": "./dist/wavetable.js"
|
|
131
|
+
},
|
|
132
|
+
"./virtual-analog": {
|
|
133
|
+
"types": "./dist/virtual-analog.d.ts",
|
|
134
|
+
"import": "./dist/virtual-analog.js"
|
|
135
|
+
},
|
|
136
|
+
"./spectral": {
|
|
137
|
+
"types": "./dist/spectral.d.ts",
|
|
138
|
+
"import": "./dist/spectral.js"
|
|
139
|
+
},
|
|
140
|
+
"./convolution": {
|
|
141
|
+
"types": "./dist/convolution.d.ts",
|
|
142
|
+
"import": "./dist/convolution.js"
|
|
143
|
+
},
|
|
144
|
+
"./frequency-shifter": {
|
|
145
|
+
"types": "./dist/frequency-shifter.d.ts",
|
|
146
|
+
"import": "./dist/frequency-shifter.js"
|
|
147
|
+
},
|
|
148
|
+
"./lookahead-limiter": {
|
|
149
|
+
"types": "./dist/lookahead-limiter.d.ts",
|
|
150
|
+
"import": "./dist/lookahead-limiter.js"
|
|
151
|
+
},
|
|
152
|
+
"./multiband-dynamics": {
|
|
153
|
+
"types": "./dist/multiband-dynamics.d.ts",
|
|
154
|
+
"import": "./dist/multiband-dynamics.js"
|
|
155
|
+
},
|
|
156
|
+
"./musical-examples": {
|
|
157
|
+
"types": "./dist/musical-examples.d.ts",
|
|
158
|
+
"import": "./dist/musical-examples.js"
|
|
159
|
+
},
|
|
160
|
+
"./curve-shaper": {
|
|
161
|
+
"types": "./dist/curve-shaper.d.ts",
|
|
162
|
+
"import": "./dist/curve-shaper.js"
|
|
163
|
+
},
|
|
164
|
+
"./oversampled-drive": {
|
|
165
|
+
"types": "./dist/oversampled-drive.d.ts",
|
|
166
|
+
"import": "./dist/oversampled-drive.js"
|
|
167
|
+
},
|
|
168
|
+
"./dual-head-delay": {
|
|
169
|
+
"types": "./dist/dual-head-delay.d.ts",
|
|
170
|
+
"import": "./dist/dual-head-delay.js"
|
|
171
|
+
},
|
|
172
|
+
"./mpe-expression": {
|
|
173
|
+
"types": "./dist/mpe-expression.d.ts",
|
|
174
|
+
"import": "./dist/mpe-expression.js"
|
|
175
|
+
},
|
|
176
|
+
"./windowed-pitch-shift": {
|
|
177
|
+
"types": "./dist/windowed-pitch-shift.d.ts",
|
|
178
|
+
"import": "./dist/windowed-pitch-shift.js"
|
|
179
|
+
},
|
|
180
|
+
"./spectral-gate": {
|
|
181
|
+
"types": "./dist/spectral-gate.d.ts",
|
|
182
|
+
"import": "./dist/spectral-gate.js"
|
|
183
|
+
},
|
|
184
|
+
"./prepared-convolution": {
|
|
185
|
+
"types": "./dist/prepared-convolution.d.ts",
|
|
186
|
+
"import": "./dist/prepared-convolution.js"
|
|
187
|
+
},
|
|
188
|
+
"./loop-crossfade": {
|
|
189
|
+
"types": "./dist/loop-crossfade.d.ts",
|
|
190
|
+
"import": "./dist/loop-crossfade.js"
|
|
191
|
+
},
|
|
192
|
+
"./resident-recorder": {
|
|
193
|
+
"types": "./dist/resident-recorder.d.ts",
|
|
194
|
+
"import": "./dist/resident-recorder.js"
|
|
195
|
+
},
|
|
196
|
+
"./freeze-reverb": {
|
|
197
|
+
"types": "./dist/freeze-reverb.d.ts",
|
|
198
|
+
"import": "./dist/freeze-reverb.js"
|
|
199
|
+
},
|
|
200
|
+
"./resident-time-stretch": {
|
|
201
|
+
"types": "./dist/resident-time-stretch.d.ts",
|
|
202
|
+
"import": "./dist/resident-time-stretch.js"
|
|
203
|
+
},
|
|
204
|
+
"./pitch-quantizer": {
|
|
205
|
+
"types": "./dist/pitch-quantizer.d.ts",
|
|
206
|
+
"import": "./dist/pitch-quantizer.js"
|
|
207
|
+
},
|
|
208
|
+
"./spectral-freeze": {
|
|
209
|
+
"types": "./dist/spectral-freeze.d.ts",
|
|
210
|
+
"import": "./dist/spectral-freeze.js"
|
|
211
|
+
},
|
|
212
|
+
"./filterbank-vocoder": {
|
|
213
|
+
"types": "./dist/filterbank-vocoder.d.ts",
|
|
214
|
+
"import": "./dist/filterbank-vocoder.js"
|
|
215
|
+
},
|
|
216
|
+
"./live-buffer": {
|
|
217
|
+
"types": "./dist/live-buffer.d.ts",
|
|
218
|
+
"import": "./dist/live-buffer.js"
|
|
219
|
+
},
|
|
220
|
+
"./live-granular": {
|
|
221
|
+
"types": "./dist/live-granular.d.ts",
|
|
222
|
+
"import": "./dist/live-granular.js"
|
|
223
|
+
},
|
|
224
|
+
"./spectral-texture": {
|
|
225
|
+
"types": "./dist/spectral-texture.d.ts",
|
|
226
|
+
"import": "./dist/spectral-texture.js"
|
|
227
|
+
},
|
|
228
|
+
"./spatial-chains": {
|
|
229
|
+
"types": "./dist/spatial-chains.d.ts",
|
|
230
|
+
"import": "./dist/spatial-chains.js"
|
|
231
|
+
},
|
|
232
|
+
"./musical-controls": {
|
|
233
|
+
"types": "./dist/musical-controls.d.ts",
|
|
234
|
+
"import": "./dist/musical-controls.js"
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
"engines": {
|
|
238
|
+
"node": ">=24 <25"
|
|
239
|
+
},
|
|
240
|
+
"scripts": {
|
|
241
|
+
"build": "tsc",
|
|
242
|
+
"check": "tsc --noEmit",
|
|
243
|
+
"test": "npm run build && vitest run && node --test --test-concurrency=1 tests/*.test.mjs && node --test tests/realtime/*.test.mjs",
|
|
244
|
+
"prepack": "npm run build",
|
|
245
|
+
"build:consumer": "node scripts/build-consumer.mjs",
|
|
246
|
+
"build:integration": "node scripts/build-integration.mjs",
|
|
247
|
+
"build:site": "node scripts/build-site.mjs",
|
|
248
|
+
"build:catalog": "node scripts/build-catalog.mjs",
|
|
249
|
+
"release:version": "node scripts/release-version.mjs",
|
|
250
|
+
"release:pack": "node scripts/release-pack.mjs",
|
|
251
|
+
"test:release": "node --test tests/release.test.mjs tests/release-package.test.mjs"
|
|
252
|
+
},
|
|
253
|
+
"peerDependencies": {
|
|
254
|
+
"@unworklet/core": "0.6.0"
|
|
255
|
+
},
|
|
256
|
+
"devDependencies": {
|
|
257
|
+
"@unworklet/core": "0.6.0",
|
|
258
|
+
"@unworklet/lang": "0.6.0",
|
|
259
|
+
"@unworklet/offline": "0.6.0",
|
|
260
|
+
"@unworklet/test": "0.6.0",
|
|
261
|
+
"@unworklet/unplugin": "0.6.0",
|
|
262
|
+
"playwright": "1.60.0",
|
|
263
|
+
"typescript": "5.9.3",
|
|
264
|
+
"vite": "7.3.6",
|
|
265
|
+
"vitest": "4.1.11"
|
|
266
|
+
},
|
|
267
|
+
"publishConfig": {
|
|
268
|
+
"access": "public",
|
|
269
|
+
"registry": "https://registry.npmjs.org"
|
|
270
|
+
}
|
|
271
|
+
}
|