@flighthq/media 0.1.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.
@@ -0,0 +1,16 @@
1
+ import type { AudioChannel, AudioPlayOptions, AudioResource } from '@flighthq/types';
2
+ export declare function connectAudioChannelToNode(channel: AudioChannel, destinationNode: AudioNode): void;
3
+ export declare function fadeAudioChannelGain(channel: AudioChannel, targetGain: number, durationMs: number): void;
4
+ export declare function getAudioChannelCurrentTime(channel: AudioChannel): number;
5
+ export declare function getAudioChannelDuration(channel: AudioChannel): number;
6
+ export declare function getAudioChannelInputNode(channel: AudioChannel): AudioNode | null;
7
+ export declare function getAudioChannelOutputNode(channel: AudioChannel): AudioNode | null;
8
+ export declare function isAudioChannelPlaying(channel: AudioChannel): boolean;
9
+ export declare function pauseAudioChannel(channel: AudioChannel): void;
10
+ export declare function playAudioResource(context: AudioContext, source: AudioResource, options?: Readonly<AudioPlayOptions>): AudioChannel | null;
11
+ export declare function resumeAudioChannel(channel: AudioChannel): void;
12
+ export declare function setAudioChannelCurrentTime(channel: AudioChannel, value: number): number;
13
+ export declare function setAudioChannelGain(channel: AudioChannel, value: number): number;
14
+ export declare function setAudioChannelPlaybackRate(channel: AudioChannel, value: number): number;
15
+ export declare function stopAudioChannel(channel: AudioChannel): void;
16
+ //# sourceMappingURL=audioChannel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioChannel.d.ts","sourceRoot":"","sources":["../src/audioChannel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErF,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,GAAG,IAAI,CAQjG;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAYxG;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAIxE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAErE;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,CAGhF;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,CAGjF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAEpE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAK7D;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GACnC,YAAY,GAAG,IAAI,CAyBrB;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAG9D;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAOvF;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKhF;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKxF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAI5D"}
@@ -0,0 +1,163 @@
1
+ import { createSignal, emitSignal } from '@flighthq/signals';
2
+ export function connectAudioChannelToNode(channel, destinationNode) {
3
+ const runtime = channelRuntime.get(channel);
4
+ if (runtime === undefined)
5
+ return;
6
+ if (runtime.gainNode !== null) {
7
+ runtime.gainNode.disconnect();
8
+ runtime.gainNode.connect(destinationNode);
9
+ }
10
+ runtime.destinationNode = destinationNode;
11
+ }
12
+ export function fadeAudioChannelGain(channel, targetGain, durationMs) {
13
+ const runtime = channelRuntime.get(channel);
14
+ if (runtime?.gainNode === null || runtime?.gainNode === undefined) {
15
+ channel.gain = targetGain;
16
+ return;
17
+ }
18
+ const ctx = runtime.context;
19
+ const now = ctx.currentTime;
20
+ runtime.gainNode.gain.cancelScheduledValues(now);
21
+ runtime.gainNode.gain.setValueAtTime(runtime.gainNode.gain.value, now);
22
+ runtime.gainNode.gain.linearRampToValueAtTime(targetGain, now + durationMs / 1000);
23
+ channel.gain = targetGain;
24
+ }
25
+ export function getAudioChannelCurrentTime(channel) {
26
+ const runtime = channelRuntime.get(channel);
27
+ if (runtime === undefined || channel.state !== 'playing')
28
+ return channel.currentTime;
29
+ return Math.min((runtime.context.currentTime - runtime.startedAt) * 1000, channel.length);
30
+ }
31
+ export function getAudioChannelDuration(channel) {
32
+ return channel.length;
33
+ }
34
+ export function getAudioChannelInputNode(channel) {
35
+ const runtime = channelRuntime.get(channel);
36
+ return runtime?.sourceNode ?? null;
37
+ }
38
+ export function getAudioChannelOutputNode(channel) {
39
+ const runtime = channelRuntime.get(channel);
40
+ return runtime?.gainNode ?? null;
41
+ }
42
+ export function isAudioChannelPlaying(channel) {
43
+ return channel.state === 'playing';
44
+ }
45
+ export function pauseAudioChannel(channel) {
46
+ if (channel.state !== 'playing')
47
+ return;
48
+ channel.currentTime = getAudioChannelCurrentTime(channel);
49
+ channel.state = 'paused';
50
+ stopActiveNode(channel, false);
51
+ }
52
+ export function playAudioResource(context, source, options) {
53
+ if (source.buffer === null)
54
+ return null;
55
+ const channel = {
56
+ currentTime: options?.currentTime ?? 0,
57
+ gain: options?.gain ?? 1,
58
+ length: source.buffer.duration * 1000,
59
+ loops: options?.loops ?? 0,
60
+ playbackRate: options?.playbackRate ?? 1,
61
+ source,
62
+ state: 'stopped',
63
+ onComplete: createSignal(),
64
+ };
65
+ channelRuntime.set(channel, {
66
+ context,
67
+ destinationNode: null,
68
+ gainNode: null,
69
+ loopsRemaining: channel.loops,
70
+ sourceNode: null,
71
+ startedAt: 0,
72
+ });
73
+ startAudioChannel(channel);
74
+ return channel;
75
+ }
76
+ export function resumeAudioChannel(channel) {
77
+ if (channel.state === 'playing' || channel.source.buffer === null)
78
+ return;
79
+ startAudioChannel(channel);
80
+ }
81
+ export function setAudioChannelCurrentTime(channel, value) {
82
+ channel.currentTime = clamp(value, 0, channel.length);
83
+ if (channel.state === 'playing') {
84
+ stopActiveNode(channel, false);
85
+ startAudioChannel(channel);
86
+ }
87
+ return channel.currentTime;
88
+ }
89
+ export function setAudioChannelGain(channel, value) {
90
+ channel.gain = value;
91
+ const runtime = channelRuntime.get(channel);
92
+ if (runtime?.gainNode !== null && runtime?.gainNode !== undefined)
93
+ runtime.gainNode.gain.value = value;
94
+ return channel.gain;
95
+ }
96
+ export function setAudioChannelPlaybackRate(channel, value) {
97
+ channel.playbackRate = value;
98
+ const runtime = channelRuntime.get(channel);
99
+ if (runtime?.sourceNode !== null && runtime?.sourceNode !== undefined)
100
+ runtime.sourceNode.playbackRate.value = value;
101
+ return channel.playbackRate;
102
+ }
103
+ export function stopAudioChannel(channel) {
104
+ stopActiveNode(channel, false);
105
+ channel.currentTime = 0;
106
+ channel.state = 'stopped';
107
+ }
108
+ const channelRuntime = new WeakMap();
109
+ function clamp(value, min, max) {
110
+ return Math.min(Math.max(value, min), max);
111
+ }
112
+ function completeAudioChannel(channel) {
113
+ const runtime = channelRuntime.get(channel);
114
+ if (runtime === undefined || channel.state !== 'playing')
115
+ return;
116
+ if (runtime.loopsRemaining !== 0) {
117
+ if (runtime.loopsRemaining > 0)
118
+ runtime.loopsRemaining--;
119
+ channel.currentTime = 0;
120
+ startAudioChannel(channel);
121
+ return;
122
+ }
123
+ runtime.gainNode = null;
124
+ runtime.sourceNode = null;
125
+ channel.currentTime = channel.length;
126
+ channel.state = 'complete';
127
+ emitSignal(channel.onComplete);
128
+ }
129
+ function startAudioChannel(channel) {
130
+ const runtime = channelRuntime.get(channel);
131
+ const buffer = channel.source.buffer;
132
+ if (runtime === undefined || buffer === null)
133
+ return;
134
+ const sourceNode = runtime.context.createBufferSource();
135
+ const gainNode = runtime.context.createGain();
136
+ const currentTime = clamp(channel.currentTime, 0, channel.length);
137
+ sourceNode.buffer = buffer;
138
+ sourceNode.playbackRate.value = channel.playbackRate;
139
+ gainNode.gain.value = channel.gain;
140
+ sourceNode.connect(gainNode);
141
+ gainNode.connect(runtime.destinationNode ?? runtime.context.destination);
142
+ sourceNode.onended = () => completeAudioChannel(channel);
143
+ runtime.gainNode = gainNode;
144
+ runtime.sourceNode = sourceNode;
145
+ runtime.startedAt = runtime.context.currentTime - currentTime / 1000;
146
+ channel.currentTime = currentTime;
147
+ channel.state = 'playing';
148
+ sourceNode.start(0, currentTime / 1000);
149
+ if (runtime.context.state === 'suspended') {
150
+ runtime.context.resume().catch(() => { });
151
+ }
152
+ }
153
+ function stopActiveNode(channel, complete) {
154
+ const runtime = channelRuntime.get(channel);
155
+ const sourceNode = runtime?.sourceNode;
156
+ if (runtime === undefined || sourceNode === null || sourceNode === undefined)
157
+ return;
158
+ runtime.sourceNode = null;
159
+ runtime.gainNode = null;
160
+ sourceNode.onended = complete ? () => completeAudioChannel(channel) : null;
161
+ sourceNode.stop();
162
+ }
163
+ //# sourceMappingURL=audioChannel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioChannel.js","sourceRoot":"","sources":["../src/audioChannel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { AudioBus, AudioBusOptions, AudioChannel, AudioMixer, AudioMixerOptions } from '@flighthq/types';
2
+ export declare function addAudioBusToMixer(mixer: Readonly<AudioMixer>, bus: AudioBus): void;
3
+ export declare function createAudioBus(options?: Readonly<AudioBusOptions>): AudioBus;
4
+ export declare function createAudioMixer(context: AudioContext, options?: Readonly<AudioMixerOptions>): AudioMixer;
5
+ export declare function destroyAudioMixer(mixer: Readonly<AudioMixer>): void;
6
+ export declare function fadeAudioBusGain(mixer: Readonly<AudioMixer>, bus: AudioBus, targetGain: number, durationMs: number): void;
7
+ export declare function getAudioMixerActiveChannels(mixer: Readonly<AudioMixer>): readonly AudioChannel[];
8
+ export declare function pauseAllAudioMixerChannels(mixer: Readonly<AudioMixer>): void;
9
+ export declare function resumeAllAudioMixerChannels(mixer: Readonly<AudioMixer>): void;
10
+ export declare function routeAudioChannelToMixerBus(mixer: Readonly<AudioMixer>, channel: AudioChannel, bus: AudioBus): void;
11
+ export declare function setAudioBusGain(bus: AudioBus, value: number): number;
12
+ export declare function setAudioBusMuted(bus: AudioBus, muted: boolean): boolean;
13
+ export declare function setAudioBusPan(bus: AudioBus, value: number): number;
14
+ export declare function setAudioMixerMasterGain(mixer: AudioMixer, value: number): number;
15
+ export declare function setAudioMixerMasterMuted(mixer: AudioMixer, muted: boolean): boolean;
16
+ export declare function stopAllAudioMixerChannels(mixer: Readonly<AudioMixer>): void;
17
+ export declare function unrouteAudioChannelFromMixerBus(mixer: Readonly<AudioMixer>, channel: AudioChannel): void;
18
+ //# sourceMappingURL=audioMixer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioMixer.d.ts","sourceRoot":"","sources":["../src/audioMixer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAI9G,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAmBnF;AAED,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,GAAG,QAAQ,CAO5E;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,UAAU,CAkBzG;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAenE;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAC3B,GAAG,EAAE,QAAQ,EACb,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,IAAI,CAYN;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,SAAS,YAAY,EAAE,CAIhG;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAO5E;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAQ7E;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAYnH;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAQpE;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAIvE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAInE;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAOhF;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAOnF;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAQ3E;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAOxG"}
@@ -0,0 +1,230 @@
1
+ import { connectAudioChannelToNode, pauseAudioChannel, resumeAudioChannel, stopAudioChannel } from './audioChannel';
2
+ export function addAudioBusToMixer(mixer, bus) {
3
+ const runtime = mixerRuntimes.get(mixer);
4
+ if (runtime === undefined)
5
+ return;
6
+ if (runtime.busGainNodes.has(bus))
7
+ return;
8
+ const gainNode = runtime.context.createGain();
9
+ gainNode.gain.value = bus.muted ? 0 : bus.gain;
10
+ let pannerNode = null;
11
+ if (typeof runtime.context.createStereoPanner === 'function') {
12
+ pannerNode = runtime.context.createStereoPanner();
13
+ pannerNode.pan.value = bus.pan;
14
+ gainNode.connect(pannerNode);
15
+ pannerNode.connect(runtime.masterGainNode);
16
+ }
17
+ else {
18
+ gainNode.connect(runtime.masterGainNode);
19
+ }
20
+ runtime.busGainNodes.set(bus, gainNode);
21
+ if (pannerNode !== null)
22
+ runtime.busOutputNodes.set(bus, pannerNode);
23
+ runtime.buses.set(bus.name, bus);
24
+ registerBusInReverseMap(bus, runtime);
25
+ }
26
+ export function createAudioBus(options) {
27
+ return {
28
+ gain: options?.gain ?? 1,
29
+ muted: options?.muted ?? false,
30
+ name: options?.name ?? '',
31
+ pan: options?.pan ?? 0,
32
+ };
33
+ }
34
+ export function createAudioMixer(context, options) {
35
+ const masterGainNode = context.createGain();
36
+ masterGainNode.gain.value = options?.masterGain ?? 1;
37
+ masterGainNode.connect(context.destination);
38
+ const mixer = {
39
+ masterGain: options?.masterGain ?? 1,
40
+ masterMuted: options?.masterMuted ?? false,
41
+ };
42
+ mixerRuntimes.set(mixer, {
43
+ activeChannels: new Set(),
44
+ buses: new Map(),
45
+ busGainNodes: new Map(),
46
+ busOutputNodes: new Map(),
47
+ channelToBus: new WeakMap(),
48
+ context,
49
+ masterGainNode,
50
+ });
51
+ return mixer;
52
+ }
53
+ export function destroyAudioMixer(mixer) {
54
+ const runtime = mixerRuntimes.get(mixer);
55
+ if (runtime === undefined)
56
+ return;
57
+ // Stop every routed channel and reset its transport state.
58
+ for (const channel of runtime.activeChannels)
59
+ stopAudioChannel(channel);
60
+ runtime.activeChannels.clear();
61
+ // Tear down the Web Audio graph: bus panners, bus gains, then the master gain.
62
+ for (const pannerNode of runtime.busOutputNodes.values())
63
+ pannerNode.disconnect();
64
+ for (const bus of runtime.busGainNodes.keys())
65
+ unregisterBusFromReverseMap(bus, runtime);
66
+ for (const gainNode of runtime.busGainNodes.values())
67
+ gainNode.disconnect();
68
+ runtime.masterGainNode.disconnect();
69
+ runtime.busGainNodes.clear();
70
+ runtime.busOutputNodes.clear();
71
+ runtime.buses.clear();
72
+ mixerRuntimes.delete(mixer);
73
+ }
74
+ export function fadeAudioBusGain(mixer, bus, targetGain, durationMs) {
75
+ const runtime = mixerRuntimes.get(mixer);
76
+ const gainNode = runtime?.busGainNodes.get(bus);
77
+ if (gainNode === undefined) {
78
+ bus.gain = targetGain;
79
+ return;
80
+ }
81
+ const now = runtime.context.currentTime;
82
+ gainNode.gain.cancelScheduledValues(now);
83
+ gainNode.gain.setValueAtTime(gainNode.gain.value, now);
84
+ gainNode.gain.linearRampToValueAtTime(bus.muted ? 0 : targetGain, now + durationMs / 1000);
85
+ bus.gain = targetGain;
86
+ }
87
+ export function getAudioMixerActiveChannels(mixer) {
88
+ const runtime = mixerRuntimes.get(mixer);
89
+ if (runtime === undefined)
90
+ return [];
91
+ return Array.from(runtime.activeChannels);
92
+ }
93
+ export function pauseAllAudioMixerChannels(mixer) {
94
+ const runtime = mixerRuntimes.get(mixer);
95
+ if (runtime === undefined)
96
+ return;
97
+ // Actually stop each source node (not just flip the flag) so audio halts on pause.
98
+ for (const channel of runtime.activeChannels) {
99
+ if (channel.state === 'playing')
100
+ pauseAudioChannel(channel);
101
+ }
102
+ }
103
+ export function resumeAllAudioMixerChannels(mixer) {
104
+ const runtime = mixerRuntimes.get(mixer);
105
+ if (runtime === undefined)
106
+ return;
107
+ // Restart the source node for channels this mixer paused; bus routing survives the restart
108
+ // because the channel's destination node is preserved across stop/start.
109
+ for (const channel of runtime.activeChannels) {
110
+ if (channel.state === 'paused')
111
+ resumeAudioChannel(channel);
112
+ }
113
+ }
114
+ export function routeAudioChannelToMixerBus(mixer, channel, bus) {
115
+ const runtime = mixerRuntimes.get(mixer);
116
+ if (runtime === undefined)
117
+ return;
118
+ // Ensure the bus is registered in the Web Audio graph.
119
+ addAudioBusToMixer(mixer, bus);
120
+ runtime.activeChannels.add(channel);
121
+ runtime.channelToBus.set(channel, bus);
122
+ // Wire the channel's output to the bus gain node (the entry point into the bus graph).
123
+ const busGainNode = runtime.busGainNodes.get(bus);
124
+ if (busGainNode !== undefined) {
125
+ connectAudioChannelToNode(channel, busGainNode);
126
+ }
127
+ }
128
+ export function setAudioBusGain(bus, value) {
129
+ bus.gain = value;
130
+ // Update the bus gain node for all mixers that contain this bus.
131
+ // Since we store gain nodes per-bus inside each mixer runtime, iterate the known runtimes.
132
+ // The caller must have already added the bus to a mixer via addAudioBusToMixer or routeAudioChannelToMixerBus.
133
+ // We use a reverse lookup via busGainNodes — walk active mixers via the busGainNodes map on each runtime.
134
+ updateBusGainNode(bus);
135
+ return bus.gain;
136
+ }
137
+ export function setAudioBusMuted(bus, muted) {
138
+ bus.muted = muted;
139
+ updateBusGainNode(bus);
140
+ return bus.muted;
141
+ }
142
+ export function setAudioBusPan(bus, value) {
143
+ bus.pan = clamp(value, -1, 1);
144
+ updateBusPannerNode(bus);
145
+ return bus.pan;
146
+ }
147
+ export function setAudioMixerMasterGain(mixer, value) {
148
+ mixer.masterGain = value;
149
+ const runtime = mixerRuntimes.get(mixer);
150
+ if (runtime !== undefined) {
151
+ runtime.masterGainNode.gain.value = mixer.masterMuted ? 0 : value;
152
+ }
153
+ return mixer.masterGain;
154
+ }
155
+ export function setAudioMixerMasterMuted(mixer, muted) {
156
+ mixer.masterMuted = muted;
157
+ const runtime = mixerRuntimes.get(mixer);
158
+ if (runtime !== undefined) {
159
+ runtime.masterGainNode.gain.value = muted ? 0 : mixer.masterGain;
160
+ }
161
+ return mixer.masterMuted;
162
+ }
163
+ export function stopAllAudioMixerChannels(mixer) {
164
+ const runtime = mixerRuntimes.get(mixer);
165
+ if (runtime === undefined)
166
+ return;
167
+ for (const channel of runtime.activeChannels) {
168
+ channel.state = 'stopped';
169
+ channel.currentTime = 0;
170
+ }
171
+ runtime.activeChannels.clear();
172
+ }
173
+ export function unrouteAudioChannelFromMixerBus(mixer, channel) {
174
+ const runtime = mixerRuntimes.get(mixer);
175
+ if (runtime === undefined)
176
+ return;
177
+ runtime.activeChannels.delete(channel);
178
+ runtime.channelToBus.delete(channel);
179
+ // Reconnect the channel output to the context destination so it keeps playing if still active.
180
+ connectAudioChannelToNode(channel, runtime.context.destination);
181
+ }
182
+ const mixerRuntimes = new WeakMap();
183
+ // Reverse map from AudioBus to all mixer runtimes that contain it.
184
+ // This allows setAudioBusGain/setAudioBusMuted/setAudioBusPan to update the Web Audio graph
185
+ // without requiring the caller to pass the mixer.
186
+ const busToMixerRuntimes = new Map();
187
+ function clamp(value, min, max) {
188
+ return Math.min(Math.max(value, min), max);
189
+ }
190
+ function registerBusInReverseMap(bus, runtime) {
191
+ let runtimes = busToMixerRuntimes.get(bus);
192
+ if (runtimes === undefined) {
193
+ runtimes = new Set();
194
+ busToMixerRuntimes.set(bus, runtimes);
195
+ }
196
+ runtimes.add(runtime);
197
+ }
198
+ // Drop a runtime from a bus's reverse-map entry, deleting the entry entirely once no runtime
199
+ // references the bus. This keeps busToMixerRuntimes bounded as mixers are destroyed.
200
+ function unregisterBusFromReverseMap(bus, runtime) {
201
+ const runtimes = busToMixerRuntimes.get(bus);
202
+ if (runtimes === undefined)
203
+ return;
204
+ runtimes.delete(runtime);
205
+ if (runtimes.size === 0)
206
+ busToMixerRuntimes.delete(bus);
207
+ }
208
+ function updateBusGainNode(bus) {
209
+ const runtimes = busToMixerRuntimes.get(bus);
210
+ if (runtimes === undefined)
211
+ return;
212
+ for (const runtime of runtimes) {
213
+ const gainNode = runtime.busGainNodes.get(bus);
214
+ if (gainNode !== undefined) {
215
+ gainNode.gain.value = bus.muted ? 0 : bus.gain;
216
+ }
217
+ }
218
+ }
219
+ function updateBusPannerNode(bus) {
220
+ const runtimes = busToMixerRuntimes.get(bus);
221
+ if (runtimes === undefined)
222
+ return;
223
+ for (const runtime of runtimes) {
224
+ const pannerNode = runtime.busOutputNodes.get(bus);
225
+ if (pannerNode !== undefined && 'pan' in pannerNode) {
226
+ pannerNode.pan.value = bus.pan;
227
+ }
228
+ }
229
+ }
230
+ //# sourceMappingURL=audioMixer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioMixer.js","sourceRoot":"","sources":["../src/audioMixer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export * from './audioChannel';
2
+ export * from './audioMixer';
3
+ export * from './videoChannel';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './audioChannel';
2
+ export * from './audioMixer';
3
+ export * from './videoChannel';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { VideoChannel, VideoPlayOptions, VideoResource } from '@flighthq/types';
2
+ export declare function getVideoChannelCurrentTime(channel: VideoChannel): number;
3
+ export declare function getVideoChannelDuration(channel: VideoChannel): number;
4
+ export declare function getVideoChannelHeight(channel: VideoChannel): number;
5
+ export declare function getVideoChannelWidth(channel: VideoChannel): number;
6
+ export declare function isVideoChannelPlaying(channel: VideoChannel): boolean;
7
+ export declare function pauseVideoChannel(channel: VideoChannel): void;
8
+ export declare function playVideoResource(source: VideoResource, options?: Readonly<VideoPlayOptions>): VideoChannel | null;
9
+ export declare function resumeVideoChannel(channel: VideoChannel): void;
10
+ export declare function setVideoChannelCurrentTime(channel: VideoChannel, value: number): number;
11
+ export declare function setVideoChannelGain(channel: VideoChannel, value: number): number;
12
+ export declare function setVideoChannelPlaybackRate(channel: VideoChannel, value: number): number;
13
+ export declare function stopVideoChannel(channel: VideoChannel): void;
14
+ //# sourceMappingURL=videoChannel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"videoChannel.d.ts","sourceRoot":"","sources":["../src/videoChannel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErF,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAIxE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAErE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAGnE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAGlE;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAEpE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAO7D;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY,GAAG,IAAI,CA+BlH;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAG9D;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKvF;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKhF;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKxF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAU5D"}
@@ -0,0 +1,128 @@
1
+ import { createSignal, emitSignal } from '@flighthq/signals';
2
+ export function getVideoChannelCurrentTime(channel) {
3
+ const element = channel.source.element;
4
+ if (element === null || channel.state !== 'playing')
5
+ return channel.currentTime;
6
+ return element.currentTime * 1000;
7
+ }
8
+ export function getVideoChannelDuration(channel) {
9
+ return channel.length;
10
+ }
11
+ export function getVideoChannelHeight(channel) {
12
+ const element = channel.source.element;
13
+ return element !== null ? element.videoHeight : 0;
14
+ }
15
+ export function getVideoChannelWidth(channel) {
16
+ const element = channel.source.element;
17
+ return element !== null ? element.videoWidth : 0;
18
+ }
19
+ export function isVideoChannelPlaying(channel) {
20
+ return channel.state === 'playing';
21
+ }
22
+ export function pauseVideoChannel(channel) {
23
+ if (channel.state !== 'playing')
24
+ return;
25
+ const element = channel.source.element;
26
+ if (element === null)
27
+ return;
28
+ channel.currentTime = getVideoChannelCurrentTime(channel);
29
+ channel.state = 'paused';
30
+ element.pause();
31
+ }
32
+ export function playVideoResource(source, options) {
33
+ const element = source.element;
34
+ if (element === null)
35
+ return null;
36
+ const runtime = videoChannelRuntimes.get(element);
37
+ if (runtime !== undefined) {
38
+ element.removeEventListener('ended', runtime.onEnded);
39
+ }
40
+ const channel = {
41
+ currentTime: options?.currentTime ?? 0,
42
+ gain: options?.gain ?? 1,
43
+ length: isNaN(element.duration) ? 0 : element.duration * 1000,
44
+ loops: options?.loops ?? 0,
45
+ playbackRate: options?.playbackRate ?? 1,
46
+ source,
47
+ state: 'stopped',
48
+ onComplete: createSignal(),
49
+ };
50
+ const onEnded = () => completeVideoChannel(channel);
51
+ videoChannelRuntimes.set(element, { loopsRemaining: channel.loops, onEnded });
52
+ element.currentTime = channel.currentTime / 1000;
53
+ element.volume = channel.gain;
54
+ element.playbackRate = channel.playbackRate;
55
+ element.loop = false;
56
+ element.addEventListener('ended', onEnded);
57
+ startVideoChannel(channel);
58
+ return channel;
59
+ }
60
+ export function resumeVideoChannel(channel) {
61
+ if (channel.state === 'playing' || channel.source.element === null)
62
+ return;
63
+ startVideoChannel(channel);
64
+ }
65
+ export function setVideoChannelCurrentTime(channel, value) {
66
+ channel.currentTime = clamp(value, 0, channel.length);
67
+ const element = channel.source.element;
68
+ if (element !== null)
69
+ element.currentTime = channel.currentTime / 1000;
70
+ return channel.currentTime;
71
+ }
72
+ export function setVideoChannelGain(channel, value) {
73
+ channel.gain = value;
74
+ const element = channel.source.element;
75
+ if (element !== null)
76
+ element.volume = value;
77
+ return channel.gain;
78
+ }
79
+ export function setVideoChannelPlaybackRate(channel, value) {
80
+ channel.playbackRate = value;
81
+ const element = channel.source.element;
82
+ if (element !== null)
83
+ element.playbackRate = value;
84
+ return channel.playbackRate;
85
+ }
86
+ export function stopVideoChannel(channel) {
87
+ const element = channel.source.element;
88
+ if (element !== null) {
89
+ const runtime = videoChannelRuntimes.get(element);
90
+ if (runtime !== undefined)
91
+ element.removeEventListener('ended', runtime.onEnded);
92
+ element.pause();
93
+ element.currentTime = 0;
94
+ }
95
+ channel.currentTime = 0;
96
+ channel.state = 'stopped';
97
+ }
98
+ const videoChannelRuntimes = new WeakMap();
99
+ function clamp(value, min, max) {
100
+ return Math.min(Math.max(value, min), max);
101
+ }
102
+ function completeVideoChannel(channel) {
103
+ if (channel.state !== 'playing')
104
+ return;
105
+ const runtime = channel.source.element !== null ? videoChannelRuntimes.get(channel.source.element) : undefined;
106
+ if (runtime !== undefined && runtime.loopsRemaining !== 0) {
107
+ if (runtime.loopsRemaining > 0)
108
+ runtime.loopsRemaining--;
109
+ channel.currentTime = 0;
110
+ startVideoChannel(channel);
111
+ return;
112
+ }
113
+ channel.currentTime = channel.length;
114
+ channel.state = 'complete';
115
+ emitSignal(channel.onComplete);
116
+ }
117
+ function startVideoChannel(channel) {
118
+ const element = channel.source.element;
119
+ if (element === null)
120
+ return;
121
+ element.currentTime = channel.currentTime / 1000;
122
+ channel.state = 'playing';
123
+ element.play().catch(() => {
124
+ if (channel.state === 'playing')
125
+ channel.state = 'stopped';
126
+ });
127
+ }
128
+ //# sourceMappingURL=videoChannel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"videoChannel.js","sourceRoot":"","sources":["../src/videoChannel.ts"],"names":[],"mappings":"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"}