@map-audio/pam-mcp-server 1.21.0 → 1.25.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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +33 -7
  3. package/dist/audioAnalysis.d.ts +35 -0
  4. package/dist/audioAnalysis.js +277 -0
  5. package/dist/audioAnalysis.js.map +1 -0
  6. package/dist/bridge.d.ts +6 -0
  7. package/dist/bridge.js +151 -168
  8. package/dist/bridge.js.map +1 -1
  9. package/dist/corpusFingerprints.d.ts +17 -0
  10. package/dist/corpusFingerprints.js +10 -0
  11. package/dist/corpusFingerprints.js.map +1 -0
  12. package/dist/corpusRanges.d.ts +28 -0
  13. package/dist/corpusRanges.js +1029 -0
  14. package/dist/corpusRanges.js.map +1 -0
  15. package/dist/drumSynthEngines.json +376 -0
  16. package/dist/fingerprint.d.ts +70 -0
  17. package/dist/fingerprint.js +240 -0
  18. package/dist/fingerprint.js.map +1 -0
  19. package/dist/generated/variationSnapshot.d.ts +8 -4
  20. package/dist/generated/variationSnapshot.js +6 -4
  21. package/dist/generated/variationSnapshot.js.map +1 -1
  22. package/dist/generativePlayerPresets.json +70 -0
  23. package/dist/generativePlayers.json +134 -0
  24. package/dist/manifest-cell1.json +4972 -249
  25. package/dist/manifest-mfx.json +11571 -1800
  26. package/dist/manifest.d.ts +15 -3
  27. package/dist/manifest.js +24 -15
  28. package/dist/manifest.js.map +1 -1
  29. package/dist/manifest.json +25034 -499
  30. package/dist/mfxCombos.d.ts +45 -0
  31. package/dist/mfxCombos.js +499 -0
  32. package/dist/mfxCombos.js.map +1 -0
  33. package/dist/midiFile.d.ts +21 -0
  34. package/dist/midiFile.js +108 -0
  35. package/dist/midiFile.js.map +1 -0
  36. package/dist/mixAssist.d.ts +6 -0
  37. package/dist/mixAssist.js +96 -11
  38. package/dist/mixAssist.js.map +1 -1
  39. package/dist/players.d.ts +89 -0
  40. package/dist/players.js +235 -0
  41. package/dist/players.js.map +1 -0
  42. package/dist/presetSave.d.ts +5 -0
  43. package/dist/presetSave.js +22 -0
  44. package/dist/presetSave.js.map +1 -1
  45. package/dist/productProfile.d.ts +9 -0
  46. package/dist/productProfile.js +20 -0
  47. package/dist/productProfile.js.map +1 -0
  48. package/dist/sampleSlicing.d.ts +12 -0
  49. package/dist/sampleSlicing.js +78 -0
  50. package/dist/sampleSlicing.js.map +1 -0
  51. package/dist/server.js +2536 -483
  52. package/dist/server.js.map +1 -1
  53. package/dist/variationSessionKeys.json +34 -1
  54. package/package.json +11 -5
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Can Ince
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -6,7 +6,7 @@ MCP server for the [PAM](https://map.audio) audio plugin. Lets AI agents (Claude
6
6
 
7
7
  - macOS or Windows with **Node.js 21+** (`node --version`)
8
8
  - **PAM** installed and running (standalone or in a DAW)
9
- - **MCP Bridge enabled** inside PAM: `Settings → Experimental Mode → MCP Bridge` (default port `9847`)
9
+ - **MCP Bridge enabled** inside PAM: `Settings → Experimental → Beta Features → Enable MCP Bridge` (default port `9847`)
10
10
 
11
11
  When PAM starts with the bridge enabled it writes `~/.pam-mcp-bridge.json` — the server discovers PAM through that file, so nothing else needs configuring.
12
12
 
@@ -70,20 +70,21 @@ Use the same `mcpServers` block in the client's MCP config. Any stdio-compatible
70
70
 
71
71
  ## Troubleshooting
72
72
 
73
- - **"Not connected to PAM plugin"** — PAM isn't running, or MCP Bridge is off. Open PAM → Settings → Experimental Mode → enable MCP Bridge, then restart PAM.
73
+ - **"Not connected to PAM plugin"** — PAM isn't running, or MCP Bridge is off. Open Settings → Experimental, turn on Beta Features, then Enable MCP Bridge. The bridge starts immediately.
74
74
  - **"Failed to connect" / `pam-mcp: command not found`** — the MCP client's shell PATH doesn't include the npm global bin. Run `which pam-mcp` in a terminal and use the absolute path it prints (e.g. `/Users/you/.nvm/versions/node/v22/bin/pam-mcp`) as the `command` value in your config. macOS GUI apps don't inherit shell PATH from `~/.zshrc`/`~/.bashrc`, so absolute paths are the safest fallback.
75
75
  - **`npx: command not found`** (if you're using the npx form) — same root cause: install Node from [nodejs.org](https://nodejs.org) (not via `nvm`/`asdf`), or give the absolute path: `"command": "/usr/local/bin/npx"` / `"/opt/homebrew/bin/npx"`.
76
76
  - **Offline tools fail** (`list_presets`, `get_parameter_info`) — the manifest bundled with the package is used automatically. To target a different PAM install, set `PAM_MANIFEST_PATH` in the server's `env` block.
77
77
 
78
78
  ## What's in the box
79
79
 
80
- ~145 tools. The high-value entry points:
80
+ The main entry points:
81
81
 
82
82
  - **Read first**: `design_context` (curated parameter cheat sheet, works offline) and `get_design_overview` (compact live snapshot). Prefer these over full `get_state` dumps or broad `get_parameter_info` sweeps.
83
- - **Sound design**: `set_parameters`, `update_pattern`, `add_modulation` / `add_param_seq`, `update_effect_config`, `set_master_effects`, `set_drum_synth`, `randomize` / `randomize_samples` / `randomize_patterns`.
84
- - **Samples**: `get_default_locations` → `list_samples` → `load_sample`, plus `trim/reverse/gain/normalize_sample`, `analyze_sample_tempo`, `resample_sample_to_bpm`, `build_sample_chain`.
83
+ - **Sound design**: `set_parameters`, `update_pattern`, `add_modulation` / `add_param_seq` / `set_free_sequencer`, `update_effect_config`, `set_master_effects`, `set_drum_synth`, `randomize` / `randomize_samples` / `randomize_patterns`.
84
+ - **Generative players** (PAM): `list_players` → `set_player` — arm EUCLID / KIT / TURING / WALK / MARKOV / RATCHET / PHASE / RIFF / MASK on a cell with curated presets, genre, seed, Mask/Keep and ensemble listening; `'off'` restores the drawn pattern.
85
+ - **Samples**: `get_default_locations` → `list_samples` → `load_sample`, plus `set_slices` (equal / explicit / transient, with slice-to-sequence), `trim/reverse/gain/normalize_sample`, `analyze_sample_tempo`, `resample_sample_to_bpm`, `build_sample_chain`.
85
86
  - **Transport, MIDI & devices**: `start_transport` / `stop_transport` / `full_stop_transport`, `set_bpm`, `trigger_midi` (+ CC / program change), `midi_recording`; `get_audio_device_setup` / `set_audio_device` / `set_midi_io` (standalone).
86
- - **Presets, variations & songs**: `load_preset` / `save_preset` / `new_preset`, `save_variation` / `load_variation` / `queue_variation`, `song_mode`, `export_song` (full-track bounce), `export_audio` (incl. per-cell stems).
87
+ - **Presets, variations & songs**: `load_preset` / `save_preset` / `new_preset`, `save_variation` / `load_variation` / `queue_variation`, `song_mode`, `export_song` (full-track bounce), `export_audio` (incl. per-cell stems), `export_midi` (patterns as a Standard MIDI File).
87
88
  - **Looper**: full 8-track control — arm/record/capture, `load_audio_to_looper_track`, warp, looper variations, `live_resample`.
88
89
  - **Plugin host** (PAM builds with hosting): `scan_plugins` → `get_plugin_scan_status` → `list_plugins` → `load_plugin` → `list_loaded_plugins` → `set_plugin_param` / `set_plugin_bypass`.
89
90
  - **AI models & generation** (experimental flags required): `download_model` / `load_model` / `get_model_status` / `list_models` (engines: aigen, magenta, notochord), `generate_sample`, `generate_kit`.
@@ -92,7 +93,7 @@ Use the same `mcpServers` block in the client's MCP config. Any stdio-compatible
92
93
 
93
94
  - **MFX**: `set_mfx_routing` reads and replaces the cable patch (`input` / `sidechain` → `cellN` → `output`). MFX-only; it errors on PAM and CELL1.
94
95
 
95
- All three product manifests (PAM / CELL1 / MFX) are bundled; the server auto-selects by the connected instance's product, so one config entry drives all three products. Preset listing follows that product too — each has its own tree under `MAP Audio`.
96
+ All three product manifests (PAM / CELL1 / MFX) are bundled; this generic server auto-selects by the connected instance's product, so one development config entry can drive all three products. Preset listing follows that product too — each has its own tree under `MAP Audio`. For a customer-facing MFX-only namespace, use `@map-audio/mfx-mcp-server`; it pins MFX discovery and removes unrelated sampler workflows from tool discovery.
96
97
 
97
98
  ## Agent ergonomics
98
99
 
@@ -100,6 +101,31 @@ All three product manifests (PAM / CELL1 / MFX) are bundled; the server auto-sel
100
101
  - **Structured output.** The status tools (`connection_status`, `select_instance`, `get_transport`, `get_manifest_summary`, `get_model_status`, `get_plugin_scan_status`, `workbench_sidecar_status`) return `structuredContent` with a declared output schema, alongside the same JSON as text.
101
102
  - **Prompts.** Five guided workflows ship as MCP prompts: `build-a-beat`, `make-a-song`, `design-a-preset`, `mix-and-master`, `troubleshoot-bridge`. In Claude Code they appear as slash commands (e.g. `/pam:build-a-beat`).
102
103
  - **Multiple instances.** When several products run at once (say PAM and MFX), `select_instance` picks which one the live tools drive, matched by product name, instanceId, or port. Setting `PAM_BRIDGE_PRODUCT=MFX` in the server's `env` block pins the choice at launch. Offline parameter validation follows the selected product's manifest.
104
+ Reconnection stays on the selected instance; if it disappears, select another explicitly. Repeating the same selection preserves pending commands.
105
+
106
+ ## Preset loading and queued operations
107
+
108
+ Server 1.24.0 adds tracked preset loading. `load_preset` returns a `requestId` and
109
+ `status: "queued"`; poll `get_preset_load_status` on the same instance until it returns
110
+ `succeeded` before editing or saving. Other outcomes are `morphing`, `failed`, `cancelled`,
111
+ and `superseded`. `immediate: true` bypasses the native preset morph. The plugin must
112
+ include the matching native bridge actions; updating the npm server alone does not add them.
113
+
114
+ Randomizer replies acknowledge queued work. Poll the affected sample paths or patterns
115
+ with `get_state` before the next operation. Requests can coalesce, and a preset or
116
+ variation load can discard pending randomization. Use `randomize` with `target: "full"`
117
+ to chain samples and patterns. `lfos` and `mods` are global targets and reject `cellIds`.
118
+
119
+ `queue_variation` inherits native fade and phase settings when those options are omitted.
120
+ Song Mode accepts stagger and stepped-relation fields inside `transition.window` on
121
+ sections, connections, and song defaults; `setArrangement` verifies its command acknowledgment.
122
+
123
+ ## Preset saving
124
+
125
+ Preset saves preserve the source variation bank, including Unicode metadata. Named saves
126
+ carry that bank into their destination; unnamed saves update the active user preset. Saves
127
+ stop if that source is missing, unreadable, or malformed. After New / Init, give
128
+ `save_preset` or `save_variation` a name before saving.
103
129
 
104
130
  ## License
105
131
 
@@ -0,0 +1,35 @@
1
+ export type WavData = {
2
+ sampleRate: number;
3
+ channels: number;
4
+ /** Mono mix, -1..1. */
5
+ samples: Float32Array;
6
+ durationSeconds: number;
7
+ };
8
+ /** Minimal RIFF/WAVE reader — PCM 16/24/32-bit and 32-bit float, which covers
9
+ * everything PAM's exporters write. Chunks are walked rather than assumed at
10
+ * fixed offsets (exporters interleave LIST/fact chunks). */
11
+ export declare function decodeWav(buf: Buffer): WavData;
12
+ export type MotionMetrics = {
13
+ durationSeconds: number;
14
+ silent: boolean;
15
+ peak: number;
16
+ rmsDb: number;
17
+ /** Spectral flux: how much the spectrum changes frame to frame. */
18
+ fluxMean: number;
19
+ fluxVariability: number;
20
+ /** Brightness wander over the whole file. */
21
+ centroidHzMean: number;
22
+ centroidVariability: number;
23
+ /** Per-bar aggregates — the timescale a listener actually tracks. */
24
+ bars: number | null;
25
+ perBarCentroidVariability: number | null;
26
+ perBarRmsVariability: number | null;
27
+ /** Level movement WITHIN a bar, averaged over bars. Between-bar variance
28
+ * alone misses a bar-synced tremolo, gate or sidechain pump: every bar is
29
+ * identical, so the whole GROOVE layer reads as static without this. */
30
+ intraBarRmsVariability: number | null;
31
+ /** True when nothing meaningfully changes across the file. */
32
+ static: boolean;
33
+ notes: string[];
34
+ };
35
+ export declare function analyzeMotion(wav: WavData, bpm?: number): MotionMetrics;
@@ -0,0 +1,277 @@
1
+ // Time-domain / spectral motion analysis over rendered WAV files.
2
+ //
3
+ // WHY: the only audio feedback the MCP exposed was loudness and balance
4
+ // (get_master_analysis: LUFS/peak/crest; get_mix_analysis: an aggregate Bark
5
+ // spectrum and onset density). Both answer "is it mixed?". Neither answers
6
+ // "does it MOVE?", which is the property that separates a preset from a sample
7
+ // player — so nothing in the design loop ever optimized for it.
8
+ //
9
+ // Everything here is pure Node over a decoded WAV: no C++ change, no plugin
10
+ // connection, and it works on any file the render path produced.
11
+ /** Minimal RIFF/WAVE reader — PCM 16/24/32-bit and 32-bit float, which covers
12
+ * everything PAM's exporters write. Chunks are walked rather than assumed at
13
+ * fixed offsets (exporters interleave LIST/fact chunks). */
14
+ export function decodeWav(buf) {
15
+ if (buf.length < 12 || buf.toString("ascii", 0, 4) !== "RIFF" || buf.toString("ascii", 8, 12) !== "WAVE") {
16
+ throw new Error("Not a RIFF/WAVE file");
17
+ }
18
+ let pos = 12;
19
+ let fmt = null;
20
+ let dataStart = -1;
21
+ let dataLen = 0;
22
+ while (pos + 8 <= buf.length) {
23
+ const id = buf.toString("ascii", pos, pos + 4);
24
+ const size = buf.readUInt32LE(pos + 4);
25
+ const body = pos + 8;
26
+ if (id === "fmt ") {
27
+ fmt = {
28
+ audioFormat: buf.readUInt16LE(body),
29
+ channels: buf.readUInt16LE(body + 2),
30
+ sampleRate: buf.readUInt32LE(body + 4),
31
+ bitsPerSample: buf.readUInt16LE(body + 14),
32
+ };
33
+ }
34
+ else if (id === "data") {
35
+ dataStart = body;
36
+ // A streaming writer can leave size at 0 or 0xFFFFFFFF; fall back to the
37
+ // rest of the file rather than decoding nothing.
38
+ dataLen = size === 0 || body + size > buf.length ? buf.length - body : size;
39
+ }
40
+ pos = body + size + (size % 2); // chunks are word-aligned
41
+ if (fmt && dataStart >= 0 && pos >= buf.length)
42
+ break;
43
+ }
44
+ if (!fmt || dataStart < 0)
45
+ throw new Error("WAV missing fmt or data chunk");
46
+ const { channels, sampleRate, bitsPerSample, audioFormat } = fmt;
47
+ const bytesPerSample = bitsPerSample / 8;
48
+ const frames = Math.floor(dataLen / (bytesPerSample * channels));
49
+ const out = new Float32Array(frames);
50
+ const readOne = (off) => {
51
+ if (audioFormat === 3 && bitsPerSample === 32)
52
+ return buf.readFloatLE(off);
53
+ if (bitsPerSample === 16)
54
+ return buf.readInt16LE(off) / 32768;
55
+ if (bitsPerSample === 24) {
56
+ const v = buf.readUInt8(off) | (buf.readUInt8(off + 1) << 8) | (buf.readInt8(off + 2) << 16);
57
+ return v / 8388608;
58
+ }
59
+ if (bitsPerSample === 32)
60
+ return buf.readInt32LE(off) / 2147483648;
61
+ if (bitsPerSample === 8)
62
+ return (buf.readUInt8(off) - 128) / 128;
63
+ throw new Error(`Unsupported WAV format: ${bitsPerSample}-bit, format ${audioFormat}`);
64
+ };
65
+ for (let f = 0; f < frames; f += 1) {
66
+ let acc = 0;
67
+ const base = dataStart + f * bytesPerSample * channels;
68
+ for (let c = 0; c < channels; c += 1)
69
+ acc += readOne(base + c * bytesPerSample);
70
+ out[f] = acc / channels;
71
+ }
72
+ return { sampleRate, channels, samples: out, durationSeconds: frames / sampleRate };
73
+ }
74
+ /** In-place iterative radix-2 FFT. Size must be a power of two. */
75
+ function fft(re, im) {
76
+ const n = re.length;
77
+ for (let i = 1, j = 0; i < n; i += 1) {
78
+ let bit = n >> 1;
79
+ for (; j & bit; bit >>= 1)
80
+ j ^= bit;
81
+ j ^= bit;
82
+ if (i < j) {
83
+ [re[i], re[j]] = [re[j], re[i]];
84
+ [im[i], im[j]] = [im[j], im[i]];
85
+ }
86
+ }
87
+ for (let len = 2; len <= n; len <<= 1) {
88
+ const ang = (-2 * Math.PI) / len;
89
+ const wr = Math.cos(ang);
90
+ const wi = Math.sin(ang);
91
+ for (let i = 0; i < n; i += len) {
92
+ let cr = 1;
93
+ let ci = 0;
94
+ for (let k = 0; k < len / 2; k += 1) {
95
+ const ur = re[i + k];
96
+ const ui = im[i + k];
97
+ const vr = re[i + k + len / 2] * cr - im[i + k + len / 2] * ci;
98
+ const vi = re[i + k + len / 2] * ci + im[i + k + len / 2] * cr;
99
+ re[i + k] = ur + vr;
100
+ im[i + k] = ui + vi;
101
+ re[i + k + len / 2] = ur - vr;
102
+ im[i + k + len / 2] = ui - vi;
103
+ const nr = cr * wr - ci * wi;
104
+ ci = cr * wi + ci * wr;
105
+ cr = nr;
106
+ }
107
+ }
108
+ }
109
+ }
110
+ const FFT_SIZE = 1024;
111
+ const HOP = 512;
112
+ function spectralFrames(samples, sampleRate) {
113
+ const window = new Float64Array(FFT_SIZE);
114
+ for (let i = 0; i < FFT_SIZE; i += 1)
115
+ window[i] = 0.5 - 0.5 * Math.cos((2 * Math.PI * i) / (FFT_SIZE - 1));
116
+ const mag = [];
117
+ const times = [];
118
+ for (let start = 0; start + FFT_SIZE <= samples.length; start += HOP) {
119
+ const re = new Float64Array(FFT_SIZE);
120
+ const im = new Float64Array(FFT_SIZE);
121
+ for (let i = 0; i < FFT_SIZE; i += 1)
122
+ re[i] = samples[start + i] * window[i];
123
+ fft(re, im);
124
+ const half = FFT_SIZE / 2;
125
+ const m = new Float64Array(half);
126
+ for (let i = 0; i < half; i += 1)
127
+ m[i] = Math.hypot(re[i], im[i]);
128
+ mag.push(m);
129
+ times.push(start / sampleRate);
130
+ }
131
+ return { mag, times };
132
+ }
133
+ const mean = (a) => (a.length ? a.reduce((x, y) => x + y, 0) / a.length : 0);
134
+ const stdev = (a) => {
135
+ if (a.length < 2)
136
+ return 0;
137
+ const m = mean(a);
138
+ return Math.sqrt(mean(a.map((x) => (x - m) ** 2)));
139
+ };
140
+ /** Coefficient of variation — a scale-free "how much does this wander" number,
141
+ * so a quiet part and a loud part are judged the same way. */
142
+ const cv = (a) => {
143
+ const m = mean(a);
144
+ return m > 1e-9 ? stdev(a) / m : 0;
145
+ };
146
+ export function analyzeMotion(wav, bpm) {
147
+ const { samples, sampleRate } = wav;
148
+ let peak = 0;
149
+ let sumSq = 0;
150
+ for (let i = 0; i < samples.length; i += 1) {
151
+ const a = Math.abs(samples[i]);
152
+ if (a > peak)
153
+ peak = a;
154
+ sumSq += samples[i] * samples[i];
155
+ }
156
+ const rms = samples.length ? Math.sqrt(sumSq / samples.length) : 0;
157
+ const notes = [];
158
+ // Digital silence is the documented standalone offline-render failure, not a
159
+ // musical result — say so rather than reporting "no motion".
160
+ if (peak < 1e-5) {
161
+ return {
162
+ durationSeconds: wav.durationSeconds,
163
+ silent: true,
164
+ peak,
165
+ rmsDb: -Infinity,
166
+ fluxMean: 0,
167
+ fluxVariability: 0,
168
+ centroidHzMean: 0,
169
+ centroidVariability: 0,
170
+ bars: null,
171
+ perBarCentroidVariability: null,
172
+ perBarRmsVariability: null,
173
+ intraBarRmsVariability: null,
174
+ static: true,
175
+ notes: [
176
+ "The render is digital silence — every sample is zero. This is a render failure, not a static preset.",
177
+ "Known cause: offline export in the STANDALONE build produces silence. Capture with live_resample (source 'fullmix') while the transport rolls, or render from a plugin host instead.",
178
+ ],
179
+ };
180
+ }
181
+ const { mag, times } = spectralFrames(samples, sampleRate);
182
+ if (mag.length < 4) {
183
+ notes.push("Render too short to measure motion — need at least ~0.05 s of audio.");
184
+ }
185
+ const flux = [];
186
+ const centroid = [];
187
+ const frameRms = [];
188
+ const binHz = sampleRate / FFT_SIZE;
189
+ for (let f = 0; f < mag.length; f += 1) {
190
+ const m = mag[f];
191
+ let num = 0;
192
+ let den = 0;
193
+ let energy = 0;
194
+ for (let i = 0; i < m.length; i += 1) {
195
+ num += i * binHz * m[i];
196
+ den += m[i];
197
+ energy += m[i] * m[i];
198
+ }
199
+ centroid.push(den > 1e-9 ? num / den : 0);
200
+ frameRms.push(Math.sqrt(energy / m.length));
201
+ if (f > 0) {
202
+ const prev = mag[f - 1];
203
+ let d = 0;
204
+ // Half-wave rectified: only rising energy counts, which is what an onset
205
+ // or a filter opening looks like.
206
+ for (let i = 0; i < m.length; i += 1) {
207
+ const diff = m[i] - prev[i];
208
+ if (diff > 0)
209
+ d += diff;
210
+ }
211
+ flux.push(d);
212
+ }
213
+ }
214
+ let bars = null;
215
+ let perBarCentroidVariability = null;
216
+ let perBarRmsVariability = null;
217
+ let intraBarRmsVariability = null;
218
+ if (bpm && bpm > 0) {
219
+ const barSeconds = (60 / bpm) * 4;
220
+ bars = Math.floor(wav.durationSeconds / barSeconds);
221
+ if (bars >= 2) {
222
+ const barCentroid = [];
223
+ const barRms = [];
224
+ const withinBar = [];
225
+ for (let b = 0; b < bars; b += 1) {
226
+ const lo = b * barSeconds;
227
+ const hi = lo + barSeconds;
228
+ const idx = times.map((t, i) => ({ t, i })).filter(({ t }) => t >= lo && t < hi).map(({ i }) => i);
229
+ if (!idx.length)
230
+ continue;
231
+ barCentroid.push(mean(idx.map((i) => centroid[i])));
232
+ barRms.push(mean(idx.map((i) => frameRms[i])));
233
+ withinBar.push(cv(idx.map((i) => frameRms[i])));
234
+ }
235
+ perBarCentroidVariability = Math.round(cv(barCentroid) * 10000) / 10000;
236
+ perBarRmsVariability = Math.round(cv(barRms) * 10000) / 10000;
237
+ intraBarRmsVariability = Math.round(mean(withinBar) * 10000) / 10000;
238
+ }
239
+ else {
240
+ notes.push(`Only ${bars} full bar(s) at ${bpm} BPM — per-bar motion needs at least 2. Render longer.`);
241
+ }
242
+ }
243
+ else {
244
+ notes.push("No bpm supplied, so per-bar motion was not computed. Pass bpm for the timescale a listener tracks.");
245
+ }
246
+ const fluxVariability = Math.round(cv(flux) * 10000) / 10000;
247
+ const centroidVariability = Math.round(cv(centroid) * 10000) / 10000;
248
+ // Thresholds are deliberately loose — this flags "nothing happens", it does
249
+ // not grade musicality. A sustained pad legitimately scores low on flux but
250
+ // should still wander in centroid or per-bar level if anything modulates it.
251
+ const isStatic = centroidVariability < 0.05 &&
252
+ (perBarCentroidVariability === null || perBarCentroidVariability < 0.02) &&
253
+ (perBarRmsVariability === null || perBarRmsVariability < 0.05) &&
254
+ // A bar-synced gate/tremolo/pump makes every bar identical, so it only
255
+ // shows up inside the bar.
256
+ (intraBarRmsVariability === null || intraBarRmsVariability < 0.15);
257
+ if (isStatic) {
258
+ notes.push("Nothing changes measurably over time: brightness and per-bar level are both flat. Either no modulation reached an audible target, or its depth is too low to hear.");
259
+ }
260
+ return {
261
+ durationSeconds: Math.round(wav.durationSeconds * 1000) / 1000,
262
+ silent: false,
263
+ peak: Math.round(peak * 10000) / 10000,
264
+ rmsDb: Math.round(20 * Math.log10(Math.max(rms, 1e-12)) * 10) / 10,
265
+ fluxMean: Math.round(mean(flux) * 100) / 100,
266
+ fluxVariability,
267
+ centroidHzMean: Math.round(mean(centroid)),
268
+ centroidVariability,
269
+ bars,
270
+ perBarCentroidVariability,
271
+ perBarRmsVariability,
272
+ intraBarRmsVariability,
273
+ static: isStatic,
274
+ notes,
275
+ };
276
+ }
277
+ //# sourceMappingURL=audioAnalysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audioAnalysis.js","sourceRoot":"","sources":["../src/audioAnalysis.ts"],"names":[],"mappings":"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"}
package/dist/bridge.d.ts CHANGED
@@ -22,15 +22,21 @@ export declare class PluginBridge {
22
22
  private pending;
23
23
  private connected;
24
24
  private connectedInstance;
25
+ private selectedTarget;
26
+ private connecting;
27
+ private connectionGeneration;
25
28
  discover(): Promise<BridgeInfo[]>;
26
29
  private static matchesTarget;
27
30
  connect(target?: ConnectTarget): Promise<boolean>;
31
+ private connectTo;
28
32
  disconnect(): void;
29
33
  isConnected(): boolean;
30
34
  /** The discovery entry of the instance this bridge is connected to, if known. */
31
35
  getConnectedInstance(): BridgeInfo | null;
32
36
  private static readonly SLOW_ACTIONS;
33
37
  private static readonly VERY_SLOW_ACTIONS;
38
+ private static readonly ACTION_TIMEOUTS_MS;
39
+ private static timeoutFor;
34
40
  send(action: string, ...args: unknown[]): Promise<unknown>;
35
41
  private translateBridgeError;
36
42
  private processBuffer;