@maccesar/titools 5.2.4 → 5.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -11
- package/docs/examples.md +9 -4
- package/package.json +1 -1
- package/skills/ti-synthengine/SKILL.md +42 -23
- package/skills/ti-synthengine/assets/example/README.md +15 -9
- package/skills/ti-synthengine/assets/example/app.js +49 -12
- package/skills/ti-synthengine/assets/index.d.ts +106 -0
- package/skills/ti-synthengine/references/advanced-examples.md +10 -10
- package/skills/ti-synthengine/references/api.md +96 -26
- package/skills/ti-synthengine/references/audio-engine.md +17 -10
- package/skills/ti-synthengine/references/audio-pipeline-validation.md +1 -1
- package/skills/ti-synthengine/references/examples.md +5 -5
- package/skills/ti-synthengine/references/guide.md +26 -24
- package/skills/ti-synthengine/references/instruments-and-effects.md +31 -24
- package/skills/ti-synthengine/references/native-tone-repetition-validation.md +59 -0
- package/skills/ti-synthengine/references/native-variation-proposal.md +1 -1
- package/skills/ti-synthengine/references/native-variation-validation.md +1 -1
- package/skills/ti-synthengine/references/native-variation.md +45 -43
- package/skills/ti-synthengine/references/recipes-interaction.md +3 -1
- package/skills/ti-synthengine/references/recipes.md +3 -2
- package/skills/ti-synthengine/references/recommendations.md +4 -4
- package/skills/ti-synthengine/references/sound-design.md +5 -5
- package/skills/ti-synthengine/references/source-notes.md +35 -10
- package/skills/ti-synthengine/references/source-snapshot.json +168 -89
- package/skills/ti-synthengine/references/stats-performance.md +1 -1
- package/skills/ti-synthengine/references/troubleshooting.md +15 -15
package/README.md
CHANGED
|
@@ -172,7 +172,7 @@ The knowledge index is based on the latest Titanium SDK documentation. If your p
|
|
|
172
172
|
| ti-ui | UI/UX patterns | Complex layouts, ListViews, platform UI |
|
|
173
173
|
| ti-game | 2D games with the `ti.game` module | Sprites, physics, tile maps, HUDs, camera, focused keyboard/mouse/gamepad actions, Apple Metal/Catalyst |
|
|
174
174
|
| ti-game-assets | Visual and sound assets | Image generation/editing, synthesis variants, stereo placement, alpha cleanup, manifests, parallax and complete exports |
|
|
175
|
-
| ti-synthengine | Sound design with `ti.synthengine` | Tones, chords, retro/UI effects, alarms, sweeps,
|
|
175
|
+
| ti-synthengine | Sound design with `ti.synthengine` | Tones, finite-tone repetition, chords, retro/UI effects, alarms, sweeps, ADSR, filters, FM, binaural positioning, held voices, native sequences, master effects, LFOs, statistics, bounded attack variation, seeds, TypeScript declarations, instrument/effect fidelity and troubleshooting |
|
|
176
176
|
| ti-admob-unified | Advertising, privacy and mediation | Official `ti.admob.unified` guides, copy-ready library, banners/fullscreen, UMP/ATT and selected-provider configuration |
|
|
177
177
|
| ti-api | Complete Titanium API reference | Looking up properties, methods, events |
|
|
178
178
|
| ti-guides | SDK fundamentals | tiapp.xml, Hyperloop, distribution, JDK/Xcode compatibility, release notes |
|
|
@@ -184,7 +184,7 @@ Notes:
|
|
|
184
184
|
- The first eight (`ti-reuse-first`, `ti-expert`, `purgetss`, `ti-ui`, `ti-game`, `ti-game-assets`, `ti-synthengine`, `ti-admob-unified`) are specialist workflow skills reflecting TiTools' Titanium conventions and native-module contracts.
|
|
185
185
|
- `ti-reuse-first` runs before the others. It asks whether a thing needs to exist and what already does it — a search order that stops at the first rung that holds — and sweeps an existing `app/` for near-identical controllers, single-listener events, wrappers around one call, and layout recomputed in JavaScript. It is deliberately two-sided: it says when adding a module or a Widget is the right answer, so the bias does not simply invert.
|
|
186
186
|
- `ti-game` documents the `ti.game` native module (2D sprite engine using OpenGL ES 2.0 on Android and Metal on iPhone, iPad and Mac Catalyst). Its API reference was verified against the module source and records the reviewed upstream commit and fork documentation snapshot; it applies to Alloy and Classic projects alike and does not depend on PurgeTSS.
|
|
187
|
-
- `ti-synthengine` translates sound requests into checked JavaScript for published Android/iOS `ti.synthengine` 1.0
|
|
187
|
+
- `ti-synthengine` translates sound requests into checked JavaScript for published Android/iOS `ti.synthengine` 1.1.0 / API 1.1.0, with compatibility guidance for 1.0.2 / API 1.0.0. Its 25-method surface includes finite-tone repetition, held voices, identified native sequences, tempo, categories/sends, master effects, live controls and diagnostics. Two curated recipe guides cover retro cues and interactive instruments. Official-source mirrors, validation reports, bundled examples, TypeScript declarations and raw evidence retain provenance; verified corrections are applied to official source prose before mirroring. Source notes distinguish reviewed source commits, published artifacts, platform differences and scoped listening/performance evidence.
|
|
188
188
|
- `ti-game-assets` treats images and sounds as essential game assets. It coordinates integrated `image_gen` artwork with `ti-synthengine` sound design, variants and stereo placement, and ships Pillow helpers for conservative alpha cleanup and per-world visual/audio manifests.
|
|
189
189
|
- The latter five are documentation-mirror skills, audited against official sources via the internal `titools-skill-auditor`. See [Where the references come from](#where-the-references-come-from).
|
|
190
190
|
- `purgetss` reference files are audited against the official PurgeTSS documentation and against the package source (the CLI and the generated `utilities.tss`), but its workflow conventions are opinionated.
|
|
@@ -546,18 +546,18 @@ frequency and pause/audio/input ownership remain application policies.
|
|
|
546
546
|
|
|
547
547
|
### ti-synthengine
|
|
548
548
|
|
|
549
|
-
Sound design and synthesis with the public native `ti.synthengine` 1.0
|
|
549
|
+
Sound design and synthesis with the public native `ti.synthengine` 1.1.0 release (public API 1.1.0) for Android and iOS. It adds `repeatTone`, `updateTone`, `stopTone`, `updateNote`, `enableStats` and `disableStats`, plus capability-gated native attack variation. Published 1.0.2 / API 1.0.0 remains documented for compatibility; it does not support repetition or variation. Read the [skill entry point](skills/ti-synthengine/SKILL.md) for task routing, exact API references and source provenance.
|
|
550
550
|
|
|
551
551
|
Public repository: [macCesar/TiSynthEngine](https://github.com/macCesar/TiSynthEngine).
|
|
552
|
-
Download [Android 1.0
|
|
553
|
-
and [iOS 1.0
|
|
552
|
+
Download [Android 1.1.0](https://github.com/macCesar/TiSynthEngine/releases/tag/android-1.1.0)
|
|
553
|
+
and [iOS 1.1.0](https://github.com/macCesar/TiSynthEngine/releases/tag/ios-1.1.0),
|
|
554
554
|
copy the ZIPs into the Titanium app root and follow the [installation guide](skills/ti-synthengine/references/guide.md).
|
|
555
555
|
Requires Titanium SDK 13.2.0.GA+, Android compile API35+, and iOS 15+; the Apple package also supports Mac Catalyst.
|
|
556
556
|
|
|
557
557
|
When it activates:
|
|
558
558
|
- `tiapp.xml` declares `ti.synthengine`, or code calls `require('ti.synthengine')`
|
|
559
559
|
- Generated UI/game cues, instruments, alarms, chords, percussion, sweeps or binaural headphone placement
|
|
560
|
-
-
|
|
560
|
+
- Finite-tone repetition and future-attack edits, held voices, simultaneous native sequences, shared tempo, selective effects/sends, priorities or live voice controls
|
|
561
561
|
- Bounded native attack variation, deterministic seeds, complete effect playback or playable instrument adaptations
|
|
562
562
|
- Rejected calls, startup glitches, voice/queue diagnostics, render-load measurements or source/artifact compatibility questions
|
|
563
563
|
|
|
@@ -569,7 +569,9 @@ Example prompts:
|
|
|
569
569
|
"Run music and a victory cue as independent native sequences, then cancel only the cue."
|
|
570
570
|
"Apply reverb to music while keeping UI dry, and change the global tempo."
|
|
571
571
|
"Explain what the Android Sim80 headphone result proves about performance."
|
|
572
|
-
"Vary repeated impacts natively on
|
|
572
|
+
"Vary repeated impacts natively on public 1.1.0 and retain a clean fallback on published 1.0.2."
|
|
573
|
+
"Repeat the original swept shot with repeatTone, edit its interval and stop future attacks without truncating sounding shots."
|
|
574
|
+
"Use updateNote and enableStats/disableStats, and check this recipe against the bundled TypeScript declarations."
|
|
573
575
|
```
|
|
574
576
|
|
|
575
577
|
Key rules:
|
|
@@ -577,15 +579,18 @@ Key rules:
|
|
|
577
579
|
- Preserve complete effects and layer gains when adapting or repeating them; read [instruments and effects](skills/ti-synthengine/references/instruments-and-effects.md)
|
|
578
580
|
- Read constants and exact ranges from the API; strict option dictionaries reject invalid fields or conflicting pitch sources
|
|
579
581
|
- Timed tone/chord `duration` includes release. Native sequence intervals and note lengths are separate; held voices release through their IDs
|
|
580
|
-
-
|
|
582
|
+
- Use `repeatTone` for the original finite-tone renderer and `playSequence` for ordered scores; retain each accepted ID. `stopTone` preserves admitted finite attacks, while `stopSequence` releases its emitted voices. `stopAll()` is global panic
|
|
583
|
+
- Native repetition requires its capability and methods, integer `intervalMs` 1–60,000, and capacity for overlaps. Its 32 slots are independent of sequence capacity; all attacks share the voice pool
|
|
584
|
+
- `updateTone` preserves the next deadline, validates merged recipes and changes future attacks. Independent gameplay calls and intentionally JavaScript-timed finite bursts remain supported; clear app-owned timers during teardown
|
|
585
|
+
- Use `updateNote`, `enableStats` and `disableStats` in new 1.1.0 code. `updateVoice` and `setStatsEnabled(Boolean)` remain deprecated equivalent aliases; feature-detect the aliases when supporting 1.0.2
|
|
581
586
|
- `setTempo` drives beat-based transport and synchronized modulation; millisecond sequences keep fixed timing
|
|
582
587
|
- `bus`/`applyTo` select processed categories; explicit `effectSend` overrides that selection. One shared chain and final limiter remain global
|
|
583
588
|
- Held spatial position, noise clock and one-pole cutoff support compatible 10 ms updates. A stereo voice cannot become spatial through an update
|
|
584
589
|
- Omit both spatial coordinates for stereo; zero coordinates enable binaural center. Do not combine binaural coordinates with stereo pan fields
|
|
585
|
-
- Start after layout, keep one lifecycle owner, handle Boolean acceptance and sequence IDs, release held notes on cancellation and shut down during teardown
|
|
590
|
+
- Start after layout, keep one lifecycle owner, handle Boolean acceptance and tone/sequence IDs, release held notes and owned repetitions on cancellation, and shut down during teardown
|
|
586
591
|
- Current platform metadata, zero-envelope and diagnostic differences are documented. Host checks and a short accepted listening scene do not establish complete physical maximum-load acceptance
|
|
587
592
|
|
|
588
|
-
The [retro recipes](skills/ti-synthengine/references/recipes.md) and [interaction/instrument recipes](skills/ti-synthengine/references/recipes-interaction.md) preserve acoustic intent, overlap budgets and cleanup. [Source notes](skills/ti-synthengine/references/source-notes.md) identify the reviewed native commit and evidence limits.
|
|
593
|
+
The [retro recipes](skills/ti-synthengine/references/recipes.md) and [interaction/instrument recipes](skills/ti-synthengine/references/recipes-interaction.md) preserve acoustic intent, overlap budgets and cleanup. The [official declarations](skills/ti-synthengine/assets/index.d.ts) provide TypeScript signatures alongside the runtime API. [Repetition validation](skills/ti-synthengine/references/native-tone-repetition-validation.md) separates native checks, transport storage and bounded host measurements from device/listening acceptance. [Source notes](skills/ti-synthengine/references/source-notes.md) identify the reviewed native commit and evidence limits.
|
|
589
594
|
|
|
590
595
|
---
|
|
591
596
|
|
|
@@ -898,7 +903,7 @@ This pattern is documented across four bundled TiTools skills: `ti-ui`, `ti-expe
|
|
|
898
903
|
| ti-game | Native 2D Game Workflow | 12 files (API, input, source notes, setup, physics, patterns, recipes, tile maps, debugging, roadmap) |
|
|
899
904
|
| ti-game-assets | Visual and Sound Assets | 10 guides and a manifest example; alpha and contract validation scripts |
|
|
900
905
|
| ti-admob-unified | Unified Advertising | 20 Markdown references including production, rewarded interstitial, mediation parity, integration library guidance, provenance and game monetization; source/hash checks and official example assets |
|
|
901
|
-
| ti-synthengine | Native Sound Synthesis |
|
|
906
|
+
| ti-synthengine | Native Sound Synthesis | 18 Markdown references (15 official parts, 2 curated recipe guides, maintenance notes), official TypeScript declarations, complete validation reports/evidence and a reversible source hash manifest |
|
|
902
907
|
| ti-api | Titanium API | 20 references for core/platform APIs and native modules |
|
|
903
908
|
| ti-guides | SDK Fundamentals | 16 references for setup, configuration, CLI and distribution |
|
|
904
909
|
| ti-howtos | Native Integrations | 18 references for platform features and integration workflows |
|
package/docs/examples.md
CHANGED
|
@@ -37,14 +37,19 @@ an audio or advertising module.
|
|
|
37
37
|
|
|
38
38
|
## Native synthesis — ti-synthengine
|
|
39
39
|
|
|
40
|
-
- "Install the public TiSynthEngine 1.0
|
|
40
|
+
- "Install the public TiSynthEngine 1.1.0 Android/iOS packages and start audio after the window layout settles."
|
|
41
41
|
- "Move a held spatial motor, process only music with reverb, and stop one native sequence without cancelling unrelated sounds."
|
|
42
|
-
- "Use native attack variation with
|
|
42
|
+
- "Use native attack variation with public 1.1.0: bounded noise/filter ranges, deterministic seeds and an old-package fallback."
|
|
43
43
|
- "Repeat this complete layered effect natively without changing its envelope, sweep timing or gains."
|
|
44
|
+
- "Use repeatTone for this finite shot, edit its interval with updateTone, and stop future attacks with stopTone while sounding shots finish."
|
|
45
|
+
- "Use updateNote and enableStats/disableStats, checking the bundled TypeScript declarations and a 1.0.2 alias fallback."
|
|
46
|
+
- "Keep these three standalone playTone calls as an intentional finite JavaScript burst and cancel their timers when the owner closes."
|
|
44
47
|
|
|
45
48
|
Use the [synthesis skill](../skills/ti-synthengine/SKILL.md) for exact options,
|
|
46
|
-
public downloads and scoped performance evidence.
|
|
47
|
-
|
|
49
|
+
public downloads, bundled TypeScript declarations and scoped performance evidence.
|
|
50
|
+
Native finite-tone repetitions, ordered sequences, held voices and standalone
|
|
51
|
+
JavaScript events have distinct ownership and timing contracts. Public 1.0.2 /
|
|
52
|
+
API 1.0.0 lacks repetition and variation; detect support before enabling them.
|
|
48
53
|
|
|
49
54
|
## Advertising — ti-admob-unified
|
|
50
55
|
|
package/package.json
CHANGED
|
@@ -1,27 +1,30 @@
|
|
|
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 needs generated tones, chords, native sequences,
|
|
3
|
+
description: "Use when a Titanium app declares ti.synthengine in tiapp.xml, imports require('ti.synthengine'), or needs generated tones, chords, repeatTone/updateTone/stopTone, native sequences, held noteOn/noteOff/updateNote, ADSR, sweeps, FM, resonant filters, noise, binaural spatialX/spatialY, shared tempo, selective music/effects/ui/ambience processing, effectSend, priorities, chorus/delay/reverb/saturation, LFOs, sequenceend events, gain staging, statistics with enableStats/disableStats, bounded native per-attack variation, seeds, TypeScript declarations or render-load diagnosis. Not for audio-file decoding, sample streaming or unrelated synthesizers."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# ti.synthengine — native sound synthesis for Titanium
|
|
7
7
|
|
|
8
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
|
-
These references cover **published module 1.0
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
and [iOS](https://github.com/macCesar/TiSynthEngine/releases/tag/ios-1.0.2)
|
|
10
|
+
These references cover **published Android/iOS module 1.1.0 with public API
|
|
11
|
+
1.1.0**, retaining compatibility guidance for published 1.0.2 / API 1.0.0.
|
|
12
|
+
Version 1.1.0 adds native finite-tone repetition, attack variation and the
|
|
13
|
+
recommended held-note/statistics method names. Version 1.0.2 supports the older
|
|
14
|
+
core methods and aliases but lacks repetition and rejects variation options.
|
|
15
|
+
Download matching [Android](https://github.com/macCesar/TiSynthEngine/releases/tag/android-1.1.0)
|
|
16
|
+
and [iOS](https://github.com/macCesar/TiSynthEngine/releases/tag/ios-1.1.0)
|
|
18
17
|
packages from the public [repository](https://github.com/macCesar/TiSynthEngine).
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
The
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
Read the [guide](references/guide.md) for both platform declarations, rebuilding
|
|
19
|
+
and installation; check the actual methods and feature metadata your app needs.
|
|
20
|
+
The reviewed source commit/state, reversible source/mirror hashes and release
|
|
21
|
+
artifact checksums are recorded in [source-snapshot.json](references/source-snapshot.json)
|
|
22
|
+
and [source notes](references/source-notes.md).
|
|
23
|
+
The current [interactive example](assets/example/README.md) includes both helpers
|
|
24
|
+
and native repetition controls. The bundled [TypeScript declarations](assets/index.d.ts)
|
|
25
|
+
mirror the official module types; read them with the API rather than substituting
|
|
26
|
+
type-checking for runtime acceptance. Earlier development packages reused API
|
|
27
|
+
version strings, so version checks alone do not establish every capability.
|
|
25
28
|
|
|
26
29
|
## Required workflow
|
|
27
30
|
|
|
@@ -32,7 +35,10 @@ Read the relevant references before writing or reviewing code. When updating the
|
|
|
32
35
|
| Any public method, option, default, return value or limit | [API](references/api.md) |
|
|
33
36
|
| Download public releases, install, initialize, own or clean up an engine | [Guide](references/guide.md) |
|
|
34
37
|
| Design an effect, instrument, reward, alarm or game motor | [Sound design](references/sound-design.md), [recipes](references/recipes.md), [examples](references/examples.md) |
|
|
35
|
-
| Complete effect playback, playable adaptations,
|
|
38
|
+
| Complete effect playback, playable adaptations, importing layers and audition fidelity | [Instruments and effects](references/instruments-and-effects.md) |
|
|
39
|
+
| Repeat an original finite tone, edit its next attacks or cancel while sounding attacks finish | [Repetition API](references/api.md#finite-tone-repetition), [instruments and effects](references/instruments-and-effects.md#repeated-firing-uses-the-native-clock) |
|
|
40
|
+
| Repetition test coverage, transport memory and scoped host measurements | [Repetition verification](references/native-tone-repetition-validation.md) |
|
|
41
|
+
| TypeScript signatures, option dictionaries and return types | [Official declarations](assets/index.d.ts), [API](references/api.md) |
|
|
36
42
|
| Native per-attack variation, ranges, amount, seeds, chords, held starts and loop/revision behavior | [Variation](references/native-variation.md), [API](references/api.md) |
|
|
37
43
|
| Variation memory/callback measurements, package scope and listening follow-up | [Variation verification](references/native-variation-validation.md) |
|
|
38
44
|
| Historical variation design, feasibility and deferred API questions | [Historical proposal](references/native-variation-proposal.md); current behavior comes from the implemented guide |
|
|
@@ -64,13 +70,16 @@ if (!synth.start({maxVoices: 32, maxSequences: 4,
|
|
|
64
70
|
}
|
|
65
71
|
```
|
|
66
72
|
|
|
67
|
-
Both
|
|
73
|
+
Both 1.1.0 platforms announce `capabilities.variation === true` and `variationSchemaVersion === 1`; require both before sending `variation`, even for amount zero. Published 1.0.2 does not accept that key. Android also announces native-sequence/processing/modulation flags and `limits.stepDurationMs`; iOS implements those operations without those Android-only metadata entries. Both return the sequence-capacity, priority and send limits. [source: references/api.md] [source: references/native-variation.md]
|
|
74
|
+
|
|
75
|
+
Use `updateNote` for held-note edits and `enableStats()` / `disableStats()` for diagnostics in new 1.1.0 code. `updateVoice` and `setStatsEnabled(Boolean)` remain deprecated equivalent aliases, without repeated warnings or a scheduled removal date. For 1.0.2 compatibility, detect and use its aliases; detect repetition and variation separately before enabling those features. [source: references/api.md]
|
|
68
76
|
|
|
69
77
|
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]
|
|
70
78
|
|
|
71
79
|
## Scheduling contract
|
|
72
80
|
|
|
73
|
-
- `playTone`
|
|
81
|
+
- `playTone` plays one finite event and returns Boolean acceptance; it rejects `intervalMs`. `playChord` plays one simultaneous atomic chord. Use `repeatTone` for ongoing native repetition of the original finite-tone recipe, `playSequence` for ordered scores, and `noteOn`/`noteOff`/`updateNote` for interaction-owned held voices.
|
|
82
|
+
- Independent gameplay calls and intentionally JavaScript-timed finite bursts remain supported. Keep their Boolean `playTone` returns and cancel app-owned timers on teardown. Native repetition and sequences own their ongoing sample-clock attacks; UI polling does not drive them.
|
|
74
83
|
- `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.
|
|
75
84
|
- 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.
|
|
76
85
|
- `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.
|
|
@@ -82,11 +91,21 @@ Choose the actual required sequence capacity, 1–4; the snippet's four slots su
|
|
|
82
91
|
|
|
83
92
|
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]
|
|
84
93
|
|
|
94
|
+
## Native finite-tone repetition
|
|
95
|
+
|
|
96
|
+
Require a present `contract.capabilities` map with `toneRepetition === true` and the presence of `repeatTone`, `updateTone` and `stopTone` before enabling native repetition. Published 1.0.2 lacks it. Keep an existing independent-event path or disable the unavailable control; converting a timed recipe to sequence length/sweeps changes its rendering interpretation. [source: references/api.md] [source: references/instruments-and-effects.md]
|
|
97
|
+
|
|
98
|
+
`repeatTone({intervalMs,...recipe})` requires an integer interval of 1–60,000 ms and returns a positive `toneId` or numeric `0`. It preserves the finite-tone envelope, endpoint sweeps, gain, routes and optional variation. The first attack starts at the first render opportunity; later deadlines preserve fractional samples across blocks and ignore tempo changes. There are 32 repetition slots independent of the 1–4 sequence slots, sharing the configured pool of at most 32 voices. Reserve capacity for overlaps, prior attacks after edits and other owners; publication does not guarantee admission of every future attack.
|
|
99
|
+
|
|
100
|
+
`updateTone({toneId,...changes})` requires a live ID and at least one change. It merges with the last accepted recipe and validates the complete result; `note` and `frequency` replace one another, while supplying both rejects the edit. Invalid edits retain the accepted recipe. Edits affect the next scheduled attack without moving its deadline; the new interval controls the following gap. Sounding attacks retain their original configuration. A supplied variation dictionary replaces the previous dictionary; `{amount:0}` disables future variation. The native stream/counter survives edits unless the seed identity changes. Dropped attacks consume no variation selection and produce no catch-up work.
|
|
101
|
+
|
|
102
|
+
`stopTone({toneId})` returns Boolean acceptance and cancels future attacks at the next block, including before the first attack. Already admitted finite voices finish their original lifetimes. Stop remains publishable when the ordinary command queue is full. Unknown/retired IDs reject edits and stops; IDs never repeat during module lifetime, including shutdown/start. There is no `toneend` event. Retain each layer's ID and cancel it on release, cancellation, preset change, pause and owner close. Global `stopAll`, shutdown and destruction invalidate repetitions and pending edits. [source: references/api.md] [source: references/native-variation.md]
|
|
103
|
+
|
|
85
104
|
## Native attack variation
|
|
86
105
|
|
|
87
106
|
Variation samples compatible bounded parameters once per admitted attack, preserving authored envelopes, cadence, routes and voice counts. Read all eight source-dependent bounds before constructing ranges. Amount interpolates linearly from the authored value; pitch uses cents. Keep application gain consistent in authored volume and volume-range endpoints.
|
|
88
107
|
|
|
89
|
-
An explicit seed repeats standalone selections; native loops advance their stream across attacks. Chords sample independently by voice ordinal. Sustained voices retain their selection through release; `
|
|
108
|
+
An explicit seed repeats standalone selections; native loops advance their stream across attacks. Chords sample independently by voice ordinal. Sustained voices retain their selection through release; `updateNote` rejects `variation`. Step dictionaries replace the whole inherited dictionary. Sequence revisions affect future attacks; root omission retains variation, and disabling inherited and explicit-step variation requires appropriate amount-zero replacements. Use the native sampler for this variation dictionary. Seeds reproduce parameters, not cross-platform noise PCM. [source: references/native-variation.md]
|
|
90
109
|
|
|
91
110
|
## Voices, routes and continuous controls
|
|
92
111
|
|
|
@@ -94,13 +113,13 @@ An explicit seed repeats standalone selections; native loops advance their strea
|
|
|
94
113
|
|
|
95
114
|
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]
|
|
96
115
|
|
|
97
|
-
Compatible `
|
|
116
|
+
Compatible `updateNote` 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]
|
|
98
117
|
|
|
99
118
|
`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]
|
|
100
119
|
|
|
101
120
|
Module 1.0.2 retains zero samples at final output: stereo-linked peak protection acts immediately, recovers exponentially with a 100 ms time constant and uses ceilings of 0.85, or 0.70 for `speakerSafe`. These are sample ceilings, not speaker or inter-sample guarantees; overload changes waveform shape. Master volume uses an independent linear 10 ms ramp on both platforms. iOS now applies the documented `raw` gain, so review existing raw mixes when upgrading. Native Android and Apple callback checks run in CI; device latency, listening and extended maximum-load acceptance remain separate. [source: references/audio-pipeline-validation.md]
|
|
102
121
|
|
|
103
|
-
`stopAll()` stops every native sequence, cancels future attacks, fades voices and invalidates effect histories. Use `stopSequence({sequenceId})` for one owner’s sequence. Android closes the engine on root activity destruction; explicit owner teardown remains required. Idle event polling stops when no control work remains and does not schedule musical attacks. [source: references/api.md] [source: references/guide.md] [source: references/audio-engine.md]
|
|
122
|
+
`stopAll()` stops every native sequence and finite-tone repetition, cancels future attacks, fades voices and invalidates effect histories. Use `stopSequence({sequenceId})` for one owner’s sequence or `stopTone({toneId})` for its finite repetition. Android closes the engine on root activity destruction; explicit owner teardown remains required. Idle event polling stops when no control work remains and does not schedule musical attacks. [source: references/api.md] [source: references/guide.md] [source: references/audio-engine.md]
|
|
104
123
|
|
|
105
124
|
## Sound and validation rules
|
|
106
125
|
|
|
@@ -114,8 +133,8 @@ Module 1.0.2 retains zero samples at final output: stereo-linked peak protection
|
|
|
114
133
|
|
|
115
134
|
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]
|
|
116
135
|
|
|
117
|
-
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]
|
|
136
|
+
Timed zero attack/release and rejection diagnostics currently differ between native platforms. Submit exact integer repetition intervals: Apple currently tolerates and truncates extremely near-integer values that Android rejects; see the documented [native interval edge](references/source-notes.md#known-native-interval-edge). 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]
|
|
118
137
|
|
|
119
|
-
Diagnostics are opt-in
|
|
138
|
+
Diagnostics are opt-in through `enableStats()` / `disableStats()`. 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]
|
|
120
139
|
|
|
121
140
|
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.
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
> Source snapshot: official TiSynthEngine documentation at commit `
|
|
1
|
+
> Source snapshot: official TiSynthEngine documentation at commit `ec04f4e634075c41b55f66279eabcd78b9652d58` (2026-11-02). Published module 1.1.0; public API 1.1.0. Upstream `example/README.md` SHA-256: `e191a701a3a913c85b15503fd256e0aec085eb731a587b1bf4faa43865c81982`.
|
|
2
2
|
|
|
3
3
|
# Interactive example
|
|
4
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
|
|
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 requires module version 1.1.0 and public API 1.1.0 for native finite-tone repetition, attack variation and the recommended note/statistics methods. 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
6
|
|
|
7
7
|
## Run it
|
|
8
8
|
|
|
9
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 the official [Android 1.0
|
|
11
|
-
3. Put the archive for each target platform in the test app root.
|
|
10
|
+
2. Download the official [Android 1.1.0](https://github.com/macCesar/TiSynthEngine/releases/tag/android-1.1.0) and [iOS 1.1.0](https://github.com/macCesar/TiSynthEngine/releases/tag/ios-1.1.0) packages, or build the current module source. Source builds produce `android/dist/ti.synthengine-android-1.1.0.zip` and `ios/dist/ti.synthengine-iphone-1.1.0.zip`; select version `1.1.0` in both module entries when using them.
|
|
11
|
+
3. Put the archive for each target platform in the test app root. Add these entries inside its `tiapp.xml`:
|
|
12
12
|
|
|
13
13
|
```xml
|
|
14
14
|
<modules>
|
|
15
|
-
<module platform="android" version="1.0
|
|
16
|
-
<module platform="iphone" version="1.0
|
|
15
|
+
<module platform="android" version="1.1.0">ti.synthengine</module>
|
|
16
|
+
<module platform="iphone" version="1.1.0">ti.synthengine</module>
|
|
17
17
|
</modules>
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Both packages report public API `1.1.0`; detect variation through both capability/schema announcements. Rebuild and reinstall after switching packages.
|
|
21
21
|
|
|
22
22
|
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.
|
|
23
23
|
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).
|
|
24
24
|
|
|
25
|
-
The example checks the installed API version, spatial limits and
|
|
25
|
+
The example checks the installed API version, spatial limits and the recommended enable/disable 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.
|
|
26
26
|
|
|
27
27
|
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.
|
|
28
28
|
|
|
@@ -88,4 +88,10 @@ The example regression executes its real action callbacks with simulated Titaniu
|
|
|
88
88
|
|
|
89
89
|
## Native attack variation
|
|
90
90
|
|
|
91
|
-
The
|
|
91
|
+
The ATTACK VARIATION button submits the same metal-strike recipe on each press. With `capabilities.variation === true` and `variationSchemaVersion === 1`, the renderer chooses pitch, FM depth and level once per admitted attack. Older packages receive the original recipe without the dictionary. This button uses independent timed events; the [variation guide](../../references/native-variation.md) separately demonstrates sustained ownership and native sequence retriggers. Physical listening acceptance remains separate from host correctness checks.
|
|
92
|
+
|
|
93
|
+
## Native finite-tone repetition
|
|
94
|
+
|
|
95
|
+
START REPEATING calls `repeatTone` once with a complete 105 ms square-wave shot and required `intervalMs: 200`. It retains the positive tone ID. EDIT REPEATING calls `updateTone` for that ID, keeping the next deadline and changing subsequent separation to 150 ms. STOP REPEATING calls `stopTone`, cancelling future attacks while admitted shots finish. Close, session changes and global Stop also release or invalidate ownership. There is no JavaScript attack timer for this demo.
|
|
96
|
+
|
|
97
|
+
`playTone` remains a standalone Boolean operation and rejects `intervalMs`; `repeatTone` always returns a numeric ID or 0 and requires the interval. Independent JavaScript calls remain supported, including finite bursts scheduled by an application's own event clock. See [the full contract and standalone burst example](../../references/api.md#finite-tone-repetition).
|
|
@@ -7,14 +7,15 @@ var sequenceOwner = require('lib/sequenceOwner')(Synth, {
|
|
|
7
7
|
function publishSequence(options) { return sequenceOwner.submit(options) }
|
|
8
8
|
|
|
9
9
|
var defaults = Synth.getDefaults()
|
|
10
|
-
if (!defaults || defaults.apiVersion !== '1.
|
|
11
|
-
throw new Error('TiSynthEngine 1.
|
|
10
|
+
if (!defaults || defaults.apiVersion !== '1.1.0') {
|
|
11
|
+
throw new Error('TiSynthEngine 1.1.0 is required')
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
if (!defaults.limits || !defaults.limits.spatialX || !defaults.limits.spatialY
|
|
15
15
|
|| typeof Synth.getStats !== 'function' || typeof Synth.resetStats !== 'function'
|
|
16
|
-
|| typeof Synth.
|
|
17
|
-
|
|
16
|
+
|| typeof Synth.enableStats !== 'function' || typeof Synth.disableStats !== 'function'
|
|
17
|
+
|| typeof Synth.repeatTone !== 'function' || typeof Synth.updateTone !== 'function' || typeof Synth.stopTone !== 'function') {
|
|
18
|
+
throw new Error('Install the current TiSynthEngine 1.1.0 packages, then rebuild and reinstall this app')
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
var WAVE = defaults.waveTypes
|
|
@@ -23,6 +24,7 @@ var engineRunning = false
|
|
|
23
24
|
var startTimer = null
|
|
24
25
|
var statsTimer = null
|
|
25
26
|
var diagnosticsEnabled = false
|
|
27
|
+
var repeatingToneId = 0
|
|
26
28
|
var selectedSession = 'playback'
|
|
27
29
|
var masterVolume = 1
|
|
28
30
|
var binauralEnabled = true
|
|
@@ -200,7 +202,7 @@ function makeHero() {
|
|
|
200
202
|
height: Ti.UI.SIZE,
|
|
201
203
|
top: dp(16)
|
|
202
204
|
})
|
|
203
|
-
badgeRow.add(makeBadge('API 1.
|
|
205
|
+
badgeRow.add(makeBadge('API 1.1.0', COLORS.indigo))
|
|
204
206
|
badgeRow.add(makeBadge('ANDROID + iOS', COLORS.surfaceMuted))
|
|
205
207
|
hero.add(badgeRow)
|
|
206
208
|
hero.add(statusPill)
|
|
@@ -399,6 +401,40 @@ waveNames.forEach(function (name, index) {
|
|
|
399
401
|
waveSection.add(Ti.UI.createView({ height: dp(12) }))
|
|
400
402
|
scrollView.add(waveSection)
|
|
401
403
|
|
|
404
|
+
// A repeated finite recipe uses its native owner ID; there is no attack timer.
|
|
405
|
+
function stopRepeatingTone() {
|
|
406
|
+
if (!repeatingToneId) return true
|
|
407
|
+
if (!Synth.stopTone({ toneId: repeatingToneId })) return false
|
|
408
|
+
repeatingToneId = 0
|
|
409
|
+
return true
|
|
410
|
+
}
|
|
411
|
+
var repeatSection = makeSection('Finite-tone repetition',
|
|
412
|
+
'The same complete 105 ms shot repeats every 200 ms. Edit its future attacks; stop lets current shots finish.',
|
|
413
|
+
COLORS.teal)
|
|
414
|
+
repeatSection.add(makeAction({
|
|
415
|
+
title: 'START REPEATING', color: COLORS.teal, pressedColor: COLORS.tealPressed,
|
|
416
|
+
onPress: function () {
|
|
417
|
+
if (repeatingToneId) return true
|
|
418
|
+
var id = Synth.repeatTone({ frequency: 1380, frequencyEnd: 340,
|
|
419
|
+
duration: 105, attack: 2, release: 40, waveType: WAVE.SQUARE,
|
|
420
|
+
volume: 0.1, intervalMs: 200 })
|
|
421
|
+
if (!Number.isInteger(id) || id <= 0) return false
|
|
422
|
+
repeatingToneId = id
|
|
423
|
+
return true
|
|
424
|
+
}
|
|
425
|
+
}))
|
|
426
|
+
repeatSection.add(makeAction({
|
|
427
|
+
title: 'EDIT REPEATING', color: COLORS.teal, pressedColor: COLORS.tealPressed,
|
|
428
|
+
onPress: function () {
|
|
429
|
+
return !!repeatingToneId && Synth.updateTone({ toneId: repeatingToneId, intervalMs: 150, volume: 0.08 })
|
|
430
|
+
}
|
|
431
|
+
}))
|
|
432
|
+
repeatSection.add(makeAction({
|
|
433
|
+
title: 'STOP REPEATING', color: COLORS.surfaceMuted, pressedColor: COLORS.surfaceRaised,
|
|
434
|
+
onPress: stopRepeatingTone
|
|
435
|
+
}))
|
|
436
|
+
scrollView.add(repeatSection)
|
|
437
|
+
|
|
402
438
|
// ---------------------------------------------------------------------------
|
|
403
439
|
// 2. Note names
|
|
404
440
|
// ---------------------------------------------------------------------------
|
|
@@ -999,7 +1035,7 @@ var sessionLabel = makeText('Session: playback', { left: dp(16), right: dp(16),
|
|
|
999
1035
|
color: COLORS.blueDark, pressedColor: COLORS.blue,
|
|
1000
1036
|
accessibilityHint: 'Restarts the engine with this session policy',
|
|
1001
1037
|
onPress: function () {
|
|
1002
|
-
sequenceOwner.reset(); Synth.shutdown()
|
|
1038
|
+
repeatingToneId = 0; sequenceOwner.reset(); Synth.shutdown()
|
|
1003
1039
|
engineRunning = false
|
|
1004
1040
|
selectedSession = session
|
|
1005
1041
|
patternEndLabel.text = 'sequenceend: cancelled by shutdown (no event)'
|
|
@@ -1046,7 +1082,7 @@ statsSection.add(makeAction({
|
|
|
1046
1082
|
title: 'TOGGLE DIAGNOSTICS', color: COLORS.orange, pressedColor: COLORS.orangePressed,
|
|
1047
1083
|
accessibilityHint: 'Enables or disables timing and signal measurements',
|
|
1048
1084
|
onPress: function () {
|
|
1049
|
-
if (!Synth.
|
|
1085
|
+
if (!(diagnosticsEnabled ? Synth.disableStats() : Synth.enableStats())) return false
|
|
1050
1086
|
diagnosticsEnabled = !diagnosticsEnabled
|
|
1051
1087
|
stopStatsPolling()
|
|
1052
1088
|
if (diagnosticsEnabled) statsTimer = setInterval(refreshStats, 200)
|
|
@@ -1103,10 +1139,10 @@ boostRow.add(makeGridAction({
|
|
|
1103
1139
|
title: 'STOP ALL\nRelease active voices',
|
|
1104
1140
|
color: COLORS.redDark,
|
|
1105
1141
|
pressedColor: COLORS.red,
|
|
1106
|
-
status: '
|
|
1107
|
-
accessibilityHint: '
|
|
1142
|
+
status: 'Future attacks cancelled; active voices fading',
|
|
1143
|
+
accessibilityHint: 'Cancels future attacks and fades current voices',
|
|
1108
1144
|
onPress: function () {
|
|
1109
|
-
sequenceOwner.stop(); Synth.stopAll()
|
|
1145
|
+
repeatingToneId = 0; sequenceOwner.stop(); Synth.stopAll()
|
|
1110
1146
|
}
|
|
1111
1147
|
}))
|
|
1112
1148
|
controlSection.add(boostRow)
|
|
@@ -1170,8 +1206,9 @@ function hideAndroidActionBar() {
|
|
|
1170
1206
|
}
|
|
1171
1207
|
|
|
1172
1208
|
function cleanup() {
|
|
1209
|
+
if (!stopRepeatingTone()) Ti.API.warn('Repeating tone stop rejected; shutting down owner')
|
|
1173
1210
|
stopStatsPolling()
|
|
1174
|
-
Synth.
|
|
1211
|
+
Synth.disableStats()
|
|
1175
1212
|
diagnosticsEnabled = false
|
|
1176
1213
|
Synth.removeEventListener('sequenceend', onSequenceEnd)
|
|
1177
1214
|
win.removeEventListener('postlayout', onFirstPostLayout)
|
|
@@ -1184,7 +1221,7 @@ function cleanup() {
|
|
|
1184
1221
|
startTimer = null
|
|
1185
1222
|
}
|
|
1186
1223
|
if (engineRunning) {
|
|
1187
|
-
sequenceOwner.reset(); Synth.shutdown()
|
|
1224
|
+
repeatingToneId = 0; sequenceOwner.reset(); Synth.shutdown()
|
|
1188
1225
|
engineRunning = false
|
|
1189
1226
|
}
|
|
1190
1227
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/** TiSynthEngine local 1.1.0 candidate, public API 1.1.0. */
|
|
2
|
+
declare namespace synth {
|
|
3
|
+
type Bus = 'music' | 'effects' | 'ui' | 'ambience';
|
|
4
|
+
type FilterType = 'none' | 'lowpass' | 'highpass' | 'bandpass';
|
|
5
|
+
type Range = [number, number];
|
|
6
|
+
interface Variation {
|
|
7
|
+
amount?: number;
|
|
8
|
+
seed?: number;
|
|
9
|
+
ranges?: Partial<Record<'volume' | 'filterHz' | 'filterQ' | 'fmDepth' |
|
|
10
|
+
'noiseRate' | 'lowPassHz' | 'pulseWidth' | 'pitchCents', Range>>;
|
|
11
|
+
}
|
|
12
|
+
interface VoiceOptions {
|
|
13
|
+
attack?: number; decay?: number; sustain?: number; release?: number;
|
|
14
|
+
volume?: number; waveType?: number; pan?: number;
|
|
15
|
+
lfoFreq?: number; lfoDepth?: number; noiseRate?: number; lowPassHz?: number;
|
|
16
|
+
pulseWidth?: number; waveTable?: number[]; bitDepth?: number;
|
|
17
|
+
filterType?: FilterType; filterHz?: number; filterQ?: number;
|
|
18
|
+
fmRatio?: number; fmDepth?: number; spatialX?: number; spatialY?: number;
|
|
19
|
+
bus?: Bus; effectSend?: number; priority?: number; variation?: Variation;
|
|
20
|
+
}
|
|
21
|
+
type Pitch = { note?: string; frequency?: never } | { frequency?: number; note?: never };
|
|
22
|
+
interface FiniteOptions extends VoiceOptions {
|
|
23
|
+
duration?: number; panEnd?: number; frequencyEnd?: number;
|
|
24
|
+
noiseRateEnd?: number; pulseWidthEnd?: number; filterHzEnd?: number;
|
|
25
|
+
fmDepthEnd?: number; detune?: number;
|
|
26
|
+
}
|
|
27
|
+
type ToneOptions = FiniteOptions & Pitch;
|
|
28
|
+
type RepeatingToneOptions = ToneOptions & { intervalMs: number };
|
|
29
|
+
/** Partial changes merge with the latest accepted recipe; never retriggers immediately. */
|
|
30
|
+
type ToneUpdate = Partial<FiniteOptions> & Pitch & { toneId: number; intervalMs?: number };
|
|
31
|
+
interface Modulation {
|
|
32
|
+
target: 'filterHz' | 'pulseWidth' | 'fmDepth';
|
|
33
|
+
wave?: 'sine' | 'triangle'; rate?: number; sync?: string; depth?: number;
|
|
34
|
+
}
|
|
35
|
+
type NoteOptions = VoiceOptions & Pitch & { voiceId: number; detune?: number; modulations?: Modulation[] };
|
|
36
|
+
type NoteUpdate = Pick<VoiceOptions, 'volume' | 'pan' | 'lfoFreq' | 'lfoDepth' |
|
|
37
|
+
'noiseRate' | 'lowPassHz' | 'pulseWidth' | 'filterHz' | 'filterQ' |
|
|
38
|
+
'fmRatio' | 'fmDepth' | 'spatialX' | 'spatialY' | 'effectSend'> & Pitch &
|
|
39
|
+
{ voiceId: number; modulations?: Modulation[] };
|
|
40
|
+
type ChordOptions = VoiceOptions & { duration?: number; detune?: number;
|
|
41
|
+
detunes?: number[]; pans?: number[]; panSpread?: number } &
|
|
42
|
+
({ notes: string[]; frequencies?: never } | { frequencies: number[]; notes?: never });
|
|
43
|
+
interface StartOptions {
|
|
44
|
+
maxVoices?: number; maxSequences?: number;
|
|
45
|
+
mixingProfile?: 'conservative' | 'raw' | 'balanced' | 'speakerSafe';
|
|
46
|
+
audioSession?: 'playback' | 'ambient';
|
|
47
|
+
}
|
|
48
|
+
interface Defaults {
|
|
49
|
+
apiVersion: '1.1.0';
|
|
50
|
+
capabilities: { variation: true; toneRepetition: true; [key: string]: boolean };
|
|
51
|
+
variationSchemaVersion: 1;
|
|
52
|
+
limits: Record<string, { min: number; max: number }>;
|
|
53
|
+
defaults: Record<string, unknown>;
|
|
54
|
+
waveTypes: Record<'SINE' | 'SQUARE' | 'SAWTOOTH' | 'TRIANGLE' | 'NOISE' | 'WAVETABLE', number>;
|
|
55
|
+
mixingProfiles: string[]; audioSessions: string[]; buses: Bus[]; filterTypes: FilterType[];
|
|
56
|
+
}
|
|
57
|
+
interface SequenceVoice extends Omit<FiniteOptions, 'duration' | 'detune'> { modulations?: Modulation[] }
|
|
58
|
+
type SequenceStep = { duration?: number; length?: number; gate?: number;
|
|
59
|
+
overrides?: SequenceVoice; bus?: Bus; effectSend?: number; priority?: number } &
|
|
60
|
+
({ notes: number[]; frequencies?: never; rest?: never } |
|
|
61
|
+
{ frequencies: number[]; notes?: never; rest?: never } |
|
|
62
|
+
{ rest: true; notes?: never; frequencies?: never });
|
|
63
|
+
interface SequenceOptions {
|
|
64
|
+
timeUnit?: 'beats' | 'ms'; stepDuration?: number; gate?: number; loop?: boolean;
|
|
65
|
+
swing?: number; mode?: 'normal' | 'up' | 'down' | 'updown'; tuning?: number;
|
|
66
|
+
detune?: number; voice?: SequenceVoice; steps: SequenceStep[];
|
|
67
|
+
bus?: Bus; effectSend?: number; priority?: number;
|
|
68
|
+
}
|
|
69
|
+
interface SequenceState {
|
|
70
|
+
sequenceId: number; playing: boolean; step: number; beat: number;
|
|
71
|
+
position: number; bpm: number; revision: number;
|
|
72
|
+
}
|
|
73
|
+
function getDefaults(): Defaults;
|
|
74
|
+
function start(options?: StartOptions): boolean;
|
|
75
|
+
/** One finite attack. intervalMs is rejected; use repeatTone for repetition. */
|
|
76
|
+
function playTone(options: ToneOptions & { intervalMs?: never }): boolean;
|
|
77
|
+
/** Integer 1-60000 ms: positive module-owned ID, or 0 on rejection. */
|
|
78
|
+
function repeatTone(options: RepeatingToneOptions): number;
|
|
79
|
+
function updateTone(options: ToneUpdate): boolean;
|
|
80
|
+
/** Cancels future attacks at the next block; admitted attacks finish. */
|
|
81
|
+
function stopTone(options: { toneId: number }): boolean;
|
|
82
|
+
function playChord(options: ChordOptions): boolean;
|
|
83
|
+
function noteOn(options: NoteOptions): boolean;
|
|
84
|
+
function updateNote(options: NoteUpdate): boolean;
|
|
85
|
+
/** @deprecated Use updateNote; identical behavior and voiceId contract. */
|
|
86
|
+
function updateVoice(options: NoteUpdate): boolean;
|
|
87
|
+
function noteOff(options: { voiceId: number }): boolean;
|
|
88
|
+
function playSequence(options: SequenceOptions): number;
|
|
89
|
+
function updateSequence(options: Partial<Omit<SequenceOptions, 'timeUnit'>> & { sequenceId: number }): boolean;
|
|
90
|
+
function stopSequence(options: { sequenceId: number }): boolean;
|
|
91
|
+
function getSequenceState(options: { sequenceId: number }): SequenceState | null;
|
|
92
|
+
function setTempo(options: { bpm: number }): boolean;
|
|
93
|
+
function setVolume(options: { volume: number }): boolean;
|
|
94
|
+
function setMasterProcessing(options: Record<string, unknown>): boolean;
|
|
95
|
+
function enableStats(): boolean;
|
|
96
|
+
function disableStats(): boolean;
|
|
97
|
+
/** @deprecated Use enableStats or disableStats; identical diagnostic behavior. */
|
|
98
|
+
function setStatsEnabled(enabled: boolean): boolean;
|
|
99
|
+
function getStats(): Record<string, number | boolean | string | null>;
|
|
100
|
+
function resetStats(): void;
|
|
101
|
+
function stopAll(): void;
|
|
102
|
+
function shutdown(): void;
|
|
103
|
+
function addEventListener(name: 'sequenceend', listener: (event: { sequenceId: number; reason: 'completed' | 'stopped' }) => void): void;
|
|
104
|
+
function removeEventListener(name: 'sequenceend', listener: (event: { sequenceId: number; reason: 'completed' | 'stopped' }) => void): void;
|
|
105
|
+
}
|
|
106
|
+
export = synth;
|