@datamoc/mw_games 0.18.0 → 0.19.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 CHANGED
@@ -5,6 +5,19 @@ 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.19.0] - 2026-09-26
9
+
10
+ A game that plays five instruments no longer ships all 128: the audio module learns which
11
+ programs its MIDI files actually use and writes a smaller SoundFont carrying only those.
12
+
13
+ ### Added
14
+
15
+ - `audio.collectSoundFontUsage` lists the (bank, program) pairs scheduled notes request
16
+ across MIDI files, with drums mapped to bank 128 the way the renderer maps them.
17
+ - `audio.subsetSoundFont` writes a smaller, valid SoundFont 2 file carrying only the used
18
+ programs, with zones, ranges, tuning, envelopes and sample loops copied verbatim and
19
+ every index remapped, so a compiled game ships just the samples it plays.
20
+
8
21
  ## [0.18.0] - 2026-09-25
9
22
 
10
23
  ### Added
@@ -1,15 +1,4 @@
1
- /**
2
- * A SoundFont 2 reader: presets to instruments to sample zones, enough to play
3
- * General MIDI music with real samples. Supported: key and velocity ranges, root key
4
- * and tuning, sample loop modes, the volume envelope (attack, hold, decay, sustain,
5
- * release), pan and attenuation, with the global-zone and preset-plus-instrument
6
- * layering rules. Not supported: modulators, filters and LFOs, 24-bit samples, or
7
- * stereo-linked sample pairs beyond playing each side as its own mono voice.
8
- *
9
- * A SoundFont file is only data (recorded samples plus preset tables), so reading one
10
- * is ordinary format engineering; the licence that matters is the font's own, checked
11
- * before it ships, never here.
12
- */
1
+ import { type MidiFile } from './Midi.ts';
13
2
  /** one mono sample: raw frames plus its loop region in frames and native rate */
14
3
  export interface SoundFontSample {
15
4
  data: Float32Array;
@@ -45,6 +34,11 @@ export interface SoundFont {
45
34
  hasPreset(bank: number, program: number): boolean;
46
35
  readonly presetCount: number;
47
36
  }
37
+ /** one used program: the voice a game's MIDI files actually request */
38
+ export interface SoundFontProgram {
39
+ bank: number;
40
+ program: number;
41
+ }
48
42
  /**
49
43
  * Reads SoundFont 2 bytes into layered preset voices.
50
44
  *
@@ -61,4 +55,44 @@ export interface SoundFont {
61
55
  * ```
62
56
  */
63
57
  export declare function parseSoundFont(data: ArrayBuffer | ArrayBufferView): SoundFont;
58
+ /**
59
+ * Every sampled voice the given MIDI files can request, as (bank, program) pairs:
60
+ * the channel voice in effect at each scheduled note, with drums mapped to bank 128
61
+ * the same way the renderer maps them. A game's compile step feeds this straight
62
+ * into `subsetSoundFont` so the shipped font carries only these programs.
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * import { parseMidi, collectSoundFontUsage } from '@datamoc/mw_games/audio';
67
+ *
68
+ * declare const midiBytes: ArrayBuffer;
69
+ *
70
+ * const usage = collectSoundFontUsage([parseMidi(midiBytes)]);
71
+ * console.log(usage.length);
72
+ * ```
73
+ */
74
+ export declare function collectSoundFontUsage(files: readonly MidiFile[]): SoundFontProgram[];
75
+ /**
76
+ * Writes a smaller, valid SoundFont 2 file carrying only the used programs: their
77
+ * presets (names kept), instruments and samples, with zones, ranges, tuning,
78
+ * envelopes and sample loops copied verbatim and every index remapped. Zones that
79
+ * reference samples missing from the file (ROM samples) are dropped, matching what
80
+ * the reader voices for the full font; the library, genre and morphology metadata
81
+ * is zeroed and the INFO list, when present, rides along untouched. Modulator lists
82
+ * are emptied and 24-bit upper bits are dropped: the reader voices neither, so what
83
+ * it plays is unchanged, while a third-party player would miss those.
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * import { parseMidi, collectSoundFontUsage, subsetSoundFont } from '@datamoc/mw_games/audio';
88
+ *
89
+ * declare const midiBytes: ArrayBuffer;
90
+ * declare const soundfontBytes: ArrayBuffer;
91
+ *
92
+ * const usage = collectSoundFontUsage([parseMidi(midiBytes)]);
93
+ * const pruned = subsetSoundFont(soundfontBytes, usage);
94
+ * console.log(usage.length, pruned.byteLength);
95
+ * ```
96
+ */
97
+ export declare function subsetSoundFont(data: ArrayBuffer | ArrayBufferView, usage: readonly SoundFontProgram[]): ArrayBuffer;
64
98
  //# sourceMappingURL=SoundFont.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SoundFont.d.ts","sourceRoot":"","sources":["../../src/audio/SoundFont.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAoBH,iFAAiF;AACjF,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB;AAQD,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACzB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CAAC;IACvF,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAClD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC7B;AAmBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,eAAe,GAAG,SAAS,CA6L7E"}
1
+ {"version":3,"file":"SoundFont.d.ts","sourceRoot":"","sources":["../../src/audio/SoundFont.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAwCxD,iFAAiF;AACjF,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,wDAAwD;AACxD,MAAM,WAAW,cAAc;IAC9B,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACzB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CAAC;IACvF,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAClD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC7B;AAED,uEAAuE;AACvE,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CAChB;AAyMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,eAAe,GAAG,SAAS,CAkG7E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,GAAG,gBAAgB,EAAE,CAcpF;AA6CD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,eAAe,EAAE,KAAK,EAAE,SAAS,gBAAgB,EAAE,GAAG,WAAW,CAiOpH"}