cacophony 0.25.0 → 0.28.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/README.md +47 -16
- package/dist/bus.d.ts +180 -8
- package/dist/cacophony.d.ts +52 -155
- package/dist/effects.d.ts +167 -123
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +1395 -1065
- package/dist/index.mjs.map +1 -1
- package/dist/mediaStream.d.ts +25 -1
- package/dist/sound.d.ts +8 -2
- package/dist/synth.d.ts +3 -2
- package/dist/worklets.d.ts +58 -0
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/AudioCache.html +7 -7
- package/docs/classes/BiquadEffect.html +2 -2
- package/docs/classes/Bus.html +138 -22
- package/docs/classes/Cacophony.html +86 -165
- package/docs/classes/DynamicsEffect.html +8 -5
- package/docs/classes/FdnReverbEffect.html +8 -5
- package/docs/classes/FoaDecoder.html +15 -16
- package/docs/classes/FoaDecoderEffect.html +8 -0
- package/docs/classes/Group.html +13 -13
- package/docs/classes/ImpulseResponseEffect.html +10 -0
- package/docs/classes/KWeightingFilter.html +3 -3
- package/docs/classes/LoudnessMeter.html +11 -11
- package/docs/classes/MediaStreamPlayback.html +24 -18
- package/docs/classes/MediaStreamSound.html +20 -19
- package/docs/classes/MicrophonePlayback.html +3 -3
- package/docs/classes/ModulatedDelayEffect.html +6 -5
- package/docs/classes/PhaserEffect.html +8 -5
- package/docs/classes/Playback.html +36 -36
- package/docs/classes/ReverbEffect.html +8 -5
- package/docs/classes/ShareEffect.html +2 -2
- package/docs/classes/Sound.html +36 -32
- package/docs/classes/Synth.html +22 -21
- package/docs/classes/SynthGroup.html +2 -2
- package/docs/classes/TremoloEffect.html +6 -5
- package/docs/classes/TruePeakDetector.html +7 -7
- package/docs/classes/WaveshaperEffect.html +6 -5
- package/docs/functions/encodeMonoToFoaSN3D.html +1 -1
- package/docs/functions/integratedLoudness.html +1 -1
- package/docs/functions/integratedUngatedLoudness.html +1 -1
- package/docs/functions/loudnessRange.html +1 -1
- package/docs/functions/timeStretch.html +1 -1
- package/docs/functions/timeStretchChannels.html +1 -1
- package/docs/functions/truePeakDb.html +1 -1
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +17 -4
- package/docs/interfaces/AudioBuffer.html +2 -2
- package/docs/interfaces/AudioBufferSourceNode.html +4 -4
- package/docs/interfaces/AudioEventCallbacks.html +1 -1
- package/docs/interfaces/AudioListener.html +2 -2
- package/docs/interfaces/AudioNode.html +3 -3
- package/docs/interfaces/AudioParam.html +2 -2
- package/docs/interfaces/AudioWorklet.html +2 -2
- package/docs/interfaces/AudioWorkletNode.html +4 -4
- package/docs/interfaces/BaseContext.html +2 -2
- package/docs/interfaces/BaseSound.html +2 -2
- package/docs/interfaces/BiquadCoefficients.html +2 -2
- package/docs/interfaces/BiquadFilterNode.html +4 -4
- package/docs/interfaces/BuiltEffectGraph.html +10 -0
- package/docs/interfaces/CacheErrorEvent.html +2 -2
- package/docs/interfaces/CacheHitEvent.html +2 -2
- package/docs/interfaces/CacheMissEvent.html +2 -2
- package/docs/interfaces/CacophonyEffect.html +2 -2
- package/docs/interfaces/ChannelMergerNode.html +3 -3
- package/docs/interfaces/ChannelSplitterNode.html +3 -3
- package/docs/interfaces/ConvolverNode.html +26 -0
- package/docs/interfaces/DynamicsOptions.html +7 -7
- package/docs/interfaces/FadeStartEvent.html +2 -2
- package/docs/interfaces/FdnReverbOptions.html +6 -6
- package/docs/interfaces/FoaDecoderOptions.html +2 -2
- package/docs/interfaces/GainNode.html +3 -3
- package/docs/interfaces/GlobalPlaybackEvent.html +2 -2
- package/docs/interfaces/ImpulseResponseOptions.html +9 -0
- package/docs/interfaces/LoadingCompleteEvent.html +2 -2
- package/docs/interfaces/LoadingErrorEvent.html +2 -2
- package/docs/interfaces/LoadingProgressEvent.html +2 -2
- package/docs/interfaces/LoadingStartEvent.html +2 -2
- package/docs/interfaces/LoudnessChannelInput.html +2 -2
- package/docs/interfaces/LoudnessReading.html +5 -5
- package/docs/interfaces/MediaElementSourceNode.html +3 -3
- package/docs/interfaces/MediaStreamAudioSourceNode.html +3 -3
- package/docs/interfaces/MediaStreamSoundOptions.html +13 -2
- package/docs/interfaces/ModulatedDelayOptions.html +10 -8
- package/docs/interfaces/OfflineOptions.html +2 -2
- package/docs/interfaces/OscillatorNode.html +4 -4
- package/docs/interfaces/PannerNode.html +3 -3
- package/docs/interfaces/PhaserOptions.html +7 -7
- package/docs/interfaces/PlayOptions.html +2 -2
- package/docs/interfaces/PlaybackErrorEvent.html +2 -2
- package/docs/interfaces/ReverbOptions.html +13 -13
- package/docs/interfaces/RuntimeOptions.html +2 -2
- package/docs/interfaces/SoundCleanupHoldings.html +2 -2
- package/docs/interfaces/SoundErrorEvent.html +2 -2
- package/docs/interfaces/StereoPannerNode.html +3 -3
- package/docs/interfaces/TimeStretchOptions.html +5 -5
- package/docs/interfaces/TremoloOptions.html +7 -5
- package/docs/interfaces/WaveshaperOptions.html +8 -5
- package/docs/modules.html +7 -0
- package/docs/types/BaseAudioEvents.html +1 -1
- package/docs/types/BuiltEffect.html +1 -0
- package/docs/types/BusConnectionTarget.html +1 -1
- package/docs/types/CacheEventCallback.html +1 -1
- package/docs/types/CacophonyEvents.html +1 -1
- package/docs/types/ErrorEventCallback.html +1 -1
- package/docs/types/FadeType.html +1 -1
- package/docs/types/HrtfPannerOptions.html +1 -1
- package/docs/types/ImpulseResponseSource.html +1 -0
- package/docs/types/LoadingEventCallback.html +1 -1
- package/docs/types/LoopCount.html +1 -1
- package/docs/types/LoudnessChannel.html +1 -1
- package/docs/types/Orientation.html +1 -1
- package/docs/types/PanCloneOverrides.html +1 -1
- package/docs/types/PanType.html +1 -1
- package/docs/types/PlaybackEvents.html +1 -1
- package/docs/types/Position.html +1 -1
- package/docs/types/SoundEvents.html +1 -1
- package/docs/types/SoundType.html +1 -1
- package/docs/types/SourceNode.html +1 -1
- package/docs/types/SynthEvents.html +1 -1
- package/docs/types/ThreeDOptions.html +1 -1
- package/docs/variables/CHANNEL_WEIGHTS.html +1 -1
- package/docs/variables/K_WEIGHTING_STAGE1_48K.html +1 -1
- package/docs/variables/K_WEIGHTING_STAGE2_48K.html +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -350,9 +350,9 @@ API documented below. The Bus class supersedes the older user-built
|
|
|
350
350
|
A `Bus` is a named summing node with its own filter chain and per-edge
|
|
351
351
|
gain on outgoing connections. Sounds and synths route to buses via
|
|
352
352
|
`routeTo`; buses can carry rich effects (not just BiquadFilter) by
|
|
353
|
-
adding a `CacophonyEffect` to their filter chain. The built-in
|
|
354
|
-
`cacophony.createReverb()`
|
|
355
|
-
into a bus.
|
|
353
|
+
adding a `CacophonyEffect` to their filter chain. The built-in
|
|
354
|
+
`cacophony.createReverb()` and `cacophony.createImpulseResponse()` effects
|
|
355
|
+
are ready to drop into a bus.
|
|
356
356
|
|
|
357
357
|
```typescript
|
|
358
358
|
// 1. Create a named bus
|
|
@@ -393,29 +393,60 @@ the same node as `cacophony.globalGainNode`, so the existing
|
|
|
393
393
|
transparently. Routing a sound to `cacophony.master` (or never calling
|
|
394
394
|
`routeTo`) sends it through the master path.
|
|
395
395
|
|
|
396
|
-
### Bus-to-bus routing with per-edge gain
|
|
396
|
+
### Bus-to-bus routing with per-edge gain
|
|
397
397
|
|
|
398
398
|
```typescript
|
|
399
399
|
const groupBus = cacophony.createBus('group');
|
|
400
400
|
const sendBus = cacophony.createBus('aux');
|
|
401
401
|
groupBus.connect(sendBus, 0.2); // 20% send: groupBus.output → sendGain(0.2) → sendBus.input
|
|
402
|
-
groupBus.disconnect(sendBus); // tears down the sendGain too
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
###
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
`
|
|
409
|
-
|
|
410
|
-
|
|
402
|
+
groupBus.disconnect(sendBus); // tears down the sendGain too
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Native impulse responses
|
|
406
|
+
|
|
407
|
+
`createImpulseResponse()` builds a native `ConvolverNode` effect from an
|
|
408
|
+
`AudioBuffer` or URL. URL-backed IRs are fetched and decoded once per audio
|
|
409
|
+
context and URL; failed loads are evicted so a later call can retry. Convolver
|
|
410
|
+
normalization defaults to `false`, preserving measured IR gain.
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
// Wet-only send bus: returns a single ConvolverNode internally.
|
|
414
|
+
const chamber = cacophony.createBus('chamber');
|
|
415
|
+
await chamber.addFilter(cacophony.createImpulseResponse('/irs/chamber.wav'));
|
|
416
|
+
vocals.routeTo(chamber, 0.25);
|
|
417
|
+
|
|
418
|
+
// Inline dry/wet graph: exposes dry/wet AudioParams for bus automation.
|
|
419
|
+
const room = cacophony.createImpulseResponse('/irs/room.wav', {
|
|
420
|
+
dry: 0.7,
|
|
421
|
+
wet: 0.3,
|
|
422
|
+
normalize: false,
|
|
423
|
+
});
|
|
424
|
+
const handle = await bus.addFilter(room);
|
|
425
|
+
bus.rampFilterParam(handle, 'wet', 0.6, { duration: 500 });
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Adding custom effects to a bus
|
|
429
|
+
|
|
430
|
+
Bus filter chains accept Cacophony-built BiquadFilters and any
|
|
431
|
+
`CacophonyEffect`. Raw third-party AudioNodes are rejected unless you
|
|
432
|
+
wrap them explicitly with `cacophony.shareEffect(node)` — this surfaces
|
|
433
|
+
the shared-state intent (the same node will run on every bus that adds it).
|
|
434
|
+
An effect can build either a single `AudioNode` or a `BuiltEffectGraph` with
|
|
435
|
+
separate `input`/`output` endpoints for multi-node processors.
|
|
411
436
|
|
|
412
437
|
```typescript
|
|
413
438
|
const eq = cacophony.createBiquadFilter({ type: 'highshelf', frequency: 4000, gain: 3 });
|
|
414
439
|
await bus.addFilter(eq);
|
|
415
440
|
|
|
416
|
-
const sharedWorklet = new AudioWorkletNode(cacophony.context, 'my-fx');
|
|
417
|
-
await bus.addFilter(cacophony.shareEffect(sharedWorklet));
|
|
418
|
-
```
|
|
441
|
+
const sharedWorklet = new AudioWorkletNode(cacophony.context, 'my-fx');
|
|
442
|
+
await bus.addFilter(cacophony.shareEffect(sharedWorklet));
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
FOA binaural decoding is available in both forms. Use
|
|
446
|
+
`createFoaDecoder()` when you want explicit custom wiring through
|
|
447
|
+
`decoder.input` and `decoder.output`; use `createFoaDecoderEffect()` only on a
|
|
448
|
+
dedicated 4-channel ACN/SN3D FOA bus, typically as the first and only filter
|
|
449
|
+
that converts that bus to stereo binaural output.
|
|
419
450
|
|
|
420
451
|
### Cleaning up
|
|
421
452
|
|
package/dist/bus.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FadeType } from './cacophony';
|
|
1
2
|
import { AudioNode, BaseContext, BiquadFilterNode, GainNode } from './context';
|
|
2
3
|
import { CacophonyEffect } from './effects';
|
|
3
4
|
/**
|
|
@@ -6,6 +7,20 @@ import { CacophonyEffect } from './effects';
|
|
|
6
7
|
* directly to it — escape hatch for advanced wiring).
|
|
7
8
|
*/
|
|
8
9
|
export type BusConnectionTarget = Bus | AudioNode;
|
|
10
|
+
/**
|
|
11
|
+
* Structural contract a routed source (e.g. a {@link Sound}) implements so a
|
|
12
|
+
* Bus can move it off itself before teardown. Declared here — rather than
|
|
13
|
+
* importing `Sound` — to avoid an import cycle (`sound.ts` already imports
|
|
14
|
+
* `Bus`). A Bus only ever needs this one method on its inbound sources.
|
|
15
|
+
*/
|
|
16
|
+
export interface BusRoutedSource {
|
|
17
|
+
/**
|
|
18
|
+
* Called by {@link Bus.drainTo} to move this source off the draining bus
|
|
19
|
+
* onto `target`. The source reroutes its primary route and/or any send that
|
|
20
|
+
* targeted `bus`.
|
|
21
|
+
*/
|
|
22
|
+
_onBusDrained(bus: Bus, target: Bus): void;
|
|
23
|
+
}
|
|
9
24
|
/**
|
|
10
25
|
* A named summing node with a filter chain and per-edge send gain. See
|
|
11
26
|
* module-level docstring for topology.
|
|
@@ -24,10 +39,26 @@ export declare class Bus {
|
|
|
24
39
|
*/
|
|
25
40
|
readonly output: GainNode;
|
|
26
41
|
private readonly _context;
|
|
27
|
-
private readonly
|
|
42
|
+
private readonly _filterEntries;
|
|
43
|
+
/**
|
|
44
|
+
* Filter nodes currently bypassed (skipped in the audible chain). A bypassed
|
|
45
|
+
* node stays in {@link _filterEntries} — so {@link filters} order, identity, and
|
|
46
|
+
* its live AudioParams are preserved — but {@link _desiredFilterChainEdges}
|
|
47
|
+
* builds the series chain over the NON-bypassed filters only, wiring the
|
|
48
|
+
* signal around it. Membership is by node identity.
|
|
49
|
+
*/
|
|
50
|
+
private readonly _bypassedFilters;
|
|
28
51
|
private readonly _filterChainEdges;
|
|
29
52
|
private readonly _sendGains;
|
|
30
53
|
private readonly _directConnections;
|
|
54
|
+
/**
|
|
55
|
+
* Inbound sources currently routed to this bus (primary route and/or sends).
|
|
56
|
+
* A Web Audio node cannot enumerate its own inputs, so sources register
|
|
57
|
+
* themselves here (via {@link _registerRoutedSource}) when they route to
|
|
58
|
+
* this bus and unregister on reroute/cleanup. {@link drainTo} walks this set
|
|
59
|
+
* to move live sounds off the bus before it is torn down.
|
|
60
|
+
*/
|
|
61
|
+
private readonly _routedSources;
|
|
31
62
|
/**
|
|
32
63
|
* Hook invoked by the owning Cacophony instance to remove this bus from
|
|
33
64
|
* the named-bus registry on destroy. Anonymous buses leave this undefined.
|
|
@@ -61,10 +92,15 @@ export declare class Bus {
|
|
|
61
92
|
* `cacophony.shareEffect(node)` (or a proper CacophonyEffect class) to
|
|
62
93
|
* make the shared-state intent explicit.
|
|
63
94
|
*
|
|
95
|
+
* @returns the built AudioNode that was added to the chain. For a biquad this
|
|
96
|
+
* is the argument itself; for a {@link CacophonyEffect} it is the node
|
|
97
|
+
* produced by `build`. The returned handle can be passed to
|
|
98
|
+
* {@link rampFilterParam} to automate the node's parameters. Existing
|
|
99
|
+
* callers that ignore the result keep working unchanged.
|
|
64
100
|
* @throws if the bus has been destroyed, or if the argument is a raw
|
|
65
101
|
* AudioNode that is not a Cacophony-built biquad.
|
|
66
102
|
*/
|
|
67
|
-
addFilter(arg: BiquadFilterNode | CacophonyEffect | AudioNode): Promise<
|
|
103
|
+
addFilter(arg: BiquadFilterNode | CacophonyEffect | AudioNode): Promise<AudioNode>;
|
|
68
104
|
/**
|
|
69
105
|
* Remove a filter node from the bus's chain. The node must have been added
|
|
70
106
|
* via {@link addFilter}; the same object identity is used to match.
|
|
@@ -72,6 +108,93 @@ export declare class Bus {
|
|
|
72
108
|
* @throws if the bus has been destroyed or if the node was never added.
|
|
73
109
|
*/
|
|
74
110
|
removeFilter(node: AudioNode): void;
|
|
111
|
+
/**
|
|
112
|
+
* Reorder the existing filter chain. `nodes` must be a PERMUTATION of the
|
|
113
|
+
* current filters — the same set of node objects (matched by identity), the
|
|
114
|
+
* same length, with no duplicates — just in a new order. Because
|
|
115
|
+
* {@link _refreshFilters} is incremental, only the edges that actually move
|
|
116
|
+
* are reconnected; unchanged edges are left untouched.
|
|
117
|
+
*
|
|
118
|
+
* @throws if the bus has been destroyed, or if `nodes` is not a permutation
|
|
119
|
+
* of the current filters.
|
|
120
|
+
*/
|
|
121
|
+
setFilterOrder(nodes: readonly AudioNode[]): void;
|
|
122
|
+
/**
|
|
123
|
+
* Bypass (or un-bypass) a filter without removing it from the chain. A
|
|
124
|
+
* bypassed filter stays in {@link filters} — its order, identity, and live
|
|
125
|
+
* AudioParams are preserved (so an automation target survives a bypass) — but
|
|
126
|
+
* it is skipped in the audible series chain: the signal is wired around it.
|
|
127
|
+
* Un-bypassing wires it back in at its original position.
|
|
128
|
+
*
|
|
129
|
+
* The reconnect goes through the incremental {@link _refreshFilters}, so only
|
|
130
|
+
* the seam around `node` is touched — the rest of the chain is left connected.
|
|
131
|
+
*
|
|
132
|
+
* @param node A filter node currently on this bus (from {@link addFilter} or
|
|
133
|
+
* {@link filters}).
|
|
134
|
+
* @param bypassed `true` to skip the node, `false` to wire it back in. A no-op
|
|
135
|
+
* if the node is already in the requested state.
|
|
136
|
+
* @throws if the bus has been destroyed, or if `node` was never added to this
|
|
137
|
+
* bus.
|
|
138
|
+
*/
|
|
139
|
+
setFilterBypassed(node: AudioNode, bypassed: boolean): void;
|
|
140
|
+
/**
|
|
141
|
+
* Whether `node` is currently bypassed (skipped in the audible chain). Returns
|
|
142
|
+
* `false` for nodes that were never added to this bus.
|
|
143
|
+
*/
|
|
144
|
+
isFilterBypassed(node: AudioNode): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Ramp an effect node's parameter to a target value over time. This is the
|
|
147
|
+
* uniform automation handle for filter-chain effects: pass a node obtained
|
|
148
|
+
* from {@link addFilter} (or the {@link filters} getter) and the name of the
|
|
149
|
+
* parameter to drive.
|
|
150
|
+
*
|
|
151
|
+
* Parameter resolution:
|
|
152
|
+
* - If `node` exposes a worklet-style `parameters` AudioParamMap, the param
|
|
153
|
+
* is resolved via `parameters.get(paramName)` (e.g. a worklet effect's
|
|
154
|
+
* named params).
|
|
155
|
+
* - Otherwise, if `node[paramName]` is itself an AudioParam (native nodes
|
|
156
|
+
* such as a biquad expose `.frequency` / `.Q` / `.gain` directly), that is
|
|
157
|
+
* used.
|
|
158
|
+
*
|
|
159
|
+
* Ramp shape (mirrors the codebase fade convention): the target time base is
|
|
160
|
+
* `node.context.currentTime`. With no `duration` (or `duration <= 0`) the
|
|
161
|
+
* value is set immediately via `setValueAtTime(value, now)`. Otherwise the
|
|
162
|
+
* start is pinned with `setValueAtTime(param.value, now)` and the value ramps
|
|
163
|
+
* to `now + duration / 1000` (milliseconds) using `linearRampToValueAtTime`
|
|
164
|
+
* (default) or `exponentialRampToValueAtTime` when `type` is `"exponential"`
|
|
165
|
+
* (an exponential target of 0 is floored to 0.0001, matching `fadeTo`).
|
|
166
|
+
*
|
|
167
|
+
* Automation degrades gracefully: if `node` is not on this bus, or the
|
|
168
|
+
* parameter cannot be resolved to an AudioParam, a warning is logged and the
|
|
169
|
+
* call is a no-op. The only condition that throws is a destroyed bus.
|
|
170
|
+
*
|
|
171
|
+
* @param node A filter node currently on this bus (from {@link addFilter}).
|
|
172
|
+
* @param paramName The name of the parameter to automate.
|
|
173
|
+
* @param value The target value.
|
|
174
|
+
* @param options.duration Ramp duration in milliseconds. Absent/`<= 0` sets
|
|
175
|
+
* the value immediately.
|
|
176
|
+
* @param options.type Ramp curve, `"linear"` (default) or `"exponential"`.
|
|
177
|
+
* @throws if the bus has been destroyed.
|
|
178
|
+
*/
|
|
179
|
+
rampFilterParam(node: AudioNode, paramName: string, value: number, options?: {
|
|
180
|
+
duration?: number;
|
|
181
|
+
type?: FadeType;
|
|
182
|
+
}): void;
|
|
183
|
+
/**
|
|
184
|
+
* Resolve the named {@link AudioParam} on a node. Tries the worklet
|
|
185
|
+
* `parameters` map first, then a directly-exposed native param
|
|
186
|
+
* (`node[paramName]`). Returns `undefined` if neither yields an AudioParam.
|
|
187
|
+
*
|
|
188
|
+
* Detection is structural (duck-typed), never `instanceof` — the mocked test
|
|
189
|
+
* context may not provide the `AudioParam` global.
|
|
190
|
+
*/
|
|
191
|
+
private _resolveAudioParam;
|
|
192
|
+
/**
|
|
193
|
+
* Structural AudioParam check: a value is treated as an AudioParam if it
|
|
194
|
+
* exposes the ramp scheduling methods. Avoids `instanceof AudioParam` so it
|
|
195
|
+
* works under the standardized-audio-context mock (which may lack the global).
|
|
196
|
+
*/
|
|
197
|
+
private _isAudioParam;
|
|
75
198
|
/**
|
|
76
199
|
* Connect this bus's output to another bus or to a raw AudioNode.
|
|
77
200
|
*
|
|
@@ -95,22 +218,71 @@ export declare class Bus {
|
|
|
95
218
|
* @throws if the bus has been destroyed.
|
|
96
219
|
*/
|
|
97
220
|
disconnect(target: BusConnectionTarget): void;
|
|
221
|
+
/**
|
|
222
|
+
* Register an inbound source that routes to this bus (primary and/or send).
|
|
223
|
+
* Called by the source when it begins routing here. Idempotent (Set). Safe
|
|
224
|
+
* to call without a destroyed guard — registration during normal routing
|
|
225
|
+
* must never throw — but a destroyed bus has nothing to drain, so this
|
|
226
|
+
* early-returns once destroyed.
|
|
227
|
+
*
|
|
228
|
+
* @internal
|
|
229
|
+
*/
|
|
230
|
+
_registerRoutedSource(source: BusRoutedSource): void;
|
|
231
|
+
/**
|
|
232
|
+
* Unregister an inbound source (it rerouted away or was cleaned up). No-op
|
|
233
|
+
* if the source was never registered.
|
|
234
|
+
*
|
|
235
|
+
* @internal
|
|
236
|
+
*/
|
|
237
|
+
_unregisterRoutedSource(source: BusRoutedSource): void;
|
|
238
|
+
/**
|
|
239
|
+
* Move every source currently routed to this bus onto `target`, so live
|
|
240
|
+
* sounds keep feeding a live bus instead of the dead `input` after this bus
|
|
241
|
+
* is torn down. Each registered source's {@link BusRoutedSource._onBusDrained}
|
|
242
|
+
* reroutes its primary route and/or the send that targeted this bus.
|
|
243
|
+
*
|
|
244
|
+
* @throws if this bus has been destroyed, or if `target` is this bus.
|
|
245
|
+
*/
|
|
246
|
+
drainTo(target: Bus): void;
|
|
98
247
|
/**
|
|
99
248
|
* Tear down the bus — disconnects input, output, every send-gain, every
|
|
100
249
|
* filter, then deregisters from the owner Cacophony's named-bus map.
|
|
101
250
|
* Subsequent `addFilter`/`removeFilter`/`connect`/`disconnect` calls throw.
|
|
102
251
|
*
|
|
103
|
-
*
|
|
252
|
+
* If `options.drainTo` is provided, every source routed to this bus is first
|
|
253
|
+
* rerouted onto that bus (via {@link drainTo}) so live sounds keep playing
|
|
254
|
+
* through a live bus. With no options the default teardown is unchanged:
|
|
255
|
+
* sounds routed to the destroyed bus fall back to master on their next
|
|
104
256
|
* playback (the routeTo machinery checks `destroyed` at preplay).
|
|
105
257
|
*/
|
|
106
|
-
destroy(
|
|
258
|
+
destroy(options?: {
|
|
259
|
+
drainTo?: Bus;
|
|
260
|
+
}): void;
|
|
107
261
|
/**
|
|
108
|
-
*
|
|
109
|
-
* after any add/remove of a filter.
|
|
110
|
-
*
|
|
111
|
-
*
|
|
262
|
+
* Reconcile the live chain to `input → [filter1 → ... → filterN] → output`.
|
|
263
|
+
* Called after any add/remove/reorder of a filter. This is an INCREMENTAL
|
|
264
|
+
* diff, not a full rebuild: it disconnects only edges that are no longer part
|
|
265
|
+
* of the desired chain and connects only edges that are newly required,
|
|
266
|
+
* leaving edges present in both the old and new chain connected and
|
|
267
|
+
* untouched (no audible click on the unchanged portion of the chain).
|
|
268
|
+
*
|
|
269
|
+
* Edges are matched by OBJECT IDENTITY on both endpoints. Only this bus's own
|
|
270
|
+
* internal `input → ... → output` edges are touched — never a broad
|
|
271
|
+
* `node.disconnect()`, never the outbound send/direct edges.
|
|
112
272
|
*/
|
|
113
273
|
private _refreshFilters;
|
|
274
|
+
/**
|
|
275
|
+
* Compute the desired ordered chain edge list from the current
|
|
276
|
+
* `_filterEntries`, skipping any node in {@link _bypassedFilters}: the series
|
|
277
|
+
* chain is built over the NON-bypassed filters only. With no active (non-
|
|
278
|
+
* bypassed) filters — whether the bus has no filters at all or every filter is
|
|
279
|
+
* bypassed — the desired list is `[[input, output]]` (the direct edge);
|
|
280
|
+
* otherwise `[[input, a1], [a1, a2], ..., [aN, output]]` over the active
|
|
281
|
+
* filters `a1..aN`. Bypassed nodes stay in {@link _filterEntries} (and thus in
|
|
282
|
+
* {@link filters}) but receive no inbound/outbound chain edge.
|
|
283
|
+
*/
|
|
284
|
+
private _desiredFilterChainEdges;
|
|
285
|
+
private _normalizeBuiltEffect;
|
|
114
286
|
private _connectFilterChainEdge;
|
|
115
287
|
private _disconnectFilterChainEdges;
|
|
116
288
|
private _throwIfDestroyed;
|
package/dist/cacophony.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Bus } from './bus';
|
|
2
2
|
import { ICache } from './cache';
|
|
3
3
|
import { AudioBuffer, AudioListener, AudioNode, AudioWorkletNode, BaseContext, BiquadFilterNode, ChannelMergerNode, ChannelSplitterNode, GainNode, PannerNode } from './context';
|
|
4
|
-
import { CacophonyEffect, DynamicsEffect, DynamicsOptions, FdnReverbEffect, FdnReverbOptions, FoaDecoder, FoaDecoderOptions, ModulatedDelayEffect, ModulatedDelayOptions, PhaserEffect, PhaserOptions, ReverbEffect, ReverbOptions, TremoloEffect, TremoloOptions, WaveshaperEffect, WaveshaperOptions } from './effects';
|
|
4
|
+
import { CacophonyEffect, DynamicsEffect, DynamicsOptions, FdnReverbEffect, FdnReverbOptions, FoaDecoder, FoaDecoderEffect, FoaDecoderOptions, ImpulseResponseEffect, ImpulseResponseOptions, ImpulseResponseSource, ModulatedDelayEffect, ModulatedDelayOptions, PhaserEffect, PhaserOptions, ReverbEffect, ReverbOptions, TremoloEffect, TremoloOptions, WaveshaperEffect, WaveshaperOptions } from './effects';
|
|
5
5
|
import { CacophonyEvents } from './events';
|
|
6
6
|
import { Group } from './group';
|
|
7
7
|
import { MediaStreamSound, MediaStreamSoundOptions } from './mediaStream';
|
|
@@ -11,6 +11,7 @@ import { ThreeDOptions } from './pannerMixin';
|
|
|
11
11
|
import { TimeStretchOptions } from './processors/timestretch-core';
|
|
12
12
|
import { Sound } from './sound';
|
|
13
13
|
import { Synth } from './synth';
|
|
14
|
+
import { WorkletModule } from './worklets';
|
|
14
15
|
export type SoundType = "html" | "streaming" | "buffer" | "oscillator";
|
|
15
16
|
/**
|
|
16
17
|
* Represents a 3D position in space.
|
|
@@ -148,6 +149,12 @@ export declare class Cacophony {
|
|
|
148
149
|
* `loadFoaHrir` calls share a single fetch/decode.
|
|
149
150
|
*/
|
|
150
151
|
private foaHrirCache;
|
|
152
|
+
/**
|
|
153
|
+
* Per-context, per-URL decoded impulse-response cache. Stores in-flight
|
|
154
|
+
* promises so concurrent effect builds for the same context/URL share the
|
|
155
|
+
* same fetch/decode. Rejected promises are evicted so the caller can retry.
|
|
156
|
+
*/
|
|
157
|
+
private impulseResponseCache;
|
|
151
158
|
private finalizationRegistry;
|
|
152
159
|
private eventEmitter;
|
|
153
160
|
private cache;
|
|
@@ -253,162 +260,24 @@ export declare class Cacophony {
|
|
|
253
260
|
off<K extends keyof CacophonyEvents>(event: K, listener: (data: CacophonyEvents[K]) => void): void;
|
|
254
261
|
emit<K extends keyof CacophonyEvents>(event: K, data: CacophonyEvents[K]): void;
|
|
255
262
|
emitAsync<K extends keyof CacophonyEvents>(event: K, data: CacophonyEvents[K]): Promise<void>;
|
|
256
|
-
loadWorklets(signal?: AbortSignal): Promise<void>;
|
|
257
|
-
loadStereoToBFormatWorklet(signal?: AbortSignal): Promise<void>;
|
|
258
|
-
/**
|
|
259
|
-
* Idempotently registers the `phase-vocoder` AudioWorkletProcessor (peak-based
|
|
260
|
-
* pitch-shifter with Identity Phase-Locking, Laroche & Dolson 1999 WASPAA) on
|
|
261
|
-
* this context. Safe to call repeatedly — subsequent calls short-circuit via
|
|
262
|
-
* the per-context {@link loadedAudioWorklets} set. Cross-context: pass
|
|
263
|
-
* `context` so a node built against a bus on a different context loads there.
|
|
264
|
-
*/
|
|
265
|
-
loadPhaseVocoder(signal?: AbortSignal, context?: BaseContext): Promise<void>;
|
|
266
|
-
/**
|
|
267
|
-
* Constructs a `phase-vocoder` AudioWorkletNode. Caller is expected to have
|
|
268
|
-
* loaded the module already (via {@link loadPhaseVocoder} or {@link loadWorklets}).
|
|
269
|
-
* Uses the same construct/fallback path as {@link createWorkletNode}. The
|
|
270
|
-
* returned node carries a single `pitchFactor` AudioParam (1 = no shift).
|
|
271
|
-
*/
|
|
272
|
-
createPhaseVocoderNode(options?: AudioWorkletNodeOptions, context?: BaseContext): Promise<AudioWorkletNode>;
|
|
273
|
-
/**
|
|
274
|
-
* Idempotently registers the DattorroReverb AudioWorkletProcessor on this
|
|
275
|
-
* context. Safe to call repeatedly — subsequent calls short-circuit via
|
|
276
|
-
* the {@link loadedAudioWorklets} set used by
|
|
277
|
-
* {@link loadAudioWorkletModule}.
|
|
278
|
-
*
|
|
279
|
-
* @param signal Optional abort signal forwarded to the module load.
|
|
280
|
-
* @param context Optional BaseContext to load the worklet on. Defaults to
|
|
281
|
-
* the host Cacophony instance's `context`. Supplied so a
|
|
282
|
-
* {@link ReverbEffect} added to a bus whose context is NOT this host's
|
|
283
|
-
* own (cross-context use) can load the worklet on the right context.
|
|
284
|
-
*/
|
|
285
|
-
loadDattorroReverb(signal?: AbortSignal, context?: BaseContext): Promise<void>;
|
|
286
|
-
/**
|
|
287
|
-
* Constructs a DattorroReverb AudioWorkletNode. Caller is expected to have
|
|
288
|
-
* loaded the module already (via {@link loadDattorroReverb} or by reaching
|
|
289
|
-
* here through {@link ReverbEffect.build}). Uses the same construct/fallback
|
|
290
|
-
* path as {@link createWorkletNode}.
|
|
291
|
-
*
|
|
292
|
-
* @param options AudioWorkletNode construction options.
|
|
293
|
-
* @param context Optional BaseContext to construct on. Defaults to the
|
|
294
|
-
* host Cacophony instance's `context`. See {@link loadDattorroReverb}
|
|
295
|
-
* for the cross-context rationale.
|
|
296
|
-
*/
|
|
297
|
-
createDattorroReverbNode(options: AudioWorkletNodeOptions, context?: BaseContext): Promise<AudioWorkletNode>;
|
|
298
|
-
/**
|
|
299
|
-
* Idempotently registers the `dynamics` AudioWorkletProcessor (feed-forward
|
|
300
|
-
* compressor/limiter/expander/gate, Giannoulis 2012) on this context. Safe to
|
|
301
|
-
* call repeatedly — subsequent calls short-circuit via the per-context
|
|
302
|
-
* {@link loadedAudioWorklets} set. Cross-context: pass `context` so a
|
|
303
|
-
* {@link DynamicsEffect} added to a bus on a different context loads there.
|
|
304
|
-
*/
|
|
305
|
-
loadDynamics(signal?: AbortSignal, context?: BaseContext): Promise<void>;
|
|
306
|
-
/**
|
|
307
|
-
* Constructs a `dynamics` AudioWorkletNode. Caller is expected to have loaded
|
|
308
|
-
* the module already (via {@link loadDynamics} or by reaching here through
|
|
309
|
-
* {@link DynamicsEffect.build}). Uses the same construct/fallback path as
|
|
310
|
-
* {@link createWorkletNode}.
|
|
311
|
-
*/
|
|
312
|
-
createDynamicsNode(options: AudioWorkletNodeOptions, context?: BaseContext): Promise<AudioWorkletNode>;
|
|
313
|
-
/**
|
|
314
|
-
* Idempotently registers the `fdn-reverb` AudioWorkletProcessor (Feedback
|
|
315
|
-
* Delay Network reverb — lossless paraunitary Hadamard feedback per Schlecht
|
|
316
|
-
* & Habets 2019, per-line absorption T60 per Jot 1991, velvet-noise diffusion
|
|
317
|
-
* per Fagerström 2020) on this context. Safe to call repeatedly — subsequent
|
|
318
|
-
* calls short-circuit via the per-context {@link loadedAudioWorklets} set.
|
|
319
|
-
* Cross-context: pass `context` so an {@link FdnReverbEffect} added to a bus
|
|
320
|
-
* on a different context loads there.
|
|
321
|
-
*/
|
|
322
|
-
loadFdnReverb(signal?: AbortSignal, context?: BaseContext): Promise<void>;
|
|
323
|
-
/**
|
|
324
|
-
* Constructs an `fdn-reverb` AudioWorkletNode. Caller is expected to have
|
|
325
|
-
* loaded the module already (via {@link loadFdnReverb} or by reaching here
|
|
326
|
-
* through {@link FdnReverbEffect.build}). Uses the same construct/fallback
|
|
327
|
-
* path as {@link createWorkletNode}.
|
|
328
|
-
*/
|
|
329
|
-
createFdnReverbNode(options: AudioWorkletNodeOptions, context?: BaseContext): Promise<AudioWorkletNode>;
|
|
330
|
-
/**
|
|
331
|
-
* Idempotently registers the `waveshaper` AudioWorkletProcessor (antialiased
|
|
332
|
-
* distortion/waveshaper via first-order Antiderivative Antialiasing, Parker,
|
|
333
|
-
* Zavalishin & Le Bivic 2016, DAFx-16) on this context. Safe to call
|
|
334
|
-
* repeatedly — subsequent calls short-circuit via the per-context
|
|
335
|
-
* {@link loadedAudioWorklets} set. Cross-context: pass `context` so a
|
|
336
|
-
* {@link WaveshaperEffect} added to a bus on a different context loads there.
|
|
337
|
-
*/
|
|
338
|
-
loadWaveshaper(signal?: AbortSignal, context?: BaseContext): Promise<void>;
|
|
339
|
-
/**
|
|
340
|
-
* Constructs a `waveshaper` AudioWorkletNode. Caller is expected to have
|
|
341
|
-
* loaded the module already (via {@link loadWaveshaper} or by reaching here
|
|
342
|
-
* through {@link WaveshaperEffect.build}). Uses the same construct/fallback
|
|
343
|
-
* path as {@link createWorkletNode}.
|
|
344
|
-
*/
|
|
345
|
-
createWaveshaperNode(options: AudioWorkletNodeOptions, context?: BaseContext): Promise<AudioWorkletNode>;
|
|
346
263
|
/**
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
*
|
|
351
|
-
*
|
|
352
|
-
* set. Cross-context: pass `context` so a {@link ModulatedDelayEffect} added to
|
|
353
|
-
* a bus on a different context loads there.
|
|
264
|
+
* Eagerly registers every bundled AudioWorklet module on this context. This is
|
|
265
|
+
* OPTIONAL — effects load their own worklet lazily in `build`, and the
|
|
266
|
+
* pitch-shift path loads the phase-vocoder on first use. Call this up front to
|
|
267
|
+
* pay the registration cost ahead of time. Idempotent per context (each module
|
|
268
|
+
* short-circuits via the per-context {@link loadedAudioWorklets} set).
|
|
354
269
|
*/
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
* Constructs a `modulated-delay` AudioWorkletNode. Caller is expected to have
|
|
358
|
-
* loaded the module already (via {@link loadModulatedDelay} or by reaching here
|
|
359
|
-
* through {@link ModulatedDelayEffect.build}). Uses the same construct/fallback
|
|
360
|
-
* path as {@link createWorkletNode}.
|
|
361
|
-
*/
|
|
362
|
-
createModulatedDelayNode(options: AudioWorkletNodeOptions, context?: BaseContext): Promise<AudioWorkletNode>;
|
|
363
|
-
/**
|
|
364
|
-
* Idempotently registers the `phaser` AudioWorkletProcessor — a classic
|
|
365
|
-
* MXR/Univibe-style allpass-cascade phase shifter (Smith STAN-M-21; PASP §8.9:
|
|
366
|
-
* a cascade of first-order allpass sections at a common LFO-swept break
|
|
367
|
-
* frequency, summed additively with the dry signal to sweep notches) on this
|
|
368
|
-
* context. Safe to call repeatedly — subsequent calls short-circuit via the
|
|
369
|
-
* per-context {@link loadedAudioWorklets} set. Cross-context: pass `context` so
|
|
370
|
-
* a {@link PhaserEffect} added to a bus on a different context loads there.
|
|
371
|
-
*/
|
|
372
|
-
loadPhaser(signal?: AbortSignal, context?: BaseContext): Promise<void>;
|
|
373
|
-
/**
|
|
374
|
-
* Constructs a `phaser` AudioWorkletNode. Caller is expected to have loaded the
|
|
375
|
-
* module already (via {@link loadPhaser} or by reaching here through
|
|
376
|
-
* {@link PhaserEffect.build}). Uses the same construct/fallback path as
|
|
377
|
-
* {@link createWorkletNode}.
|
|
378
|
-
*/
|
|
379
|
-
createPhaserNode(options: AudioWorkletNodeOptions, context?: BaseContext): Promise<AudioWorkletNode>;
|
|
380
|
-
/**
|
|
381
|
-
* Idempotently registers the `tremolo` AudioWorkletProcessor — LFO-driven
|
|
382
|
-
* amplitude modulation (a VCA swung by a low-frequency oscillator; standard AM
|
|
383
|
-
* theory + Dattorro 1997 p.776 quadrature stereo LFO + Mitcheltree et al.
|
|
384
|
-
* DAFx23 LFO framing) on this context. Safe to call repeatedly — subsequent
|
|
385
|
-
* calls short-circuit via the per-context {@link loadedAudioWorklets} set.
|
|
386
|
-
* Cross-context: pass `context` so a {@link TremoloEffect} added to a bus on a
|
|
387
|
-
* different context loads there.
|
|
388
|
-
*/
|
|
389
|
-
loadTremolo(signal?: AbortSignal, context?: BaseContext): Promise<void>;
|
|
390
|
-
/**
|
|
391
|
-
* Constructs a `tremolo` AudioWorkletNode. Caller is expected to have loaded the
|
|
392
|
-
* module already (via {@link loadTremolo} or by reaching here through
|
|
393
|
-
* {@link TremoloEffect.build}). Uses the same construct/fallback path as
|
|
394
|
-
* {@link createWorkletNode}.
|
|
395
|
-
*/
|
|
396
|
-
createTremoloNode(options: AudioWorkletNodeOptions, context?: BaseContext): Promise<AudioWorkletNode>;
|
|
397
|
-
/**
|
|
398
|
-
* Idempotently registers the `loudness-meter` AudioWorkletProcessor (ITU-R
|
|
399
|
-
* BS.1770-5 momentary / short-term / integrated loudness + true-peak) on this
|
|
400
|
-
* context. Safe to call repeatedly — subsequent calls short-circuit via the
|
|
401
|
-
* per-context {@link loadedAudioWorklets} set. Cross-context: pass `context`
|
|
402
|
-
* so a meter tapping a bus on a different context loads there.
|
|
403
|
-
*/
|
|
404
|
-
loadLoudnessMeter(signal?: AbortSignal, context?: BaseContext): Promise<void>;
|
|
270
|
+
loadWorklets(signal?: AbortSignal): Promise<void>;
|
|
271
|
+
loadStereoToBFormatWorklet(signal?: AbortSignal): Promise<void>;
|
|
405
272
|
/**
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
273
|
+
* The single worklet-effect construction seam ({@link WorkletEffectHost}).
|
|
274
|
+
* Idempotently registers `worklet`'s module on `context` — or this host's own
|
|
275
|
+
* context when omitted, honoring the cross-context contract that effects'
|
|
276
|
+
* `build(context)` promises — then constructs the AudioWorkletNode with
|
|
277
|
+
* `parameterData`. Every worklet-backed {@link CacophonyEffect} routes through
|
|
278
|
+
* here, as does the phase-vocoder pitch-shift path ({@link Playback.setPitchShift}).
|
|
410
279
|
*/
|
|
411
|
-
|
|
280
|
+
buildWorkletEffect(worklet: WorkletModule, parameterData: Record<string, number>, context?: BaseContext): Promise<AudioWorkletNode>;
|
|
412
281
|
/**
|
|
413
282
|
* Fetches and decodes the bundled order-1 SH-HRIR
|
|
414
283
|
* (`sh_hrir_order_1.wav`, from Omnitone, Apache-2.0 — see
|
|
@@ -426,6 +295,18 @@ export declare class Cacophony {
|
|
|
426
295
|
* a different context decodes the HRIR on the right context.
|
|
427
296
|
*/
|
|
428
297
|
loadFoaHrir(context?: BaseContext): Promise<AudioBuffer>;
|
|
298
|
+
/**
|
|
299
|
+
* Fetches and decodes an impulse response URL on the requested audio context,
|
|
300
|
+
* memoized per context and URL. Buffers decoded by one context are not reused
|
|
301
|
+
* on another context, matching Web Audio's context-bound decode behavior.
|
|
302
|
+
*
|
|
303
|
+
* @param url Impulse-response audio URL.
|
|
304
|
+
* @param context Optional decode context. Defaults to this Cacophony instance.
|
|
305
|
+
* @param signal Optional abort signal for the fetch. Decode itself is not
|
|
306
|
+
* abortable in Web Audio, but an already-aborted signal is honored before
|
|
307
|
+
* decode starts.
|
|
308
|
+
*/
|
|
309
|
+
loadImpulseResponseBuffer(url: string, context?: BaseContext, signal?: AbortSignal): Promise<AudioBuffer>;
|
|
429
310
|
createWorkletNode(name: string, url: string, signal?: AbortSignal, options?: AudioWorkletNodeOptions, context?: BaseContext): Promise<AudioWorkletNode>;
|
|
430
311
|
createStereoToBFormatNode(signal?: AbortSignal): Promise<AudioWorkletNode>;
|
|
431
312
|
/**
|
|
@@ -439,6 +320,7 @@ export declare class Cacophony {
|
|
|
439
320
|
private markWorkletLoadedOn;
|
|
440
321
|
private loadAudioWorkletModule;
|
|
441
322
|
private createAbortError;
|
|
323
|
+
private waitForImpulseResponseLoad;
|
|
442
324
|
private createMediaSound;
|
|
443
325
|
clearMemoryCache(): void;
|
|
444
326
|
createOscillator(options: OscillatorOptions, panType?: PanType): Synth;
|
|
@@ -529,6 +411,14 @@ export declare class Cacophony {
|
|
|
529
411
|
* chain via `bus.addFilter(effect)`.
|
|
530
412
|
*/
|
|
531
413
|
createReverb(options?: ReverbOptions): ReverbEffect;
|
|
414
|
+
/**
|
|
415
|
+
* Creates a native ConvolverNode impulse-response effect. Pass an AudioBuffer
|
|
416
|
+
* for an already-decoded IR or a URL to fetch/decode through the per-context
|
|
417
|
+
* IR cache. The default is wet-only (`dry: 0`, `wet: 1`) and returns a single
|
|
418
|
+
* ConvolverNode when added to a bus; setting `dry` or non-unity `wet` builds
|
|
419
|
+
* an owned dry/wet endpoint graph exposing `dry` and `wet` automation params.
|
|
420
|
+
*/
|
|
421
|
+
createImpulseResponse(source: ImpulseResponseSource, options?: ImpulseResponseOptions): ImpulseResponseEffect;
|
|
532
422
|
/**
|
|
533
423
|
* Creates a Feedback Delay Network (FDN) {@link CacophonyEffect} — an
|
|
534
424
|
* algorithmic reverb with a lossless degree-0 paraunitary Hadamard feedback
|
|
@@ -668,8 +558,8 @@ export declare class Cacophony {
|
|
|
668
558
|
* Omnitone's WY/ZX 2-stereo-ConvolverNode packing and the bundled order-1
|
|
669
559
|
* SH-HRIR.
|
|
670
560
|
*
|
|
671
|
-
* It is 4-channel-in / 2-channel-out
|
|
672
|
-
*
|
|
561
|
+
* It is 4-channel-in / 2-channel-out; this method returns the explicit
|
|
562
|
+
* endpoint object for custom graph wiring:
|
|
673
563
|
* feed FOA into `decoder.input` (4-ch) and route `decoder.output` (2-ch
|
|
674
564
|
* stereo) downstream:
|
|
675
565
|
* ```ts
|
|
@@ -682,6 +572,13 @@ export declare class Cacophony {
|
|
|
682
572
|
* `createStereoToBFormatNode` (the perceptual, approximate stereo-upmix path).
|
|
683
573
|
*/
|
|
684
574
|
createFoaDecoder(options?: FoaDecoderOptions, context?: BaseContext): Promise<FoaDecoder>;
|
|
575
|
+
/**
|
|
576
|
+
* Creates a bus-filter wrapper around {@link FoaDecoder}. Use this on a
|
|
577
|
+
* dedicated 4-channel ACN/SN3D FOA bus, typically as the first and only
|
|
578
|
+
* filter that converts that bus to stereo binaural output. For custom manual
|
|
579
|
+
* wiring, use {@link createFoaDecoder} instead.
|
|
580
|
+
*/
|
|
581
|
+
createFoaDecoderEffect(options?: FoaDecoderOptions): FoaDecoderEffect;
|
|
685
582
|
/**
|
|
686
583
|
* Creates an ITU-R BS.1770-5 {@link LoudnessMeter} that TAPS the output of a
|
|
687
584
|
* target node without altering the audible path. The meter reports momentary
|