openaudio-suite 2.4.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/CHANGELOG.md +196 -0
- package/CONTRIBUTING.md +349 -0
- package/LICENSE +674 -0
- package/OpenAudio.js +386 -0
- package/OpenAudio_r.js +863 -0
- package/OpenAudio_s.js +445 -0
- package/README.md +433 -0
- package/docs/COMPARISON.md +449 -0
- package/docs/OPENAUDIO-v1.1.0.md +641 -0
- package/docs/OPENAUDIO_R.md +571 -0
- package/docs/OPENAUDIO_S.md +760 -0
- package/package.json +79 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the OpenAudio suite are documented here.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## OpenAudio.js
|
|
10
|
+
|
|
11
|
+
### [1.1.0] — 2025-03-15
|
|
12
|
+
|
|
13
|
+
#### Added
|
|
14
|
+
- **Background tab detection** — Listens to Page Visibility API (`document.visibilitychange`)
|
|
15
|
+
- **`pauseOnHidden` option** — Pause audio when tab hides, resume when tab returns
|
|
16
|
+
- **`onHidden` callback** — Fires when tab becomes hidden
|
|
17
|
+
- **`onVisible` callback** — Fires when tab becomes visible
|
|
18
|
+
- **`#boundVisibility` bound listener** — Proper cleanup prevents stale listeners in SPAs
|
|
19
|
+
|
|
20
|
+
#### Fixed
|
|
21
|
+
- Stale visibilitychange listeners in SPA environments (React, Vue, Svelte, etc.)
|
|
22
|
+
- Listener cleanup in `destroy()` now removes the exact function reference
|
|
23
|
+
|
|
24
|
+
#### Changed
|
|
25
|
+
- Class renamed: `SingleAudio` → `OpenAudio` (matches filename)
|
|
26
|
+
- Improved documentation with background tab behavior examples
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
### [1.0.0] — 2025-01-15
|
|
31
|
+
|
|
32
|
+
#### Added
|
|
33
|
+
- Initial release: Single-clip, one-shot player
|
|
34
|
+
- Silent MP3 unlock for autoplay policy compliance
|
|
35
|
+
- `onPlay` and `onEnd` callbacks
|
|
36
|
+
- `destroy()` method for SPA cleanup
|
|
37
|
+
- `canPlay()` static format checking
|
|
38
|
+
- Complete API documentation
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## OpenAudio_s.js
|
|
43
|
+
|
|
44
|
+
### [1.0.0] — 2025-01-15
|
|
45
|
+
|
|
46
|
+
#### Added
|
|
47
|
+
- Initial release: Sequential playlist player
|
|
48
|
+
- Click-to-advance playback control
|
|
49
|
+
- Jump to clip by index or label
|
|
50
|
+
- Pause/resume support
|
|
51
|
+
- Progress tracking
|
|
52
|
+
- Complete API documentation with usage patterns
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## OpenAudio_r.js
|
|
57
|
+
|
|
58
|
+
### [2.4.0] — 2025-03-15
|
|
59
|
+
|
|
60
|
+
### Added
|
|
61
|
+
- **`#isUnlocking` flag** — Prevents duplicate unlock attempts when `start()` is called rapidly (spam-clicks). The unlock play() is async; without this flag, a race condition allowed multiple overlapping unlock sequences.
|
|
62
|
+
- **`destroy()` method** — Removes the `visibilitychange` listener. Essential for SPAs (React, Vue, Svelte, etc.) where engine instances are created and destroyed across component lifecycles. Without it, stale listeners accumulate on `document` and defunct engines wake up on every tab-focus event.
|
|
63
|
+
- **`AudioEngine.canPlay(type)` static method** — Wraps `HTMLAudioElement.canPlayType()` with a clean boolean return. Use to check browser support for `.ogg`, `.wav`, or `.flac` before constructing an engine, rather than discovering a silent failure at play() time.
|
|
64
|
+
- **Callback resilience for `onCycleReset`** — Wrapped in try/catch, matching the existing resilience applied to `onPlay` and `onEnd`. A throwing `onCycleReset` can no longer stall the engine loop.
|
|
65
|
+
- **Comprehensive documentation** — Added HTML5 AUDIO vs. WEB AUDIO API comparison, browser autoplay policy deep-dive, background tab throttling mitigation, and callback resilience guarantees.
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
- Race condition where spam-clicking `start()` could trigger multiple `#scheduleNext()` calls before the first unlock completed.
|
|
69
|
+
- Potential memory leak: `visibilitychange` listener now properly removed on `destroy()`.
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
- Better error messages in console (include clip label and context).
|
|
73
|
+
|
|
74
|
+
### Documentation
|
|
75
|
+
- Added CHANGELOG.md (this file)
|
|
76
|
+
- Expanded README with better examples and API reference
|
|
77
|
+
- Created CONTRIBUTING.md with PR guidelines and testing checklist
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## [2.3.0] — 2025-02-20
|
|
82
|
+
|
|
83
|
+
### Added
|
|
84
|
+
- **Clip src validation** — Constructor and `addClip()` now verify that every clip has a non-empty string `src`. Previously a clip with missing or non-string `src` would silently map `undefined` into the engine, producing a confusing audio error rather than a clear failure at the point of entry.
|
|
85
|
+
- **Next-clip prefetch** — `#scheduleNext()` now sets `#audio.src` to the next selected clip immediately after the current clip ends, before the inter-clip delay fires. The browser begins buffering the file during the gap, eliminating the network fetch delay at `#playNext()` time. The clip is still marked played and selected at schedule time, preserving shuffle-bag correctness.
|
|
86
|
+
- **Background tab throttling mitigation** — `#scheduleNext()` records the wall-clock time (`#timerSetAt`) and delay duration (`#timerDelay`). A `visibilitychange` listener fires when the tab returns to foreground. If elapsed time meets or exceeds the intended delay, the pending timer is cancelled and `#playNext()` is called immediately. Otherwise, the remaining time is rescheduled precisely.
|
|
87
|
+
|
|
88
|
+
### Fixed
|
|
89
|
+
- Network latency no longer visible as gaps between clips (prefetch eliminates fetch delay).
|
|
90
|
+
- Background tab throttling no longer causes clips to bunch together on tab return (recalculation uses wall-clock time, not timer promises).
|
|
91
|
+
|
|
92
|
+
### Changed
|
|
93
|
+
- Improved console logging for debugging background tab behavior.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## [2.2.0] — 2025-01-10
|
|
98
|
+
|
|
99
|
+
### Added
|
|
100
|
+
- **`reset()` method** — Stops playback, clears all `played` flags, and optionally resets the current clip. Next `start()` begins a completely fresh random cycle.
|
|
101
|
+
- **`setVolume()` method** — Updates volume immediately on live playback and all future clips. Clamps to [0, 1].
|
|
102
|
+
|
|
103
|
+
### Fixed
|
|
104
|
+
- Volume no longer resets to default on clip transition.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## [2.1.0] — 2024-12-05
|
|
109
|
+
|
|
110
|
+
### Added
|
|
111
|
+
- **`addClip(clip)` method** — Add new clips to the engine at runtime without reconstructing.
|
|
112
|
+
- **Cycle-boundary repeat prevention** — When the unplayed pool is empty (cycle reset), the next clip is selected from all clips *except* the current clip, preventing the same clip from playing twice in a row across a cycle boundary.
|
|
113
|
+
|
|
114
|
+
### Fixed
|
|
115
|
+
- Shuffle bag now correctly prevents the same clip from playing at the start and end of successive cycles.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## [2.0.0] — 2024-10-01
|
|
120
|
+
|
|
121
|
+
### Added
|
|
122
|
+
- **Public API methods** — `start()`, `stop()`, `start()` for public control.
|
|
123
|
+
- **Lifecycle callbacks** — `onPlay(clip)`, `onEnd(clip)`, `onCycleReset()` for integration with game/app logic.
|
|
124
|
+
- **Options object** — `lowTime`, `maxTime`, `volume`, and callback configuration.
|
|
125
|
+
- **Shuffle bag algorithm** — Guarantees each clip plays exactly once per cycle before repeats.
|
|
126
|
+
- **Browser autoplay policy handling** — Silent base64 MP3 unlock on first `start()` call, subsequent clips scheduled via `setTimeout`.
|
|
127
|
+
- **Background tab throttling mitigation** — Page Visibility API monitoring and wall-clock delay recalculation.
|
|
128
|
+
|
|
129
|
+
### Documentation
|
|
130
|
+
- Comprehensive JSDoc comments throughout
|
|
131
|
+
- Browser compatibility notes
|
|
132
|
+
- Web Audio API vs. HTML5 Audio comparison
|
|
133
|
+
- Usage examples in code comments
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## [1.0.0] — 2024-09-01
|
|
138
|
+
|
|
139
|
+
### Initial Release
|
|
140
|
+
- Self-contained randomized audio scheduling engine
|
|
141
|
+
- No dependencies, no external libraries
|
|
142
|
+
- HTML5 `<audio>` element-based scheduling
|
|
143
|
+
- Basic shuffle bag implementation
|
|
144
|
+
- Mobile-compatible (respects autoplay policies)
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Upgrade Guide
|
|
149
|
+
|
|
150
|
+
### 2.3 → 2.4
|
|
151
|
+
- **No breaking changes.** New features are additive.
|
|
152
|
+
- **Recommended:** Call `engine.destroy()` when tearing down in SPAs to prevent listener accumulation.
|
|
153
|
+
- **New:** Use `AudioEngine.canPlay('audio/ogg')` to check format support before constructing.
|
|
154
|
+
|
|
155
|
+
### 2.2 → 2.3
|
|
156
|
+
- **No breaking changes.** Prefetch is transparent.
|
|
157
|
+
- **Benefit:** Faster clip transitions due to network prefetch during inter-clip gap.
|
|
158
|
+
|
|
159
|
+
### 2.0 → 2.1
|
|
160
|
+
- **No breaking changes.** New methods are additive.
|
|
161
|
+
- **New:** Cycle-boundary repeat prevention automatically enabled.
|
|
162
|
+
|
|
163
|
+
### 1.0 → 2.0
|
|
164
|
+
- **Breaking:** Old version had no public API. Complete rewrite with methods and callbacks.
|
|
165
|
+
- **Migration:** Wrap old code in a new `AudioEngine` constructor.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Future Considerations
|
|
170
|
+
|
|
171
|
+
These features are **out of scope** for OpenAudio_r.js (it would violate the "self-contained, no dependencies" principle):
|
|
172
|
+
|
|
173
|
+
- Crossfading between clips
|
|
174
|
+
- Sub-second precision scheduling
|
|
175
|
+
- Real-time DSP effects (reverb, EQ, compression)
|
|
176
|
+
- Frequency analysis or visualization
|
|
177
|
+
|
|
178
|
+
For these, consider graduating to the **Web Audio API**. See README.md for comparison.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Contributing
|
|
183
|
+
|
|
184
|
+
Have a feature request or bug to report? See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
185
|
+
|
|
186
|
+
All contributions will be credited in the changelog.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
OpenAudio_r.js is licensed under the GNU General Public License v3.0 or later. See [LICENSE](./LICENSE) for details.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
*Last updated: March 15, 2025*
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
# Contributing to OpenAudio Suite
|
|
2
|
+
|
|
3
|
+
Thank you for considering a contribution to the OpenAudio Suite! Contributions—whether bug reports, feature suggestions, or code—are how these projects improve.
|
|
4
|
+
|
|
5
|
+
The OpenAudio Suite consists of three libraries:
|
|
6
|
+
- **OpenAudio_r.js** (v2.4.0) — Randomized audio scheduler
|
|
7
|
+
- **OpenAudio_s.js** (v1.0.0) — Sequential playlist player
|
|
8
|
+
- **OpenAudio.js** (v1.1.0) — Single-clip player with background tab detection
|
|
9
|
+
|
|
10
|
+
## Code of Conduct
|
|
11
|
+
|
|
12
|
+
This project adheres to the [Contributor Covenant](https://www.contributor-covenant.org/). By participating, you are expected to uphold this code of conduct.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Reporting Bugs
|
|
17
|
+
|
|
18
|
+
Before submitting a bug report, please:
|
|
19
|
+
|
|
20
|
+
1. **Check existing issues** — Your bug may already be reported.
|
|
21
|
+
2. **Check the browser console** — Paste any errors.
|
|
22
|
+
3. **Test in a different browser** — Narrow down the scope.
|
|
23
|
+
4. **Read the troubleshooting section** of README.md.
|
|
24
|
+
|
|
25
|
+
### Bug Report Template
|
|
26
|
+
|
|
27
|
+
When opening an issue, include:
|
|
28
|
+
|
|
29
|
+
```markdown
|
|
30
|
+
**Describe the bug:**
|
|
31
|
+
A clear description of what is broken.
|
|
32
|
+
|
|
33
|
+
**Steps to reproduce:**
|
|
34
|
+
1. I created an engine with clips: [paste code]
|
|
35
|
+
2. I clicked the play button...
|
|
36
|
+
3. Expected: audio plays
|
|
37
|
+
4. Actual: [what actually happens]
|
|
38
|
+
|
|
39
|
+
**Browser & OS:**
|
|
40
|
+
- Browser: Chrome 120 / Firefox 121 / Safari 17
|
|
41
|
+
- OS: Windows 11 / macOS 14 / iOS 17
|
|
42
|
+
|
|
43
|
+
**Console errors:**
|
|
44
|
+
(paste any errors from DevTools Console)
|
|
45
|
+
|
|
46
|
+
**Minimal code example:**
|
|
47
|
+
(paste the smallest code snippet that reproduces the bug)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Suggesting Features
|
|
53
|
+
|
|
54
|
+
Have an idea? Open an issue with:
|
|
55
|
+
|
|
56
|
+
1. **Clear title** — What is the feature?
|
|
57
|
+
2. **Motivation** — Why would this be useful?
|
|
58
|
+
3. **Proposed API** — How would a user call it?
|
|
59
|
+
4. **Alternatives** — Other approaches considered?
|
|
60
|
+
|
|
61
|
+
Example:
|
|
62
|
+
|
|
63
|
+
```markdown
|
|
64
|
+
**Feature Request: Crossfade between clips**
|
|
65
|
+
|
|
66
|
+
Currently, clips change abruptly. It would sound more polished if clips
|
|
67
|
+
faded out/in over 500ms.
|
|
68
|
+
|
|
69
|
+
Proposed API:
|
|
70
|
+
engine = new AudioEngine(clips, {
|
|
71
|
+
fadeInDuration: 500, // ms
|
|
72
|
+
fadeOutDuration: 500 // ms
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
This is a common pattern in game audio engines.
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Note:** Feature requests for crossfading, real-time DSP, or sub-second precision
|
|
79
|
+
are better suited to the Web Audio API. OpenAudio_r.js is intentionally simple.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Submitting Code Changes
|
|
84
|
+
|
|
85
|
+
### Setup
|
|
86
|
+
|
|
87
|
+
1. Fork the repository
|
|
88
|
+
2. Clone your fork
|
|
89
|
+
```bash
|
|
90
|
+
git clone https://github.com/YOUR-USERNAME/openaudio-r.git
|
|
91
|
+
cd openaudio-r
|
|
92
|
+
```
|
|
93
|
+
3. Create a branch
|
|
94
|
+
```bash
|
|
95
|
+
git checkout -b fix/autoplay-ios
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Make Changes
|
|
99
|
+
|
|
100
|
+
- **Edit only `OpenAudio_r.js`** (unless updating docs).
|
|
101
|
+
- **Test thoroughly** in multiple browsers and on mobile.
|
|
102
|
+
- **Update JSDoc comments** if you change signatures.
|
|
103
|
+
- **Add/update examples** if adding features.
|
|
104
|
+
- **Update CHANGELOG.md** with your change.
|
|
105
|
+
|
|
106
|
+
### Code Style
|
|
107
|
+
|
|
108
|
+
- **Naming:** Use camelCase for variables/methods, PascalCase for classes.
|
|
109
|
+
- **Comments:** Comment *why*, not *what*. The code shows what; comments explain why.
|
|
110
|
+
- **JSDoc:** Document all public methods with parameter types and return values.
|
|
111
|
+
- **Error messages:** Be specific (include clip label, current time, etc.).
|
|
112
|
+
- **Callbacks:** Wrap in try/catch (see existing `onPlay`, `onEnd`, `onCycleReset` patterns).
|
|
113
|
+
|
|
114
|
+
### Testing Checklist
|
|
115
|
+
|
|
116
|
+
Before opening a PR, test:
|
|
117
|
+
|
|
118
|
+
- [ ] **Desktop browsers:** Chrome, Firefox, Safari (all latest versions)
|
|
119
|
+
- [ ] **Mobile:** iOS Safari, Chrome Android
|
|
120
|
+
- [ ] **First play on page load:** Must be inside a user gesture
|
|
121
|
+
- [ ] **Background tab test:** Switch to another tab, wait 10 seconds, switch back—next clip should fire correctly
|
|
122
|
+
- [ ] **Multiple clips:** Add 5+ clips and verify shuffle bag (no repeats in a cycle)
|
|
123
|
+
- [ ] **volume control:** Verify `setVolume()` updates live playback
|
|
124
|
+
- [ ] **destroy():** Ensure listeners are removed (no memory leaks)
|
|
125
|
+
- [ ] **Example code:** Test minimal and advanced examples from README
|
|
126
|
+
|
|
127
|
+
### Commit Messages
|
|
128
|
+
|
|
129
|
+
Write clear, atomic commits:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
git commit -m "Fix: prevent double unlock on rapid start() calls
|
|
133
|
+
|
|
134
|
+
- Added #isUnlocking flag to track unlock phase
|
|
135
|
+
- Rapid clicks to start() are now ignored until unlock completes
|
|
136
|
+
- Solves race condition where multiple #scheduleNext() calls overlap"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Guidelines:**
|
|
140
|
+
- Start with a type: `fix:`, `feat:`, `docs:`, `refactor:`, `test:`
|
|
141
|
+
- Reference any related issue: `Fixes #42`
|
|
142
|
+
- Explain *why*, not just *what*
|
|
143
|
+
|
|
144
|
+
### Opening a Pull Request
|
|
145
|
+
|
|
146
|
+
1. **Push to your fork**
|
|
147
|
+
```bash
|
|
148
|
+
git push origin fix/autoplay-ios
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
2. **Open PR on GitHub**
|
|
152
|
+
- Title: `fix: prevent audio unlock race condition`
|
|
153
|
+
- Description: Explain the problem, your solution, and testing steps
|
|
154
|
+
- Link any related issues: `Fixes #42`
|
|
155
|
+
- Check the "allow edits from maintainers" box
|
|
156
|
+
|
|
157
|
+
3. **PR Template**
|
|
158
|
+
|
|
159
|
+
```markdown
|
|
160
|
+
## Description
|
|
161
|
+
Briefly explain the change.
|
|
162
|
+
|
|
163
|
+
## Type
|
|
164
|
+
- [ ] Bug fix (non-breaking change fixing an issue)
|
|
165
|
+
- [ ] New feature (non-breaking change adding functionality)
|
|
166
|
+
- [ ] Breaking change (fix or feature that changes existing API)
|
|
167
|
+
- [ ] Documentation update
|
|
168
|
+
|
|
169
|
+
## Related Issue
|
|
170
|
+
Fixes #42
|
|
171
|
+
|
|
172
|
+
## Testing
|
|
173
|
+
How did you verify this change?
|
|
174
|
+
- [ ] Tested in Chrome 120
|
|
175
|
+
- [ ] Tested in Firefox 121
|
|
176
|
+
- [ ] Tested in Safari 17
|
|
177
|
+
- [ ] Tested on iOS
|
|
178
|
+
- [ ] Tested on Android
|
|
179
|
+
|
|
180
|
+
## Checklist
|
|
181
|
+
- [ ] Code follows project style (camelCase, JSDoc)
|
|
182
|
+
- [ ] Comments added for new logic
|
|
183
|
+
- [ ] CHANGELOG.md updated
|
|
184
|
+
- [ ] README.md updated (if API change)
|
|
185
|
+
- [ ] No breaking changes introduced
|
|
186
|
+
- [ ] Tests pass in all listed browsers
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Documentation Changes
|
|
192
|
+
|
|
193
|
+
### Updating README.md
|
|
194
|
+
|
|
195
|
+
- Use clear, concise language
|
|
196
|
+
- Include code examples
|
|
197
|
+
- Test all code snippets (they should work as-is)
|
|
198
|
+
- Update table of contents if adding new sections
|
|
199
|
+
|
|
200
|
+
### Adding Examples
|
|
201
|
+
|
|
202
|
+
1. Create `/examples/your-example.html`
|
|
203
|
+
2. Include a comment block explaining what it demonstrates
|
|
204
|
+
3. Make it self-contained (no external dependencies)
|
|
205
|
+
4. Link it from README.md
|
|
206
|
+
|
|
207
|
+
Example structure:
|
|
208
|
+
|
|
209
|
+
```html
|
|
210
|
+
<!DOCTYPE html>
|
|
211
|
+
<html>
|
|
212
|
+
<head>
|
|
213
|
+
<title>OpenAudio_r.js — [Feature] Example</title>
|
|
214
|
+
</head>
|
|
215
|
+
<body>
|
|
216
|
+
<h1>[Feature] Example</h1>
|
|
217
|
+
<p>This example demonstrates [feature].</p>
|
|
218
|
+
|
|
219
|
+
<button id="play">Play</button>
|
|
220
|
+
<button id="stop">Stop</button>
|
|
221
|
+
<div id="status"></div>
|
|
222
|
+
|
|
223
|
+
<script src="../OpenAudio_r.js"></script>
|
|
224
|
+
<script>
|
|
225
|
+
// Your example code here
|
|
226
|
+
</script>
|
|
227
|
+
</body>
|
|
228
|
+
</html>
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Review Process
|
|
234
|
+
|
|
235
|
+
After you submit a PR:
|
|
236
|
+
|
|
237
|
+
1. **Automated checks** run (linting, tests if any)
|
|
238
|
+
2. **Code review** — I'll review the code and suggest changes if needed
|
|
239
|
+
3. **Discussion** — We'll discuss any questions or concerns
|
|
240
|
+
4. **Approval & merge** — Once approved, your code is merged
|
|
241
|
+
|
|
242
|
+
Expect 2–7 days for a response (I review contributions in batches).
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Project Structure
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
openaudio-r/
|
|
250
|
+
├── OpenAudio_r.js # Main source file
|
|
251
|
+
├── README.md # Project documentation
|
|
252
|
+
├── CONTRIBUTING.md # This file
|
|
253
|
+
├── CHANGELOG.md # Version history
|
|
254
|
+
├── LICENSE # GPL-3.0-or-later
|
|
255
|
+
├── .gitignore # Git ignore rules
|
|
256
|
+
├── package.json # npm metadata (if publishing)
|
|
257
|
+
├── /examples # HTML demo files
|
|
258
|
+
├── /docs # Extra documentation
|
|
259
|
+
└── /test # Test files (if added)
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Development Tips
|
|
265
|
+
|
|
266
|
+
### Testing Autoplay Policy
|
|
267
|
+
|
|
268
|
+
Browsers block autoplay unless inside a user gesture. Test this:
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
// ✅ This will work
|
|
272
|
+
document.addEventListener('click', () => engine.start());
|
|
273
|
+
|
|
274
|
+
// ❌ This will fail
|
|
275
|
+
setTimeout(() => engine.start(), 1000);
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Debugging Background Tab Throttling
|
|
279
|
+
|
|
280
|
+
1. Open DevTools
|
|
281
|
+
2. Go to Console
|
|
282
|
+
3. Type: `engine.#timerSetAt` (to check timer state)
|
|
283
|
+
4. Switch tabs and wait
|
|
284
|
+
5. Return to tab and check if next clip fires on schedule
|
|
285
|
+
|
|
286
|
+
### Memory Leaks
|
|
287
|
+
|
|
288
|
+
Always call `destroy()` when tearing down:
|
|
289
|
+
|
|
290
|
+
```javascript
|
|
291
|
+
// React
|
|
292
|
+
useEffect(() => {
|
|
293
|
+
const engine = new AudioEngine(clips);
|
|
294
|
+
return () => engine.destroy();
|
|
295
|
+
}, []);
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## Versioning
|
|
301
|
+
|
|
302
|
+
This project uses [Semantic Versioning](https://semver.org/):
|
|
303
|
+
|
|
304
|
+
- **MAJOR** (2.0.0) — Breaking API changes
|
|
305
|
+
- **MINOR** (2.4.0) — New features, backward-compatible
|
|
306
|
+
- **PATCH** (2.4.1) — Bug fixes
|
|
307
|
+
|
|
308
|
+
Version numbers appear in:
|
|
309
|
+
- `OpenAudio_r.js` header (line 4)
|
|
310
|
+
- `CHANGELOG.md`
|
|
311
|
+
- `package.json` (if published to npm)
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Deployment & Publishing
|
|
316
|
+
|
|
317
|
+
### Releases
|
|
318
|
+
|
|
319
|
+
1. Update version in `OpenAudio_r.js` header
|
|
320
|
+
2. Update `CHANGELOG.md`
|
|
321
|
+
3. Create a GitHub Release with tag `v2.4.0`
|
|
322
|
+
4. Add release notes summarizing changes
|
|
323
|
+
|
|
324
|
+
### npm Publishing (if applicable)
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
npm login
|
|
328
|
+
npm publish
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
This will publish the package to https://www.npmjs.com/package/openaudio-r.
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Questions?
|
|
336
|
+
|
|
337
|
+
- 💬 Open a GitHub Discussion
|
|
338
|
+
- 📧 Mention me in an issue
|
|
339
|
+
- 🐛 Check existing issues first
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## Recognition
|
|
344
|
+
|
|
345
|
+
Contributors will be listed in CHANGELOG.md and credited in commit messages. Thank you for helping make OpenAudio_r.js better!
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
**Happy coding! 🎵**
|