Skip to content

Commit 5a88f7c

Browse files
committed
Fix Audio SFX Copy JSON and align frequency handling with engine utility - PR_26145_002-audio-sfx-copy-json-and-frequency-engine-alignment
1 parent 7a56aa2 commit 5a88f7c

3 files changed

Lines changed: 162 additions & 8 deletions

File tree

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ docs/dev/reports/codex_review.diff
2828
docs/dev/reports/coverage_changed_js_guardrail.txt
2929
docs/dev/reports/playwright_v8_coverage_report.txt
3030

31-
3231
.npm-cache
32+
.ms-playwright
3333

34-
# Ignore media files
3534
*.mp4
3635
*.mkv
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Audio / SFX Playground V2 Copy JSON and Frequency Alignment Validation
2+
3+
PR: `PR_26145_002-audio-sfx-copy-json-and-frequency-engine-alignment`
4+
5+
Playwright impacted: Yes.
6+
7+
## Scope
8+
9+
- Fixed Audio / SFX Playground V2 Copy JSON to copy the current exported JSON payload through the Clipboard API when available.
10+
- Added a DOM copy fallback for browsers where `navigator.clipboard.writeText` is unavailable.
11+
- Added visible Status success and failure messages for Copy JSON.
12+
- Audited engine frequency usage for an existing shared frequency class.
13+
14+
## Frequency Audit
15+
16+
Found `src/engine/audio/FrequencyPlayer.js`.
17+
18+
Result:
19+
20+
- `FrequencyPlayer` is a sequence playback class that maps existing frequency values to `AudioService.playSequence`.
21+
- It does not provide frequency/cents conversion.
22+
- No shared engine frequency/cents conversion class was found.
23+
- No new frequency helper/model was added.
24+
- Audio / SFX Playground V2 continues to pass `frequencyHz` to `oscillator.frequency` and `pitchSweepCents` to Web Audio `detune`, preserving existing engine-native cents behavior.
25+
26+
## Targeted Validation
27+
28+
PASS: JavaScript syntax validation
29+
30+
Command:
31+
32+
```powershell
33+
Get-ChildItem -Recurse -File tools/audio-sfx-playground-v2/js -Filter *.js | ForEach-Object { node --check $_.FullName }
34+
```
35+
36+
PASS: HTML/CSS static validation
37+
38+
Checked Audio / SFX Playground V2 HTML/CSS for empty files, inline event handlers, `<style>` blocks, and inline `<script>` blocks.
39+
40+
PASS: Frequency helper duplication scan
41+
42+
Command:
43+
44+
```powershell
45+
rg "class .*Frequency|Frequency[A-Za-z]*|centsTo|frequencyTo|Math\.pow\(2" tools/audio-sfx-playground-v2 src/engine/audio -g "*.js" -g "*.mjs"
46+
```
47+
48+
The scan found the existing `FrequencyPlayer` and `MidiPlayer` note conversion only. No duplicate Audio / SFX frequency helper/model was introduced.
49+
50+
PASS: Targeted Node behavior validation
51+
52+
Validated with an inline Node module script:
53+
54+
- Copy JSON writes valid exported JSON through `navigator.clipboard.writeText`.
55+
- Copy JSON includes current `frequencyHz`.
56+
- Copy JSON includes current `pitchSweepCents`.
57+
- Copy JSON shows a visible success Status message.
58+
- DOM fallback copy selects the current exported JSON payload.
59+
- Missing Clipboard API and missing fallback command show visible, actionable failure.
60+
- Audio engine still reports an actionable Web Audio unavailable error when no audio context exists.
61+
62+
PASS: Targeted Playwright validation
63+
64+
Validated with a temporary local HTTP server and Chromium:
65+
66+
- Audio / SFX Playground V2 launched without console errors.
67+
- Copy JSON copied valid JSON.
68+
- Copied JSON referenced `tools/schemas/tools/audio-sfx-playground-v2.schema.json`.
69+
- Copied JSON included the current editor name.
70+
- Copied JSON included the current frequency value.
71+
- Copied JSON included the current cents sweep value.
72+
- Status showed copy success.
73+
- Forced clipboard-unavailable state showed visible copy failure.
74+
75+
PASS: Diff whitespace validation
76+
77+
Command:
78+
79+
```powershell
80+
git diff --check -- tools/audio-sfx-playground-v2 tools/schemas
81+
```
82+
83+
## Workspace V2 Validation
84+
85+
PARTIAL: `npm.cmd run test:workspace-v2`
86+
87+
Command:
88+
89+
```powershell
90+
$env:PLAYWRIGHT_BROWSERS_PATH='.ms-playwright'
91+
npm.cmd run test:workspace-v2
92+
```
93+
94+
Result:
95+
96+
- The Workspace V2 Playwright suite launched successfully with local Chromium.
97+
- The run timed out after 15 minutes at test 70 of 72.
98+
- 67 tests passed before timeout.
99+
- 3 unrelated tests were marked failed before timeout:
100+
- Input Mapping V2 column/live-highlight layout test.
101+
- Object Vector Studio V2 layout shell/schema-only palette gate test.
102+
- Object Vector Studio V2 compact geometry layout/selected palette state test.
103+
- The timeout/failures are outside the Audio / SFX Playground V2 Copy JSON and frequency alignment scope.
104+
105+
Expected Playwright pass behavior:
106+
107+
- Audio / SFX Playground V2 launches from Workspace V2 without console errors.
108+
- Copy JSON copies the current exported payload.
109+
- Copy success is visible in Status.
110+
- Copy failure is visible and actionable in Status.
111+
- Frequency and sweep values remain intact in copied/exported JSON.
112+
- No duplicate frequency helper/model is introduced.
113+
114+
Expected Playwright fail behavior:
115+
116+
- Fail if Copy JSON does not write valid JSON.
117+
- Fail if copied JSON omits current frequency or cents sweep values.
118+
- Fail if copy success/failure has no visible Status message.
119+
- Fail if a new competing frequency conversion helper/model appears.
120+
- Fail if console errors occur.
121+
122+
## Coverage
123+
124+
Playwright V8 coverage was not collected during the focused inline browser validation.
125+
126+
WARN: `tools/audio-sfx-playground-v2/js/AudioSfxPlaygroundV2App.js` - changed runtime JavaScript; coverage unavailable.
127+
128+
## Full Samples Smoke Test
129+
130+
Skipped. This PR only impacts Audio / SFX Playground V2 copy behavior and frequency utility alignment.

tools/audio-sfx-playground-v2/js/AudioSfxPlaygroundV2App.js

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -325,19 +325,44 @@ export class AudioSfxPlaygroundV2App {
325325
}
326326

327327
this.inspector.showObject(exportResult.toolState);
328-
if (typeof this.window.navigator?.clipboard?.writeText !== "function") {
329-
this.statusLog.error("Copy JSON failed: Clipboard API is unavailable.");
330-
return;
331-
}
332328

333329
try {
334-
await this.window.navigator.clipboard.writeText(exportResult.json);
335-
this.statusLog.write("JSON copied.");
330+
await this.writeClipboardText(exportResult.json);
331+
this.statusLog.write(`Copied JSON for ${activeSoundFromToolState(exportResult.toolState)?.name || "audio-sfx"}.`);
336332
} catch (error) {
337333
this.statusLog.error(`Copy JSON failed: ${error.message}`);
338334
}
339335
}
340336

337+
async writeClipboardText(text) {
338+
if (typeof this.window.navigator?.clipboard?.writeText === "function") {
339+
await this.window.navigator.clipboard.writeText(text);
340+
return;
341+
}
342+
343+
const documentRef = this.window.document;
344+
if (!documentRef?.body || typeof documentRef.execCommand !== "function") {
345+
throw new Error("Clipboard API is unavailable.");
346+
}
347+
348+
const textArea = documentRef.createElement("textarea");
349+
textArea.value = text;
350+
textArea.setAttribute("readonly", "");
351+
textArea.style.position = "fixed";
352+
textArea.style.left = "-9999px";
353+
textArea.style.top = "0";
354+
try {
355+
documentRef.body.append(textArea);
356+
textArea.focus();
357+
textArea.select();
358+
if (!documentRef.execCommand("copy")) {
359+
throw new Error("Browser copy command returned false.");
360+
}
361+
} finally {
362+
textArea.remove();
363+
}
364+
}
365+
341366
downloadJson(exportResult) {
342367
const documentRef = this.window.document;
343368
const BlobConstructor = this.window.Blob;

0 commit comments

Comments
 (0)