audio-mixer-engine 1.1.6 → 1.3.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/README.md CHANGED
@@ -8,6 +8,7 @@ A part-centric JavaScript audio library for mixer applications. Provides individ
8
8
  - **MIDI processing**: Parse files, beat/bar mapping, tempo changes, metadata extraction
9
9
  - **Dual audio engines**: SpessaSynth (soundfont, ~10-50MB) or Lightweight (samples, ~574KB bundle)
10
10
  - **Playback control**: Metronome, lead-in, seeking, speed changes, bar navigation, real-time events
11
+ - **MusicXML support**: Load MusicXML/MXL files directly — repeats, voltas, jumps, lyrics, dynamics
11
12
  - **Mixer-ready**: Designed for solo/mute, routing, and level monitoring workflows
12
13
 
13
14
  ## Installation
@@ -63,6 +64,38 @@ for (const [partName, outputNode] of manager.getPartOutputs()) {
63
64
  await manager.play({ leadIn: true, metronome: true });
64
65
  ```
65
66
 
67
+ ### Loading MusicXML Files
68
+
69
+ PlaybackManager auto-detects MusicXML strings and MXL/ZIP ArrayBuffers:
70
+
71
+ ```javascript
72
+ import { loadMusicXml } from 'audio-mixer-engine';
73
+
74
+ // MXL file (ArrayBuffer) — auto-detected from ZIP magic bytes
75
+ await manager.load(mxlArrayBuffer);
76
+
77
+ // MusicXML string — auto-detected from <?xml or <score-partwise> prefix
78
+ const xmlString = await loadMusicXml(fileArrayBuffer);
79
+ await manager.load(xmlString);
80
+
81
+ // With metadata overrides (title, composer, per-part instrument mapping)
82
+ await manager.load(xmlString, metadataOverrides);
83
+
84
+ // From here on, playback works exactly the same as MIDI
85
+ await manager.play({ leadIn: true, metronome: true });
86
+ ```
87
+
88
+ You can also convert manually for more control:
89
+
90
+ ```javascript
91
+ import { MusicXmlConverter, loadMusicXml } from 'audio-mixer-engine';
92
+
93
+ const xmlString = await loadMusicXml(fileArrayBuffer);
94
+ const converter = new MusicXmlConverter();
95
+ const parsedData = converter.convert(xmlString, { defaultTempo: 120 }, metadataOverrides);
96
+ await manager.load(parsedData);
97
+ ```
98
+
66
99
  ## Key Concepts
67
100
 
68
101
  **Part-centric design**: Each musical part gets an independent `ChannelHandle` with its own `AudioNode` output. Your application connects these outputs to gain controls, analyzers, and effects.
@@ -80,8 +113,12 @@ await manager.play({ leadIn: true, metronome: true });
80
113
  ### PlaybackManager
81
114
 
82
115
  ```javascript
83
- // Lifecycle
84
- await manager.load(midiArrayBuffer, metadata, instrumentMap);
116
+ // Lifecycle — load() auto-detects input type
117
+ await manager.load(midiArrayBuffer); // MIDI ArrayBuffer
118
+ await manager.load(mxlArrayBuffer); // MXL/ZIP ArrayBuffer (auto-detected)
119
+ await manager.load(musicXmlString); // MusicXML string (auto-detected)
120
+ await manager.load(parsedData); // Pre-parsed data object
121
+ await manager.load(input, metadata, instrumentMap); // With optional overrides
85
122
  manager.reset();
86
123
 
87
124
  // Transport
@@ -198,6 +235,42 @@ audioEngine.allSoundsOff();
198
235
  audioEngine.destroy();
199
236
  ```
200
237
 
238
+ ### MusicXML Processing
239
+
240
+ ```javascript
241
+ import { MusicXmlConverter, loadMusicXml, loadMusicXmlSync } from 'audio-mixer-engine';
242
+
243
+ // Load from ArrayBuffer (MXL or plain XML)
244
+ const xmlString = await loadMusicXml(fileArrayBuffer);
245
+
246
+ // Or load synchronously when data is already available
247
+ const xmlString2 = loadMusicXmlSync(uint8ArrayData);
248
+
249
+ // Convert to parsedData (same format as MidiParser output)
250
+ const converter = new MusicXmlConverter();
251
+ const parsedData = converter.convert(xmlString, {
252
+ defaultTempo: 120, // Fallback tempo if none in score
253
+ defaultVelocity: 80 // Fallback note velocity
254
+ }, metadataOverrides); // Optional: override title, composer, per-part instruments
255
+
256
+ // parsedData includes parts, barStructure, metadata, and structureMetadata
257
+ // Use with PlaybackManager or MidiPlayer just like MIDI-parsed data
258
+ ```
259
+
260
+ ### Metadata Utilities
261
+
262
+ ```javascript
263
+ import { resolveInstrument, normalizeLegacyMetadata } from 'audio-mixer-engine';
264
+
265
+ // Map instrument names/numbers to MIDI program numbers
266
+ resolveInstrument('piano'); // 0
267
+ resolveInstrument('choir_aahs'); // 52
268
+ resolveInstrument(40); // 40
269
+
270
+ // Normalize legacy v1 metadata format to v2
271
+ const normalized = normalizeLegacyMetadata(legacyMetadata);
272
+ ```
273
+
201
274
  ## Mixer Example
202
275
 
203
276
  ```javascript
@@ -251,11 +324,13 @@ class AudioMixer {
251
324
 
252
325
  ## Additional Documentation
253
326
 
327
+ - **[MUSICXML.md](./MUSICXML.md)** - MusicXML/MXL file loading, supported elements, and API reference
254
328
  - **[LIGHTWEIGHT_ENGINE.md](./LIGHTWEIGHT_ENGINE.md)** - Lightweight engine setup and sample file configuration
255
329
  - **[METADATA.md](./METADATA.md)** - Score metadata, part configuration, and playback modifiers
256
330
  - **[BEATMAPPING.md](./BEATMAPPING.md)** - Beat mapping and non-linear playback structures
257
331
  - **[INTERFACE.md](./INTERFACE.md)** - Complete interface contract for UI integration
258
332
  - **[INIT_PROGRESS.md](./INIT_PROGRESS.md)** - Initialization progress tracking and best practices
333
+ - **[IOS_AUDIO_RESUMPTION.md](./IOS_AUDIO_RESUMPTION.md)** - Handling iOS screen lock/background audio suspension
259
334
 
260
335
  ## Development
261
336
 
@@ -281,3 +356,4 @@ MIT License - see LICENSE file for details.
281
356
 
282
357
  - **Chromium browsers** (Chrome, Edge, Brave): May experience audio distortion due to Web Audio API bugs
283
358
  - **Safari**: Should work with standard Web Audio API support
359
+ - **iOS Safari**: AudioContext is suspended on screen lock/app background. Consuming applications must handle resumption -- see [IOS_AUDIO_RESUMPTION.md](./IOS_AUDIO_RESUMPTION.md)