@maccesar/titools 5.1.1 → 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 (98) hide show
  1. package/CONTRIBUTING.md +69 -0
  2. package/README.md +112 -72
  3. package/agents/ti-pro.md +5 -1
  4. package/commands/ti-audit.md +5 -1
  5. package/docs/examples.md +91 -0
  6. package/docs/knowledge-index.md +57 -0
  7. package/lib/config.js +2 -0
  8. package/lib/downloader.js +1 -1
  9. package/package.json +4 -2
  10. package/skills/purgetss/references/multi-density-images.md +1 -1
  11. package/skills/ti-admob-unified/SKILL.md +58 -0
  12. package/skills/ti-admob-unified/agents/openai.yaml +4 -0
  13. package/skills/ti-admob-unified/assets/example/app.js +1207 -0
  14. package/skills/ti-admob-unified/assets/example/lib/ads.js +646 -0
  15. package/skills/ti-admob-unified/assets/example/library-usage.js +136 -0
  16. package/skills/ti-admob-unified/references/api-reference.md +615 -0
  17. package/skills/ti-admob-unified/references/banners.md +435 -0
  18. package/skills/ti-admob-unified/references/contributing.md +233 -0
  19. package/skills/ti-admob-unified/references/dependencies.md +91 -0
  20. package/skills/ti-admob-unified/references/fullscreen.md +238 -0
  21. package/skills/ti-admob-unified/references/game-monetization.md +148 -0
  22. package/skills/ti-admob-unified/references/getting-started.md +319 -0
  23. package/skills/ti-admob-unified/references/index.md +33 -0
  24. package/skills/ti-admob-unified/references/integration.md +87 -0
  25. package/skills/ti-admob-unified/references/library.md +220 -0
  26. package/skills/ti-admob-unified/references/mediation-parity.md +17 -0
  27. package/skills/ti-admob-unified/references/mediation.md +145 -0
  28. package/skills/ti-admob-unified/references/migration.md +259 -0
  29. package/skills/ti-admob-unified/references/module-changelog.md +84 -0
  30. package/skills/ti-admob-unified/references/module-license.txt +21 -0
  31. package/skills/ti-admob-unified/references/privacy.md +281 -0
  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 +143 -0
  35. package/skills/ti-admob-unified/references/source-notes.md +80 -0
  36. package/skills/ti-admob-unified/references/source-snapshot.json +644 -0
  37. package/skills/ti-admob-unified/references/third-party-notices.md +22 -0
  38. package/skills/ti-game/SKILL.md +31 -5
  39. package/skills/ti-game/references/api.md +36 -24
  40. package/skills/ti-game/references/debugging-performance.md +22 -7
  41. package/skills/ti-game/references/examples.md +113 -20
  42. package/skills/ti-game/references/input.md +101 -0
  43. package/skills/ti-game/references/patterns.md +56 -10
  44. package/skills/ti-game/references/physics.md +530 -0
  45. package/skills/ti-game/references/project-setup.md +131 -47
  46. package/skills/ti-game/references/recipes-action.md +149 -18
  47. package/skills/ti-game/references/recipes-adventure-effects.md +47 -4
  48. package/skills/ti-game/references/roadmap.md +11 -4
  49. package/skills/ti-game/references/source-notes.md +81 -0
  50. package/skills/ti-game/references/tilemaps.md +13 -4
  51. package/skills/ti-game-assets/SKILL.md +53 -0
  52. package/skills/ti-game-assets/agents/openai.yaml +4 -0
  53. package/skills/ti-game-assets/references/alpha.md +26 -0
  54. package/skills/ti-game-assets/references/art-direction.md +37 -0
  55. package/skills/ti-game-assets/references/integration.md +49 -0
  56. package/skills/ti-game-assets/references/manifest.example.json +429 -0
  57. package/skills/ti-game-assets/references/manifest.md +39 -0
  58. package/skills/ti-game-assets/references/offline-audio.md +33 -0
  59. package/skills/ti-game-assets/references/prompts.md +33 -0
  60. package/skills/ti-game-assets/references/repeating-textures.md +17 -0
  61. package/skills/ti-game-assets/references/responsible-ads.md +31 -0
  62. package/skills/ti-game-assets/references/sound-assets.md +42 -0
  63. package/skills/ti-game-assets/references/vector-sources.md +21 -0
  64. package/skills/ti-game-assets/scripts/alpha_tools.py +160 -0
  65. package/skills/ti-game-assets/scripts/requirements.txt +1 -0
  66. package/skills/ti-game-assets/scripts/validate_manifest.py +267 -0
  67. package/skills/ti-synthengine/SKILL.md +77 -67
  68. package/skills/ti-synthengine/assets/example/README.md +84 -0
  69. package/skills/ti-synthengine/assets/example/app.js +1178 -0
  70. package/skills/ti-synthengine/assets/example/lib/sequenceOwner.js +83 -0
  71. package/skills/ti-synthengine/assets/example/lib/sequenceScore.js +25 -0
  72. package/skills/ti-synthengine/references/advanced-examples.md +174 -0
  73. package/skills/ti-synthengine/references/android-sim80-correction-evidence.zip +0 -0
  74. package/skills/ti-synthengine/references/android-sim80-correction.json +162 -0
  75. package/skills/ti-synthengine/references/api.md +573 -153
  76. package/skills/ti-synthengine/references/audio-engine.md +272 -124
  77. package/skills/ti-synthengine/references/bypass-physical-recheck-evidence.zip +0 -0
  78. package/skills/ti-synthengine/references/examples.md +355 -106
  79. package/skills/ti-synthengine/references/frontier-android-evidence.zip +0 -0
  80. package/skills/ti-synthengine/references/frontier-ipad-evidence.zip +0 -0
  81. package/skills/ti-synthengine/references/frontier-physical-validation.json +1918 -0
  82. package/skills/ti-synthengine/references/guide.md +426 -75
  83. package/skills/ti-synthengine/references/performance-review-evidence.zip +0 -0
  84. package/skills/ti-synthengine/references/performance-review.json +1146 -0
  85. package/skills/ti-synthengine/references/physical-validation.json +1457 -0
  86. package/skills/ti-synthengine/references/recipes-interaction.md +549 -0
  87. package/skills/ti-synthengine/references/recipes.md +434 -420
  88. package/skills/ti-synthengine/references/recommendations.md +72 -85
  89. package/skills/ti-synthengine/references/sound-design.md +375 -155
  90. package/skills/ti-synthengine/references/source-notes.md +109 -0
  91. package/skills/ti-synthengine/references/source-snapshot.json +452 -0
  92. package/skills/ti-synthengine/references/stats-performance.json +2992 -0
  93. package/skills/ti-synthengine/references/stats-performance.md +82 -0
  94. package/skills/ti-synthengine/references/studio-validation.json +6202 -0
  95. package/skills/ti-synthengine/references/troubleshooting.md +123 -78
  96. package/skills/ti-synthengine/references/unified-bypass-performance.json +22425 -0
  97. package/skills/ti-synthengine/references/unified-validation.json +314 -0
  98. package/AGENTS-VERCEL-RESEARCH.md +0 -175
@@ -1,97 +1,77 @@
1
- > Source snapshot: official TiSynthEngine 1.0.0 documentation at commit `6685b81` (2026-08-29).
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 and its source gain accounts for its voice count. Separate `playTone()`
13
- calls are appropriate for independent touches and effects, but their start
14
- 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.
15
10
 
16
- For keys or pads a user can trigger freely, keep each event around 0.4 to 0.7
17
- until the worst overlap has been heard. Raising every event above 1 is usually
18
- 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.
19
12
 
20
13
  ## Choose the mixing profile once
21
14
 
22
- | Situation | Profile |
23
- | --- | --- |
24
- | General app audio and chords | `conservative` |
25
- | Mostly single notes that need more level | `balanced` |
26
- | Low pitches or distortion from a small phone speaker | `speakerSafe` |
27
- | 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` |
28
21
 
29
- The profile is fixed for the stream. Changing it requires `shutdown()` and a
30
- 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.
31
23
 
32
- If a phone buzzes under `speakerSafe`, lower the event volume or raise the
33
- pitch. Small drivers can distort acoustically even when the digital output is
34
- 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.
35
25
 
36
26
  ## Size `maxVoices` for real overlap
37
27
 
38
28
  `maxVoices` controls capacity. It does not make the engine louder or quieter.
39
29
 
40
- | App behavior | Starting value |
41
- | --- | ---: |
42
- | Occasional interface feedback | 4 to 8 |
43
- | Game effects with overlap | 8 to 16 |
44
- | Chords, keys or long release tails | 16 to 24 |
45
- | 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 |
46
36
 
47
- Count release tails, not just buttons pressed at the same instant. A new voice
48
- steals the slot with the least time remaining when the pool is full. The short
49
- 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.
50
38
 
51
39
  ## Keep one lifecycle owner
52
40
 
53
- Require the module in one audio service or controller, start it after the first
54
- layout settles, and shut it down from the same owner. This avoids an engine that
55
- 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.
56
42
 
57
- A 250 ms debounce after `postlayout` is a practical baseline for a plain
58
- screen. Heavy startup work, advertisements or entry animations may need more.
59
- 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.
60
44
 
61
- Route recovery is automatic. Do not call `shutdown()` just because headphones
62
- were inserted or removed. The sound crossing the transition may end early;
63
- 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.
64
46
 
65
47
  ## Coexisting with other audio
66
48
 
67
- On iOS, the audio session is app-wide and the last component to configure it
68
- wins. TiSynthEngine selects `Playback`, which ignores the ring/silent switch and
69
- normally interrupts other apps. That behavior fits an instrument or an app
70
- 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.
71
50
 
72
- A game that should respect the silent switch may set Titanium's ambient
73
- category after the last engine startup:
51
+ A game that should respect the silent switch and let other apps' music keep playing starts the engine with the ambient session:
74
52
 
75
53
  ```javascript
76
- if (Ti.Platform.osname !== 'android') {
77
- Ti.Media.audioSessionCategory = Ti.Media.AUDIO_SESSION_CATEGORY_AMBIENT
78
- }
54
+ synth.start({ audioSession: 'ambient' })
79
55
  ```
80
56
 
81
- The order is important because `startEngine()` configures the session. Other
82
- native audio modules may configure it again. Test the final startup sequence,
83
- interruptions, background behavior and route changes on iOS before relying on
84
- an override.
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.
58
+
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.
60
+
61
+ ## Keep resonance, FM and detune in check
85
62
 
86
- Android mixes independent output streams at the system level, but another app
87
- or stale test process can still consume low-latency resources. Force-stop old
88
- test builds when diagnosing a glitch that does not reproduce after reboot.
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.
89
71
 
90
72
  ## Validate values at the app boundary
91
73
 
92
- The native API rejects invalid values instead of clamping them. Use
93
- `getDefaults().limits` for a user-facing slider, remote configuration or saved
94
- 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.
95
75
 
96
76
  ```javascript
97
77
  function acceptedFrequency (raw) {
@@ -103,24 +83,17 @@ function acceptedFrequency (raw) {
103
83
  }
104
84
  ```
105
85
 
106
- Do not copy the frequency maximum into application code. It depends on the
107
- 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.
87
+
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.
108
89
 
109
- Check Boolean return values during development. A rejected call includes the
110
- method, key and reason in the native log. Logging that result at the caller is
111
- 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.
112
91
 
113
92
  ## Test the intended sound
114
93
 
115
- Listen on the output people will use. Headphones reveal noise and stereo detail;
116
- the phone speaker reveals acoustic buzz, weak bass and mono collapse. Test at
117
- 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.
118
95
 
119
- Use one sustained chord when judging polyphonic timbre. A loop that starts the
120
- same chord before its predecessor finishes deliberately changes the number of
121
- overlapping events. That can drive the limiter in a repeating cycle and sound
122
- like pumping. Keep the loop as an extreme scheduling and recovery test, not as
123
- 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.
124
97
 
125
98
  Exercise the real worst case:
126
99
 
@@ -128,23 +101,37 @@ Exercise the real worst case:
128
101
  - the fastest pattern the app can request;
129
102
  - a long release followed by unrelated feedback;
130
103
  - a route change while a note is playing;
131
- - screen off, interruption and background transitions if the product depends
132
- on them.
104
+ - screen off, interruption and background transitions if the product depends on them.
105
+
106
+ An underrun counter only describes transport. A clean counter cannot tell you whether a waveform, pitch or mix is pleasant.
133
107
 
134
- An underrun counter only describes transport. A clean counter cannot tell you
135
- whether a waveform, pitch or mix is pleasant.
108
+ ## Binaural placement
109
+
110
+ Use the [integration guide](guide.md#integrate-binaural-in-a-2d-app) to convert each effect source into signed spatial coordinates. Keep switch and amplitude percentages in the app, enable the controls only when both spatial limits are present, and test with headphones. Count concurrently spatial voices and replacement tails when measuring CPU.
136
111
 
137
112
  ## Known limits
138
113
 
139
- - There are no per-voice handles. A single active note cannot be edited or
140
- stopped; `stopAll()` affects the whole pool.
141
- - 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.
142
116
  - The module synthesizes waveforms and does not play audio files.
143
- - Only one pattern scheduler is pending at a time.
144
- - There is no completion event for a note, chord or pattern.
145
- - The module emits no JavaScript events.
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.
146
119
  - Voice capacity and mixing profile remain fixed until shutdown.
147
- - Pattern scheduling is timer-based, not sample-accurate.
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.
122
+ - FM has one modulator and works only on `SINE`.
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).
148
136
 
149
- Use a sample player or a dedicated music engine when a product needs streaming,
150
- 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.