@maccesar/titools 5.2.0 → 5.2.2

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 (81) hide show
  1. package/CONTRIBUTING.md +82 -0
  2. package/README.md +83 -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/commands/uninstall.js +19 -16
  8. package/lib/commands/update.js +1 -1
  9. package/lib/downloader.js +1 -1
  10. package/lib/utils.js +2 -0
  11. package/package.json +4 -2
  12. package/skills/purgetss/references/multi-density-images.md +1 -1
  13. package/skills/ti-admob-unified/SKILL.md +21 -7
  14. package/skills/ti-admob-unified/assets/example/app.js +229 -25
  15. package/skills/ti-admob-unified/assets/example/lib/ads.js +30 -2
  16. package/skills/ti-admob-unified/assets/example/library-usage.js +33 -1
  17. package/skills/ti-admob-unified/references/api-reference.md +39 -16
  18. package/skills/ti-admob-unified/references/banners.md +9 -9
  19. package/skills/ti-admob-unified/references/contributing.md +14 -9
  20. package/skills/ti-admob-unified/references/dependencies.md +31 -25
  21. package/skills/ti-admob-unified/references/fullscreen.md +43 -28
  22. package/skills/ti-admob-unified/references/game-monetization.md +138 -7
  23. package/skills/ti-admob-unified/references/getting-started.md +75 -31
  24. package/skills/ti-admob-unified/references/index.md +5 -2
  25. package/skills/ti-admob-unified/references/integration.md +8 -6
  26. package/skills/ti-admob-unified/references/library.md +41 -10
  27. package/skills/ti-admob-unified/references/mediation-parity.md +17 -0
  28. package/skills/ti-admob-unified/references/mediation.md +22 -9
  29. package/skills/ti-admob-unified/references/migration.md +11 -7
  30. package/skills/ti-admob-unified/references/module-changelog.md +41 -11
  31. package/skills/ti-admob-unified/references/privacy.md +35 -8
  32. package/skills/ti-admob-unified/references/production.md +67 -0
  33. package/skills/ti-admob-unified/references/rewarded-interstitial.md +101 -0
  34. package/skills/ti-admob-unified/references/roadmap.md +28 -31
  35. package/skills/ti-admob-unified/references/source-notes.md +51 -4
  36. package/skills/ti-admob-unified/references/source-snapshot.json +249 -45
  37. package/skills/ti-admob-unified/references/third-party-notices.md +4 -4
  38. package/skills/ti-game/SKILL.md +23 -6
  39. package/skills/ti-game/references/api.md +34 -30
  40. package/skills/ti-game/references/debugging-performance.md +18 -9
  41. package/skills/ti-game/references/examples.md +103 -20
  42. package/skills/ti-game/references/input.md +101 -0
  43. package/skills/ti-game/references/patterns.md +39 -15
  44. package/skills/ti-game/references/physics.md +80 -52
  45. package/skills/ti-game/references/project-setup.md +118 -56
  46. package/skills/ti-game/references/recipes-action.md +107 -8
  47. package/skills/ti-game/references/recipes-adventure-effects.md +41 -9
  48. package/skills/ti-game/references/roadmap.md +10 -3
  49. package/skills/ti-game/references/source-notes.md +81 -0
  50. package/skills/ti-game/references/tilemaps.md +12 -4
  51. package/skills/ti-synthengine/SKILL.md +81 -95
  52. package/skills/ti-synthengine/assets/example/README.md +84 -0
  53. package/skills/ti-synthengine/assets/example/app.js +1178 -0
  54. package/skills/ti-synthengine/assets/example/lib/sequenceOwner.js +83 -0
  55. package/skills/ti-synthengine/assets/example/lib/sequenceScore.js +25 -0
  56. package/skills/ti-synthengine/references/advanced-examples.md +174 -0
  57. package/skills/ti-synthengine/references/android-sim80-correction-evidence.zip +0 -0
  58. package/skills/ti-synthengine/references/android-sim80-correction.json +162 -0
  59. package/skills/ti-synthengine/references/api.md +434 -380
  60. package/skills/ti-synthengine/references/audio-engine.md +157 -230
  61. package/skills/ti-synthengine/references/bypass-physical-recheck-evidence.zip +0 -0
  62. package/skills/ti-synthengine/references/examples.md +123 -253
  63. package/skills/ti-synthengine/references/frontier-android-evidence.zip +0 -0
  64. package/skills/ti-synthengine/references/frontier-ipad-evidence.zip +0 -0
  65. package/skills/ti-synthengine/references/frontier-physical-validation.json +1918 -0
  66. package/skills/ti-synthengine/references/guide.md +188 -156
  67. package/skills/ti-synthengine/references/performance-review-evidence.zip +0 -0
  68. package/skills/ti-synthengine/references/performance-review.json +1146 -0
  69. package/skills/ti-synthengine/references/physical-validation.json +1457 -0
  70. package/skills/ti-synthengine/references/recipes-interaction.md +549 -0
  71. package/skills/ti-synthengine/references/recipes.md +423 -599
  72. package/skills/ti-synthengine/references/recommendations.md +63 -113
  73. package/skills/ti-synthengine/references/sound-design.md +134 -258
  74. package/skills/ti-synthengine/references/source-notes.md +93 -105
  75. package/skills/ti-synthengine/references/source-snapshot.json +379 -32
  76. package/skills/ti-synthengine/references/stats-performance.md +64 -20
  77. package/skills/ti-synthengine/references/studio-validation.json +6202 -0
  78. package/skills/ti-synthengine/references/troubleshooting.md +109 -121
  79. package/skills/ti-synthengine/references/unified-bypass-performance.json +22425 -0
  80. package/skills/ti-synthengine/references/unified-validation.json +314 -0
  81. package/AGENTS-VERCEL-RESEARCH.md +0 -175
@@ -1,117 +1,77 @@
1
- > Source snapshot: official TiSynthEngine 1.0.0 beta documentation from the reviewed working tree based on `95901c98af5353b86d9dc7c60b29ab9186b038cd` (2026-10-14), including uncommitted statistics changes. Upstream `documentation/recommendations.md` SHA-256: `0f09ee6ef0876b3a23021fddb509dfd1e1206d08e836acae8f32b58b6481c055`.
1
+ > Source snapshot: official TiSynthEngine 1.0.0 documentation at release source commit `e7cbbe8a6f9ab38088fd8029c7b43cef6501101f` (2026-10-24). Upstream `documentation/recommendations.md` SHA-256: `206593e03b860b2d1c39316bf286cd276307bdb0120be050c262b21749bcccd8`.
2
2
 
3
3
  # Recommendations
4
4
 
5
- The defaults work for ordinary tones and chords. The choices below matter when
6
- an app has dense overlap, user-controlled values, demanding speakers or several
7
- audio systems sharing one lifecycle.
5
+ The defaults work for ordinary tones and chords. The choices below matter when an app has dense overlap, user-controlled values, demanding speakers or several audio systems sharing one lifecycle.
8
6
 
9
7
  ## Group simultaneous notes
10
8
 
11
- Use `playChord()` when pitches form one known simultaneous event. The chord is
12
- atomic. Protected profiles normalize per-voice source gain by the square root
13
- of the event voice count; `raw` bypasses that normalization. Separate `playTone()`
14
- calls are appropriate for independent touches and effects, but their start
15
- times and gain are independent too.
9
+ Use `playChord()` when pitches form one known simultaneous event. The chord is atomic. Protected profiles normalize per-voice source gain by the square root of the event voice count; `raw` bypasses that normalization. Separate `playTone()` calls are appropriate for independent touches and effects, but their start times and gain are independent too.
16
10
 
17
- For keys or pads a user can trigger freely, keep each event around 0.4 to 0.7
18
- until the worst overlap has been heard. Raising every event above 1 is usually
19
- a sign that the session needs `balanced`, not that each note needs more gain.
11
+ For keys or pads a user can trigger freely, keep each event around 0.4 to 0.7 until you have listened to the worst overlap. If every event needs gain above 1, consider `balanced` for the session before raising individual notes further.
20
12
 
21
13
  ## Choose the mixing profile once
22
14
 
23
- | Situation | Profile |
24
- | --- | --- |
25
- | General app audio and chords | `conservative` |
26
- | Mostly single notes that need more level | `balanced` |
27
- | Low pitches or distortion from a small phone speaker | `speakerSafe` |
28
- | The app performs its own strict gain staging | `raw` |
15
+ | Situation | Profile |
16
+ | ---------------------------------------------------- | -------------- |
17
+ | General app audio and chords | `conservative` |
18
+ | Mostly single notes that need more level | `balanced` |
19
+ | Low pitches or distortion from a small phone speaker | `speakerSafe` |
20
+ | The app performs its own strict gain staging | `raw` |
29
21
 
30
- The profile is fixed for the stream. Changing it requires `shutdown()` and a
31
- new `startEngine()` call, so it should not be a live sound-design control.
22
+ The profile is fixed for the stream. Changing it requires `shutdown()` and a new `start()` call, so it should not be a live sound-design control.
32
23
 
33
- If a phone buzzes under `speakerSafe`, lower the event volume or raise the
34
- pitch. Small drivers can distort acoustically even when the digital output is
35
- well below its ceiling.
24
+ If a phone buzzes under `speakerSafe`, lower the event volume or raise the pitch. Small drivers can distort acoustically even when the digital output is well below its ceiling.
36
25
 
37
26
  ## Size `maxVoices` for real overlap
38
27
 
39
28
  `maxVoices` controls capacity. It does not make the engine louder or quieter.
40
29
 
41
- | App behavior | Starting value |
42
- | --- | ---: |
43
- | Occasional interface feedback | 4 to 8 |
44
- | Game effects with overlap | 8 to 16 |
45
- | Chords, keys or long release tails | 16 to 24 |
46
- | Explicit stress testing | 32 |
30
+ | App behavior | Starting value |
31
+ | ---------------------------------- | -------------: |
32
+ | Occasional interface feedback | 4 to 8 |
33
+ | Game effects with overlap | 8 to 16 |
34
+ | Chords, keys or long release tails | 16 to 24 |
35
+ | Explicit stress testing | 32 |
47
36
 
48
- Count release tails, not just buttons pressed at the same instant. A new voice
49
- steals the slot with the least time remaining when the pool is full. The short
50
- fade prevents a hard click but cannot preserve the stolen note.
37
+ Count release tails along with buttons pressed at the same instant. Replacement first selects the lowest eligible priority; higher-priority voices are protected. Among that priority, timed-only events steal the slot with the least time remaining; sustained/transport voices prefer a releasing slot, then the oldest attack. The short fade avoids a hard click; the stolen note still ends early.
51
38
 
52
39
  ## Keep one lifecycle owner
53
40
 
54
- Require the module in one audio service or controller, start it after the first
55
- layout settles, and shut it down from the same owner. This avoids an engine that
56
- outlives its window or a timer that starts after cleanup.
41
+ Require the module in one audio service or controller, start it after the first layout settles, and shut it down from the same owner. This avoids an engine that outlives its window or a timer that starts after cleanup.
57
42
 
58
- A 250 ms debounce after `postlayout` is a practical baseline for a plain
59
- screen. Heavy startup work, advertisements or entry animations may need more.
60
- Measure the real app instead of increasing the delay indefinitely.
43
+ A 250 ms debounce after `postlayout` is a practical baseline for a plain screen. Heavy startup work, advertisements or entry animations may need more. Measure the real app instead of increasing the delay indefinitely.
61
44
 
62
- Route recovery is automatic. Do not call `shutdown()` just because headphones
63
- were inserted or removed. The sound crossing the transition may end early;
64
- play later sounds normally once the system has moved to the new route.
45
+ Route recovery is automatic. Do not call `shutdown()` just because headphones were inserted or removed. The sound crossing the transition may end early; play later sounds normally once the system has moved to the new route.
65
46
 
66
47
  ## Coexisting with other audio
67
48
 
68
- On iOS, the audio session is app-wide and the last component to configure it
69
- wins. By default TiSynthEngine selects `Playback`, which ignores the ring/silent
70
- switch and normally interrupts other apps. That behavior fits an instrument or
71
- an app whose sound must be heard.
49
+ On iOS, the audio session is app-wide and the last component to configure it wins. By default TiSynthEngine selects `Playback`, which ignores the ring/silent switch and normally interrupts other apps. That behavior fits an instrument or an app whose sound must be heard.
72
50
 
73
- A game that should respect the silent switch and let other apps' music keep
74
- playing starts the engine with the ambient session:
51
+ A game that should respect the silent switch and let other apps' music keep playing starts the engine with the ambient session:
75
52
 
76
53
  ```javascript
77
- synth.startEngine({ audioSession: 'ambient' })
54
+ synth.start({ audioSession: 'ambient' })
78
55
  ```
79
56
 
80
- The engine applies the category at startup and again when it resumes after a
81
- route change. Other native audio modules may still configure the app-wide
82
- session later. Test the final startup sequence, interruptions, background
83
- behavior and route changes on iOS. Android accepts the option and ignores it.
57
+ The engine applies the category at startup and again when it resumes after a route change. Other native audio modules may still configure the app-wide session later. Test the final startup sequence, interruptions, background behavior and route changes on iOS. Android accepts the option and ignores it.
84
58
 
85
- Android mixes independent output streams at the system level, but another app
86
- or stale test process can still consume low-latency resources. Force-stop old
87
- test builds when diagnosing a glitch that does not reproduce after reboot.
59
+ Android mixes independent output streams at the system level, but another app or stale test process can still consume low-latency resources. Force-stop old test builds when diagnosing a glitch that does not reproduce after reboot.
88
60
 
89
61
  ## Keep resonance, FM and detune in check
90
62
 
91
- The resonant filter, FM and stacked detuned voices change level and spectrum
92
- more than the basic controls do.
93
-
94
- - A `lowpass` or `highpass` boosts the cutoff region by about `filterQ`, so Q
95
- 10 is roughly 20 dB. Raise Q in small steps and lower the event `volume` as
96
- you go. `bandpass` keeps unity gain at its center when level must stay put.
97
- - A swept cutoff passes over every harmonic, so the level moves during the
98
- sweep. Judge a wah or laser by the loudest moment, not the start.
99
- - A resonance that keeps reaching the limiter makes the whole mix pump. Lower
100
- the volume or the Q before reaching for a different profile.
101
- - FM is not band-limited. A high carrier with a large `fmDepth` and `fmRatio`
102
- aliases. Keep carriers of bell-like sounds around 500 Hz, or lower the index.
103
- - A detuned stack is one voice per copy. Count them when choosing `maxVoices`.
104
- Protected profiles divide per-voice source gain by the square root of the
105
- event voice count; `raw` does not. Correlated or phase-aligned voices can still
106
- reinforce each other, so this is not a guarantee of constant loudness or peaks.
107
- - `patternend` follows the pattern scheduler. Use it to chain cues and release
108
- state, not to line up audio to the sample.
63
+ The resonant filter, FM and stacked detuned voices change level and spectrum more than the basic controls do.
64
+
65
+ - A `lowpass` or `highpass` boosts the cutoff region by about `filterQ`, so Q 10 is roughly 20 dB. Raise Q in small steps and lower the event `volume` as you go. `bandpass` keeps unity gain at its center when level must stay put.
66
+ - A swept cutoff passes over every harmonic, so the level moves during the sweep. Judge a wah or laser at its loudest moment, which may occur after the start.
67
+ - A resonance that keeps reaching the limiter makes the whole mix pump. Lower the volume or the Q before reaching for a different profile.
68
+ - FM is not band-limited. A high carrier with a large `fmDepth` and `fmRatio` aliases. Keep carriers of bell-like sounds around 500 Hz, or lower the index.
69
+ - A detuned stack is one voice per copy. Count them when choosing `maxVoices`. Protected profiles divide per-voice source gain by the square root of the event voice count; `raw` does not. Correlated or phase-aligned voices can still reinforce each other, so this is not a guarantee of constant loudness or peaks.
70
+ - `sequenceend` reports completion or stopping by sequence identifier. Put contiguous notes into one sequence when sample timing matters; the event crosses JavaScript delivery latency.
109
71
 
110
72
  ## Validate values at the app boundary
111
73
 
112
- The native API rejects invalid values instead of clamping them. Use
113
- `getDefaults().limits` for a user-facing slider, remote configuration or saved
114
- sound preset.
74
+ The native API rejects invalid values instead of clamping them. Use `getDefaults().limits` for a user-facing slider, remote configuration or saved sound preset.
115
75
 
116
76
  ```javascript
117
77
  function acceptedFrequency (raw) {
@@ -123,30 +83,17 @@ function acceptedFrequency (raw) {
123
83
  }
124
84
  ```
125
85
 
126
- Do not copy the frequency maximum into application code. It depends on the
127
- active sample rate and should be read again after startup.
86
+ Do not copy the frequency maximum into application code. It depends on the active sample rate and should be read again after startup.
128
87
 
129
- The same rule applies to `noiseRate`, `lowPassHz` and `filterHz`. Validate a
130
- custom `waveTable` as 2 to 64 finite values from -1 to 1, and remember that
131
- `bitDepth` accepts zero or an integer from 2 to 16. For `detune`, check the
132
- resulting pitch too: a shifted pitch that leaves the frequency range is
133
- rejected even when the cents value is in range.
88
+ The same rule applies to `noiseRate`, `lowPassHz` and `filterHz`. Validate a custom `waveTable` as 2 to 64 finite values from -1 to 1, and remember that `bitDepth` accepts zero or an integer from 2 to 16. For `detune`, check the resulting pitch too: a shifted pitch that leaves the frequency range is rejected even when the cents value is in range.
134
89
 
135
- Check Boolean return values during development. A rejected call includes the
136
- method, key and reason in the native log. Logging that result at the caller is
137
- often enough to identify a stale preset or misspelled field.
90
+ Check Boolean return values during development. A rejected call includes the method, key and reason in the native log. Logging that result at the caller is often enough to identify a stale preset or misspelled field.
138
91
 
139
92
  ## Test the intended sound
140
93
 
141
- Listen on the output people will use. Headphones reveal noise and stereo detail;
142
- the phone speaker reveals acoustic buzz, weak bass and mono collapse. Test at
143
- low, normal and high system volume.
94
+ Listen on the output people will use. Headphones reveal noise and stereo detail; the phone speaker reveals acoustic buzz, weak bass and mono collapse. Test at low, normal and high system volume.
144
95
 
145
- Use one sustained chord when judging polyphonic timbre. A loop that starts the
146
- same chord before its predecessor finishes deliberately changes the number of
147
- overlapping events. That can drive the limiter in a repeating cycle and sound
148
- like pumping. Keep the loop as an extreme scheduling and recovery test, not as
149
- the reference for how the chord should sound.
96
+ Use one sustained chord when judging polyphonic timbre. A loop that starts the same chord before its predecessor finishes deliberately changes the number of overlapping events. That can drive the limiter in a repeating cycle and sound like pumping. Use the loop to stress scheduling and recovery, and the single sustained chord as the tonal reference.
150
97
 
151
98
  Exercise the real worst case:
152
99
 
@@ -154,11 +101,9 @@ Exercise the real worst case:
154
101
  - the fastest pattern the app can request;
155
102
  - a long release followed by unrelated feedback;
156
103
  - a route change while a note is playing;
157
- - screen off, interruption and background transitions if the product depends
158
- on them.
104
+ - screen off, interruption and background transitions if the product depends on them.
159
105
 
160
- An underrun counter only describes transport. A clean counter cannot tell you
161
- whether a waveform, pitch or mix is pleasant.
106
+ An underrun counter only describes transport. A clean counter cannot tell you whether a waveform, pitch or mix is pleasant.
162
107
 
163
108
  ## Binaural placement
164
109
 
@@ -166,22 +111,27 @@ Use the [integration guide](guide.md#integrate-binaural-in-a-2d-app) to convert
166
111
 
167
112
  ## Known limits
168
113
 
169
- - There are no per-voice handles. A single active note cannot be edited or
170
- stopped; `stopAll()` affects the whole pool.
171
- - Every event has a finite duration of at most 60 seconds. There is no looping.
114
+ - Use `noteOn` with app-supplied IDs for individual release and compatible live updates. Check the required methods before enabling controls; timed events do not return voice handles.
115
+ - Timed tones and chords last at most 60 seconds including release. Sequence intervals and explicit note lengths use the sequence unit, at most 300 beats or 60,000 ms; sequence ADSR remains in milliseconds and release may extend beyond the interval. Sustained `noteOn` voices last until release, replacement or shutdown.
172
116
  - The module synthesizes waveforms and does not play audio files.
173
- - Only one pattern scheduler is pending at a time.
174
- - There is no completion event for a single note or chord. Patterns report
175
- their end through `patternend`, which is the only event the module emits.
117
+ - One native transport supports up to four independent sequences, preallocated by `maxSequences`. All share at most 32 voices.
118
+ - A single tone or chord has no completion event. Sequences emit `sequenceend` with their identifier and completed/stopped reason.
176
119
  - Voice capacity and mixing profile remain fixed until shutdown.
177
- - Pattern scheduling is timer-based, not sample-accurate.
178
- - `lowPassHz` is a plain one-pole filter. The resonant filter has fixed 12 dB
179
- per octave and one exponential sweep; there is no filter envelope.
120
+ - Sequences run on the sample clock in beats or milliseconds. `duration` controls intervals; `length` independently controls note duration.
121
+ - `lowPassHz` is a plain one-pole filter. The resonant filter has fixed 12 dB per octave and one exponential sweep; there is no filter envelope.
180
122
  - FM has one modulator and works only on `SINE`.
181
- - Binaural positions are fixed per event on a front plane; there is no per-voice movement, rear positioning, distance attenuation or head tracking. Output is two channels, without a multichannel 2.1/5.1 routing API.
182
- - There is no effects bus: no reverb, delay or chorus.
183
- - The module provides generic synthesis primitives, not cycle-accurate hardware
184
- emulation.
123
+ - Binaural positions occupy a front plane. Spatial held voices support smooth live movement; there is no rear positioning, distance attenuation or head tracking. Output is two channels, without a multichannel 2.1/5.1 routing API.
124
+ - One chorus/delay/reverb/saturation chain processes selected categories; per-voice sends override selection. It does not provide arbitrary routing or one processor per category.
125
+ - The module provides generic synthesis primitives and does not emulate hardware cycle by cycle.
126
+
127
+ Use a sample player or a dedicated music engine when a product needs streaming, sample loop points, audio-file decoding or multiple independent composition tracks. Use the native sequence transport for the supported musical grid.
128
+
129
+ ## Use effects and held voices deliberately
130
+
131
+ Use `noteOn` for a sound whose duration follows interaction, such as a key, motor or beam; release its ID on touch end, cancellation, pause or scene teardown. Use `playSequence` for a finite musical cue or repeating grid. Neither needs JavaScript to keep an already accepted note alive. Both share the same 32-slot maximum with collision and interface tones; held notes can be stolen, and an accepted `updateVoice` on a stolen ID is a no-op. Optional priority 0-3 affects stealing; it reserves no voices. There is no voice-finished event.
132
+
133
+ Keep chorus/delay/reverb mixes modest when dialogue or short game feedback must remain distinct. One shared chain processes selected categories, not necessarily the whole mix. Select `applyTo` categories and each event's `bus`; an explicit `effectSend` overrides category selection. For example, select `music` for a victory sequence and leave `effects` dry, or set an individual shot's send to 0. Input/master gains and the final limiter remain global. Disabling effects lets tails drain for at most 30 seconds; use panic when immediate history invalidation is required. Start with saturation disabled and compare creative drive at matched levels. Do not use saturation as an automatic substitute for the final limiter.
134
+
135
+ Fixed input/event gain does not decrease when unrelated voices start. If level dips, inspect `maxLimiterReductionDb` and `preLimiterPeakDb`, then consider same-pitch phase cancellation or the device's speaker protection. Eight coherent independent voices can still exceed the limiter threshold; module capacity is not a clean-mix loudness guarantee. See [measurement example](advanced-examples.md#measure-peaks-and-limiter-reduction).
185
136
 
186
- Use a sample player or a dedicated music engine when a product needs streaming,
187
- loop points, per-voice control or a synchronized composition timeline.
137
+ Measure the complete workload on each target device, including held voices, binaural, LFOs, all enabled effects and tails. The [historical statistics benchmark](stats-performance.md) predates these features; the [current technical report](studio-validation.json) includes an unmet full-chain host deadline criterion. Neither is a guarantee of game-frame rate, physical audio deadlines, heat or battery life.