@mcptoolshop/claude-sfx 1.1.2 → 1.2.1

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
@@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.1] - 2026-03-30
11
+
12
+ ### Fixed
13
+ - **Windows audio playback** — use ffplay (ffmpeg) instead of PowerShell SoundPlayer, which silently failed on short audio clips. Falls back to PowerShell if ffplay is not installed.
14
+ - **Gain levels too low** — boosted all verb master gains from 0.16–0.20 to 0.50–0.60 so sounds are actually audible through system speakers
15
+
16
+ ## [1.2.0] - 2026-03-30
17
+
18
+ ### Changed
19
+ - **Complete sound redesign** — all verbs revoiced into A major pentatonic scale system
20
+ - **Multi-note motifs** replace single-tone beeps: each verb now has a 2–3 note melodic identity
21
+ - **3 variants per verb** with constrained micro-jitter (±5 cents pitch, ±6% duration, ±4ms onset) to reduce listener fatigue
22
+ - **Timbre separation** — intake uses sine/triangle blend, transform gets FM shimmer, commit has triangle/sine dyad + sparkle, navigate uses triangle radar chirp, execute sits in lower register with noise transient
23
+ - **Musical modifiers** — status:err drops the final note one scale degree instead of arbitrary pitch multiplication; status:warn uses gentler 5.5 Hz tremolo; status:ok adds a quiet perfect fifth
24
+ - **Intensity progression** (1–5) builds through harmonics → brighter intervals → FM shimmer → richer tail, NOT through loudness
25
+ - **Escalation progression** (1–5) darkens through lower register → detune → tremolo → heavy weight
26
+ - **Session sounds** now share the A major pentatonic grammar: start (A4→C#5), end (C#5→A4), fanfare (A4→C#5→E5)
27
+ - **Profile schema** updated: `MotifVerbConfig` with variant arrays replaces `ToneVerbConfig`; whoosh verbs gain `anchorVariants`
28
+ - Retro profile updated to match new architecture with square-wave motifs
29
+
30
+ ### Added
31
+ - `variantIndex` option in PlayOptions for deterministic testing
32
+ - `SCALE` constants and `scaleStepDown`/`findClosestScaleDegree` scale helpers exported from profiles
33
+ - Waveform blending (`blendWaveform`/`blendAmount`) on motif notes and chime tones
34
+ - `NoiseTransient` type for filtered percussive onsets (execute verb)
35
+ - `WhooshAnchorVariant` type for tonal anchors under whoosh verbs (move, sync)
36
+
10
37
  ## [1.1.2] - 2026-03-29
11
38
 
12
39
  ### Fixed
package/dist/player.js CHANGED
@@ -22,15 +22,25 @@ function getTempPath() {
22
22
  function getPlayCommand(filePath) {
23
23
  const platform = process.platform;
24
24
  if (platform === "win32") {
25
- // PowerShell SoundPlayersynchronous, reliable, built-in
26
- return {
27
- command: "powershell",
28
- args: [
29
- "-NoProfile",
30
- "-Command",
31
- `(New-Object Media.SoundPlayer '${filePath}').PlaySync()`,
32
- ],
33
- };
25
+ // Prefer ffplay (from ffmpeg) fast, reliable, no UI
26
+ try {
27
+ execSync("where ffplay", { stdio: "ignore" });
28
+ return {
29
+ command: "ffplay",
30
+ args: ["-nodisp", "-autoexit", "-loglevel", "quiet", filePath],
31
+ };
32
+ }
33
+ catch {
34
+ // Fallback: PowerShell SoundPlayer
35
+ return {
36
+ command: "powershell",
37
+ args: [
38
+ "-NoProfile",
39
+ "-Command",
40
+ `(New-Object Media.SoundPlayer '${filePath}').PlaySync()`,
41
+ ],
42
+ };
43
+ }
34
44
  }
35
45
  if (platform === "darwin") {
36
46
  return { command: "afplay", args: [filePath] };
@@ -2,47 +2,111 @@
2
2
  * Profile system — configurable sound palettes.
3
3
  * Each profile defines synthesis parameters for every verb + session sounds.
4
4
  * Profiles are JSON-serializable, so users can create their own.
5
+ *
6
+ * Sound design is rooted in A major pentatonic to ensure musical coherence.
5
7
  */
6
8
  import type { Waveform, Envelope } from "./synth.js";
7
- /** Synthesis params for a tone-based verb (intake, transform, commit, navigate, execute). */
8
- export interface ToneVerbConfig {
9
- type: "tone";
10
- waveform: Waveform;
9
+ export declare const SCALE: {
10
+ readonly A3: 220;
11
+ readonly B3: 246.94;
12
+ readonly Cs4: 277.18;
13
+ readonly E4: 329.63;
14
+ readonly Fs4: 369.99;
15
+ readonly A4: 440;
16
+ readonly B4: 493.88;
17
+ readonly Cs5: 554.37;
18
+ readonly E5: 659.25;
19
+ readonly Fs5: 739.99;
20
+ readonly A5: 880;
21
+ readonly B5: 987.77;
22
+ };
23
+ /** Ordered scale degrees for modifier lookups (low to high). */
24
+ export declare const SCALE_DEGREES: number[];
25
+ /** Get the next lower scale degree. Returns freq × 0.9 as fallback. */
26
+ export declare function scaleStepDown(freq: number): number;
27
+ /** Find the closest scale degree to a target frequency. */
28
+ export declare function findClosestScaleDegree(freq: number): number;
29
+ /** A single note within a motif. */
30
+ export interface MotifNote {
31
+ /** Frequency in Hz (should be a scale degree). */
11
32
  frequency: number;
12
- frequencyEnd?: number;
33
+ /** Duration in seconds. */
13
34
  duration: number;
35
+ /** Offset from motif start in milliseconds. Allows overlapping notes/chords. */
36
+ offsetMs: number;
37
+ /** Primary waveform. */
38
+ waveform: Waveform;
39
+ /** Optional secondary waveform for timbral blending. */
40
+ blendWaveform?: Waveform;
41
+ /** Blend amount 0–1 (proportion of blendWaveform vs primary). */
42
+ blendAmount?: number;
43
+ /** ADSR envelope. */
14
44
  envelope: Envelope;
45
+ /** Note gain relative to verb master gain (0–1). */
15
46
  gain: number;
47
+ /** FM modulator frequency ratio. */
16
48
  fmRatio?: number;
49
+ /** FM modulation depth in Hz. */
17
50
  fmDepth?: number;
51
+ /** Octave harmonic gain 0–1. */
18
52
  harmonicGain?: number;
19
- /** If true, mix a short noise burst underneath (execute verb). */
20
- noiseBurst?: {
21
- duration: number;
22
- gain: number;
23
- };
53
+ /** Tremolo rate in Hz (for warn modifier). */
54
+ tremoloRate?: number;
55
+ /** Tremolo depth 0–1. */
56
+ tremoloDepth?: number;
57
+ /** Detune in Hz (for err modifier / beating). */
58
+ detune?: number;
59
+ }
60
+ /** Optional filtered-noise transient (percussive onset for execute verb). */
61
+ export interface NoiseTransient {
62
+ /** Bandpass center start frequency. */
63
+ freqStart: number;
64
+ /** Bandpass center end frequency. */
65
+ freqEnd: number;
66
+ /** Filter Q (bandwidth). */
67
+ bandwidth: number;
68
+ /** Duration in seconds. */
69
+ duration: number;
70
+ /** Gain relative to verb master gain. */
71
+ gain: number;
72
+ }
73
+ /** A variant of a motif-based verb. */
74
+ export interface MotifVariant {
75
+ notes: MotifNote[];
76
+ noiseTransient?: NoiseTransient;
77
+ }
78
+ /** A tonal anchor variant for a whoosh verb. */
79
+ export interface WhooshAnchorVariant {
80
+ notes: MotifNote[];
81
+ }
82
+ /** Multi-note motif verb (intake, transform, commit, navigate, execute). */
83
+ export interface MotifVerbConfig {
84
+ type: "motif";
85
+ /** 3 variants for constrained variation. */
86
+ variants: MotifVariant[];
87
+ /** Master gain 0–1. */
88
+ gain: number;
24
89
  }
25
- /** Synthesis params for a whoosh-based verb (move, sync). */
90
+ /** Noise-sweep verb with tonal anchors (move, sync). */
26
91
  export interface WhooshVerbConfig {
27
92
  type: "whoosh";
93
+ /** Sweep duration in seconds. */
28
94
  duration: number;
29
- /** Freq pair for direction=up. [start, end] */
95
+ /** Noise sweep frequencies for upward direction [start, end]. */
30
96
  freqUp: [number, number];
31
- /** Freq pair for direction=down. [start, end] */
97
+ /** Noise sweep frequencies for downward direction [start, end]. */
32
98
  freqDown: [number, number];
99
+ /** Filter bandwidth (Q). */
33
100
  bandwidth: number;
101
+ /** Noise sweep envelope. */
34
102
  envelope: Envelope;
103
+ /** Master gain 0–1. */
35
104
  gain: number;
36
- /** Optional tonal anchor mixed underneath (sync verb). */
37
- tonalAnchor?: {
38
- freqUp: [number, number];
39
- freqDown: [number, number];
40
- envelope: Envelope;
41
- gain: number;
42
- };
105
+ /** Tonal anchor variants mixed under the whoosh. */
106
+ anchorVariants: WhooshAnchorVariant[];
43
107
  }
44
- export type VerbConfig = ToneVerbConfig | WhooshVerbConfig;
45
- /** A two-tone chime (session start/end). */
108
+ export type VerbConfig = MotifVerbConfig | WhooshVerbConfig;
109
+ /** A session chime (start/end). */
46
110
  export interface ChimeConfig {
47
111
  tone1: {
48
112
  waveform: Waveform;
@@ -51,6 +115,8 @@ export interface ChimeConfig {
51
115
  envelope: Envelope;
52
116
  gain: number;
53
117
  harmonicGain?: number;
118
+ blendWaveform?: Waveform;
119
+ blendAmount?: number;
54
120
  };
55
121
  tone2: {
56
122
  waveform: Waveform;
@@ -59,19 +125,21 @@ export interface ChimeConfig {
59
125
  envelope: Envelope;
60
126
  gain: number;
61
127
  harmonicGain?: number;
128
+ blendWaveform?: Waveform;
129
+ blendAmount?: number;
62
130
  };
63
131
  /** Offset in seconds before tone2 starts. */
64
132
  staggerSeconds: number;
65
133
  }
66
134
  /** Long-running ambient drone config. */
67
135
  export interface AmbientConfig {
68
- /** Low drone frequency */
136
+ /** Low drone frequency. */
69
137
  droneFreq: number;
70
138
  droneWaveform: Waveform;
71
139
  droneGain: number;
72
- /** Seconds per loop chunk (the drone is generated in chunks). */
140
+ /** Seconds per loop chunk. */
73
141
  chunkDuration: number;
74
- /** Resolution stinger: two ascending notes. */
142
+ /** Resolution stinger notes. */
75
143
  resolveNote1: number;
76
144
  resolveNote2: number;
77
145
  resolveWaveform: Waveform;