File size: 10,478 Bytes
b2e4883
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# 05 β€” Accessibility Strategy

## Why this isn't an afterthought

PatternTalk's founder runs [Narwall.tech](https://narwall.tech), an accessibility testing tool that uses a real screenreader to find compliance gaps. The hackathon's Accessibility & Inclusion theme is listed as a first-class track. The target users include blind and visually impaired producers, a population currently locked out of almost every AI music tool.

So accessibility is **load-bearing**, not a checklist. The voice-first design (see [`04-ux-voice-first.md`](04-ux-voice-first.md)) was driven by accessibility, not the other way around.

## Principles

1. **Test with real assistive technology, not just linters.** axe-core catches ~30% of issues. NVDA and VoiceOver catch the rest.
2. **Voice-first is screenreader-first.** Building the voice layer well means the screenreader layer works for free.
3. **Every action has a keyboard equivalent.** No mouse-only paths.
4. **Every pattern has a textual description.** Not an afterthought caption β€” the description is the data.
5. **No information conveyed by color alone.** The visual grid uses size, position, and label too.
6. **Works at 200% zoom and at high contrast.** Tested with Windows High Contrast Mode.

## Standards we comply with

- **WCAG 2.2 AA** as the floor. AAA where feasible.
- **WAI-ARIA 1.2** for semantic structure.
- **Section 508** (US federal) β€” implicit via WCAG.
- **EN 301 549** (EU) β€” implicit via WCAG.
- **VPAT 2.4** β€” generated for the demo.

## Screenreader support

### Tested screenreaders

| Screenreader | OS | Browser | Status |
|---|---|---|---|
| NVDA 2024.x | Windows | Firefox + Chrome | Primary test target |
| VoiceOver | macOS | Safari | Primary test target |
| JAWS 2024 | Windows | Chrome | Stretch target |
| TalkBack | Android | Chrome | Post-hackathon |
| VoiceOver | iOS | Safari | Post-hackathon |

### Test cadence

- **Before each commit to `main`** that touches the UI: axe-core in CI blocks on AA violations
- **Once per day during the hackathon**: manual NVDA run-through of the full flow
- **Before demo**: NVDA + VoiceOver run-through, both screenshare-able

## Keyboard navigation

Every interactive element is reachable via Tab. Focus order matches visual order. Focus is always visible (high-contrast outline).

```css
:focus-visible {
  outline: 3px solid var(--focus-color, #FFD700);
  outline-offset: 2px;
}
```

Skip links for repeated UI:

```html
<a href="#main-content" class="skip-link">Skip to main content</a>
<a href="#pattern-grid" class="skip-link">Skip to pattern grid</a>
<a href="#controls" class="skip-link">Skip to controls</a>
```

### Roving tabindex for the visual grid

The grid is a 2D structure. Arrow keys navigate within it; Tab enters/exits.

```typescript
function onGridKeydown(e: KeyboardEvent, row: number, col: number) {
  switch (e.key) {
    case "ArrowRight": moveFocus(row, col + 1); break;
    case "ArrowLeft":  moveFocus(row, col - 1); break;
    case "ArrowDown":  moveFocus(row + 1, col); break;
    case "ArrowUp":    moveFocus(row - 1, col); break;
    case "Home":       moveFocus(row, 0); break;
    case "End":        moveFocus(row, lastCol); break;
    case "Enter":      announceCurrentCell(); break;
  }
}
```

## Voice interaction as accessibility

### How voice maps to screenreaders

When PatternTalk speaks via `SpeechSynthesis`:

- **No screenreader active:** audio plays through speakers, user hears it
- **NVDA active:** NVDA mutes the speech synthesis output and reads the same text via its own voice, using the live region's text content
- **VoiceOver active:** same behavior as NVDA

This is the magic: a single voice output layer works for everyone.

### How STT maps to screenreaders

Screenreaders don't expose their STT input to web pages. So:

- **Sighted users without screenreader:** use Web Speech API STT
- **Screenreader users:** type into a regular text input, or use their screenreader's voice control (e.g., Dragon, Voice Access on Android, Voice Control on macOS)

Both paths converge on the same prompt parser. The UI offers both visibly:

```
[🎀 Hold Space to talk]  or  [Type a prompt: ____________]
```

### ARIA live regions

When PatternTalk wants to announce something (a new pattern generated, an error, a status change), it uses ARIA live regions:

```html
<div aria-live="polite" aria-atomic="true" id="status">
  <!-- PatternTalk writes here when state changes -->
  Skank beat, 4 bars at 174 BPM. MIDI ready.
</div>

<div aria-live="assertive" role="alert" id="errors">
  <!-- Errors go here, interrupt speechreader -->
</div>
```

**Polite** for routine status (don't interrupt). **Assertive** for errors (interrupt).

## Pattern description format

Every pattern has a screenreader-friendly text description. The format:

```
{Pattern name}. {Genre} at {tempo} BPM.
{Limb-by-limb description}.
{Notable characteristics}.
{Tags/context}.
```

Examples:

**D-Beat:**
```
D-Beat. Metal at 180 BPM. Kick plays on every beat with
8th-note doubles. Snare hits on 2 and 4. Ride bell plays
steady 8th notes throughout. Common in Discharge, Entombed,
and Scandinavian crust punk.
```

**Skank Beat:**
```
Skank Beat. Ska at 120 BPM. Kick on 1 and 3. Snare on
2 and 4. Hi-hat plays on every upbeat β€” the "and" of each
beat. Ska upstroke feel.
```

**Blast Traditional:**
```
Traditional Blast Beat. Metal at 200 BPM. Kick and snare
alternate in 8th notes throughout. Hi-hat plays continuous
8th notes. High intensity.
```

**Djent Polyrhythm:**
```
Djent Polyrhythm. Metal at 140 BPM. Kick plays a 4-over-3
polyrhythm against the 4/4 pulse. Snare on 2 and 4.
Ride cymbal plays 8th notes. Polyphonic, Meshuggah-style.
```

The description is generated from the template at runtime. Sighted users see it in a panel; screenreaders read it on demand.

## High contrast and theming

```css
:root {
  --bg: #ffffff;
  --fg: #1a1a1a;
  --accent: #0066cc;
  --focus: #ffd700;
  --limb-kick: #d62828;
  --limb-snare: #1d3557;
  --limb-hihat: #f4a261;
  --limb-ride: #2a9d8f;
  --limb-crash: #e76f51;
  --limb-china: #8338ec;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1a1a;
    --fg: #f0f0f0;
    --accent: #66b2ff;
  }
}

@media (prefers-contrast: more) {
  :root {
    --fg: #000000;
    --bg: #ffffff;
    --accent: #0000ee;
    --focus: #ff00ff;
  }
}
```

## Reduced motion

Some users get sick from animation. Respect `prefers-reduced-motion`:

```css
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
```

The visual grid has subtle "pulse" animations when patterns play back. With reduced motion, those are disabled β€” only color changes indicate playback position.

## Captions and transcripts

Every audio sample generated by SA3 gets a textual caption (derived from the prompt + pattern context):

```
Sample: brutal china crash, 18-inch, trashy.
Duration: 3.0 seconds. Intensity: brutal-max.
```

Captions are:
- Visible by default in the UI
- Read by screenreaders when focus moves to the sample player
- Exportable as a sidecar text file with the .wav download

## CI accessibility checks

```yaml
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
  a11y:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
      - run: npm ci
      - run: npm run build
      - run: npm run test:a11y   # axe-core via @axe-core/playwright
```

`npm run test:a11y` runs Playwright with axe-core against every page. Fails on any WCAG AA violation.

## Manual screenreader test protocol

Before each demo:

1. **Cold start:** Close browser, open PatternTalk, immediately start NVDA
2. **Full flow via keyboard only:** Generate a pattern, audition it, download MIDI, generate variations, pick one, start over
3. **Verify announcements:** Every state change should be announced within 1 second
4. **Verify focus:** Focus should never get stuck or disappear
5. **Verify grid:** Tab to grid, arrow-navigate, every cell announces its limb and velocity
6. **Verify download:** Download MIDI and sample, verify file names announced
7. **Verify errors:** Trigger an error path (e.g., Reaper not running), verify error is announced politely
8. **VoiceOver pass:** Repeat steps 1–7 with VoiceOver on macOS

A short screen recording of this is part of the demo deliverables.

## Reduced-physical-load mode (stretch)

For drummers with RSI, chronic pain, or temporary injury. The plugin generates the physically demanding parts (blast beats, double bass) and the drummer plays the parts they can play.

Implementation: split each pattern into "AI plays" vs "you play" subsets. Export two MIDI tracks. Drummer mutes the AI track they want to play themselves.

Not in scope for the 2-day hackathon, but the data model supports it (each `Hit` has a `playableBy: "ai" | "human"` flag).

## Haptic metronome (stretch)

A paired PWA on the drummer's phone vibrates on the beat. Different vibration patterns for downbeat, backbeat, fills.

Out of scope for the 2-day hackathon. Post-hackathon product.

## Real-time audio captioning (stretch)

Capture audio from the interface, run lightweight audio classification, output live captions: "kick, snare, kick-snare fill, china crash."

Out of scope for the 2-day hackathon. This is what would make the tool usable for deaf producers collaborating with hearing producers.

## Why this matters for the hackathon

Jury includes Andrew Huang, who has explicitly designed for accessibility in past work. Zack Zukowski (Stability AI) is known for caring about inclusive design. The "Accessibility & Inclusion" theme is a first-class track. The MUTEK Festival, where winners present, has an audience that includes accessibility advocates.

A demo that opens with "let me show you the screenreader view" is memorable. A demo that says "and we tested this with NVDA daily" is credible.

## Narwall integration (post-hackathon)

Long-term, PatternTalk could be tested *by* Narwall as part of its workflow β€” using Narwall's real-screenreader-based testing to continuously verify that no UI regression breaks the screenreader experience. That's a natural fit for the founder's other product and would make PatternTalk the only music tool with continuous accessibility testing baked in.

For the hackathon: mention this as the long-term plan in the demo, don't build the integration.