@datamoc/mw_games 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/README.md +1 -1
- package/dist/audio/Channels.d.ts +198 -0
- package/dist/audio/Channels.d.ts.map +1 -0
- package/dist/audio/Channels.js +456 -0
- package/dist/audio/Channels.js.map +1 -0
- package/dist/audio/Midi.d.ts +71 -9
- package/dist/audio/Midi.d.ts.map +1 -1
- package/dist/audio/Midi.js +107 -15
- package/dist/audio/Midi.js.map +1 -1
- package/dist/audio/MidiRender.d.ts +57 -0
- package/dist/audio/MidiRender.d.ts.map +1 -0
- package/dist/audio/MidiRender.js +261 -0
- package/dist/audio/MidiRender.js.map +1 -0
- package/dist/audio/SoundFont.d.ts +64 -0
- package/dist/audio/SoundFont.d.ts.map +1 -0
- package/dist/audio/SoundFont.js +219 -0
- package/dist/audio/SoundFont.js.map +1 -0
- package/dist/audio/index.d.ts +9 -2
- package/dist/audio/index.d.ts.map +1 -1
- package/dist/audio/index.js +4 -1
- package/dist/audio/index.js.map +1 -1
- package/dist/mw_games.global.js +10 -10
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
- package/tools/csp.mjs +10 -1
- package/tools/sbom.mjs +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,45 @@ All notable changes to `mwg` are documented here. Format follows
|
|
|
5
5
|
[Semantic Versioning](https://semver.org/) as of this first release - a 0.y.z version means
|
|
6
6
|
the public API may still change between minor versions.
|
|
7
7
|
|
|
8
|
+
## [0.18.0] - 2026-09-25
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `audio.parseMidi` keeps program-change, control-change and pitch-bend events and reports
|
|
13
|
+
the controller-111 loop marker as `loopStartTick`; `scheduleMidi` notes carry their channel
|
|
14
|
+
voice (`MidiVoice`: program, bank, gain, pan) and `midiLoopStart` resolves the marker to seconds.
|
|
15
|
+
- `audio.renderMidiToBuffer` renders a parsed MIDI file to stereo PCM frames, offline and
|
|
16
|
+
deterministic, voiced by an optional game-supplied `SoundFont` or the built-in waveform
|
|
17
|
+
synth, with the loop region attached.
|
|
18
|
+
- `audio.parseSoundFont` reads SoundFont 2 bytes into layered preset voices.
|
|
19
|
+
- `audio.Channel` (a seekable buffered WebAudio voice with volume, pitch, pan and a loop
|
|
20
|
+
region) and `audio.AudioBus` (independent BGM/BGS loops, ME jingles that suspend and resume
|
|
21
|
+
the BGM, overlapping SE one-shots, save and replay with playheads, plain-data snapshots).
|
|
22
|
+
## [0.17.1] - 2026-09-25
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- A page built on a Windows checkout refused its own inline script. The HTML parser turns
|
|
27
|
+
newlines into LF before it hashes an inline script, while `contentSecurityPolicy` hashed the
|
|
28
|
+
CRLF bytes a `core.autocrlf=true` checkout hands over, so Chrome computed a different hash
|
|
29
|
+
from the one the policy allowed. The page logged a Content-Security-Policy violation that
|
|
30
|
+
`mwg-smoke`, the visual smoke and `mwg-bench` read as a page error, the source-page fallback
|
|
31
|
+
script never ran, and the same build on Linux stayed quiet - which is why no browser job had
|
|
32
|
+
caught it. Inline scripts are now hashed after CRLF and lone CR become LF; the standalone
|
|
33
|
+
page's unpacker scripts stay hashed as written, since no parser touches those. A CRLF
|
|
34
|
+
checkout and an LF checkout now produce the same policy, pinned by a test.
|
|
35
|
+
- The committed-artifact checks no longer read the checkout's line endings. `api:check`,
|
|
36
|
+
`stats:check`, `sbom:check` and the committed-SBOM test compared generated text against the
|
|
37
|
+
committed file byte for byte, so a Windows clone failed them on a tree `git diff` called
|
|
38
|
+
clean; `bundle.distRaw` summed the bytes `tsc` copies out of a source file's comments, which
|
|
39
|
+
recorded who generated the file rather than what ships.
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
|
|
43
|
+
- The `check` job runs on `windows-latest` alongside `ubuntu-latest`, so the two failures above
|
|
44
|
+
fail the push instead of reaching a Windows contributor. The gates themselves are unchanged,
|
|
45
|
+
and `fail-fast` is off so one OS failing still shows the other.
|
|
46
|
+
|
|
8
47
|
## [0.17.0] - 2026-09-25
|
|
9
48
|
|
|
10
49
|
### Security
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ playable in the browser with no download, plus the generated API reference.
|
|
|
15
15
|
planning or porting a demanding game with mwg, with links to the [mwg reference](https://github.com/datamoc/mwg/blob/main/REFERENCE.md)
|
|
16
16
|
and the [mwg Pixel Dungeon study](https://datamoc.github.io/mwg-pixel-dungeon/).
|
|
17
17
|
|
|
18
|
-
> **Status: pre-alpha (v0.17.
|
|
18
|
+
> **Status: pre-alpha (v0.17.1).** Every module in the shared floor below, plus optional
|
|
19
19
|
> 3D, mobile (Capacitor) and desktop (WebView2) packaging, is built and tested - see
|
|
20
20
|
> [ROADMAP.md](https://github.com/datamoc/mwg/blob/main/ROADMAP.md) for open work, and
|
|
21
21
|
> [CLOSED.md](https://github.com/datamoc/mwg/blob/main/CLOSED.md) for the full, numbered shipped history.
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Buffered WebAudio voices for music and jingles: a `Channel` plays one looping track
|
|
3
|
+
* with volume, pitch, pan, a loop region and a seekable playhead, and an `AudioBus`
|
|
4
|
+
* wires channels into the four lifetimes a role-playing game needs from its audio.
|
|
5
|
+
* BGM and BGS are two independent looping streams, ME is an interrupting jingle that
|
|
6
|
+
* pauses the BGM and resumes it where it left off, SE is overlapping one-shots, each
|
|
7
|
+
* with its own volume, pitch and pan per play.
|
|
8
|
+
*
|
|
9
|
+
* The browser owns the clock and the nodes, so both classes take the pieces they
|
|
10
|
+
* cannot build themselves as injectables: the `AudioContext` in the constructor and,
|
|
11
|
+
* for the bus, a `load` function turning a kind and a name into a decoded buffer.
|
|
12
|
+
* Tests hand in fakes for both, the same way `Sound` and `Music` take `create()`.
|
|
13
|
+
*/
|
|
14
|
+
/** seconds within a buffer: the region a looping track repeats */
|
|
15
|
+
export interface LoopRegion {
|
|
16
|
+
start: number;
|
|
17
|
+
end: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ChannelPlayOptions {
|
|
20
|
+
/** level, 0 to 1 */
|
|
21
|
+
volume?: number;
|
|
22
|
+
/** playback ratio, 1 unchanged, above 1 higher and faster */
|
|
23
|
+
pitch?: number;
|
|
24
|
+
/** stereo position, -1 (left) to 1 (right) */
|
|
25
|
+
pan?: number;
|
|
26
|
+
/** start offset in seconds */
|
|
27
|
+
pos?: number;
|
|
28
|
+
/** region to repeat, null repeats the whole buffer */
|
|
29
|
+
loop?: LoopRegion | null;
|
|
30
|
+
/** false plays once through for jingles; true repeats */
|
|
31
|
+
repeat?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/** plain-data playback state: parameters plus playhead, without the buffer */
|
|
34
|
+
export interface ChannelState {
|
|
35
|
+
volume: number;
|
|
36
|
+
pitch: number;
|
|
37
|
+
pan: number;
|
|
38
|
+
pos: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* One buffered voice: a decoded track with a loop region and a playhead the game can
|
|
42
|
+
* read and move. Replaying the same buffer restarts it; changing parameters mid-play
|
|
43
|
+
* never does.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* import { Channel } from '@datamoc/mw_games/audio';
|
|
48
|
+
*
|
|
49
|
+
* declare const context: AudioContext;
|
|
50
|
+
* declare const buffer: AudioBuffer;
|
|
51
|
+
*
|
|
52
|
+
* const channel = new Channel(context);
|
|
53
|
+
* channel.play(buffer, { volume: 0.8, pitch: 1, pan: 0, loop: { start: 1, end: 4 } });
|
|
54
|
+
* console.log(channel.position());
|
|
55
|
+
* channel.stop();
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare class Channel {
|
|
59
|
+
private readonly context;
|
|
60
|
+
private readonly destination;
|
|
61
|
+
private source;
|
|
62
|
+
private gainNode;
|
|
63
|
+
private pannerNode;
|
|
64
|
+
private buffer;
|
|
65
|
+
private params;
|
|
66
|
+
private loopRegion;
|
|
67
|
+
private repeat;
|
|
68
|
+
private startedAt;
|
|
69
|
+
private offset;
|
|
70
|
+
constructor(context: AudioContext, destination?: AudioNode);
|
|
71
|
+
get isPlaying(): boolean;
|
|
72
|
+
get duration(): number;
|
|
73
|
+
/** starts the buffer with these parameters, stopping whatever played before */
|
|
74
|
+
play(buffer: AudioBuffer, options?: ChannelPlayOptions): void;
|
|
75
|
+
/** retunes the playing voice in place: no restart, no seek */
|
|
76
|
+
update(params: {
|
|
77
|
+
volume?: number;
|
|
78
|
+
pitch?: number;
|
|
79
|
+
pan?: number;
|
|
80
|
+
}): void;
|
|
81
|
+
/** stops the voice, fading out over `fadeSeconds` first when positive */
|
|
82
|
+
stop(fadeSeconds?: number): void;
|
|
83
|
+
/** seconds into the buffer, wrapping inside the loop region while it repeats */
|
|
84
|
+
position(): number;
|
|
85
|
+
/** moves the playhead, restarting the voice when it plays */
|
|
86
|
+
seek(pos: number): void;
|
|
87
|
+
/** plain-data state for saves and transfers: parameters plus playhead */
|
|
88
|
+
state(): ChannelState;
|
|
89
|
+
/** applies plain-data state, restarting the voice at its playhead when it plays */
|
|
90
|
+
restore(state: ChannelState): void;
|
|
91
|
+
private clearNodes;
|
|
92
|
+
}
|
|
93
|
+
export type BusKind = 'bgm' | 'bgs' | 'me' | 'se';
|
|
94
|
+
/**
|
|
95
|
+
* A named track request in role-playing units: volume 0 to 100, pitch 50 to 150
|
|
96
|
+
* percent, pan -100 to 100, an optional resume position in seconds.
|
|
97
|
+
*/
|
|
98
|
+
export interface BusTrack {
|
|
99
|
+
name: string;
|
|
100
|
+
volume?: number;
|
|
101
|
+
pitch?: number;
|
|
102
|
+
pan?: number;
|
|
103
|
+
pos?: number;
|
|
104
|
+
}
|
|
105
|
+
/** a resolved track request: every parameter filled in, ready to store or restore */
|
|
106
|
+
export interface SavedBusTrack {
|
|
107
|
+
name: string;
|
|
108
|
+
volume: number;
|
|
109
|
+
pitch: number;
|
|
110
|
+
pan: number;
|
|
111
|
+
pos: number;
|
|
112
|
+
}
|
|
113
|
+
/** a decoded track: its buffer plus the region it repeats, if any */
|
|
114
|
+
export interface LoadedTrack {
|
|
115
|
+
buffer: AudioBuffer;
|
|
116
|
+
loop?: LoopRegion | null;
|
|
117
|
+
}
|
|
118
|
+
/** turns a kind and a name into a decoded buffer, or null when it cannot */
|
|
119
|
+
export type BusLoader = (kind: BusKind, name: string) => Promise<LoadedTrack | null>;
|
|
120
|
+
/** plain-data bus state for saves and transfers: tracks plus memorized ones */
|
|
121
|
+
export interface BusSnapshot {
|
|
122
|
+
bgm: SavedBusTrack | null;
|
|
123
|
+
bgs: SavedBusTrack | null;
|
|
124
|
+
savedBgm: SavedBusTrack | null;
|
|
125
|
+
savedBgs: SavedBusTrack | null;
|
|
126
|
+
}
|
|
127
|
+
export interface AudioBusOptions {
|
|
128
|
+
destination?: AudioNode;
|
|
129
|
+
load?: BusLoader;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* The four audio lifetimes of a role-playing game over two `Channel` voices: BGM and
|
|
133
|
+
* BGS loop independently, an ME jingle suspends the BGM and resumes it where it left
|
|
134
|
+
* off, SE plays overlapping one-shots. Replaying the current track only retunes it;
|
|
135
|
+
* save and replay memorize a track with its playhead for menus and transfers.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```ts
|
|
139
|
+
* import { AudioBus } from '@datamoc/mw_games/audio';
|
|
140
|
+
*
|
|
141
|
+
* declare const context: AudioContext;
|
|
142
|
+
*
|
|
143
|
+
* const bus = new AudioBus(context, { load: (_kind, _name) => Promise.resolve(null) });
|
|
144
|
+
* void bus.playBgm({ name: 'town', volume: 90, pitch: 100, pan: 0 });
|
|
145
|
+
* console.log(bus.snapshot());
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export declare class AudioBus {
|
|
149
|
+
private readonly context;
|
|
150
|
+
private readonly destination;
|
|
151
|
+
private readonly load;
|
|
152
|
+
private readonly bgmChannel;
|
|
153
|
+
private readonly bgsChannel;
|
|
154
|
+
private readonly tracks;
|
|
155
|
+
private readonly saved;
|
|
156
|
+
private readonly requests;
|
|
157
|
+
private me;
|
|
158
|
+
private meToken;
|
|
159
|
+
private suspendedBgm;
|
|
160
|
+
private readonly seNodes;
|
|
161
|
+
constructor(context: AudioContext, options?: AudioBusOptions);
|
|
162
|
+
/** loops this BGM, or retunes it when it already loops */
|
|
163
|
+
playBgm(track: BusTrack): Promise<void>;
|
|
164
|
+
/** loops this BGS, or retunes it when it already loops */
|
|
165
|
+
playBgs(track: BusTrack): Promise<void>;
|
|
166
|
+
stopBgm(): void;
|
|
167
|
+
stopBgs(): void;
|
|
168
|
+
fadeOutBgm(seconds?: number): void;
|
|
169
|
+
fadeOutBgs(seconds?: number): void;
|
|
170
|
+
/** the intended track with its live playhead, or the one an ME suspended */
|
|
171
|
+
currentTrack(kind: 'bgm' | 'bgs'): SavedBusTrack | null;
|
|
172
|
+
/** memorizes the playing BGM with its playhead; replay restores it */
|
|
173
|
+
saveBgm(): SavedBusTrack | null;
|
|
174
|
+
/** memorizes the playing BGS with its playhead; replay restores it */
|
|
175
|
+
saveBgs(): SavedBusTrack | null;
|
|
176
|
+
replayBgm(): Promise<void>;
|
|
177
|
+
replayBgs(): Promise<void>;
|
|
178
|
+
/**
|
|
179
|
+
* Plays a jingle once, suspending the BGM and resuming it where it left off when
|
|
180
|
+
* the jingle ends. A BGM started mid-jingle takes over instead of being resumed over.
|
|
181
|
+
*/
|
|
182
|
+
playMe(track: BusTrack): Promise<void>;
|
|
183
|
+
/** stops the jingle, resuming the suspended BGM unless told not to */
|
|
184
|
+
stopMe(resume?: boolean): void;
|
|
185
|
+
/** plays one overlapping sound effect */
|
|
186
|
+
playSe(track: BusTrack): Promise<void>;
|
|
187
|
+
stopSe(): void;
|
|
188
|
+
stopAll(): void;
|
|
189
|
+
/** plain-data bus state for saves and transfers */
|
|
190
|
+
snapshot(): BusSnapshot;
|
|
191
|
+
/** replays plain-data bus state, reloading every named track */
|
|
192
|
+
restore(state: BusSnapshot | null | undefined): void;
|
|
193
|
+
private static normalize;
|
|
194
|
+
private playLoop;
|
|
195
|
+
private stopMeNodes;
|
|
196
|
+
private finishMe;
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=Channels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Channels.d.ts","sourceRoot":"","sources":["../../src/audio/Channels.ts"],"names":[],"mappings":"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"}
|