@maccesar/titools 5.2.0 → 5.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.
Files changed (78) hide show
  1. package/CONTRIBUTING.md +69 -0
  2. package/README.md +80 -72
  3. package/agents/ti-pro.md +1 -1
  4. package/commands/ti-audit.md +2 -2
  5. package/docs/examples.md +91 -0
  6. package/docs/knowledge-index.md +57 -0
  7. package/lib/downloader.js +1 -1
  8. package/package.json +4 -2
  9. package/skills/purgetss/references/multi-density-images.md +1 -1
  10. package/skills/ti-admob-unified/SKILL.md +21 -7
  11. package/skills/ti-admob-unified/assets/example/app.js +229 -25
  12. package/skills/ti-admob-unified/assets/example/lib/ads.js +30 -2
  13. package/skills/ti-admob-unified/assets/example/library-usage.js +33 -1
  14. package/skills/ti-admob-unified/references/api-reference.md +39 -16
  15. package/skills/ti-admob-unified/references/banners.md +9 -9
  16. package/skills/ti-admob-unified/references/contributing.md +14 -9
  17. package/skills/ti-admob-unified/references/dependencies.md +31 -25
  18. package/skills/ti-admob-unified/references/fullscreen.md +43 -28
  19. package/skills/ti-admob-unified/references/game-monetization.md +138 -7
  20. package/skills/ti-admob-unified/references/getting-started.md +75 -31
  21. package/skills/ti-admob-unified/references/index.md +5 -2
  22. package/skills/ti-admob-unified/references/integration.md +8 -6
  23. package/skills/ti-admob-unified/references/library.md +41 -10
  24. package/skills/ti-admob-unified/references/mediation-parity.md +17 -0
  25. package/skills/ti-admob-unified/references/mediation.md +22 -9
  26. package/skills/ti-admob-unified/references/migration.md +11 -7
  27. package/skills/ti-admob-unified/references/module-changelog.md +41 -11
  28. package/skills/ti-admob-unified/references/privacy.md +35 -8
  29. package/skills/ti-admob-unified/references/production.md +67 -0
  30. package/skills/ti-admob-unified/references/rewarded-interstitial.md +101 -0
  31. package/skills/ti-admob-unified/references/roadmap.md +28 -31
  32. package/skills/ti-admob-unified/references/source-notes.md +51 -4
  33. package/skills/ti-admob-unified/references/source-snapshot.json +249 -45
  34. package/skills/ti-admob-unified/references/third-party-notices.md +4 -4
  35. package/skills/ti-game/SKILL.md +23 -6
  36. package/skills/ti-game/references/api.md +34 -30
  37. package/skills/ti-game/references/debugging-performance.md +18 -9
  38. package/skills/ti-game/references/examples.md +103 -20
  39. package/skills/ti-game/references/input.md +101 -0
  40. package/skills/ti-game/references/patterns.md +39 -15
  41. package/skills/ti-game/references/physics.md +80 -52
  42. package/skills/ti-game/references/project-setup.md +118 -56
  43. package/skills/ti-game/references/recipes-action.md +107 -8
  44. package/skills/ti-game/references/recipes-adventure-effects.md +41 -9
  45. package/skills/ti-game/references/roadmap.md +10 -3
  46. package/skills/ti-game/references/source-notes.md +81 -0
  47. package/skills/ti-game/references/tilemaps.md +12 -4
  48. package/skills/ti-synthengine/SKILL.md +81 -95
  49. package/skills/ti-synthengine/assets/example/README.md +84 -0
  50. package/skills/ti-synthengine/assets/example/app.js +1178 -0
  51. package/skills/ti-synthengine/assets/example/lib/sequenceOwner.js +83 -0
  52. package/skills/ti-synthengine/assets/example/lib/sequenceScore.js +25 -0
  53. package/skills/ti-synthengine/references/advanced-examples.md +174 -0
  54. package/skills/ti-synthengine/references/android-sim80-correction-evidence.zip +0 -0
  55. package/skills/ti-synthengine/references/android-sim80-correction.json +162 -0
  56. package/skills/ti-synthengine/references/api.md +434 -380
  57. package/skills/ti-synthengine/references/audio-engine.md +157 -230
  58. package/skills/ti-synthengine/references/bypass-physical-recheck-evidence.zip +0 -0
  59. package/skills/ti-synthengine/references/examples.md +123 -253
  60. package/skills/ti-synthengine/references/frontier-android-evidence.zip +0 -0
  61. package/skills/ti-synthengine/references/frontier-ipad-evidence.zip +0 -0
  62. package/skills/ti-synthengine/references/frontier-physical-validation.json +1918 -0
  63. package/skills/ti-synthengine/references/guide.md +188 -156
  64. package/skills/ti-synthengine/references/performance-review-evidence.zip +0 -0
  65. package/skills/ti-synthengine/references/performance-review.json +1146 -0
  66. package/skills/ti-synthengine/references/physical-validation.json +1457 -0
  67. package/skills/ti-synthengine/references/recipes-interaction.md +549 -0
  68. package/skills/ti-synthengine/references/recipes.md +423 -599
  69. package/skills/ti-synthengine/references/recommendations.md +63 -113
  70. package/skills/ti-synthengine/references/sound-design.md +134 -258
  71. package/skills/ti-synthengine/references/source-notes.md +93 -105
  72. package/skills/ti-synthengine/references/source-snapshot.json +379 -32
  73. package/skills/ti-synthengine/references/stats-performance.md +64 -20
  74. package/skills/ti-synthengine/references/studio-validation.json +6202 -0
  75. package/skills/ti-synthengine/references/troubleshooting.md +109 -121
  76. package/skills/ti-synthengine/references/unified-bypass-performance.json +22425 -0
  77. package/skills/ti-synthengine/references/unified-validation.json +314 -0
  78. package/AGENTS-VERCEL-RESEARCH.md +0 -175
@@ -0,0 +1,81 @@
1
+ # Source provenance and audit limits
2
+
3
+ Reviewed on 2026-10-23. This skill is a curated reference, not a bundled module
4
+ binary or an assertion that a fork build has been published.
5
+
6
+ ## Reviewed sources
7
+
8
+ - Upstream: `m1ga/ti.game@88e181cb85526d8146d0be6e09b2b90c2551baad`.
9
+ Remote `refs/heads/main` was checked with `git ls-remote` during this audit.
10
+ - Fork documentation snapshot: `macCesar/ti.game@2bf5f828a3bb8028eed20d6ba27b97dd3aa9a753`
11
+ (`docs/update-current-features`). Its source tree contains the current
12
+ upstream engine, not merely the older `3bea2f4` baseline.
13
+ - Fork delta from upstream: README/tutorial/TODO/Apple build documentation,
14
+ Xcode SDK selection, Camera example key binding, demo generation and
15
+ example-input regression checks, plus maintainer instructions.
16
+ - The documentation snapshot is the exact head of
17
+ [upstream PR #39](https://github.com/m1ga/ti.game/pull/39), branch
18
+ `docs/update-current-features`. PR metadata and the remote branch both matched
19
+ `2bf5f82` when checked. Its Camera Z/X binding correction and diagnostic
20
+ launcher discovery/SDK/indirect-input fixes were included in this audit.
21
+ - Only `AGENTS.md` was dirty when the audit started; that instruction-file
22
+ edit is not a native/API modification. Audited module documentation and
23
+ native files were committed. No module files were edited by this audit.
24
+ - Both manifests: `1.0.0`, minimum Titanium `13.4.0`. Builds documented at
25
+ Titanium `13.4.1.GA`; Apple minimum iOS 15. Release/nightly artifact versions
26
+ do not identify a source commit or prove these fork clarifications shipped.
27
+
28
+ Sources are the root README, `tutorial.md`, `ios/README.md`, TODO, the complete
29
+ 35-demo launcher/catalog and helpers, plus both platforms' proxies, simulation,
30
+ input and renderer implementation where contracts require them. Maintainer
31
+ plans, personal project state and issue drafts are excluded from public API
32
+ requirements; they are not additional supported APIs.
33
+
34
+ ## Source fingerprints
35
+
36
+ SHA-256 of the reviewed committed documents/configuration:
37
+
38
+ | Source path | SHA-256 |
39
+ | --- | --- |
40
+ | `README.md` | `a1970c35c56880d7722d9397b968502b8357c9c3b0b83ee2dd2be4e18df02dd6` |
41
+ | `tutorial.md` | `a57e609935a92b6efb0513a9ddc271d4a9d1f7ead5188612d1014533ec801d7d` |
42
+ | `ios/README.md` | `89ab286034acdfed05627316cfd93b4b019cc44a99e7c5a46c8d2b38f564fd4b` |
43
+ | `TODO.md` | `a9c3b3ce25883bdc4472a908f2bcd955dcd415ec37f8d8c6b9129a7a505f4cd3` |
44
+ | `android/manifest` | `4c20ea79fb9ccb87581b37a2b8450a635f84e5f2ff53bf5c6d574faa0260340d` |
45
+ | `ios/manifest` | `472f4f0d572416b0df739ca8fcdc03febd4e20a3ecedcb99c6e494925c3ea6c0` |
46
+
47
+ ## Current corrections and unresolved source conflicts
48
+
49
+ - Apple is Metal/CAMetalLayer; Android retains OpenGL ES. No public Apple
50
+ backend selector or app-provided `default.metallib` is required.
51
+ - Configurable digital actions, keyboard/mouse focus, GameController fanout
52
+ and cancellation are current contracts; see [input.md](input.md).
53
+ - Assigning Sprite `frame` stops its animation and queued chain. Android's
54
+ optional animation completion `frame` is not portable to Apple. Set animation
55
+ definitions at creation for portable code. See [api.md](api.md).
56
+ - Damping now lets effective unopposed acceleration build speed from rest; zero-delta rope updates
57
+ freeze initialized geometry. Historical contrary guidance from `3bea2f4`
58
+ must not be applied to this source pin. See [physics.md](physics.md).
59
+ - README Draw text retains an obsolete ASCII-only sentence. Its Font section
60
+ and both native maps include precomposed accented Latin glyphs; the skill
61
+ follows the implementation and lists the actual repertoire.
62
+ - Telemetry reports CPU drawable acquisition/presentation submission, not GPU
63
+ duration or proof of display. Missing drawables/slot pressure preserve elapsed
64
+ simulation up to the documented recovery cap; pause/suspension resets clocks.
65
+ - App orientation/launch policy belongs to Titanium, not the module. The older
66
+ `ti-ui` orientation guide is not a fully audited multi-activity setup; that
67
+ dependency remains explicitly limited in [project-setup.md](project-setup.md).
68
+
69
+ ## Verification boundaries
70
+
71
+ The audit reconciles current reference guidance with source and focused host
72
+ regressions. Native resolver tests exercise Java/Objective-C binding validation,
73
+ aggregation and state transitions. Physics fixtures execute extracted production
74
+ methods with controlled collaborators. JavaScript demo/layout tests use mocked
75
+ Titanium/game objects. These do not establish GPU behavior or physical keyboard,
76
+ mouse, controller, navigation or audio acceptance.
77
+
78
+ Apple's own README records renderer acceptance on Apple Silicon Catalyst and a
79
+ physical iPad (18 tests on 2026-10-22). This audit does not rerun or extend that
80
+ evidence. Physical iPhone, Intel execution, complete interactive demo acceptance
81
+ and controlled performance comparisons remain pending in the module source.
@@ -1,6 +1,7 @@
1
1
  # Native tile maps
2
2
 
3
- Verified against `ti.game@3bea2f4`: upstream `README.md` § Tile maps, `example/tilemap.js`, both `TileLayerProxy` implementations, both native `TileLayer` engines, scene collision, and `Pathfinder`.
3
+ Reviewed on 2026-10-23 against upstream native `88e181c` and
4
+ `macCesar/ti.game@2bf5f82` documentation: `README.md` § Tile maps, `example/tilemap.js`, both `TileLayerProxy` implementations, both native `TileLayer` engines, scene collision, and `Pathfinder`.
4
5
 
5
6
  Use `Game.createTileLayer()` for a large or mostly static grid. The engine stores the whole map but renders only cells inside the camera, batches the layer through one sheet, checks only collision cells under a mover, and feeds solid cells into `findPath`. A small map whose tiles need independent sprite behavior can still use sprites; `topdown.js` is a 16×12 example of that older pattern.
6
7
 
@@ -40,7 +41,7 @@ For Tiled JSON, pass the layer data with `cols: map.width`, `rows: map.height`,
40
41
 
41
42
  ## Portable property timing
42
43
 
43
- The pinned upstream README now documents the same creation-time portability
44
+ The reviewed README documents the same creation-time portability
44
45
  boundary as the native bindings. Use this contract:
45
46
 
46
47
  | Timing | Properties |
@@ -52,6 +53,8 @@ boundary as the native bindings. Use this contract:
52
53
  iOS rebuilds the grid when `legend`, `firstGid`, `cols`, or `rows` is assigned later. Android exposes no setters for those four. Supplying them in the factory keeps both platforms aligned.
53
54
 
54
55
  `opacity`, `scrollFactor`, and `restitution` accept ratio numbers or percentage strings. `tileWidth`/`tileHeight`, coordinates, and dimensions do not.
56
+ `data` is a write-only input; inspect individual cells with `getTile()` or
57
+ `cellAt()` instead of expecting the original input shape to read back.
55
58
 
56
59
  ## Collision cells
57
60
 
@@ -116,13 +119,18 @@ function walkTo(player, destination, tileLayer, gameView) {
116
119
  }
117
120
  ```
118
121
 
119
- Bound the per-query A* search to the useful neighborhood. The layer can be enormous without rendering cost, but `findPath()` still builds a grid for the requested bounds on the calling thread.
122
+ Bound the per-query A* search to the useful neighborhood. Increasing the grid consumes more memory even though drawing only visits visible cells; `findPath()` still builds a grid for the requested bounds on the calling thread.
120
123
 
121
124
  ## Layering and performance
122
125
 
123
126
  - Stack separate layers for ground, decoration, and foreground. Layers draw below sprites at the same `zIndex`.
124
127
  - Share one sheet when layers use the same tileset.
125
128
  - Use `scrollFactor` for parallax layers; collision remains in world coordinates, just as with sprites.
129
+ - In a circular `worldWrapX` scene, the layer repeats drawing and solid cells
130
+ across the seam only when `x` equals the interval's `minX` and `width` equals
131
+ `maxX - minX`. This does not make `findPath()` or `raycast()` periodic.
126
132
  - Use `visible: false` to exclude the layer from drawing and collision.
127
- - Toggle `layer.debug` for one layer or `gameView.debug = { hitbox: true }` for every layer's solid cells.
133
+ - Toggle `layer.debug` for one layer or `gameView.debug = { hitbox: true }` for
134
+ every layer's collision cells: green outlines fully solid cells; yellow
135
+ draws the top face of one-way cells.
128
136
  - Use the performance HUD while scrolling: map dimensions should not change visible-cell draw cost.
@@ -1,116 +1,102 @@
1
1
  ---
2
2
  name: ti-synthengine
3
- description: "Use when a Titanium app declares ti.synthengine in tiapp.xml, imports require('ti.synthengine'), or asks for generated tones, chords, patterns, retro/game/UI sounds, alarms, sweeps, vibrato, envelopes (attack, decay, sustain, release), resonant filters, FM bells and electric-piano tones, detune, panning, binaural headphone positioning (spatialX/spatialY), gain staging, engine statistics, render load, the patternend event, or troubleshooting with that native module. Covers Android and iOS contract 1.0.0. Do not use for audio-file playback, streaming music, or unrelated synthesizers."
3
+ description: "Use when a Titanium app declares ti.synthengine in tiapp.xml, imports require('ti.synthengine'), or needs generated tones, chords, native sequences, sustained game motors, ADSR, sweeps, FM, resonant filters, noise, binaural spatialX/spatialY, held noteOn/noteOff/updateVoice, shared tempo, selective music/effects/ui/ambience processing, effectSend, priorities, chorus/delay/reverb/saturation, LFOs, sequenceend events, gain staging, statistics or render-load diagnosis. Covers the published Android/iOS 1.0.0 contract. Not for audio-file decoding, sample streaming or unrelated synthesizers."
4
4
  ---
5
5
 
6
- # ti.synthengine — sound synthesis for Titanium SDK
6
+ # ti.synthengine — native sound synthesis for Titanium
7
7
 
8
- Act as an audio engineer and mobile sound designer for the native `ti.synthengine` module. Translate an aesthetic request into acoustically reasoned JavaScript that uses only the module's public contract.
8
+ Act as an audio engineer and mobile sound designer. Translate the requested sound into acoustically reasoned JavaScript using the exact public contract.
9
9
 
10
- This skill follows the reviewed TiSynthEngine **1.0.0 beta working tree based on `95901c98af5353b86d9dc7c60b29ab9186b038cd` (2026-10-14)**, including uncommitted statistics changes. Eight official Markdown references and the raw statistics comparison record source hashes; [source notes](references/source-notes.md) and [snapshot metadata](references/source-snapshot.json) record the reviewed working-tree fingerprint, maintained navigation additions and exclusions. The reviewed Android and iOS source exposes eleven public methods and one event; this is not a claim about published packages. Inspect `getDefaults().limits` for `spatialX` and `spatialY` before offering binaural controls, and detect statistics methods before calling them; `apiVersion` alone does not distinguish installed beta builds.
11
-
12
- ## Visual and sound asset collaboration
13
-
14
- Use `ti-game-assets` to create/edit complete visual and sound asset sets, preserve art/acoustic palettes and provenance, validate alpha/frames/manifests, prepare exports, and coordinate variants and stereo event placement. `ti-game` governs native representation/motion/events; `ti-synthengine` governs synthesis and sound behavior with `ti.synthengine`. Both have equal domain authority. Read their relevant current references rather than duplicating manuals. Art alone does not require installing modules or adding sounds/mechanics.
10
+ These references describe the **public 1.0.0 release** at
11
+ `e7cbbe8a6f9ab38088fd8029c7b43cef6501101f` (reviewed 2026-10-24).
12
+ Download matching [Android](https://github.com/macCesar/TiSynthEngine/releases/tag/android-1.0.0)
13
+ and [iOS](https://github.com/macCesar/TiSynthEngine/releases/tag/ios-1.0.0)
14
+ packages from the public [repository](https://github.com/macCesar/TiSynthEngine).
15
+ Source/mirror hashes are in [source-snapshot.json](references/source-snapshot.json);
16
+ artifact checksums and native findings are in [source notes](references/source-notes.md).
17
+ The current [interactive example](assets/example/README.md) includes both helpers.
18
+ Earlier private packages also used version 1.0.0: require current methods and
19
+ install the official platform ZIPs rather than inferring capabilities from that
20
+ version string or adding a second JavaScript audio scheduler.
15
21
 
16
22
  ## Required workflow
17
23
 
18
- Read the references relevant to the task before proposing code. These are source snapshots, not an independent validation oracle: when reviewing the module or updating its official documentation, compare against the native contract and both renderers, then synchronize the references. Do not infer option names from Web Audio, another synthesizer, or general DSP libraries.
24
+ Read the relevant references before writing or reviewing code. When updating the module or its documentation, compare with both native platforms and the shared DSP before synchronizing these mirrors; a snapshot is not an independent correctness oracle.
19
25
 
20
26
  | Task | Read first |
21
27
  | --- | --- |
22
- | Any code using a public method, option, default, limit, or return value | [references/api.md](references/api.md) |
23
- | Position sounds in a headphone front plane, map spatial controls, or diagnose spatial/pan conflicts | [references/guide.md](references/guide.md#integrate-binaural-in-a-2d-app), [references/api.md](references/api.md), [references/audio-engine.md](references/audio-engine.md) |
24
- | Design a sound from an aesthetic description | [references/sound-design.md](references/sound-design.md), then [references/recipes.md](references/recipes.md) for a tuned starting point |
25
- | Build retro/arcade effects, a playable instrument, memory pads, layered chords, timbre comparisons, or cancellable repetition | [references/recipes.md](references/recipes.md), plus [references/api.md](references/api.md) |
26
- | Learn the official examples for tones, chords, tempo, patterns, noise, validation, startup, and cleanup | [references/examples.md](references/examples.md) |
27
- | Install the module, start it safely, or manage screen/app cleanup | [references/guide.md](references/guide.md) |
28
- | Choose a mixing profile, voice count, gain, latency strategy, or understand the signal path | [references/audio-engine.md](references/audio-engine.md), [references/recommendations.md](references/recommendations.md) |
29
- | Query/reset statistics, enable diagnostics, interpret render load/meters, or compare host performance | [references/api.md](references/api.md#getstats), [references/audio-engine.md](references/audio-engine.md#engine-statistics), [references/stats-performance.md](references/stats-performance.md), [raw trials](references/stats-performance.json) |
30
- | Diagnose `false`, silence, glitches, distortion, pattern replacement, or route changes | [references/troubleshooting.md](references/troubleshooting.md), [references/api.md](references/api.md) |
28
+ | Any public method, option, default, return value or limit | [API](references/api.md) |
29
+ | Download public releases, install, initialize, own or clean up an engine | [Guide](references/guide.md) |
30
+ | Design an effect, instrument, reward, alarm or game motor | [Sound design](references/sound-design.md), [recipes](references/recipes.md), [examples](references/examples.md) |
31
+ | Xylophone, memory pads, layered chords, FM instruments and interaction ownership | [Interaction recipes](references/recipes-interaction.md) |
32
+ | Hold, edit, release or position a sustained voice | [API](references/api.md#noteonoptions), [advanced examples](references/advanced-examples.md#sustained-game-motor) |
33
+ | Schedule simultaneous sequences, tempo, swing, edits and cancellation | [API transport](references/api.md#native-sequence-transport), [advanced examples](references/advanced-examples.md#native-sequence-with-chords-and-edits) |
34
+ | Select categories, sends, shared effects and synchronized LFOs | [Processing API](references/api.md#setmasterprocessingoptions), [engine](references/audio-engine.md), [advanced examples](references/advanced-examples.md) |
35
+ | Map headphone coordinates and stereo bypass | [Guide](references/guide.md#integrate-binaural-in-a-2d-app), [API](references/api.md) |
36
+ | Interpret gain, clipping, statistics or render performance | [Recommendations](references/recommendations.md), [statistics](references/stats-performance.md), [engine](references/audio-engine.md) |
37
+ | Diagnose rejection, silence, interruptions or glitches | [Troubleshooting](references/troubleshooting.md), [source notes](references/source-notes.md) |
38
+ | Accepted optimizations, rejected Apple runtime and physical performance limits | [Current performance review](references/performance-review.json), [engine](references/audio-engine.md), [source notes](references/source-notes.md) |
39
+ | Android binaural performance correction and its listening/load limits | [Current Sim80 correction](references/android-sim80-correction.json), [source notes](references/source-notes.md), [unified host validation](references/unified-validation.json), [bypass comparison](references/unified-bypass-performance.json) |
40
+ | Audit provenance and acceptance boundaries | [Snapshot](references/source-snapshot.json), [source notes](references/source-notes.md), [historical Studio report](references/studio-validation.json), [physical evidence](references/physical-validation.json), [Frontier measurements](references/frontier-physical-validation.json) |
41
+
42
+ Cite factual guidance with `[source: references/<file>.md]`. If the relevant source cannot be read, prefix the claim with `FROM_MEMORY (unverified):`; do not invent Web Audio or other synthesizer option names.
43
+
44
+ ## Response contract
45
+
46
+ Explain the waveform, envelope, pitch/filter motion and stereo choice briefly in the user's language. Include checked initialization if no engine owner exists, followed by focused production code. Comments and controls should explain meaningful sound choices. Obtain constants from the runtime:
47
+
48
+ ```javascript
49
+ const synth = require('ti.synthengine')
50
+ const contract = synth.getDefaults()
51
+ const WAVE = contract.waveTypes
52
+ if (!synth.start({maxVoices: 32, maxSequences: 4,
53
+ mixingProfile: 'conservative', audioSession: 'ambient'})) {
54
+ throw new Error('Audio engine rejected startup')
55
+ }
56
+ ```
31
57
 
32
- Cite factual guidance with `[source: references/<file>.md]`. If a relevant reference cannot be consulted, prefix the claim with `FROM_MEMORY (unverified):` instead of filling the gap silently.
58
+ The current iOS `getDefaults()` omits some capability and limit metadata reported by Android. Detect required methods and use the API ranges; a missing metadata flag is not proof of a missing method. [source: references/api.md]
33
59
 
34
- ## Response contract for sound requests
60
+ Choose the actual required sequence capacity, 1–4; the snippet's four slots suit games with simultaneous music, effects and cues. One engine and render callback share up to 32 voices. Start after screen layout settles; the owning service/window shuts down on teardown. On iOS, `ambient` respects silent mode and mixes with other apps; `playback` is the default and ignores silent mode. Profile, voice/sequence capacity and session require shutdown before changing them. [source: references/api.md]
35
61
 
36
- Answer in the user's language and use this order:
62
+ ## Scheduling contract
37
63
 
38
- 1. **Brief acoustic explanation.** Name the waveform, envelope, pitch movement or LFO, stereo movement, and why they create the requested perception.
39
- 2. **Safe initialization when needed.** If the surrounding code does not already own a running engine, show `require`, `getDefaults()`, a checked `startEngine()` call, and appropriate cleanup. For a screen startup, follow the post-layout lifecycle in the guide.
40
- 3. **Production JavaScript.** Return a focused, copyable block with short comments, exact option names, valid types and checked Boolean results.
64
+ - `playTone` is one timed event, `playChord` one simultaneous atomic chord, and `noteOn`/`noteOff`/`updateVoice` own sustained voices. `playSequence` is the only successive-sound scheduler. Do not add aliases or JavaScript note timers.
65
+ - `playSequence(options)` returns a positive identifier or `0`. `updateSequence({sequenceId,...changes})`, `stopSequence({sequenceId})` and `setTempo({bpm})` return Boolean acceptance. `getSequenceState({sequenceId})` returns applied revision/position or `null` for unknown/retired IDs. Acceptance can precede callback application.
66
+ - Sequence IDs do not repeat over module lifetime, including shutdown/start. Keep the accepted ID and cancel only the owner's sequence. An accepted stop does not immediately free capacity: coalesce replacement requests and publish the latest complete score after its matching `sequenceend`. A delayed event for an old ID must not change the new owner.
67
+ - `setTempo({bpm})` accepts 20–300, initially 120. It changes on the next block while conserving musical position. Synced delays/LFOs follow this tempo; free controls keep milliseconds/hertz.
68
+ - `timeUnit` is fixed for a sequence: `beats` by default, or `ms`. `stepDuration` defaults to 0.25 beats or 100 ms. `loop` defaults to false; circular Studio patterns explicitly pass true.
69
+ - Up to 512 steps each carry exactly one of MIDI `notes` (12–119), `frequencies`, or `rest:true`. Pitch arrays hold 1–32 values and permit duplicates for unison. Root shaping belongs in `voice`; per-step shaping belongs in `overrides`.
70
+ - Step `duration` changes the interval until the next attack. `gate`, initially 0.8, places release within that effective interval. Explicit `length` replaces gate and may overlap later attacks. Intervals and lengths follow the sequence time unit; ADSR remains in milliseconds without a sequence interval budget. Sweeps reach their target at note length and hold it during release.
71
+ - Swing −0.75…0.75 shifts `swing * min(A,B)` within a pair and preserves its total. Structural edits enter next step; swing next pair. Modes are normal/up/down/updown; rests participate only in normal mode.
72
+ - `sequenceend` carries `{sequenceId,reason:'completed'|'stopped'}` outside audio render. It does not establish audible silence: voice release and effect tails may remain.
41
73
 
42
- If the request cannot be represented by this synthesizer—audio-file playback, indefinite loops, per-voice control, streaming, or sample-accurate composition—say so and recommend the appropriate kind of audio engine instead of inventing an API. The same goes for reverb, delay, chorus and other effects: the module has no effect bus.
74
+ Preserve migrated score timing deliberately: a former total envelope of 150 ms with 25 ms release becomes `length:125` in a millisecond sequence, with `release:25`. Keep onset intervals separate. [source: references/api.md]
43
75
 
44
- ## Contract invariants
76
+ ## Voices, routes and continuous controls
45
77
 
46
- Start from the installed contract:
78
+ `bus` selects `music`, `effects` (default), `ui` or `ambience`. `setMasterProcessing({applyTo:[...]})` selects processed categories, initially all four; an empty array selects none. An explicit `effectSend:0…1` overrides the category selection for that voice. There is one shared chorus/delay/reverb/saturation chain. Input gain and master volume remain global. Selected audio receives processing, rejoins dry audio, and passes one final limiter. Effects and saturation start disabled. Disable closes input and retains bounded tails up to 30 seconds; panic invalidates histories. [source: references/api.md]
47
79
 
48
- ```javascript
49
- var synth = require('ti.synthengine')
50
- var contract = synth.getDefaults()
51
- var WAVE = contract.waveTypes
52
- ```
80
+ Sustained IDs are positive app-owned integers. Release on key up, touch cancellation, pause and teardown. Handle rejected release by retrying twice at 16 ms, then shut down/report if it still fails. These retry timers are lifecycle/error recovery, not a musical clock. Ended/stolen IDs accept edits as no-ops. [source: references/api.md]
53
81
 
54
- Never hardcode waveform integers when `WAVE.SINE`, `WAVE.SQUARE`, `WAVE.SAWTOOTH`, `WAVE.TRIANGLE`, `WAVE.NOISE`, and `WAVE.WAVETABLE` are available.
55
-
56
- - Option dictionaries are closed. Unknown or misspelled keys, wrong types, non-finite numbers, fractional values for integer fields, and out-of-range values make the entire call return `false`.
57
- - `playTone()` takes at most one pitch source: `note` or `frequency`. If neither is supplied, it defaults to 440 Hz. Never send both.
58
- - `playChord()` requires exactly one of `notes` or `frequencies`. It accepts `panSpread` or `pans`, the fixed shaping fields `noiseRate`, `lowPassHz`, `pulseWidth`, `waveTable`, and `bitDepth`, the fixed expressive fields `decay`, `sustain`, `filterType`, `filterHz`, `filterQ`, `fmRatio`, and `fmDepth`, and `detunes`, but no sweep, LFO, `detune`, or `*End` fields.
59
- - Every sounding `playPattern()` step needs exactly one of `note` or `frequency`; a rest uses exactly `rest: true`. Even a `NOISE` step needs a pitch field, although noise ignores its value. Pattern roots do not accept `duration`. Step `duration` overrides musical timing and controls both voice length and timeline advance; `stepDuration` is only a fallback. Use explicit rest steps for silence between short notes. [source: references/api.md]
60
- - `duration` includes attack, decay, the held level, and release. For explicit envelopes, `attack < duration` and `release <= duration - attack`.
61
- - `decay` (integer ms, 0 to 4000) and `sustain` (0 to 1) complete the ADSR envelope. `sustain` below 1 needs a `decay`. `attack + decay <= duration`, and the default 50 ms attack counts toward that budget. The release overlaps the decay and fades from wherever the level is.
62
- - `filterType` is `none`, `lowpass`, `highpass` or `bandpass`. `filterHz` (20 Hz up to the frequency limit), `filterQ` (0.5 to 10) and `filterHzEnd` (0 or 20 Hz up, an exponential sweep) are rejected while no filter type is active. This filter is separate from, and runs after, the one-pole `lowPassHz`. A chord has no `filterHzEnd`.
63
- - FM is `fmDepth` (modulation index, 0 to 10), `fmRatio` (0.1 to 16) and an optional `fmDepthEnd`; unlike the other `*End` keys, 0 is a real target, so omit the key for no sweep. Only `WAVE.SINE` can carry FM, and `fmRatio` without a depth is rejected.
64
- - `detune` (cents, -1200 to 1200) works on `playTone` and `playPattern`. `playChord()` uses `detunes`, an array aligned with the pitches. The detuned pitch, and any `frequencyEnd` target, must stay inside the frequency limits.
65
- - `patternend` is an event, not a method: it fires once per accepted `playPattern()` with `{ completed: true }` at the natural end, or `{ completed: false }` when a newer pattern replaces it. `stopAll()` and `shutdown()` fire nothing. Remove the listener when the owner closes.
66
- - `spatialX` (left/right) and `spatialY` (below/above) are finite numbers from -1 to 1 on `playTone`, `playChord`, and `playPattern` roots/steps. Supplying either enables binaural processing, with 0 for the omitted coordinate; omitting both preserves stereo. A chord shares one fixed position. Never combine coordinates with `pan`, `panEnd`, `pans` or `panSpread`, even through pattern inheritance: the call returns `false` with `conflicting_spatial_fields`. [source: references/api.md]
67
- - A binaural switch and percentage sliders belong to the app. For direct direction sliders, divide signed percentages from -100 to 100 by 100. For amplitude sliders from 0 to 100%, multiply each source's normalized coordinate by the percentage divided by 100; 100% height does not move every source above. Route every effect that should be spatial through that conversion, preserving its synthesis recipe, then send only the coordinates when enabled. When disabled, omit both coordinates; sending two zeros still enables binaural processing. The module has no separate switch option. Positions stay fixed for each event; later events can use updated coordinates. Test with stereo headphones and broadband sounds; the front plane has no rear sources, distance attenuation, room reflections or head tracking. [source: references/api.md]
68
- - `pan` and `panEnd` range from -1 to 1. `frequencyEnd` accepts 0 through the frequency maximum; targets below 1 Hz disable the linear sweep. `lfoFreq` is the modulation rate in Hz and `lfoDepth` is absolute pitch deviation in Hz, not cents.
69
- - `WAVE.WAVETABLE` requires `waveTable`: 2 to 64 finite values from -1 to 1, stepped without interpolation. `bitDepth` is 0 or an integer from 2 to 16; `pulseWidth` is 0.05 to 0.95 and only shapes `SQUARE`; `pulseWidthEnd` is 0 or 0.05 to 0.95. For `noiseRate`, `noiseRateEnd`, and `lowPassHz`, 0 means white noise, no sweep, or no filter.
70
- - `startEngine()`, `playTone()`, `playChord()`, `playPattern()`, and `setVolume()` return `Boolean`; production code must handle rejection where it matters.
71
- - `getStats()` returns a snapshot without resetting it; `resetStats()` returns nothing and does not stop playback. `setStatsEnabled(enabled)` accepts a Boolean and returns Boolean acceptance. Detect each method with `typeof synth.<method> === 'function'` when supporting older beta binaries. Basic occupancy/queue/rejection counters remain available with diagnostics off; optional render-load timing and output peak/RMS/limiter measurements default off. Android backend underrun/buffer/latency fields are best-effort and independent of that switch. Preserve `null` for unavailable or unmeasured fields: it is not zero. Poll slowly (for example, 5 Hz), cancel the timer with its owner and disable diagnostics when no owner needs them. Render load is callback elapsed work, not total app CPU; Android host comparisons do not establish iOS/device performance, physical underruns, heat or battery behavior. [source: references/api.md] [source: references/audio-engine.md] [source: references/stats-performance.md]
72
- - Only one pattern can remain pending. A new pattern replaces future steps from the previous one. `stopAll()` fades active voices but does not cancel scheduled steps; `shutdown()` does both and frees the stream.
73
-
74
- ## Acoustic decision guide
75
-
76
- Use these as starting regions, then keep every explicit value inside the API limits and the envelope intersection:
77
-
78
- | Intent | Starting design |
79
- | --- | --- |
80
- | Clean UI click or feedback | `SINE` or `TRIANGLE`, roughly 30–120 ms, 1–5 ms attack, short fitted release |
81
- | Retro pickup or melody | `SQUARE`, short notes or a rising `playPattern()`; a narrow `pulseWidth` or a `pulseWidthEnd` sweep thins it, `bitDepth` adds grit |
82
- | Retro bass | `TRIANGLE`, lower pitch, short attack and controlled release |
83
- | Hit, hat, explosion texture | `NOISE`, immediate attack and short-to-medium release; lower `noiseRate` or `lowPassHz` darkens it; layer only when the overlap budget allows |
84
- | Coarse DAC-like or buzzy custom voice | `WAVETABLE` with a short asymmetric `waveTable`, optionally with `bitDepth` |
85
- | Alarm or urgent cue | `SAWTOOTH`, repeated pitches, a sweep, or vibrato around 4–7 Hz; use larger `lfoDepth` only for an obvious effect |
86
- | Laser or sci-fi movement | One `frequency` plus `frequencyEnd`, short attack, fitted release, optional `pan` → `panEnd` |
87
- | Headphone cue above/right or below/left | Use `spatialX`/`spatialY` on a broadband sound, without stereo pan fields; verify perceived direction with headphones |
88
- | Pad or atmosphere | One `playChord()` with `SINE` or `TRIANGLE`, 2000 ms or longer, 300–600 ms attack, 800–1500 ms release when it fits |
89
- | Plucked string, marimba or keyboard note | `TRIANGLE` or `SINE`, 2 ms attack, `decay` 120–400 ms, `sustain` 0 to 0.3, release that fits |
90
- | Electric piano, bell or metallic hit | `SINE` with `fmDepth` that falls to `fmDepthEnd: 0`; `fmRatio` 1, 2 or 3.5 for tine-like tones, a non-integer ratio for bells; add `decay` and a low `sustain` |
91
- | Wah, wind or filter sweep | `SAWTOOTH` or `NOISE` through `filterType: 'bandpass'` or `'lowpass'`, `filterHz` to `filterHzEnd`, `filterQ` 2 to 6 |
92
- | Thick unison pad or supersaw | `playChord()` with the same pitch repeated and `detunes` of ±5 to ±12 cents; keep the gain staging in mind |
93
-
94
- A4 is 440 Hz under twelve-tone equal temperament; each octave doubles or halves frequency. Upward sweeps tend to read as activation, reward, or energy gain; downward sweeps tend to read as dismissal, power-down, or impact. Treat pan as supporting detail because many phone speakers collapse the stereo image.
95
-
96
- For playable controls, trigger one event when the finger enters a new key, not on every `touchmove`. For simultaneous musical voices, prefer one atomic `playChord()` call; use `detunes` (cents per pitch) when a layered sound needs beating. Cancel app-owned timers before stopping voices or shutting down the engine. [source: references/recipes.md]
97
-
98
- ## Mixing and lifecycle defaults
99
-
100
- - Begin with `mixingProfile: 'conservative'`; use `balanced` mainly for one or two voices, `speakerSafe` for demanding small speakers, and `raw` only when the app owns gain staging.
101
- - Size `maxVoices` for the largest real overlap, including release tails. Capacity is not loudness.
102
- - On iOS, the default `audioSession: 'playback'` ignores the silent switch and interrupts other apps' audio. Pass `audioSession: 'ambient'` to `startEngine()` when a game should respect the switch and mix with other apps; Android validates the value and ignores it. Profile, voice count, and session are fixed until `shutdown()`.
103
- - Use one engine owner. On a Titanium screen, start after layout settles and call `shutdown()` when the owner closes.
104
- - Test on the actual output path. Headphones expose noise and stereo detail; small phone speakers expose weak bass, resonance, and acoustic distortion that a digital limiter cannot repair.
105
-
106
- ## Before returning code
107
-
108
- - Re-read the exact method table in `references/api.md`; remove every unsupported property.
109
- - Confirm pitch fields are mutually exclusive and numeric values are finite and in range.
110
- - Compute the envelope intersection explicitly, including `attack + decay <= duration`.
111
- - Check the cross-field rules: `sustain` below 1 needs a `decay`, filter fields need a `filterType`, FM needs a sine and a depth.
112
- - Check installed spatial limits before using binaural coordinates; remove conflicting stereo fields at both pattern root and step. Omit coordinates when the app switch is off.
113
- - Use `WAVE` constants from `getDefaults()`.
114
- - Use `playChord()` for one simultaneous musical event instead of several hotter independent tones.
115
- - Include startup and cleanup only at the ownership level relevant to the request.
116
- - Cite the references that support the acoustic and API choices.
82
+ Compatible `updateVoice` fields include frequency, volume, vibrato, resonant filter targets, pulse width, FM, modulations, `noiseRate`, `lowPassHz`, stereo/spatial position and `effectSend`. Transitions take 10 ms and preserve phase, spatial history and the current envelope. `noiseRate:0` is white noise; `lowPassHz:0` bypasses its one-pole filter. Spatial updates require a voice started spatially; stereo `pan` applies to a stereo voice. Do not combine spatial coordinates with stereo pan fields. [source: references/api.md]
83
+
84
+ `priority:0…3`, initially 0, controls eligible replacement under the shared voice pool. Higher priorities remain protected. Chords are admitted or discarded completely; there are no reserved per-category quotas. Gain is fixed per event, with initial chord compensation. Starting unrelated voices does not normalize earlier voices. [source: references/api.md]
85
+
86
+ ## Sound and validation rules
87
+
88
+ - Closed option dictionaries reject unknown keys, wrong types, non-finite/out-of-range values and fractional integer fields. Check acceptance at meaningful boundaries; never silently clamp native options.
89
+ - A tone uses at most one of note/frequency; a chord uses exactly one notes/frequencies array. Tone/chord note names differ from sequence MIDI integers.
90
+ - Timed tone/chord `duration` includes release: explicit attack must be shorter, release must fit after attack, and attack+decay must fit. `sustain < 1` requires decay. Held/sequence ADSR has its own documented rules.
91
+ - FM requires sine; enabled filter fields require a filter type. `fmDepthEnd:0` is a real target, so omit it to disable a sweep. Plain tone FM ratio requires active depth; held/sequence FM-target modulation can start at zero depth.
92
+ - WAVETABLE needs 2–64 samples in −1…1. `bitDepth` is 0 or integer 2–16. Pulse width shapes square voices. Read the exact discontinuous ranges and source rules in the API.
93
+ - Up to two native sine/triangle LFOs target filterHz, pulseWidth or fmDepth. Free rates and tempo sync are distinct. Empty modulations disables them; omission on update preserves them.
94
+ - Use noise for impacts/wind, square for retro rewards, triangle for bass/plucks, sine FM for bells/keys, and filtered saw/noise for moving textures. Keep gains modest enough for release overlap and coherent unison. Listen on the actual speaker/headphones before approving timbre.
95
+
96
+ Binaural coordinates span a headphone front plane. Omit both spatial keys to bypass; two zeros still enable binaural center. Map app percentages explicitly and preserve pitch/envelope recipes. Height perception depends on the listener and sound spectrum; output remains stereo without rear sources, room reflections or head tracking. [source: references/api.md]
97
+
98
+ Timed zero attack/release and rejection diagnostics currently differ between native platforms. Check API acceptance directly; do not infer sample-identical envelopes or a complete rejection tally from validator parity. Read [source notes](references/source-notes.md) for independently rechecked findings. [source: references/api.md]
99
+
100
+ Diagnostics are opt-in. Preserve unavailable/null readings; poll UI slowly and clean up its timer. Render load is callback work divided by deadline, not app CPU. Historical host reports, validator parity and hash equality do not establish current physical real-time or listening acceptance. Keep technical results and César's auditory acceptance separate. [source: references/audio-engine.md] [source: references/source-notes.md]
101
+
102
+ Use `ti-game` for native movement/physics and `ti-game-assets` for related visual/audio asset production. Audio scheduling remains in TiSynthEngine; do not change gameplay or install on physical devices without the task's authorization.
@@ -0,0 +1,84 @@
1
+ > Source snapshot: official TiSynthEngine 1.0.0 documentation at release source commit `e7cbbe8a6f9ab38088fd8029c7b43cef6501101f` (2026-10-24). Upstream `example/README.md` SHA-256: `c3c5041be11c3addfab7fb1248c0aaba81b311c1720c2861e47974412d743bcf`.
2
+
3
+ # Interactive example
4
+
5
+ The Classic Titanium app in [app.js](app.js) demonstrates the timed sounds, native sequences and statistics with the `sequenceend` event on Android and iOS. It uses the current 1.0.0 module packages, including binaural and statistics support. Held voices, master processing and voice LFOs have copyable examples in the [advanced documentation](../../references/advanced-examples.md#sustained-game-motor); this reference app does not expose those newer controls. The default engine configuration is 16 voices, `conservative` mixing and the `playback` session; master volume starts at 100% and optional diagnostics start off.
6
+
7
+ ## Run it
8
+
9
+ 1. Create a Classic Titanium application with Android and/or iOS support. If the app uses Alloy, create a separate Classic test project and leave the Alloy-generated files in place.
10
+ 2. Download matching official [Android 1.0.0](https://github.com/macCesar/TiSynthEngine/releases/tag/android-1.0.0) and [iOS 1.0.0](https://github.com/macCesar/TiSynthEngine/releases/tag/ios-1.0.0) packages, or build the matching module source. Source builds produce `android/dist/ti.synthengine-android-1.0.0.zip` and `ios/dist/ti.synthengine-iphone-1.0.0.zip`.
11
+ 3. Put the archive for each target platform in the test app root. Add these entries inside its `tiapp.xml`:
12
+
13
+ ```xml
14
+ <modules>
15
+ <module platform="android" version="1.0.0">ti.synthengine</module>
16
+ <module platform="iphone" version="1.0.0">ti.synthengine</module>
17
+ </modules>
18
+ ```
19
+
20
+ 4. Copy the entire `example/` folder into the test app's `Resources/`, including [app.js](app.js), [sequenceScore.js](lib/sequenceScore.js) and [sequenceOwner.js](lib/sequenceOwner.js). It needs no images or audio files.
21
+ 5. Build and run the test app with the Titanium CLI or your existing Titanium launch configuration. Use Titanium SDK 13.2.0.GA or newer, Android compile API 35 or newer, and iOS 15 or newer. See the [module installation guide](../../references/guide.md#install-the-module).
22
+
23
+ The example checks the installed API version, spatial limits and all three statistics methods before constructing the screen. If it requests current packages, replace the native module, then rebuild and reinstall the app; copying module files alone does not update an app already on a device.
24
+
25
+ Audio starts after the first layout settles. Sound controls report native rejections. If startup fails, the session buttons remain available to retry. Closing the window removes its sequence listener, clears startup/statistics timers, disables diagnostics and shuts down the engine. The example plays finite sounds in the foreground and does not demonstrate background audio. Turn diagnostics off before leaving it in the background.
26
+
27
+ ## Synthesis and sequencing
28
+
29
+ - Compare all six waveforms and equivalent English/solfege note names.
30
+ - Try stereo pan, pitch sweep, vibrato, variable-rate noise, pulse width, custom wavetable and quantization.
31
+ - Compare atomic chords with explicit pans, matched arpeggios, tempo/swing and noise percussion.
32
+ - Hear decay/sustain, resonant filtering, FM bell/electric piano and detuned voices.
33
+
34
+ Keep system volume moderate while comparing sounds. Master BOOST intentionally raises the bus above unity; use the 100% control to restore it. Repeated taps overlap events and may cause limiting or voice replacement.
35
+
36
+ ## Headphone positioning
37
+
38
+ Use stereo headphones. In the binaural section, compare each of the nine noise positions one at a time: left/right runs from -1 to 1, above/below from 1 to -1. The center still uses binaural processing. Elevation perception varies with the listener and headphones, so the controls cannot guarantee localization for each person.
39
+
40
+ Select STEREO MODE and repeat points with the same horizontal position. Their height no longer affects placement because both spatial keys are omitted. BINAURAL MODE restores per-event coordinates. These two modes affect this section only; the ordinary stereo demos remain unchanged. An active voice keeps its original position.
41
+
42
+ SPATIAL CHORD places the whole chord above/right. SPATIAL PATTERN places three broadband hits above/left, below/center and above/right using per-step coordinates. Neither sends stereo pan fields while binaural is active. The output remains two channels on a front plane, without rear positioning, distance attenuation or head tracking. See the [app integration guide](../../references/guide.md#integrate-binaural-in-a-2d-app) for source mapping and amplitude sliders.
43
+
44
+ ## Audio session
45
+
46
+ On iOS, compare PLAYBACK SESSION and AMBIENT SESSION. Changing the selection shuts down the engine, silently cancels any pending pattern, starts the new policy and restores the selected master volume. It does not resume the previous sound. The policy is fixed while the stream runs; a second `start()` alone cannot change it.
47
+
48
+ On an iOS device, play music from another app and try a short sound in ambient mode; compare with playback. Also compare the device's silent mode where available. Ambient should respect silent mode and mix with other apps; playback ignores silent mode and normally interrupts their audio. Android validates both strings but does not change its output. Simulator behavior does not establish the physical silent-mode, interruption or route behavior.
49
+
50
+ ## Sequence completion and cancellation
51
+
52
+ 1. Tap PATTERN END and wait for `sequenceend: completed`.
53
+ 2. Tap it twice quickly. The example requests stop for its accepted sequence, coalesces repeated taps to the latest complete score, and publishes it only after the matching retirement event frees capacity. Native `sequenceend` events report `{ sequenceId, reason: 'completed' | 'stopped' }`.
54
+ 3. Selecting a session shuts down the engine and restarts it with the selected policy. Events already queued for JavaScript can still arrive.
55
+ 4. STOP ALL releases active voices and cancels future attacks. Closing the example shuts down its engine.
56
+
57
+ All successive attacks run on the native sample clock. The example compiles its note-name scores to millisecond sequences with explicit `duration` and `length`, preserving the original interval and release onset. Each sequence has one of `frequencies`, MIDI `notes`, or `rest: true` per step, with sound shaping in `voice`/`overrides`. Copy the entire `example/` folder, including `lib/sequenceScore.js` and `lib/sequenceOwner.js`, into a Classic app's Resources folder.
58
+
59
+ Completion marks the final scheduled step; releases and shared effect tails can remain audible. See the [event contract](../../references/api.md#sequenceend-event).
60
+
61
+ ## Statistics
62
+
63
+ - READ STATS takes a fresh snapshot without resetting counters or enabling diagnostics.
64
+ - TOGGLE DIAGNOSTICS enables callback timing and signal meters, refreshing at 5 Hz. Toggle it off to stop the timer and optional measurements; basic counters remain available.
65
+ - RESET STATS clears accumulated statistics without stopping voices, cancelling queued work or changing the diagnostic switch. The next callback applies render-owned resets.
66
+
67
+ The panel shows active/peak/spatial/tail voices, pending commands, replacements, request/publication rejections, priority drops, callback load, stereo output peak and backend underruns. It displays `n/a` for unmeasured or unavailable values, keeping them distinct from zero. Signal windows need about 200 ms of output after enabling. Native snapshots also include RMS, limiter reduction, sample rate, buffer and latency fields; consult the [complete field reference](../../references/api.md#getstats) when integrating a full diagnostic view.
68
+
69
+ Render load divides callback elapsed time by the audio budget for that block; it does not measure total app CPU. The panel multiplies the native fraction by 100, so a reading of 1.20% means that fraction of the block budget, not 120%.
70
+
71
+ Even with zero voices, the stream renders silent blocks and runs the output/limiter and any enabled diagnostics. Expect a small, changing baseline. The two decimal places are display formatting and do not guarantee that precision.
72
+
73
+ Compare readings on the same device with the same configuration and load; simulator and phone readings are not equivalent. Android backend metrics are best-effort. This iOS backend has no underrun/buffer/latency measurement, and a clean counter cannot establish sound quality.
74
+
75
+ ## Checks and limits
76
+
77
+ Run these focused checks from the module repository root:
78
+
79
+ ```sh
80
+ node tests/documentation_regression.js
81
+ node --test tests/example_app_regression.js
82
+ ```
83
+
84
+ The example regression executes its real action callbacks with simulated Titanium UI/audio boundaries. It covers rejection feedback, placement/bypass, session restart and gain preservation, diagnostic cleanup and close-before-start. It does not render native audio or establish layout, perceived elevation, silent-mode behavior or sound quality. Use the device checklist above, including headphones and an output-route change, before claiming those results.