@zcomponent/core 1.2.0-beta → 1.3.0-beta
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/lib/animation/tracks/streamtrack.d.ts +1 -2
- package/lib/components/Audio.d.ts +59 -0
- package/lib/components/Audio.js +96 -0
- package/lib/components/AudioLayerSettings.d.ts +26 -0
- package/lib/components/AudioLayerSettings.js +22 -0
- package/lib/contexts/audiocontextcontext.d.ts +14 -0
- package/lib/contexts/audiocontextcontext.js +38 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/types.d.ts +1 -0
- package/lib/types.js +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { StreamTrackEntity } from '../../data';
|
|
2
|
-
import { Entity } from '../../entity';
|
|
3
2
|
import { Animation } from '../animation';
|
|
4
3
|
import { Keyframe } from '../keyframe';
|
|
5
4
|
import { Stream, StreamState } from '../stream';
|
|
@@ -18,7 +17,7 @@ export declare class StreamTrack extends Track {
|
|
|
18
17
|
private _lastTick?;
|
|
19
18
|
private _lastLoopNumber?;
|
|
20
19
|
private _lastRate;
|
|
21
|
-
constructor(animation: Animation, _entity:
|
|
20
|
+
constructor(animation: Animation, _entity: any, _property: (string | number)[]);
|
|
22
21
|
get influencedPaths(): string[];
|
|
23
22
|
get stream(): Stream | undefined;
|
|
24
23
|
computePathProperty(t: number, p: string, valueBefore: any, parentWeight?: number): any;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { PlayOptions, Stream } from "../animation";
|
|
2
|
+
import { Component } from "../component";
|
|
3
|
+
import { ContextManager } from "../context";
|
|
4
|
+
import { Observable } from "../observable";
|
|
5
|
+
export interface AudioConstructorProps {
|
|
6
|
+
/** @zprop
|
|
7
|
+
* @zvalues files *.+(mp3|wav)
|
|
8
|
+
*/
|
|
9
|
+
source: string;
|
|
10
|
+
/**
|
|
11
|
+
* @zprop
|
|
12
|
+
* @zdefault default
|
|
13
|
+
*/
|
|
14
|
+
audioLayer?: string;
|
|
15
|
+
/** @zprop
|
|
16
|
+
* @zdefault false
|
|
17
|
+
*/
|
|
18
|
+
autoplay?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @zcomponent
|
|
22
|
+
* @ztag core/audio
|
|
23
|
+
* @zgroup Media
|
|
24
|
+
* @zicon music_note
|
|
25
|
+
* @zstream
|
|
26
|
+
*/
|
|
27
|
+
export declare class Audio extends Component<undefined, AudioConstructorProps> implements Stream {
|
|
28
|
+
audioContext: AudioContext;
|
|
29
|
+
destination: AudioNode;
|
|
30
|
+
audioBuffer?: AudioBuffer;
|
|
31
|
+
private _gain;
|
|
32
|
+
private _playhead;
|
|
33
|
+
private _session?;
|
|
34
|
+
/** @zprop
|
|
35
|
+
* @zdefault false
|
|
36
|
+
* @zgroup Audio
|
|
37
|
+
* @zgrouppriority 20
|
|
38
|
+
*/
|
|
39
|
+
muted: Observable<boolean, never>;
|
|
40
|
+
constructor(mgr: ContextManager, props: AudioConstructorProps);
|
|
41
|
+
private _load;
|
|
42
|
+
private _updateVolume;
|
|
43
|
+
/**
|
|
44
|
+
* @zprop
|
|
45
|
+
* @ztype proportion
|
|
46
|
+
* @zdefault 1
|
|
47
|
+
*/
|
|
48
|
+
volume: Observable<number, never>;
|
|
49
|
+
/** @zprop */
|
|
50
|
+
play(opts?: PlayOptions): void;
|
|
51
|
+
/** @zprop */
|
|
52
|
+
pause(): void;
|
|
53
|
+
/** @zprop */
|
|
54
|
+
stop(): void;
|
|
55
|
+
/** @zprop */
|
|
56
|
+
seek(t: number): void;
|
|
57
|
+
length(): number | undefined;
|
|
58
|
+
dispose(): never;
|
|
59
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Component } from "../component";
|
|
2
|
+
import { AudioContextContext, useAudioContext } from "../contexts/audiocontextcontext";
|
|
3
|
+
import { isDesignTime } from "../contexts/environmentcontext";
|
|
4
|
+
import { registerLoadable, started } from "../contexts/loadcontext";
|
|
5
|
+
import { Observable } from "../observable";
|
|
6
|
+
/**
|
|
7
|
+
* @zcomponent
|
|
8
|
+
* @ztag core/audio
|
|
9
|
+
* @zgroup Media
|
|
10
|
+
* @zicon music_note
|
|
11
|
+
* @zstream
|
|
12
|
+
*/
|
|
13
|
+
export class Audio extends Component {
|
|
14
|
+
constructor(mgr, props) {
|
|
15
|
+
super(mgr, props);
|
|
16
|
+
this._playhead = 0;
|
|
17
|
+
/** @zprop
|
|
18
|
+
* @zdefault false
|
|
19
|
+
* @zgroup Audio
|
|
20
|
+
* @zgrouppriority 20
|
|
21
|
+
*/
|
|
22
|
+
this.muted = new Observable(false);
|
|
23
|
+
this._updateVolume = () => {
|
|
24
|
+
this._gain.gain.value = this.muted.value === true ? 0 : this.volume.value;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* @zprop
|
|
28
|
+
* @ztype proportion
|
|
29
|
+
* @zdefault 1
|
|
30
|
+
*/
|
|
31
|
+
this.volume = new Observable(1, this._updateVolume);
|
|
32
|
+
const audioContextContext = mgr.get(AudioContextContext);
|
|
33
|
+
this.audioContext = useAudioContext(mgr);
|
|
34
|
+
this._gain = this.audioContext.createGain();
|
|
35
|
+
this._gain.connect(audioContextContext.getLayer(props.audioLayer));
|
|
36
|
+
this.destination = this._gain;
|
|
37
|
+
registerLoadable(mgr, this._load());
|
|
38
|
+
if (!isDesignTime(this.contextManager) && props.autoplay)
|
|
39
|
+
started(mgr).then(() => this.play());
|
|
40
|
+
}
|
|
41
|
+
async _load() {
|
|
42
|
+
const source = this.constructorProps?.source;
|
|
43
|
+
if (!source)
|
|
44
|
+
return;
|
|
45
|
+
const data = await (await fetch(source)).arrayBuffer();
|
|
46
|
+
const audioContext = useAudioContext(this.contextManager);
|
|
47
|
+
this.audioBuffer = await audioContext.decodeAudioData(data);
|
|
48
|
+
}
|
|
49
|
+
/** @zprop */
|
|
50
|
+
play(opts) {
|
|
51
|
+
if (!this.audioBuffer)
|
|
52
|
+
return;
|
|
53
|
+
if (this._session)
|
|
54
|
+
this.stop();
|
|
55
|
+
if (this._playhead >= this.audioBuffer.duration)
|
|
56
|
+
this._playhead = 0;
|
|
57
|
+
const source = this.audioContext.createBufferSource();
|
|
58
|
+
source.buffer = this.audioBuffer;
|
|
59
|
+
source.playbackRate.value = opts?.speed ?? 1;
|
|
60
|
+
source.connect(this.destination);
|
|
61
|
+
const startedAt = this.audioContext.currentTime - (this._playhead / source.playbackRate.value);
|
|
62
|
+
source.start(0, this._playhead);
|
|
63
|
+
this._session = { source, startedAt };
|
|
64
|
+
}
|
|
65
|
+
/** @zprop */
|
|
66
|
+
pause() {
|
|
67
|
+
if (!this._session)
|
|
68
|
+
return;
|
|
69
|
+
this._playhead = this._session.source.playbackRate.value * (this.audioContext.currentTime - this._session.startedAt);
|
|
70
|
+
this._session.source.stop();
|
|
71
|
+
this._session.source.disconnect();
|
|
72
|
+
delete this._session;
|
|
73
|
+
}
|
|
74
|
+
/** @zprop */
|
|
75
|
+
stop() {
|
|
76
|
+
this.pause();
|
|
77
|
+
this._playhead = 0;
|
|
78
|
+
}
|
|
79
|
+
/** @zprop */
|
|
80
|
+
seek(t) {
|
|
81
|
+
let previousSession = this._session;
|
|
82
|
+
if (previousSession)
|
|
83
|
+
this.pause();
|
|
84
|
+
this._playhead = t / 1000;
|
|
85
|
+
if (previousSession)
|
|
86
|
+
this.play({ speed: previousSession.source.playbackRate.value });
|
|
87
|
+
}
|
|
88
|
+
length() {
|
|
89
|
+
return this.audioBuffer ? (this.audioBuffer.duration * 1000) : undefined;
|
|
90
|
+
}
|
|
91
|
+
dispose() {
|
|
92
|
+
this.stop();
|
|
93
|
+
this._gain.disconnect();
|
|
94
|
+
return super.dispose();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Component } from "../component";
|
|
2
|
+
import { ContextManager } from "../context";
|
|
3
|
+
import { Observable } from "../observable";
|
|
4
|
+
interface AudioLayerSettingsConstuctorProps {
|
|
5
|
+
/**
|
|
6
|
+
* @zprop
|
|
7
|
+
* @zdefault default
|
|
8
|
+
*/
|
|
9
|
+
layer?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* @zcomponent
|
|
13
|
+
* @ztag core/audiolayersettings
|
|
14
|
+
* @zgroup Media
|
|
15
|
+
* @zicon volume_up
|
|
16
|
+
*/
|
|
17
|
+
export declare class AudioLayerSettings extends Component<undefined, AudioLayerSettingsConstuctorProps> {
|
|
18
|
+
constructor(contextManager: ContextManager, props: AudioLayerSettingsConstuctorProps);
|
|
19
|
+
/**
|
|
20
|
+
* @zprop
|
|
21
|
+
* @ztype proportion
|
|
22
|
+
* @zdefault 1
|
|
23
|
+
*/
|
|
24
|
+
volume: Observable<number, never>;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Component } from "../component";
|
|
2
|
+
import { AudioContextContext } from "../contexts/audiocontextcontext";
|
|
3
|
+
import { Observable } from "../observable";
|
|
4
|
+
/**
|
|
5
|
+
* @zcomponent
|
|
6
|
+
* @ztag core/audiolayersettings
|
|
7
|
+
* @zgroup Media
|
|
8
|
+
* @zicon volume_up
|
|
9
|
+
*/
|
|
10
|
+
export class AudioLayerSettings extends Component {
|
|
11
|
+
constructor(contextManager, props) {
|
|
12
|
+
super(contextManager, props);
|
|
13
|
+
/**
|
|
14
|
+
* @zprop
|
|
15
|
+
* @ztype proportion
|
|
16
|
+
* @zdefault 1
|
|
17
|
+
*/
|
|
18
|
+
this.volume = new Observable(1, v => {
|
|
19
|
+
this.contextManager.get(AudioContextContext).setVolumeForLayer(this.constructorProps?.layer, v);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ContextManager, Context } from '../context';
|
|
2
|
+
/** @zcontext */
|
|
3
|
+
export declare class AudioContextContext extends Context {
|
|
4
|
+
constructorProps: {};
|
|
5
|
+
audioContext: AudioContext;
|
|
6
|
+
private _layers;
|
|
7
|
+
layers: Map<string, AudioNode>;
|
|
8
|
+
constructor(contextManager: ContextManager, constructorProps: {});
|
|
9
|
+
private _getLayer;
|
|
10
|
+
getLayer(name?: string): AudioNode;
|
|
11
|
+
setVolumeForLayer(name: string | undefined, v: number): void;
|
|
12
|
+
dispose(): never;
|
|
13
|
+
}
|
|
14
|
+
export declare function useAudioContext(ctx: ContextManager): AudioContext;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Context } from '../context';
|
|
2
|
+
import { nextUserEvent } from './usereventcontext';
|
|
3
|
+
/** @zcontext */
|
|
4
|
+
export class AudioContextContext extends Context {
|
|
5
|
+
constructor(contextManager, constructorProps) {
|
|
6
|
+
super(contextManager, constructorProps);
|
|
7
|
+
this.constructorProps = constructorProps;
|
|
8
|
+
this.audioContext = new AudioContext();
|
|
9
|
+
this._layers = new Map();
|
|
10
|
+
this.layers = this._layers;
|
|
11
|
+
nextUserEvent(contextManager).then(() => {
|
|
12
|
+
this.audioContext.resume();
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
_getLayer(name) {
|
|
16
|
+
let existing = this._layers.get(name ?? 'default');
|
|
17
|
+
if (!existing) {
|
|
18
|
+
existing = new GainNode(this.audioContext);
|
|
19
|
+
existing.connect(this.audioContext.destination);
|
|
20
|
+
this._layers.set(name ?? 'default', existing);
|
|
21
|
+
}
|
|
22
|
+
return existing;
|
|
23
|
+
}
|
|
24
|
+
getLayer(name) {
|
|
25
|
+
return this._getLayer(name);
|
|
26
|
+
}
|
|
27
|
+
setVolumeForLayer(name, v) {
|
|
28
|
+
const layer = this._getLayer(name);
|
|
29
|
+
layer.gain.value = v;
|
|
30
|
+
}
|
|
31
|
+
dispose() {
|
|
32
|
+
this.audioContext.close();
|
|
33
|
+
return super.dispose();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function useAudioContext(ctx) {
|
|
37
|
+
return ctx.get(AudioContextContext).audioContext;
|
|
38
|
+
}
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export * from './contexts/tagcontext';
|
|
|
14
14
|
export * from './contexts/gamepadcontext';
|
|
15
15
|
export * from './observable';
|
|
16
16
|
export * from './contexts/environmentcontext';
|
|
17
|
+
export * from './contexts/audiocontextcontext';
|
|
17
18
|
export * from './animation';
|
|
18
19
|
const link = document.createElement('link');
|
|
19
20
|
link.setAttribute('rel', 'stylesheet');
|
package/lib/types.d.ts
CHANGED
package/lib/types.js
CHANGED