@datamoc/mw_games 0.42.0 → 0.44.2
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 +126 -0
- package/README.md +84 -1
- package/REFERENCE.md +134 -6
- package/api-surface.json +1814 -116
- package/data/microgm-essential.PROVENANCE.md +13 -0
- package/data/microgm-essential.sf2 +0 -0
- package/data/soundfont-catalog.json +8 -0
- package/dist/actors/Resource.d.ts.map +1 -1
- package/dist/actors/Resource.js +2 -3
- package/dist/actors/Resource.js.map +1 -1
- package/dist/audio/AdaptiveMusic.d.ts +85 -0
- package/dist/audio/AdaptiveMusic.d.ts.map +1 -0
- package/dist/audio/AdaptiveMusic.js +230 -0
- package/dist/audio/AdaptiveMusic.js.map +1 -0
- package/dist/audio/AudioLoader.d.ts +33 -0
- package/dist/audio/AudioLoader.d.ts.map +1 -0
- package/dist/audio/AudioLoader.js +58 -0
- package/dist/audio/AudioLoader.js.map +1 -0
- package/dist/audio/AudioViews.d.ts +70 -0
- package/dist/audio/AudioViews.d.ts.map +1 -0
- package/dist/audio/AudioViews.js +119 -0
- package/dist/audio/AudioViews.js.map +1 -0
- package/dist/audio/BusBudget.d.ts +89 -0
- package/dist/audio/BusBudget.d.ts.map +1 -0
- package/dist/audio/BusBudget.js +120 -0
- package/dist/audio/BusBudget.js.map +1 -0
- package/dist/audio/Channels.d.ts +66 -1
- package/dist/audio/Channels.d.ts.map +1 -1
- package/dist/audio/Channels.js +119 -31
- package/dist/audio/Channels.js.map +1 -1
- package/dist/audio/CoreHost.d.ts +114 -0
- package/dist/audio/CoreHost.d.ts.map +1 -0
- package/dist/audio/CoreHost.js +335 -0
- package/dist/audio/CoreHost.js.map +1 -0
- package/dist/audio/DecoderGuard.d.ts +139 -0
- package/dist/audio/DecoderGuard.d.ts.map +1 -0
- package/dist/audio/DecoderGuard.js +208 -0
- package/dist/audio/DecoderGuard.js.map +1 -0
- package/dist/audio/Fft.d.ts +3 -0
- package/dist/audio/Fft.d.ts.map +1 -0
- package/dist/audio/Fft.js +45 -0
- package/dist/audio/Fft.js.map +1 -0
- package/dist/audio/LoopTags.d.ts +18 -0
- package/dist/audio/LoopTags.d.ts.map +1 -1
- package/dist/audio/LoopTags.js +20 -0
- package/dist/audio/LoopTags.js.map +1 -1
- package/dist/audio/Midi.d.ts +35 -0
- package/dist/audio/Midi.d.ts.map +1 -1
- package/dist/audio/Midi.js +71 -1
- package/dist/audio/Midi.js.map +1 -1
- package/dist/audio/MidiRender.d.ts +47 -0
- package/dist/audio/MidiRender.d.ts.map +1 -1
- package/dist/audio/MidiRender.js +100 -2
- package/dist/audio/MidiRender.js.map +1 -1
- package/dist/audio/MidiSynth.d.ts +147 -0
- package/dist/audio/MidiSynth.d.ts.map +1 -0
- package/dist/audio/MidiSynth.js +205 -0
- package/dist/audio/MidiSynth.js.map +1 -0
- package/dist/audio/MusicPlayer.d.ts +80 -0
- package/dist/audio/MusicPlayer.d.ts.map +1 -0
- package/dist/audio/MusicPlayer.js +147 -0
- package/dist/audio/MusicPlayer.js.map +1 -0
- package/dist/audio/Playable.d.ts +7 -0
- package/dist/audio/Playable.d.ts.map +1 -1
- package/dist/audio/Playable.js.map +1 -1
- package/dist/audio/Positional.d.ts +12 -4
- package/dist/audio/Positional.d.ts.map +1 -1
- package/dist/audio/Positional.js +5 -2
- package/dist/audio/Positional.js.map +1 -1
- package/dist/audio/Resample.d.ts +61 -0
- package/dist/audio/Resample.d.ts.map +1 -0
- package/dist/audio/Resample.js +97 -0
- package/dist/audio/Resample.js.map +1 -0
- package/dist/audio/SampleDecoder.d.ts +16 -2
- package/dist/audio/SampleDecoder.d.ts.map +1 -1
- package/dist/audio/SampleDecoder.js +10 -6
- package/dist/audio/SampleDecoder.js.map +1 -1
- package/dist/audio/Settings.d.ts +99 -0
- package/dist/audio/Settings.d.ts.map +1 -0
- package/dist/audio/Settings.js +134 -0
- package/dist/audio/Settings.js.map +1 -0
- package/dist/audio/Sfx.d.ts +148 -0
- package/dist/audio/Sfx.d.ts.map +1 -0
- package/dist/audio/Sfx.js +213 -0
- package/dist/audio/Sfx.js.map +1 -0
- package/dist/audio/Sound.d.ts +2 -0
- package/dist/audio/Sound.d.ts.map +1 -1
- package/dist/audio/Sound.js +3 -0
- package/dist/audio/Sound.js.map +1 -1
- package/dist/audio/SoundFont.d.ts +5 -3
- package/dist/audio/SoundFont.d.ts.map +1 -1
- package/dist/audio/SoundFont.js +10 -8
- package/dist/audio/SoundFont.js.map +1 -1
- package/dist/audio/SpectralDistance.d.ts +34 -0
- package/dist/audio/SpectralDistance.d.ts.map +1 -0
- package/dist/audio/SpectralDistance.js +64 -0
- package/dist/audio/SpectralDistance.js.map +1 -0
- package/dist/audio/StreamChannel.d.ts +150 -0
- package/dist/audio/StreamChannel.d.ts.map +1 -0
- package/dist/audio/StreamChannel.js +390 -0
- package/dist/audio/StreamChannel.js.map +1 -0
- package/dist/audio/StreamPlayable.d.ts +73 -0
- package/dist/audio/StreamPlayable.d.ts.map +1 -0
- package/dist/audio/StreamPlayable.js +130 -0
- package/dist/audio/StreamPlayable.js.map +1 -0
- package/dist/audio/Synth.d.ts +1 -1
- package/dist/audio/Synth.d.ts.map +1 -1
- package/dist/audio/Synth.js +4 -0
- package/dist/audio/Synth.js.map +1 -1
- package/dist/audio/SyxBank.d.ts +73 -0
- package/dist/audio/SyxBank.d.ts.map +1 -0
- package/dist/audio/SyxBank.js +130 -0
- package/dist/audio/SyxBank.js.map +1 -0
- package/dist/audio/Underrun.d.ts +25 -0
- package/dist/audio/Underrun.d.ts.map +1 -0
- package/dist/audio/Underrun.js +18 -0
- package/dist/audio/Underrun.js.map +1 -0
- package/dist/audio/Wav.d.ts +56 -0
- package/dist/audio/Wav.d.ts.map +1 -0
- package/dist/audio/Wav.js +164 -0
- package/dist/audio/Wav.js.map +1 -0
- package/dist/audio/WebMidi.d.ts +58 -0
- package/dist/audio/WebMidi.d.ts.map +1 -0
- package/dist/audio/WebMidi.js +79 -0
- package/dist/audio/WebMidi.js.map +1 -0
- package/dist/audio/humanize/Onsets.d.ts.map +1 -1
- package/dist/audio/humanize/Onsets.js +1 -44
- package/dist/audio/humanize/Onsets.js.map +1 -1
- package/dist/audio/index.d.ts +43 -7
- package/dist/audio/index.d.ts.map +1 -1
- package/dist/audio/index.js +21 -3
- package/dist/audio/index.js.map +1 -1
- package/dist/battle/AttackPreview.d.ts.map +1 -1
- package/dist/battle/AttackPreview.js +8 -8
- package/dist/battle/AttackPreview.js.map +1 -1
- package/dist/battle/StatStages.d.ts.map +1 -1
- package/dist/battle/StatStages.js +2 -1
- package/dist/battle/StatStages.js.map +1 -1
- package/dist/board/Engine.d.ts +2 -0
- package/dist/board/Engine.d.ts.map +1 -1
- package/dist/board/Engine.js +1 -1
- package/dist/board/Engine.js.map +1 -1
- package/dist/board/HexSkirmish.d.ts.map +1 -1
- package/dist/board/HexSkirmish.js +11 -72
- package/dist/board/HexSkirmish.js.map +1 -1
- package/dist/board/Tactics.d.ts.map +1 -1
- package/dist/board/Tactics.js +3 -5
- package/dist/board/Tactics.js.map +1 -1
- package/dist/board/tourney.d.ts.map +1 -1
- package/dist/board/tourney.js +2 -19
- package/dist/board/tourney.js.map +1 -1
- package/dist/core/Handles.js +7 -7
- package/dist/core/Handles.js.map +1 -1
- package/dist/mw_games.global.js +25 -22
- package/dist/mwl/conditions.d.ts +12 -0
- package/dist/mwl/conditions.d.ts.map +1 -1
- package/dist/mwl/conditions.js +49 -8
- package/dist/mwl/conditions.js.map +1 -1
- package/dist/mwl/index.d.ts +13 -0
- package/dist/mwl/index.d.ts.map +1 -1
- package/dist/mwl/index.js +7 -0
- package/dist/mwl/index.js.map +1 -1
- package/dist/mwl/objects.d.ts +31 -0
- package/dist/mwl/objects.d.ts.map +1 -0
- package/dist/mwl/objects.js +83 -0
- package/dist/mwl/objects.js.map +1 -0
- package/dist/mwl/package-container.d.ts +185 -0
- package/dist/mwl/package-container.d.ts.map +1 -0
- package/dist/mwl/package-container.js +446 -0
- package/dist/mwl/package-container.js.map +1 -0
- package/dist/mwl/package-document.d.ts +217 -0
- package/dist/mwl/package-document.d.ts.map +1 -0
- package/dist/mwl/package-document.js +639 -0
- package/dist/mwl/package-document.js.map +1 -0
- package/dist/mwl/package-rom.d.ts +37 -0
- package/dist/mwl/package-rom.d.ts.map +1 -0
- package/dist/mwl/package-rom.js +96 -0
- package/dist/mwl/package-rom.js.map +1 -0
- package/dist/mwl/package-verify.d.ts +34 -0
- package/dist/mwl/package-verify.d.ts.map +1 -0
- package/dist/mwl/package-verify.js +111 -0
- package/dist/mwl/package-verify.js.map +1 -0
- package/dist/mwl/package.d.ts +184 -0
- package/dist/mwl/package.d.ts.map +1 -0
- package/dist/mwl/package.js +382 -0
- package/dist/mwl/package.js.map +1 -0
- package/dist/mwl/schema.d.ts +1 -1
- package/dist/mwl/schema.d.ts.map +1 -1
- package/dist/mwl/tables.d.ts +2 -0
- package/dist/mwl/tables.d.ts.map +1 -1
- package/dist/mwl/tables.js +13 -0
- package/dist/mwl/tables.js.map +1 -1
- package/dist/physics/PhysicsWorld.d.ts.map +1 -1
- package/dist/physics/PhysicsWorld.js +4 -3
- package/dist/physics/PhysicsWorld.js.map +1 -1
- package/dist/physics/XpbdWorld.d.ts +23 -5
- package/dist/physics/XpbdWorld.d.ts.map +1 -1
- package/dist/physics/XpbdWorld.js +91 -6
- package/dist/physics/XpbdWorld.js.map +1 -1
- package/dist/testing/FakeAudio.d.ts +149 -0
- package/dist/testing/FakeAudio.d.ts.map +1 -0
- package/dist/testing/FakeAudio.js +219 -0
- package/dist/testing/FakeAudio.js.map +1 -0
- package/dist/testing/index.d.ts +18 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +22 -0
- package/dist/testing/index.js.map +1 -1
- package/dist/threads/index.d.ts +2 -2
- package/dist/threads/index.d.ts.map +1 -1
- package/dist/threads/index.js +1 -1
- package/dist/threads/index.js.map +1 -1
- package/dist/threads/spawn.d.ts +32 -0
- package/dist/threads/spawn.d.ts.map +1 -1
- package/dist/threads/spawn.js +35 -11
- package/dist/threads/spawn.js.map +1 -1
- package/dist/three-d/Collision3D.d.ts +46 -2
- package/dist/three-d/Collision3D.d.ts.map +1 -1
- package/dist/three-d/Collision3D.js +46 -2
- package/dist/three-d/Collision3D.js.map +1 -1
- package/dist/three-d/Grid.d.ts +12 -1
- package/dist/three-d/Grid.d.ts.map +1 -1
- package/dist/three-d/Grid.js +12 -1
- package/dist/three-d/Grid.js.map +1 -1
- package/dist/three-d/Vox.d.ts +13 -1
- package/dist/three-d/Vox.d.ts.map +1 -1
- package/dist/three-d/Vox.js +13 -1
- package/dist/three-d/Vox.js.map +1 -1
- package/dist/two-d/Game.d.ts +32 -1
- package/dist/two-d/Game.d.ts.map +1 -1
- package/dist/two-d/Game.js +105 -14
- package/dist/two-d/Game.js.map +1 -1
- package/dist/two-d/Scene2D.d.ts +24 -0
- package/dist/two-d/Scene2D.d.ts.map +1 -1
- package/dist/two-d/Scene2D.js +30 -0
- package/dist/two-d/Scene2D.js.map +1 -1
- package/dist/two-d/render/HazeLayer.d.ts.map +1 -1
- package/dist/two-d/render/HazeLayer.js +2 -1
- package/dist/two-d/render/HazeLayer.js.map +1 -1
- package/dist/two-d/render/ImageModifiers.d.ts +4 -2
- package/dist/two-d/render/ImageModifiers.d.ts.map +1 -1
- package/dist/two-d/render/ImageModifiers.js +13 -8
- package/dist/two-d/render/ImageModifiers.js.map +1 -1
- package/dist/two-d/render/NeonGlow.d.ts.map +1 -1
- package/dist/two-d/render/NeonGlow.js +2 -1
- package/dist/two-d/render/NeonGlow.js.map +1 -1
- package/dist/two-d/render/Particles.d.ts.map +1 -1
- package/dist/two-d/render/Particles.js +2 -1
- package/dist/two-d/render/Particles.js.map +1 -1
- package/dist/two-d/render/SceneTransition.d.ts +301 -0
- package/dist/two-d/render/SceneTransition.d.ts.map +1 -0
- package/dist/two-d/render/SceneTransition.js +458 -0
- package/dist/two-d/render/SceneTransition.js.map +1 -0
- package/dist/two-d/render/ScreenEffects.d.ts.map +1 -1
- package/dist/two-d/render/ScreenEffects.js +2 -1
- package/dist/two-d/render/ScreenEffects.js.map +1 -1
- package/dist/two-d/render/SkeletalSprite.d.ts.map +1 -1
- package/dist/two-d/render/SkeletalSprite.js +2 -1
- package/dist/two-d/render/SkeletalSprite.js.map +1 -1
- package/dist/two-d/render/Types2D.d.ts +2 -2
- package/dist/two-d/render/Types2D.d.ts.map +1 -1
- package/dist/two-d/render/Types2D.js +2 -2
- package/dist/two-d/render/Types2D.js.map +1 -1
- package/dist/two-d/render/index.d.ts +2 -0
- package/dist/two-d/render/index.d.ts.map +1 -1
- package/dist/two-d/render/index.js +1 -0
- package/dist/two-d/render/index.js.map +1 -1
- package/dist/two-d/ui/Bar.d.ts.map +1 -1
- package/dist/two-d/ui/Bar.js +3 -5
- package/dist/two-d/ui/Bar.js.map +1 -1
- package/dist/two-d/ui/Button.d.ts +23 -0
- package/dist/two-d/ui/Button.d.ts.map +1 -1
- package/dist/two-d/ui/Button.js +37 -0
- package/dist/two-d/ui/Button.js.map +1 -1
- package/dist/two-d/ui/Dropdown.d.ts +5 -1
- package/dist/two-d/ui/Dropdown.d.ts.map +1 -1
- package/dist/two-d/ui/Dropdown.js +8 -1
- package/dist/two-d/ui/Dropdown.js.map +1 -1
- package/dist/two-d/ui/DropdownView.d.ts +63 -3
- package/dist/two-d/ui/DropdownView.d.ts.map +1 -1
- package/dist/two-d/ui/DropdownView.js +168 -9
- package/dist/two-d/ui/DropdownView.js.map +1 -1
- package/dist/two-d/ui/FloatingText.d.ts.map +1 -1
- package/dist/two-d/ui/FloatingText.js +2 -1
- package/dist/two-d/ui/FloatingText.js.map +1 -1
- package/dist/two-d/ui/IconGrid.d.ts.map +1 -1
- package/dist/two-d/ui/IconGrid.js +2 -1
- package/dist/two-d/ui/IconGrid.js.map +1 -1
- package/dist/two-d/ui/ListView.d.ts.map +1 -1
- package/dist/two-d/ui/ListView.js +2 -1
- package/dist/two-d/ui/ListView.js.map +1 -1
- package/dist/two-d/ui/ScrollBox.d.ts +96 -0
- package/dist/two-d/ui/ScrollBox.d.ts.map +1 -1
- package/dist/two-d/ui/ScrollBox.js +218 -5
- package/dist/two-d/ui/ScrollBox.js.map +1 -1
- package/dist/two-d/ui/ScrollText.d.ts +131 -0
- package/dist/two-d/ui/ScrollText.d.ts.map +1 -0
- package/dist/two-d/ui/ScrollText.js +218 -0
- package/dist/two-d/ui/ScrollText.js.map +1 -0
- package/dist/two-d/ui/Slider.d.ts.map +1 -1
- package/dist/two-d/ui/Slider.js +4 -4
- package/dist/two-d/ui/Slider.js.map +1 -1
- package/dist/two-d/ui/Tooltip.d.ts +70 -1
- package/dist/two-d/ui/Tooltip.d.ts.map +1 -1
- package/dist/two-d/ui/Tooltip.js +115 -3
- package/dist/two-d/ui/Tooltip.js.map +1 -1
- package/dist/two-d/ui/Window.d.ts +35 -2
- package/dist/two-d/ui/Window.d.ts.map +1 -1
- package/dist/two-d/ui/Window.js +58 -3
- package/dist/two-d/ui/Window.js.map +1 -1
- package/dist/two-d/ui/index.d.ts +7 -5
- package/dist/two-d/ui/index.d.ts.map +1 -1
- package/dist/two-d/ui/index.js +3 -2
- package/dist/two-d/ui/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +14 -3
- package/sbom.cdx.json +19 -260
- package/tools/audio.d.mts +75 -0
- package/tools/audio.mjs +437 -0
- package/tools/browser-driver.mjs +3 -3
- package/tools/browser-smoke.mjs +19 -2
- package/tools/build-tablebases.mjs +7 -3
- package/tools/compile-openings.mjs +7 -3
- package/tools/compile-resources.d.mts +2 -0
- package/tools/compile-resources.mjs +13 -1
- package/tools/emit-page.d.mts +6 -0
- package/tools/emit-page.mjs +43 -3
- package/tools/find-chrome.mjs +4 -2
- package/tools/init.mjs +11 -3
- package/tools/mwl.mjs +144 -2
- package/tools/play-uci.mjs +9 -5
- package/tools/vite.mjs +9 -1
- package/tools.md +2 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MidiSynth.js","sourceRoot":"","sources":["../../src/audio/MidiSynth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Signal } from '../core/Signal.ts';
|
|
2
|
+
import { type RenderedMidi } from './MidiRender.ts';
|
|
3
|
+
export interface MusicPlayerOptions {
|
|
4
|
+
/** level, 0 to 1; 1 when omitted */
|
|
5
|
+
volume?: number;
|
|
6
|
+
/** where the sound goes; the context's destination when omitted (pass a gain or compressor to shape it) */
|
|
7
|
+
destination?: AudioNode;
|
|
8
|
+
}
|
|
9
|
+
export interface MusicPlayOptions {
|
|
10
|
+
/** start offset in seconds */
|
|
11
|
+
pos?: number;
|
|
12
|
+
/** true repeats the track through its loop region instead of ending; false when omitted */
|
|
13
|
+
repeat?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* One music track at a time with the controls a game's jukebox needs: load a decoded track or a
|
|
17
|
+
* rendered MIDI file, play, pause, resume, read the position, seek, and be told when the track
|
|
18
|
+
* ends so the game can pick the next one. It wraps a `Channel`, so the buffer, the loop region
|
|
19
|
+
* and the playhead behave as they do there; what it adds is the paused state and the end of the
|
|
20
|
+
* track. Like `Music`, nothing advances on its own: call `update()` each frame.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { MusicPlayer, renderMidiToBufferAsync } from '@datamoc/mw_games/audio';
|
|
25
|
+
*
|
|
26
|
+
* declare const context: AudioContext;
|
|
27
|
+
* declare const midiBytes: ArrayBuffer;
|
|
28
|
+
* declare function nextTrack(): Promise<ArrayBuffer>;
|
|
29
|
+
*
|
|
30
|
+
* const player = new MusicPlayer(context, { volume: 0.8 });
|
|
31
|
+
* player.load(await renderMidiToBufferAsync(midiBytes));
|
|
32
|
+
* player.play();
|
|
33
|
+
* async function playNext(): Promise<void> {
|
|
34
|
+
* player.load(await renderMidiToBufferAsync(await nextTrack()));
|
|
35
|
+
* player.play();
|
|
36
|
+
* }
|
|
37
|
+
* player.onEnded.add(() => { void playNext(); });
|
|
38
|
+
*
|
|
39
|
+
* // in the scene's update:
|
|
40
|
+
* player.update();
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare class MusicPlayer {
|
|
44
|
+
/** fires once when a track that was not repeating plays through to its end */
|
|
45
|
+
readonly onEnded: Signal<void>;
|
|
46
|
+
private readonly context;
|
|
47
|
+
private readonly channel;
|
|
48
|
+
private buffer;
|
|
49
|
+
private loop;
|
|
50
|
+
private repeat;
|
|
51
|
+
private playing;
|
|
52
|
+
private paused;
|
|
53
|
+
private resumeAt;
|
|
54
|
+
private volume_;
|
|
55
|
+
constructor(context: AudioContext, options?: MusicPlayerOptions);
|
|
56
|
+
/** stops what plays and makes this track the one to play; a rendered MIDI file is copied into a buffer first */
|
|
57
|
+
load(track: RenderedMidi | AudioBuffer): void;
|
|
58
|
+
/** plays the loaded track from the start, or from `pos` */
|
|
59
|
+
play(options?: MusicPlayOptions): void;
|
|
60
|
+
pause(): void;
|
|
61
|
+
resume(): void;
|
|
62
|
+
/** pauses a playing track and resumes a paused one */
|
|
63
|
+
togglePause(): void;
|
|
64
|
+
/** stops and forgets the position; `play()` starts over */
|
|
65
|
+
stop(): void;
|
|
66
|
+
get isPlaying(): boolean;
|
|
67
|
+
get isPaused(): boolean;
|
|
68
|
+
/** seconds of the loaded track */
|
|
69
|
+
get duration(): number;
|
|
70
|
+
/** seconds into the track, held while paused */
|
|
71
|
+
position(): number;
|
|
72
|
+
/** moves the playhead, keeping a paused track paused */
|
|
73
|
+
seek(pos: number): void;
|
|
74
|
+
get volume(): number;
|
|
75
|
+
set volume(level: number);
|
|
76
|
+
/** call each frame: fires `onEnded` once when a non-repeating track has finished */
|
|
77
|
+
update(): void;
|
|
78
|
+
private start;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=MusicPlayer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MusicPlayer.d.ts","sourceRoot":"","sources":["../../src/audio/MusicPlayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IAClC,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2GAA2G;IAC3G,WAAW,CAAC,EAAE,SAAS,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAChC,8BAA8B;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,qBAAa,WAAW;IACvB,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,eAAsB;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAA+C;IAC3D,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,OAAO,CAAS;IAExB,YAAY,OAAO,EAAE,YAAY,EAAE,OAAO,GAAE,kBAAuB,EAIlE;IAED,gHAAgH;IAChH,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,WAAW,GAAG,IAAI,CAS5C;IAED,2DAA2D;IAC3D,IAAI,CAAC,OAAO,GAAE,gBAAqB,GAAG,IAAI,CAOzC;IAED,KAAK,IAAI,IAAI,CAKZ;IAED,MAAM,IAAI,IAAI,CAIb;IAED,sDAAsD;IACtD,WAAW,IAAI,IAAI,CAGlB;IAED,2DAA2D;IAC3D,IAAI,IAAI,IAAI,CAKX;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,kCAAkC;IAClC,IAAI,QAAQ,IAAI,MAAM,CAErB;IAED,gDAAgD;IAChD,QAAQ,IAAI,MAAM,CAGjB;IAED,wDAAwD;IACxD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAKtB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAGvB;IAED,oFAAoF;IACpF,MAAM,IAAI,IAAI,CAKb;IAED,OAAO,CAAC,KAAK;CASb"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Signal } from '../core/Signal.js';
|
|
2
|
+
import { Channel } from './Channels.js';
|
|
3
|
+
import { toAudioBuffer } from './MidiRender.js';
|
|
4
|
+
/**
|
|
5
|
+
* One music track at a time with the controls a game's jukebox needs: load a decoded track or a
|
|
6
|
+
* rendered MIDI file, play, pause, resume, read the position, seek, and be told when the track
|
|
7
|
+
* ends so the game can pick the next one. It wraps a `Channel`, so the buffer, the loop region
|
|
8
|
+
* and the playhead behave as they do there; what it adds is the paused state and the end of the
|
|
9
|
+
* track. Like `Music`, nothing advances on its own: call `update()` each frame.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { MusicPlayer, renderMidiToBufferAsync } from '@datamoc/mw_games/audio';
|
|
14
|
+
*
|
|
15
|
+
* declare const context: AudioContext;
|
|
16
|
+
* declare const midiBytes: ArrayBuffer;
|
|
17
|
+
* declare function nextTrack(): Promise<ArrayBuffer>;
|
|
18
|
+
*
|
|
19
|
+
* const player = new MusicPlayer(context, { volume: 0.8 });
|
|
20
|
+
* player.load(await renderMidiToBufferAsync(midiBytes));
|
|
21
|
+
* player.play();
|
|
22
|
+
* async function playNext(): Promise<void> {
|
|
23
|
+
* player.load(await renderMidiToBufferAsync(await nextTrack()));
|
|
24
|
+
* player.play();
|
|
25
|
+
* }
|
|
26
|
+
* player.onEnded.add(() => { void playNext(); });
|
|
27
|
+
*
|
|
28
|
+
* // in the scene's update:
|
|
29
|
+
* player.update();
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export class MusicPlayer {
|
|
33
|
+
constructor(context, options = {}) {
|
|
34
|
+
/** fires once when a track that was not repeating plays through to its end */
|
|
35
|
+
this.onEnded = new Signal();
|
|
36
|
+
this.buffer = null;
|
|
37
|
+
this.loop = null;
|
|
38
|
+
this.repeat = false;
|
|
39
|
+
this.playing = false;
|
|
40
|
+
this.paused = false;
|
|
41
|
+
this.resumeAt = 0;
|
|
42
|
+
this.context = context;
|
|
43
|
+
this.channel = new Channel(context, options.destination);
|
|
44
|
+
this.volume_ = Math.min(1, Math.max(0, options.volume ?? 1));
|
|
45
|
+
}
|
|
46
|
+
/** stops what plays and makes this track the one to play; a rendered MIDI file is copied into a buffer first */
|
|
47
|
+
load(track) {
|
|
48
|
+
this.stop();
|
|
49
|
+
if ('left' in track) {
|
|
50
|
+
this.buffer = toAudioBuffer(this.context, track);
|
|
51
|
+
this.loop = { start: track.loopStart, end: track.loopEnd };
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
this.buffer = track;
|
|
55
|
+
this.loop = null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** plays the loaded track from the start, or from `pos` */
|
|
59
|
+
play(options = {}) {
|
|
60
|
+
if (!this.buffer)
|
|
61
|
+
return;
|
|
62
|
+
this.repeat = options.repeat ?? false;
|
|
63
|
+
this.paused = false;
|
|
64
|
+
this.playing = true;
|
|
65
|
+
this.resumeAt = options.pos ?? 0;
|
|
66
|
+
this.start();
|
|
67
|
+
}
|
|
68
|
+
pause() {
|
|
69
|
+
if (!this.playing || this.paused)
|
|
70
|
+
return;
|
|
71
|
+
this.resumeAt = this.channel.position();
|
|
72
|
+
this.paused = true;
|
|
73
|
+
this.channel.stop();
|
|
74
|
+
}
|
|
75
|
+
resume() {
|
|
76
|
+
if (!this.paused || !this.buffer)
|
|
77
|
+
return;
|
|
78
|
+
this.paused = false;
|
|
79
|
+
this.start();
|
|
80
|
+
}
|
|
81
|
+
/** pauses a playing track and resumes a paused one */
|
|
82
|
+
togglePause() {
|
|
83
|
+
if (this.paused)
|
|
84
|
+
this.resume();
|
|
85
|
+
else
|
|
86
|
+
this.pause();
|
|
87
|
+
}
|
|
88
|
+
/** stops and forgets the position; `play()` starts over */
|
|
89
|
+
stop() {
|
|
90
|
+
this.channel.stop();
|
|
91
|
+
this.playing = false;
|
|
92
|
+
this.paused = false;
|
|
93
|
+
this.resumeAt = 0;
|
|
94
|
+
}
|
|
95
|
+
get isPlaying() {
|
|
96
|
+
return this.playing && !this.paused;
|
|
97
|
+
}
|
|
98
|
+
get isPaused() {
|
|
99
|
+
return this.paused;
|
|
100
|
+
}
|
|
101
|
+
/** seconds of the loaded track */
|
|
102
|
+
get duration() {
|
|
103
|
+
return this.buffer?.duration ?? 0;
|
|
104
|
+
}
|
|
105
|
+
/** seconds into the track, held while paused */
|
|
106
|
+
position() {
|
|
107
|
+
if (!this.playing)
|
|
108
|
+
return 0;
|
|
109
|
+
return this.paused ? this.resumeAt : this.channel.position();
|
|
110
|
+
}
|
|
111
|
+
/** moves the playhead, keeping a paused track paused */
|
|
112
|
+
seek(pos) {
|
|
113
|
+
if (!this.buffer)
|
|
114
|
+
return;
|
|
115
|
+
const target = Math.min(Math.max(0, pos), this.buffer.duration);
|
|
116
|
+
if (this.paused)
|
|
117
|
+
this.resumeAt = target;
|
|
118
|
+
else if (this.playing)
|
|
119
|
+
this.play({ pos: target, repeat: this.repeat });
|
|
120
|
+
}
|
|
121
|
+
get volume() {
|
|
122
|
+
return this.volume_;
|
|
123
|
+
}
|
|
124
|
+
set volume(level) {
|
|
125
|
+
this.volume_ = Math.min(1, Math.max(0, level));
|
|
126
|
+
this.channel.update({ volume: this.volume_ });
|
|
127
|
+
}
|
|
128
|
+
/** call each frame: fires `onEnded` once when a non-repeating track has finished */
|
|
129
|
+
update() {
|
|
130
|
+
if (!this.playing || this.paused || this.channel.isPlaying)
|
|
131
|
+
return;
|
|
132
|
+
this.playing = false;
|
|
133
|
+
this.resumeAt = 0;
|
|
134
|
+
this.onEnded.dispatch();
|
|
135
|
+
}
|
|
136
|
+
start() {
|
|
137
|
+
if (!this.buffer)
|
|
138
|
+
return;
|
|
139
|
+
this.channel.play(this.buffer, {
|
|
140
|
+
volume: this.volume_,
|
|
141
|
+
pos: this.resumeAt,
|
|
142
|
+
loop: this.loop,
|
|
143
|
+
repeat: this.repeat,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=MusicPlayer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MusicPlayer.js","sourceRoot":"","sources":["../../src/audio/MusicPlayer.ts"],"names":[],"mappings":"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"}
|
package/dist/audio/Playable.d.ts
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
* already provides, named here so a test (or a game with its own audio backend) can supply
|
|
4
4
|
* a fake without a real `Audio` element existing, which nothing outside a browser can
|
|
5
5
|
* create.
|
|
6
|
+
*
|
|
7
|
+
* A backend that synthesises its sound instead of decoding a file (see `StreamPlayable`) has to
|
|
8
|
+
* answer the questions `HTMLAudioElement` answers implicitly: `currentTime` reads and seeks the
|
|
9
|
+
* playhead and holds the duration once a track that does not loop has ended; `playbackRate` is
|
|
10
|
+
* honoured (by resampling) or ignored but never throws; `onended` fires once at the end of a
|
|
11
|
+
* track that does not loop and never for one that does; and `play()` may return a promise that
|
|
12
|
+
* settles when the audio is allowed to start.
|
|
6
13
|
*/
|
|
7
14
|
export interface Playable {
|
|
8
15
|
play(): void | Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Playable.d.ts","sourceRoot":"","sources":["../../src/audio/Playable.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"Playable.d.ts","sourceRoot":"","sources":["../../src/audio/Playable.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,QAAQ;IACxB,IAAI,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,yFAAyF;IACzF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;+EAC2E;IAC3E,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,IAAI,CAAC;CAC7C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAUlD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Playable.js","sourceRoot":"","sources":["../../src/audio/Playable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"Playable.js","sourceRoot":"","sources":["../../src/audio/Playable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAC;AA4BhD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACvC,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACJ,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,0FAA0F;QAC1F,OAAO,CAAC,IAAI,CAAC,GAAI,KAAe,CAAC,OAAO,OAAO,IAAI,kBAAkB,CAAC,CAAC;QACvE,OAAO,cAAc,EAAE,CAAC;IACzB,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,4FAA4F;AAC5F,SAAS,cAAc;IACtB,OAAO,EAAE,IAAI,KAAI,CAAC,EAAE,KAAK,KAAI,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC1E,CAAC"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/** anything a `SoundSource` can play at a mix: a `Sound`, or an `SfxSound` that also takes a pan */
|
|
2
|
+
export interface PositionalSound {
|
|
3
|
+
play(gain?: number, pitch?: number, pan?: number): unknown;
|
|
4
|
+
}
|
|
2
5
|
/** A point in the same 2D space the game's camera works in, in world units. */
|
|
3
6
|
export interface AudioPoint {
|
|
4
7
|
x: number;
|
|
@@ -113,13 +116,18 @@ export declare class SoundSource implements AudioPoint {
|
|
|
113
116
|
y: number;
|
|
114
117
|
private readonly sound;
|
|
115
118
|
private readonly falloff;
|
|
116
|
-
constructor(sound:
|
|
119
|
+
constructor(sound: PositionalSound, options?: SoundSourceOptions);
|
|
117
120
|
moveTo(x: number, y: number): void;
|
|
118
121
|
gainTo(listener: AudioPoint): number;
|
|
119
122
|
panTo(listener: AudioPoint & {
|
|
120
123
|
facing: number;
|
|
121
124
|
}): number;
|
|
122
|
-
/**
|
|
123
|
-
|
|
125
|
+
/**
|
|
126
|
+
* Plays the source at the gain the listener hears it; returns the gain actually used. A listener
|
|
127
|
+
* with a `facing` also pans the sound, for a sound that takes a pan (a `Sound` ignores it).
|
|
128
|
+
*/
|
|
129
|
+
playFor(listener: AudioPoint | (AudioPoint & {
|
|
130
|
+
facing: number;
|
|
131
|
+
})): number;
|
|
124
132
|
}
|
|
125
133
|
//# sourceMappingURL=Positional.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Positional.d.ts","sourceRoot":"","sources":["../../src/audio/Positional.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"Positional.d.ts","sourceRoot":"","sources":["../../src/audio/Positional.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,MAAM,WAAW,eAAe;IAC/B,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3D;AAED,+EAA+E;AAC/E,MAAM,WAAW,UAAU;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACV;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC5B,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAU9E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAW9F;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAc,YAAW,UAAU;IAC/C,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IAEV,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,OAAO,GAAE;QAAE,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,EAIpE;IAED,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAGjC;IAED,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1B;CACD;AAED,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACvD,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;CACX;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,WAAY,YAAW,UAAU;IAC7C,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IAEV,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IAEvC,YAAY,KAAK,EAAE,eAAe,EAAE,OAAO,GAAE,kBAAuB,EASnE;IAED,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAGjC;IAED,MAAM,CAAC,QAAQ,EAAE,UAAU,GAAG,MAAM,CAEnC;IAED,KAAK,CAAC,QAAQ,EAAE,UAAU,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAEvD;IAED;;;OAGG;IACH,OAAO,CAAC,QAAQ,EAAE,UAAU,GAAG,CAAC,UAAU,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,MAAM,CAKxE;CACD"}
|
package/dist/audio/Positional.js
CHANGED
|
@@ -123,12 +123,15 @@ export class SoundSource {
|
|
|
123
123
|
panTo(listener) {
|
|
124
124
|
return audioPan(listener, this);
|
|
125
125
|
}
|
|
126
|
-
/**
|
|
126
|
+
/**
|
|
127
|
+
* Plays the source at the gain the listener hears it; returns the gain actually used. A listener
|
|
128
|
+
* with a `facing` also pans the sound, for a sound that takes a pan (a `Sound` ignores it).
|
|
129
|
+
*/
|
|
127
130
|
playFor(listener) {
|
|
128
131
|
const gain = this.gainTo(listener);
|
|
129
132
|
if (gain <= 0)
|
|
130
133
|
return 0;
|
|
131
|
-
this.sound.play(gain);
|
|
134
|
+
this.sound.play(gain, 1, 'facing' in listener ? this.panTo(listener) : 0);
|
|
132
135
|
return gain;
|
|
133
136
|
}
|
|
134
137
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Positional.js","sourceRoot":"","sources":["../../src/audio/Positional.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Positional.js","sourceRoot":"","sources":["../../src/audio/Positional.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain-array helpers for fitting rendered audio to a budget: cut to a length with a fade,
|
|
3
|
+
* fold to mono, halve the rate, convert between rates. They work on the `Float32Array`
|
|
4
|
+
* pairs a render produces, so nothing here needs an `AudioContext`.
|
|
5
|
+
*/
|
|
6
|
+
/** stereo frames at a sample rate: the shape every renderer in this module hands back */
|
|
7
|
+
export interface StereoFrames {
|
|
8
|
+
sampleRate: number;
|
|
9
|
+
left: Float32Array;
|
|
10
|
+
right: Float32Array;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Converts stereo frames to another sample rate by linear interpolation. Linear is audibly
|
|
14
|
+
* soft above the new Nyquist, which is the right trade for ambience and background music where
|
|
15
|
+
* this is used to save memory; a game that needs a clean conversion renders at the target
|
|
16
|
+
* rate instead.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { resampleStereo } from '@datamoc/mw_games/audio';
|
|
21
|
+
*
|
|
22
|
+
* declare const frames: { sampleRate: number; left: Float32Array; right: Float32Array };
|
|
23
|
+
*
|
|
24
|
+
* const half = resampleStereo(frames, frames.sampleRate / 2);
|
|
25
|
+
* console.log(half.left.length);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function resampleStereo<T extends StereoFrames>(frames: T, sampleRate: number): T;
|
|
29
|
+
/** what a track may cost: every field optional, an omitted one leaves that dimension alone */
|
|
30
|
+
export interface RenderBudget {
|
|
31
|
+
/** cut the track to this many seconds, fading the cut so it does not click */
|
|
32
|
+
maxSeconds?: number;
|
|
33
|
+
/** seconds of fade at a cut; 0.5 when omitted */
|
|
34
|
+
fadeSeconds?: number;
|
|
35
|
+
/** fold both channels into one, stored twice-referenced so a stereo consumer still works */
|
|
36
|
+
mono?: boolean;
|
|
37
|
+
/** halve the sample rate, for ambience that carries no high frequencies */
|
|
38
|
+
halfRate?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Fits a rendered track to a budget: cuts it to `maxSeconds` with a fade, folds it to mono
|
|
42
|
+
* and halves its rate, in that order. A mono track shares one array between both channels, so
|
|
43
|
+
* it costs half the memory in the renderer's hands even though a stereo `AudioBuffer` made
|
|
44
|
+
* from it later still has two. Loop points past the cut are pulled back to the new end.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* import { fitToBudget, renderMidiToBuffer, parseMidi } from '@datamoc/mw_games/audio';
|
|
49
|
+
*
|
|
50
|
+
* declare const midiBytes: ArrayBuffer;
|
|
51
|
+
*
|
|
52
|
+
* const ambience = fitToBudget(renderMidiToBuffer(parseMidi(midiBytes)), { maxSeconds: 60, mono: true, halfRate: true });
|
|
53
|
+
* console.log(ambience.duration);
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export declare function fitToBudget<T extends StereoFrames & {
|
|
57
|
+
loopStart?: number;
|
|
58
|
+
loopEnd?: number;
|
|
59
|
+
duration?: number;
|
|
60
|
+
}>(track: T, budget: RenderBudget): T;
|
|
61
|
+
//# sourceMappingURL=Resample.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Resample.d.ts","sourceRoot":"","sources":["../../src/audio/Resample.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,yFAAyF;AACzF,MAAM,WAAW,YAAY;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;CACpB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,CAiBvF;AAED,8FAA8F;AAC9F,MAAM,WAAW,YAAY;IAC5B,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4FAA4F;IAC5F,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,YAAY,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/G,KAAK,EAAE,CAAC,EACR,MAAM,EAAE,YAAY,GAClB,CAAC,CAyBH"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain-array helpers for fitting rendered audio to a budget: cut to a length with a fade,
|
|
3
|
+
* fold to mono, halve the rate, convert between rates. They work on the `Float32Array`
|
|
4
|
+
* pairs a render produces, so nothing here needs an `AudioContext`.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Converts stereo frames to another sample rate by linear interpolation. Linear is audibly
|
|
8
|
+
* soft above the new Nyquist, which is the right trade for ambience and background music where
|
|
9
|
+
* this is used to save memory; a game that needs a clean conversion renders at the target
|
|
10
|
+
* rate instead.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { resampleStereo } from '@datamoc/mw_games/audio';
|
|
15
|
+
*
|
|
16
|
+
* declare const frames: { sampleRate: number; left: Float32Array; right: Float32Array };
|
|
17
|
+
*
|
|
18
|
+
* const half = resampleStereo(frames, frames.sampleRate / 2);
|
|
19
|
+
* console.log(half.left.length);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function resampleStereo(frames, sampleRate) {
|
|
23
|
+
if (!(sampleRate > 0))
|
|
24
|
+
throw new Error('target sample rate must be positive');
|
|
25
|
+
if (sampleRate === frames.sampleRate)
|
|
26
|
+
return frames;
|
|
27
|
+
const length = Math.max(1, Math.round((frames.left.length * sampleRate) / frames.sampleRate));
|
|
28
|
+
const step = frames.sampleRate / sampleRate;
|
|
29
|
+
const left = new Float32Array(length);
|
|
30
|
+
const right = new Float32Array(length);
|
|
31
|
+
const last = frames.left.length - 1;
|
|
32
|
+
for (let i = 0; i < length; i++) {
|
|
33
|
+
const position = i * step;
|
|
34
|
+
const floor = Math.min(last, Math.floor(position));
|
|
35
|
+
const next = Math.min(last, floor + 1);
|
|
36
|
+
const fraction = position - floor;
|
|
37
|
+
left[i] = frames.left[floor] + (frames.left[next] - frames.left[floor]) * fraction;
|
|
38
|
+
right[i] = frames.right[floor] + (frames.right[next] - frames.right[floor]) * fraction;
|
|
39
|
+
}
|
|
40
|
+
return { ...frames, sampleRate, left, right };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Fits a rendered track to a budget: cuts it to `maxSeconds` with a fade, folds it to mono
|
|
44
|
+
* and halves its rate, in that order. A mono track shares one array between both channels, so
|
|
45
|
+
* it costs half the memory in the renderer's hands even though a stereo `AudioBuffer` made
|
|
46
|
+
* from it later still has two. Loop points past the cut are pulled back to the new end.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* import { fitToBudget, renderMidiToBuffer, parseMidi } from '@datamoc/mw_games/audio';
|
|
51
|
+
*
|
|
52
|
+
* declare const midiBytes: ArrayBuffer;
|
|
53
|
+
*
|
|
54
|
+
* const ambience = fitToBudget(renderMidiToBuffer(parseMidi(midiBytes)), { maxSeconds: 60, mono: true, halfRate: true });
|
|
55
|
+
* console.log(ambience.duration);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export function fitToBudget(track, budget) {
|
|
59
|
+
let result = track;
|
|
60
|
+
if (budget.maxSeconds !== undefined) {
|
|
61
|
+
if (!(budget.maxSeconds > 0))
|
|
62
|
+
throw new Error('budget maxSeconds must be positive');
|
|
63
|
+
const limit = Math.max(1, Math.floor(budget.maxSeconds * result.sampleRate));
|
|
64
|
+
if (result.left.length > limit) {
|
|
65
|
+
const left = result.left.slice(0, limit);
|
|
66
|
+
const right = result.right.slice(0, limit);
|
|
67
|
+
const fade = Math.min(limit, Math.floor((budget.fadeSeconds ?? 0.5) * result.sampleRate));
|
|
68
|
+
for (let i = 0; i < fade; i++) {
|
|
69
|
+
const gain = i / fade;
|
|
70
|
+
left[limit - 1 - i] *= gain;
|
|
71
|
+
right[limit - 1 - i] *= gain;
|
|
72
|
+
}
|
|
73
|
+
const seconds = limit / result.sampleRate;
|
|
74
|
+
result = withEnd({ ...result, left, right }, seconds);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (budget.mono) {
|
|
78
|
+
const mixed = new Float32Array(result.left.length);
|
|
79
|
+
for (let i = 0; i < mixed.length; i++)
|
|
80
|
+
mixed[i] = (result.left[i] + result.right[i]) / 2;
|
|
81
|
+
result = { ...result, left: mixed, right: mixed };
|
|
82
|
+
}
|
|
83
|
+
if (budget.halfRate)
|
|
84
|
+
result = resampleStereo(result, result.sampleRate / 2);
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
function withEnd(track, seconds) {
|
|
88
|
+
const next = { ...track };
|
|
89
|
+
if (next.duration !== undefined)
|
|
90
|
+
next.duration = seconds;
|
|
91
|
+
if (next.loopEnd !== undefined)
|
|
92
|
+
next.loopEnd = Math.min(next.loopEnd, seconds);
|
|
93
|
+
if (next.loopStart !== undefined)
|
|
94
|
+
next.loopStart = Math.min(next.loopStart, Math.max(0, seconds - 0.1));
|
|
95
|
+
return next;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=Resample.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Resample.js","sourceRoot":"","sources":["../../src/audio/Resample.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,11 +21,25 @@ export interface SampleDecodingContext {
|
|
|
21
21
|
export declare const MIN_SAMPLE_RATE = 400;
|
|
22
22
|
export declare const MAX_SAMPLE_RATE = 200000;
|
|
23
23
|
export declare const MAX_SAMPLE_FRAMES: number;
|
|
24
|
+
/**
|
|
25
|
+
* How much a SoundFont 3 may decode to, in frames. The defaults (`MAX_SAMPLE_FRAMES` for one sample, 128
|
|
26
|
+
* million, 256 MB of 16-bit audio, for the whole font) suit a game font; raise them for a very large one
|
|
27
|
+
* you trust, since each frame is two bytes of memory and a damaged font can ask for any number.
|
|
28
|
+
*/
|
|
29
|
+
export interface SoundFontLimits {
|
|
30
|
+
/** frames one decoded sample may have */
|
|
31
|
+
sampleFrames?: number;
|
|
32
|
+
/** frames all the decoded samples of one font may have */
|
|
33
|
+
totalFrames?: number;
|
|
34
|
+
}
|
|
35
|
+
/** the whole-font default of {@link SoundFontLimits} */
|
|
36
|
+
export declare const MAX_TOTAL_FRAMES: number;
|
|
24
37
|
/**
|
|
25
38
|
* A decoder over WebAudio's `decodeAudioData`, for a browser: each sample decodes in a context
|
|
26
39
|
* created at the sample's own rate, so the browser does not resample it and the loop points keep
|
|
27
40
|
* meaning what the font wrote. A rate outside what a context accepts (8 to 96 kHz) decodes at
|
|
28
|
-
* the nearest accepted rate and is resampled back. `create` replaces the context factory
|
|
41
|
+
* the nearest accepted rate and is resampled back. `create` replaces the context factory and `limits`
|
|
42
|
+
* the longest sample it will return.
|
|
29
43
|
*
|
|
30
44
|
* @example
|
|
31
45
|
* ```ts
|
|
@@ -37,5 +51,5 @@ export declare const MAX_SAMPLE_FRAMES: number;
|
|
|
37
51
|
* console.log(font.presetCount);
|
|
38
52
|
* ```
|
|
39
53
|
*/
|
|
40
|
-
export declare function webAudioSampleDecoder(create?: (rate: number) => SampleDecodingContext): SoundFontSampleDecoder;
|
|
54
|
+
export declare function webAudioSampleDecoder(create?: (rate: number) => SampleDecodingContext, limits?: SoundFontLimits): SoundFontSampleDecoder;
|
|
41
55
|
//# sourceMappingURL=SampleDecoder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SampleDecoder.d.ts","sourceRoot":"","sources":["../../src/audio/SampleDecoder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEzG,yFAAyF;AACzF,MAAM,WAAW,qBAAqB;IACrC,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC;QAC3C,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC;KAC9C,CAAC,CAAC;CACH;AAMD;;;;GAIG;AACH,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,iBAAiB,QAAU,CAAC;AA+
|
|
1
|
+
{"version":3,"file":"SampleDecoder.d.ts","sourceRoot":"","sources":["../../src/audio/SampleDecoder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEzG,yFAAyF;AACzF,MAAM,WAAW,qBAAqB;IACrC,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC;QAC3C,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC;KAC9C,CAAC,CAAC;CACH;AAMD;;;;GAIG;AACH,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,iBAAiB,QAAU,CAAC;AAEzC;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wDAAwD;AACxD,eAAO,MAAM,gBAAgB,QAAU,CAAC;AA+BxC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACpC,MAAM,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,qBAAsC,EAChE,MAAM,GAAE,eAAoB,GAC1B,sBAAsB,CAcxB"}
|
|
@@ -9,6 +9,8 @@ const MAX_RATE = 96000;
|
|
|
9
9
|
export const MIN_SAMPLE_RATE = 400;
|
|
10
10
|
export const MAX_SAMPLE_RATE = 200000;
|
|
11
11
|
export const MAX_SAMPLE_FRAMES = 1 << 24;
|
|
12
|
+
/** the whole-font default of {@link SoundFontLimits} */
|
|
13
|
+
export const MAX_TOTAL_FRAMES = 1 << 27;
|
|
12
14
|
function toInt16(frames) {
|
|
13
15
|
const out = new Int16Array(frames.length);
|
|
14
16
|
for (let index = 0; index < frames.length; index++) {
|
|
@@ -17,9 +19,9 @@ function toInt16(frames) {
|
|
|
17
19
|
return out;
|
|
18
20
|
}
|
|
19
21
|
/** linear resampling, only for the rare sample whose rate a context cannot be created at */
|
|
20
|
-
function resample(frames, from, to) {
|
|
22
|
+
function resample(frames, from, to, maxFrames) {
|
|
21
23
|
const length = Math.max(1, Math.round((frames.length * to) / from));
|
|
22
|
-
if (length >
|
|
24
|
+
if (length > maxFrames)
|
|
23
25
|
throw new Error('a decoded sample is longer than a SoundFont sample may be');
|
|
24
26
|
const out = new Float32Array(length);
|
|
25
27
|
for (let index = 0; index < out.length; index++) {
|
|
@@ -40,7 +42,8 @@ function offlineContext(rate) {
|
|
|
40
42
|
* A decoder over WebAudio's `decodeAudioData`, for a browser: each sample decodes in a context
|
|
41
43
|
* created at the sample's own rate, so the browser does not resample it and the loop points keep
|
|
42
44
|
* meaning what the font wrote. A rate outside what a context accepts (8 to 96 kHz) decodes at
|
|
43
|
-
* the nearest accepted rate and is resampled back. `create` replaces the context factory
|
|
45
|
+
* the nearest accepted rate and is resampled back. `create` replaces the context factory and `limits`
|
|
46
|
+
* the longest sample it will return.
|
|
44
47
|
*
|
|
45
48
|
* @example
|
|
46
49
|
* ```ts
|
|
@@ -52,7 +55,8 @@ function offlineContext(rate) {
|
|
|
52
55
|
* console.log(font.presetCount);
|
|
53
56
|
* ```
|
|
54
57
|
*/
|
|
55
|
-
export function webAudioSampleDecoder(create = offlineContext) {
|
|
58
|
+
export function webAudioSampleDecoder(create = offlineContext, limits = {}) {
|
|
59
|
+
const maxFrames = limits.sampleFrames ?? MAX_SAMPLE_FRAMES;
|
|
56
60
|
return async (ogg, rate) => {
|
|
57
61
|
if (!(rate >= MIN_SAMPLE_RATE && rate <= MAX_SAMPLE_RATE)) {
|
|
58
62
|
throw new Error(`a sample rate of ${rate} Hz is not one a SoundFont can state`);
|
|
@@ -61,10 +65,10 @@ export function webAudioSampleDecoder(create = offlineContext) {
|
|
|
61
65
|
//decodeAudioData detaches what it is given, and `ogg` is a view into the caller's font
|
|
62
66
|
const copy = ogg.slice().buffer;
|
|
63
67
|
const decoded = await create(contextRate).decodeAudioData(copy);
|
|
64
|
-
if (decoded.length >
|
|
68
|
+
if (decoded.length > maxFrames)
|
|
65
69
|
throw new Error('a decoded sample is longer than a SoundFont sample may be');
|
|
66
70
|
const channel = decoded.getChannelData(0);
|
|
67
|
-
return toInt16(decoded.sampleRate === rate ? channel : resample(channel, decoded.sampleRate, rate));
|
|
71
|
+
return toInt16(decoded.sampleRate === rate ? channel : resample(channel, decoded.sampleRate, rate, maxFrames));
|
|
68
72
|
};
|
|
69
73
|
}
|
|
70
74
|
//# sourceMappingURL=SampleDecoder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SampleDecoder.js","sourceRoot":"","sources":["../../src/audio/SampleDecoder.ts"],"names":[],"mappings":"AAiBA,4EAA4E;AAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,MAAM,QAAQ,GAAG,KAAK,CAAC;AAEvB;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AACnC,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"SampleDecoder.js","sourceRoot":"","sources":["../../src/audio/SampleDecoder.ts"],"names":[],"mappings":"AAiBA,4EAA4E;AAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC;AACtB,MAAM,QAAQ,GAAG,KAAK,CAAC;AAEvB;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AACnC,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC;AACtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,CAAC;AAczC,wDAAwD;AACxD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,CAAC;AAExC,SAAS,OAAO,CAAC,MAAoB;IACpC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1C,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACpD,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,4FAA4F;AAC5F,SAAS,QAAQ,CAAC,MAAoB,EAAE,IAAY,EAAE,EAAU,EAAE,SAAiB;IAClF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACpE,IAAI,MAAM,GAAG,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IACrG,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;IACrC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACjD,MAAM,EAAE,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACnD,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IACnC,IAAI,OAAO,mBAAmB,KAAK,WAAW,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,IAAI,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,qBAAqB,CACpC,MAAM,GAA4C,cAAc,EAChE,MAAM,GAAoB,EAAE;IAE5B,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,IAAI,iBAAiB,CAAC;IAC3D,OAAO,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC1B,IAAI,CAAC,CAAC,IAAI,IAAI,eAAe,IAAI,IAAI,IAAI,eAAe,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,sCAAsC,CAAC,CAAC;QACjF,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;QACjE,uFAAuF;QACvF,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,MAAqB,CAAC;QAC/C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAChE,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC7G,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;QAC1C,OAAO,OAAO,CAAC,OAAO,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IAChH,CAAC,CAAC;AACH,CAAC"}
|