tutticode 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,8 +9,15 @@ Claude Desktop and friends.
9
9
 
10
10
  Rendering happens **in your own browser**, on the same engine as
11
11
  tuttidaw.com/code, so a file sounds exactly like the editor. Nothing is
12
- rendered on a server, there is no account, and it costs nothing. Every result
13
- carries an `editUrl` that opens the program in TuttiDAW to keep editing.
12
+ rendered on a server and it costs nothing. Every result carries an `editUrl`
13
+ that opens the program in TuttiDAW to keep editing.
14
+
15
+ Once TuttiDAW switches its limits on (they are being rolled out; until then
16
+ no render is cut or tagged), renders without an account are limited to 60 s,
17
+ and renders over 30 s carry a spoken "register at TuttiDAW" tag. A free
18
+ account lifts both:
19
+ `tutticode login` (renders up to 5 minutes, no tag). See
20
+ [Sign-in and limits](#sign-in-and-limits).
14
21
 
15
22
  ## Install
16
23
 
@@ -52,7 +59,7 @@ anywhere else (for example a project's `.claude/skills`).
52
59
  tutticode check song.tc # diagnostics, no audio
53
60
  tutticode render song.tc -o bed.wav --seconds 12 --fade-out 1.5 --lufs -16 --json
54
61
  tutticode render song.tc -o loop.flac --loops 4 --stems stems/
55
- tutticode open song.tc # open it in TuttiCode for a human
62
+ tutticode open song.tc # open it in TuttiCode for a human (--headless: prints the link)
56
63
  cat song.tc | tutticode check - # read the program from stdin
57
64
  ```
58
65
 
@@ -60,16 +67,25 @@ cat song.tc | tutticode check - # read the program from stdin
60
67
  `--format wav|flac|mp3` (default from the `-o` extension),
61
68
  `--sample-rate 44100|48000`, `--bit-depth 16|24`, `--stems <dir>`,
62
69
  `--fade-in s`, `--fade-out s`, `--tail s`, `--lufs N`, `--true-peak N`,
63
- `--json`, `--timeout s`. `--lufs` applies one static gain; when the true-peak
64
- ceiling cannot be met the render fails with `clip` instead of being limited.
70
+ `--limit`, `--json`, `--timeout s`. No file is written clipped: a render
71
+ whose true peak would pass the ceiling (`--true-peak`, default -1 dBTP) is
72
+ lowered by one static gain, and the CLI says so ("Lowered 4.6 dB to avoid
73
+ clipping"). `--lufs` applies one static gain; when the true-peak ceiling
74
+ cannot be met the render fails with `clip`, unless you add `--limit`: a
75
+ true-peak limiter on the mix (not the stems), reported as `limitDb`.
65
76
 
66
77
  `--json` prints the render report: length, bars, tempo, loudness and true
67
78
  peak, the gain applied, per-voice levels, the bar and beat grid (seconds, for
68
79
  syncing cuts), the check report, the analysis, the `editUrl` and the written
69
80
  files. Audio is never printed.
70
81
 
82
+ `--no-brand-tag` (or `TUTTICODE_BRAND_TAG=0`) leaves the "Made with
83
+ TuttiCode" metadata out of the files; signed-in renders only.
84
+
71
85
  Exit codes: `0` ok, `1` errors in the code (or a loudness target that would
72
- clip), `2` bridge or browser problem, `3` usage.
86
+ clip), `2` bridge or browser problem, `3` usage, `4` not signed in
87
+ (`whoami`), `5` over a limit without sign-in, `6` this tutticode is too old
88
+ (`npm i -g tutticode@latest`).
73
89
 
74
90
  ### MCP tools
75
91
 
@@ -83,8 +99,58 @@ skill teaches both:
83
99
  | `code_compare` | compare a render with goals (or a Muse style), or two renders |
84
100
  | `code_open` | open a program in a visible TuttiCode tab (`tutticode mcp --headless`: no window, returns the link) |
85
101
  | `code_reference` | search the TuttiCode reference shipped in the package |
102
+ | `code_account` | signed in or not, the length limits and today's usage |
86
103
 
87
104
  The reference documents are also MCP resources (`tutticode://skills/...`).
105
+ `tutticode mcp` uses the same sign-in as the CLI (`tutticode login`, or
106
+ `TUTTICODE_TOKEN` in its environment); it never starts a sign-in itself.
107
+
108
+ ## Sign-in and limits
109
+
110
+ The limits below apply once TuttiDAW switches them on (they are being rolled
111
+ out; until then every render runs in full and untagged). The sign-in works
112
+ today.
113
+
114
+ | | Without sign-in | Free account |
115
+ | --- | --- | --- |
116
+ | Longest render | 60 s (longer: error `limit`, exit 5) | 5 minutes |
117
+ | Voice tag "register at TuttiDAW" | mixed in throughout renders over 30 s | never |
118
+ | Formats, stems | all | all |
119
+
120
+ ```sh
121
+ tutticode login # opens your browser; approve, come back
122
+ tutticode login --device # no browser here (SSH, a server): approve a code on any device
123
+ tutticode whoami # who renders, the limits, today's usage
124
+ tutticode logout # sign this computer out
125
+ ```
126
+
127
+ **For agents.** On a `limit` error, tell the user its message in one
128
+ sentence and carry on within the limit. `tutticode login --device --no-wait
129
+ --json` prints `{verificationUri, verificationUriComplete, userCode,
130
+ expiresIn}` and returns at once: give the user the link, keep working, and
131
+ tutticode finishes the sign-in in the background once they approve. `login`
132
+ without `--no-wait` needs a terminal (exit 3 otherwise).
133
+
134
+ **The voice tag.** An anonymous render over 30 s has the tag mixed in from
135
+ the start, every few seconds, in the mix and in every stem, before any
136
+ measurement: the loudness, bands, voice levels and `code_compare` include
137
+ it. The report says so (`watermark: {reason, at, removeWith}`) and the CLI
138
+ prints one line. The tag is not part of your program: do not change the code
139
+ to remove it. `tutticode login` (free) does.
140
+
141
+ **What the sign-in can do.** It can only render with TuttiCode: it cannot
142
+ open your projects, account or billing. It lasts a year; the access token is
143
+ refreshed on its own. Revoke a device, or create an access token for CI, on
144
+ the account page (tuttidaw.com/studio/account).
145
+
146
+ **CI.** Set `TUTTICODE_TOKEN` to an access token from the account page; it
147
+ wins over a stored sign-in and is never refreshed.
148
+
149
+ **Where it is stored.** `~/.tutticode/credentials`, one entry per site,
150
+ readable only by you (mode 0600; on Windows an ACL with only your user).
151
+ `tutticode doctor` checks it and `tutticode doctor --fix` repairs it.
152
+ `~/.tutticode/install-id` is a random id the page counts anonymous installs
153
+ by; it is not tied to you.
88
154
 
89
155
  ## How it works
90
156
 
@@ -125,8 +191,11 @@ written inside the stems folder, and never through a symbolic link.
125
191
 
126
192
  ## Commands
127
193
 
128
- - `tutticode doctor` - Node, the browser, the page, the connection and the
129
- engine version.
194
+ - `tutticode doctor [--fix]` - Node, the browser, the page, the connection,
195
+ the engine version, who renders and whether the credentials file is
196
+ private (`--fix` makes it private again).
197
+ - `tutticode login [--device [--no-wait] [--json]]`, `tutticode logout`,
198
+ `tutticode whoami [--json]` - see [Sign-in and limits](#sign-in-and-limits).
130
199
  - `tutticode setup` - explains, asks, and then sets the browser policy
131
200
  `LocalNetworkAccessAllowedForUrls = ["https://tuttidaw.com"]` for your
132
201
  user (Windows: HKCU registry; macOS: `defaults`; Linux: a managed policy
@@ -141,13 +210,16 @@ Bridge flags for every command: `--show` / `--headless`,
141
210
  `--browser chrome|edge|<path>`, `--origin <url>` (staging / local dev),
142
211
  `--dev-origin <url>`, `--locale <locale>`, `--no-daemon`, `--verbose`.
143
212
  Environment: `TUTTICODE_BROWSER` (browser path), `TUTTICODE_HOME` (state
144
- folder), `TUTTICODE_BROWSER_ARGS` (extra browser flags).
213
+ folder), `TUTTICODE_BROWSER_ARGS` (extra browser flags), `TUTTICODE_TOKEN`
214
+ (an access token, for CI), `TUTTICODE_BRAND_TAG=0` (no metadata tag).
145
215
 
146
216
  ## Privacy
147
217
 
148
218
  tutticode sends no telemetry. Your program goes only to the TuttiCode page
149
- in your own browser. Logs stay in `~/.tutticode/logs` and never contain your
150
- program or audio.
219
+ in your own browser. The page records each render's length, format and
220
+ outcome (with your account when signed in, else as anonymous counts), never
221
+ the program, file names or audio. Logs stay in `~/.tutticode/logs` and
222
+ never contain your program, audio or tokens.
151
223
 
152
224
  ## Browsers
153
225
 
package/README.zh-CN.md CHANGED
@@ -7,8 +7,12 @@ Strudel 的超集)变成音频文件,任何 agent 或脚本都能用。它是一
7
7
  MCP server,适用于 Claude Code、Copilot CLI、Codex、Cursor、Claude Desktop 等。
8
8
 
9
9
  渲染**在你自己的浏览器里**进行,用的就是 tuttidaw.com/code 的同一个引擎,所以
10
- 文件和编辑器里听到的一模一样。不经过服务器渲染,不需要账号,也不收费。每个结果
11
- 都带一个 `editUrl`,可以在 TuttiDAW 里打开这段程序继续编辑。
10
+ 文件和编辑器里听到的一模一样。不经过服务器渲染,也不收费。每个结果都带一个
11
+ `editUrl`,可以在 TuttiDAW 里打开这段程序继续编辑。
12
+
13
+ TuttiDAW 启用限制后(正在逐步上线;在此之前渲染既不截断也不加标签),不登录时每次渲染最长 60 秒,超过 30 秒的渲染会混入一段语音标签
14
+ "register at TuttiDAW"。用免费账号登录(`tutticode login`)就没有这些限制:
15
+ 每次最长 5 分钟,没有语音标签。见[登录与限制](#登录与限制)。
12
16
 
13
17
  ## 安装
14
18
 
@@ -45,23 +49,30 @@ Claude Code、Copilot CLI 和 Codex 分别从 `~/.claude/skills`、`~/.copilot/s
45
49
  tutticode check song.tc # 只检查,不出声音
46
50
  tutticode render song.tc -o bed.wav --seconds 12 --fade-out 1.5 --lufs -16 --json
47
51
  tutticode render song.tc -o loop.flac --loops 4 --stems stems/
48
- tutticode open song.tc # 在 TuttiCode 里打开给人看
52
+ tutticode open song.tc # 在 TuttiCode 里打开给人看(--headless:只打印链接)
49
53
  cat song.tc | tutticode check - # 从 stdin 读程序
50
54
  ```
51
55
 
52
56
  `render` 参数: `--seconds|--bars|--loops N`、`--bpm N`、
53
57
  `--format wav|flac|mp3`(默认按 `-o` 的扩展名)、`--sample-rate 44100|48000`、
54
58
  `--bit-depth 16|24`、`--stems <目录>`、`--fade-in 秒`、`--fade-out 秒`、
55
- `--tail 秒`、`--lufs N`、`--true-peak N`、`--json`、`--timeout 秒`。
59
+ `--tail 秒`、`--lufs N`、`--true-peak N`、`--limit`、`--json`、`--timeout 秒`。
60
+ 不会写出削波的文件:true peak 超过上限(`--true-peak`,默认 -1 dBTP)的渲染会
61
+ 整体降低一次静态增益,CLI 会说明("Lowered 4.6 dB to avoid clipping")。
56
62
  `--lufs` 只做一次静态增益;如果达不到 true peak 上限,会以 `clip` 失败,而不是
57
- 偷偷加限制器。
63
+ 偷偷加限制器;需要时加 `--limit`:对混音(不含分轨)加 true peak 限制器,
64
+ 报告里的 `limitDb` 是它最多压下的量。
58
65
 
59
66
  `--json` 输出渲染报告:时长、小节数、速度、响度和 true peak、施加的增益、每个
60
67
  声部的电平、小节和拍的时间点(秒,用来对齐剪辑点)、检查报告、分析结果、
61
68
  `editUrl` 和写出的文件路径。永远不会把音频打印到终端。
62
69
 
70
+ `--no-brand-tag`(或 `TUTTICODE_BRAND_TAG=0`)不在文件里写 "Made with
71
+ TuttiCode" 元数据;仅登录后有效。
72
+
63
73
  退出码: `0` 成功, `1` 代码有错(或响度目标会削波), `2` bridge / 浏览器问题,
64
- `3` 用法错误。
74
+ `3` 用法错误, `4` 未登录(`whoami`), `5` 超出未登录时的限制, `6` tutticode
75
+ 版本太旧(`npm i -g tutticode@latest`)。
65
76
 
66
77
  ### MCP 工具
67
78
 
@@ -74,8 +85,51 @@ cat song.tc | tutticode check - # 从 stdin 读程序
74
85
  | `code_compare` | 把一次渲染和目标(或 Muse 风格)比较,或比较两次渲染 |
75
86
  | `code_open` | 在可见的 TuttiCode 标签页里打开程序(`tutticode mcp --headless` 时不开窗口,只返回链接) |
76
87
  | `code_reference` | 搜索包里自带的 TuttiCode 参考文档 |
88
+ | `code_account` | 是否已登录、时长限制和今天的用量 |
77
89
 
78
90
  参考文档同时作为 MCP resources 提供(`tutticode://skills/...`)。
91
+ `tutticode mcp` 和 CLI 用同一个登录(`tutticode login`,或它环境里的
92
+ `TUTTICODE_TOKEN`);它自己从不发起登录。
93
+
94
+ ## 登录与限制
95
+
96
+ 下面的限制在 TuttiDAW 启用后生效(正在逐步上线;在此之前每次渲染都完整、不加标签)。
97
+ 登录现在就能用。
98
+
99
+ | | 不登录 | 免费账号 |
100
+ | --- | --- | --- |
101
+ | 每次渲染最长 | 60 秒(更长:错误 `limit`,退出码 5) | 5 分钟 |
102
+ | 语音标签 "register at TuttiDAW" | 超过 30 秒的渲染全程混入 | 没有 |
103
+ | 格式、分轨 | 全部 | 全部 |
104
+
105
+ ```sh
106
+ tutticode login # 打开浏览器,确认后回到终端
107
+ tutticode login --device # 这台机器没有浏览器(SSH、服务器):在任意设备上确认一个码
108
+ tutticode whoami # 谁在渲染、限制、今天的用量
109
+ tutticode logout # 让这台电脑退出登录
110
+ ```
111
+
112
+ **给 agent。** 遇到 `limit` 错误时,用一句话把错误信息转告用户,然后在限制内继续。
113
+ `tutticode login --device --no-wait --json` 会输出 `{verificationUri,
114
+ verificationUriComplete, userCode, expiresIn}` 并立即返回:把链接交给用户,继续
115
+ 工作;用户确认后,tutticode 会在后台完成登录。不带 `--no-wait` 的 `login` 需要
116
+ 终端(否则退出码 3)。
117
+
118
+ **语音标签。** 不登录、超过 30 秒的渲染,从开头起每隔几秒混入一次标签,混音和
119
+ 每个分轨都有,而且在所有测量之前混入:响度、频段、声部电平和 `code_compare` 都包含
120
+ 它。报告会注明(`watermark: {reason, at, removeWith}`),CLI 也会打印一行说明。
121
+ 标签不是你程序的一部分:不要为了去掉它而修改代码。`tutticode login`(免费)即可去掉。
122
+
123
+ **登录能做什么。** 它只能用 TuttiCode 渲染:打不开你的项目、账号或账单。有效期一年;
124
+ access token 会自动刷新。在账号页面(tuttidaw.com/studio/account)可以撤销某台设备,
125
+ 或为 CI 创建 access token。
126
+
127
+ **CI。** 把 `TUTTICODE_TOKEN` 设为账号页面创建的 access token;它优先于已保存的
128
+ 登录,而且不会被刷新。
129
+
130
+ **保存在哪里。** `~/.tutticode/credentials`,每个站点一条,只有你能读(权限 0600;
131
+ Windows 上 ACL 只含你的用户)。`tutticode doctor` 会检查,`tutticode doctor --fix`
132
+ 会修复。`~/.tutticode/install-id` 是一个随机 id,页面用它统计匿名安装数,和你本人无关。
79
133
 
80
134
  ## 工作原理
81
135
 
@@ -107,7 +161,10 @@ token 通信,网页无法访问。无头浏览器通过私有管道(`--remote-de
107
161
 
108
162
  ## 命令
109
163
 
110
- - `tutticode doctor` —— 检查 Node、浏览器、页面、连接和引擎版本。
164
+ - `tutticode doctor [--fix]` —— 检查 Node、浏览器、页面、连接、引擎版本、谁在渲染,
165
+ 以及登录凭据文件是否只有你能读(`--fix` 修复)。
166
+ - `tutticode login [--device [--no-wait] [--json]]`、`tutticode logout`、
167
+ `tutticode whoami [--json]` —— 见[登录与限制](#登录与限制)。
111
168
  - `tutticode setup` —— 先说明、再询问,同意后为当前用户设置浏览器策略
112
169
  `LocalNetworkAccessAllowedForUrls = ["https://tuttidaw.com"]`
113
170
  (Windows:HKCU 注册表;macOS:`defaults`;Linux:托管策略文件,需要 sudo),
@@ -121,12 +178,15 @@ token 通信,网页无法访问。无头浏览器通过私有管道(`--remote-de
121
178
  `--browser chrome|edge|<路径>`、`--origin <url>`(预发 / 本地开发)、
122
179
  `--dev-origin <url>`、`--locale <语言>`、`--no-daemon`、`--verbose`。
123
180
  环境变量:`TUTTICODE_BROWSER`(浏览器路径)、`TUTTICODE_HOME`(状态目录)、
124
- `TUTTICODE_BROWSER_ARGS`(额外的浏览器参数)。
181
+ `TUTTICODE_BROWSER_ARGS`(额外的浏览器参数)、`TUTTICODE_TOKEN`(access token,
182
+ 用于 CI)、`TUTTICODE_BRAND_TAG=0`(不写元数据标签)。
125
183
 
126
184
  ## 隐私
127
185
 
128
186
  tutticode 不发送任何遥测数据。你的程序只会交给你自己浏览器里的 TuttiCode 页面。
129
- 日志保存在 `~/.tutticode/logs`,不包含程序内容和音频。
187
+ 页面会记录每次渲染的时长、格式和结果(登录时记在你的账号下,否则只是匿名计数),
188
+ 从不记录程序、文件名或音频。日志保存在 `~/.tutticode/logs`,不包含程序内容、音频
189
+ 或 token。
130
190
 
131
191
  ## 浏览器
132
192
 
@@ -71,10 +71,11 @@ _lead: n("0 2 4 7").scale("C:minor") // a leading _ mutes a voice
71
71
  The same tools, with the same names and report shapes, run on two backends.
72
72
  Use whichever this agent has; prefer the local one.
73
73
 
74
- - **Local `tutticode`** (default; free, no account): the `tutticode` CLI
74
+ - **Local `tutticode`** (default; free): the `tutticode` CLI
75
75
  and MCP server (`npm i -g tutticode`, `tutticode mcp`) render in the
76
76
  user's own browser with the tuttidaw.com/code engine and write files to
77
- disk, up to 300 s. Its tool descriptions say "Runs locally". Without MCP,
77
+ disk, up to 300 s (60 s without sign-in once the limits are on, below). Its tool descriptions
78
+ say "Runs locally". Without MCP,
78
79
  call the CLI: `tutticode check prog.tc`, `tutticode render prog.tc -o
79
80
  out.wav --seconds 12 --lufs -16 --json`, `tutticode open prog.tc`.
80
81
  Program code goes only to the user's browser, never to TuttiDAW's servers.
@@ -91,6 +92,15 @@ Use whichever this agent has; prefer the local one.
91
92
  | `code_compare` | a render against goals (or a Muse `style`), or two renders (A/B) |
92
93
  | `code_open` | (local) open the program in a visible TuttiCode tab for the user |
93
94
  | `code_reference` | (local) search these references |
95
+ | `code_account` | (local) signed in or not, the length limits, today's usage |
96
+
97
+ **Without sign-in**, once TuttiDAW switches its limits on (they are being
98
+ rolled out; until then no local render is cut or tagged), local renders
99
+ stop at 60 s (error `limit`) and over 30 s carry a spoken "register at
100
+ TuttiDAW" tag (`watermark`; it is in every stat, not in your program:
101
+ never edit code to remove it). When a render hits one, tell the user once;
102
+ `tutticode login` (free) lifts both. Agents: run `tutticode login
103
+ --device --no-wait --json`, give the user its link (`references/agent-loop.md`).
94
104
 
95
105
  ## Workflow: write -> check -> render -> revise
96
106
 
@@ -125,6 +135,7 @@ Read only what the task needs:
125
135
  - `references/mini-notation.md`: Mini-notation. The rhythm language inside the quotes - sequences, rests, groups, alternation, polymeter, Euclidean rhythms and chance.
126
136
  - `references/time-and-structure.md`: Time and structure. Functions that speed up, shift, reverse, repeat and combine patterns, and arrange them into sections.
127
137
  - `references/harmony-and-scales.md`: Harmony and scales. Note names and octaves, scale degrees, transposition, chord symbols, voicings and arpeggios.
138
+ - `references/melodies-with-do-re-mi.md`: Melodies with do re mi. Write notes in solfège (do re mi fa sol la si) wherever a note name goes; strudel.cc gets letters.
128
139
  - `references/sounds.md`: Sounds. Drum kits and banks, synth waveforms, General MIDI instrument names, Ensemble sounds and your own samples.
129
140
  - `references/effect-controls.md`: Effect controls. Filters, reverb, delay, distortion, panning, envelopes and synth controls - and moving them with signals.
130
141
  - `references/sample-operations.md`: Sample operations. Play part of a sample, change its speed, cut it into slices, fit it to the tempo and choke it.
@@ -136,5 +147,5 @@ Read only what the task needs:
136
147
  - `references/functions.md`: every function, method and signal, with signature, description and example (generated from the engine).
137
148
  - `references/devices.md`: every instrument and effect for `.inst/.fx/.midifx`, with `references/devices/<id>.md` per device: param keys, ranges, units, presets (generated from the device catalogue).
138
149
 
139
- Language: PATTERN LANGUAGE 1.2.0, engine 15.
150
+ Language: PATTERN LANGUAGE 1.2.0, engine 16.
140
151
  Human guide: https://tuttidaw.com/code/learn; agents: https://tuttidaw.com/code/learn/for-agents
@@ -40,8 +40,9 @@ differences are marked *local* or *web*.
40
40
 
41
41
  *local* returns `files` (`audio`, `stems`: paths written on disk),
42
42
  `editUrl`, `window` (`bars`, `seconds`, `bpm`), `loudness` (`lufs`,
43
- `truePeak` of the delivered file, `gainDb` applied for a `lufs` target),
44
- `voices[]` (each voice's solo `lufs` and `truePeak`), `barTimes` /
43
+ `truePeak` of the delivered file, `gainDb` applied for a `lufs` target or
44
+ to avoid clipping, `limitDb` with `limit`), `warnings` (what was done to
45
+ the audio), `voices[]` (each voice's solo `lufs` and `truePeak`), `barTimes` /
45
46
  `beatTimes` (seconds of each bar and beat: sync video cuts to them),
46
47
  `check` and `analysis`. *web* returns `analysis`, a `listenUrl` (24 h) and
47
48
  signed audio links.
@@ -71,13 +72,48 @@ or mute (`_`) the voices you are not listening to.
71
72
  (whole loops ring out past their end). `tail` adds seconds after the
72
73
  length for reverbs and delays and makes the file exactly length + tail;
73
74
  `fadeIn` / `fadeOut` are linear, in seconds.
75
+ - No file is written clipped: without `lufs`, a render whose true peak
76
+ would pass `truePeak` (default -1 dBTP) is lowered by one static gain
77
+ (negative `gainDb`, a line in `warnings`); a stem that would clip on
78
+ its own is lowered further (its `gainDb` in `voices[]`). *web* lowers
79
+ the audio file the same way and says so in `warnings`; its `analysis`
80
+ measures the program before that gain.
74
81
  - `lufs` applies one static gain to that integrated loudness, the same on
75
- the stems. When the true peak would pass `truePeak` (default -1 dBTP)
76
- the render fails with code `clip` instead of limiting: ask for a lower
77
- `lufs`, or make the program less peaky (lower its loudest voice). Under
78
- 0.4 s there is no integrated loudness and `lufs` is ignored.
82
+ the stems. When the true peak would pass `truePeak` the render fails
83
+ with code `clip`: ask for a lower `lufs`, make the program less peaky
84
+ (lower its loudest voice), or add `limit: true` (`--limit`), a
85
+ true-peak limiter on the mix (not the stems) that reports the most it
86
+ took off in `limitDb`. Under 0.4 s there is no integrated loudness and
87
+ `lufs` is ignored.
79
88
  - Exit codes (CLI): 0 ok, 1 errors in the code or `clip`, 2 bridge or
80
- browser problem (run `tutticode doctor`), 3 usage.
89
+ browser problem (run `tutticode doctor`), 3 usage, 4 not signed in
90
+ (`whoami`), 5 `limit`, 6 `upgrade`.
91
+
92
+ ## Sign-in, limits and the voice tag (*local*)
93
+
94
+ - **Limits.** Once TuttiDAW switches them on (they are being rolled out;
95
+ until then no render is cut or tagged), a render without sign-in is at
96
+ most 60 s, and a render over 30 s carries a spoken "register at
97
+ TuttiDAW" tag throughout. A free account (`tutticode login`) lifts both. `code_account` (or `tutticode
98
+ whoami --json`) says which applies (`limits.maxSeconds`,
99
+ `limits.watermarkAfterSeconds`, null = never tagged): plan within it,
100
+ for example keep an anonymous draft at 30 s or less.
101
+ - **`limit` error** (CLI exit 5), with `limit: {name, value,
102
+ signedInValue}`: tell the user its message in one sentence and carry on
103
+ within the limit. To get the user's approval without a terminal, run
104
+ `tutticode login --device --no-wait --json`, give the user its
105
+ `verificationUriComplete` link (or `verificationUri` and `userCode`),
106
+ and keep working: the sign-in finishes in the background and later
107
+ renders use it. Never wait on it.
108
+ - **`watermark`** in a report (`{reason, at: [start of each tag, s],
109
+ removeWith}`, and one CLI line on stderr): the tag is in the file and in
110
+ every stat (loudness, bands, voice levels, compare). It is not part of
111
+ the program: do not change the code to remove it or to fix the stats it
112
+ moves. Tell the user once that `tutticode login` (free) removes it.
113
+ - **`upgrade`** (exit 6): the user runs `npm i -g tutticode@latest`.
114
+ - The sign-in can only render with TuttiCode (no projects, account or
115
+ billing). Never print or ask for tokens; CI sets `TUTTICODE_TOKEN` (an
116
+ access token from the account page).
81
117
 
82
118
  ## Targets
83
119
 
@@ -225,4 +225,4 @@ Accepted names: `sampler`, `drumsampler`.
225
225
 
226
226
  ## Factory presets
227
227
 
228
- 808 BNYX Stopper · 808 Selector Rack · Ac Flugelhorn · Ac Strings Orch · Ac Strings Pizz Basic · Ac Strings Pizz Oct · Ac Strings Pizz Stage · Acid Meltdown Bass · Ambient Encounters Bass · Ambient Feeling · Ambient Swells · Ambiente Pad · Analog Stab Lead · Analogue Bass · Arp 5th Lead · Arp Poly Lead · B Bass · B Seven Bass · Big Modules Bass · Biig Saw Pad · Bit Growl Bass · Byte Sized Bass · Celeste · Ceramic Bowl · Ceramic Tiles · Childhood Home Piano · Chill Outzone · Chimes Finger Down · Choir Pad Avalon · Chord Floot Aboot Pad · Chord Soft Keys · Classical Keys · Clay Flute · Click And Finer Cuts · Click Noise · Cnarz FX · Dark Corner Pad · Dark One · Dark Thought Lead · Daysleeper Swells Pad · DnB Tools 1 Lead · DnB Tools 2 Lead · DnB Tools 3 Lead · Downstairs Pad · Drift Pad · Duetta Pad · E-Piano Cheap · Electric Bass Raw · Electric Bass Soft · Electroflow Keys · Fat Heavy Drone Pad · Fine Pulse Bass · Frozen Rings Pad · Galactica Pad · Git Proc Loop · Glide Square Bass · Glidesynth Lead 1 · Glidesynth Lead 2 · Good Old Vintage Phat 1 Lead · Good Old Vintage Phat 2 Lead · Good Old Vintage Phat Bass · Grand Piano · Grand Piano Single Sample · House Stab · Inclement Drone Pad · Independence Day · Indian Flute · Infected Bass · JX Chorus Bass · Jarble Ambience · Jarble Ambience Pad · Jarble Disto Bass · Klickering Lead Modern · LoFi Voodoo · LoFi Warp Drone · Lovely Keys · MPE Alder Waldgeist · MPE Bower Close · MPE Depth Pressure Pad · MPE Dream Grain Drone · MPE Dulcimatica · MPE FM Arp · MPE Inside Angel · MPE Pearlescent Tides Pad · MPE Sci-Fi Flicks · Machine Punk Bass · Mamas Bass · Marimba Concert · Marimba Maple · Megaphatness Pad · Metallic Love Keys · Metallo Shake · Mini 1 OSC Bass · Mini 1 OSC Reso Bass · Mini 2 OSC LFO Bass · Mini 2 OSC Solo Bass · Mini 3 OSC Bass · Mini 3 OSC Xectro Bass · Mini Wobble Bass · Mod Bass · Modular Organ Pad · Music Box · Muugy Bass · No 3O3 FM 1 Lead · No 3O3 FM 2 Lead · Nostalgic VHS Bells · PPP Pad · Panorama Pad · Phantasm Pad · Piano Bass · Pitched Ambience · Pitched Ambiente · Pixelated Bass · Plock Blip · Psycho Tables Pad · Pulse Bass · Reso Clicks · Revenge of Q Pad · Reverberant Keys · Rhyt Mo · Rhythmic Sine Saw Square · Ring Modular Lead · Sandblaster Lead · Saw Filtered Bass · Saw Percussion · Seashore Pad · Seashore Pad (Evolving) · Seashore Pad (Synth Pad) · Simple One Pad · Slow Drown Pad · Smooth Synth Keys · Soft Industry · Soover Lead · Space FlicFlac · Stab Dense · Stab Ibiza · Stab Proga · Stadium Pluck · Steel Pan · Strange Beats 1 · Strange Beats 2 · Strange Space Beats · Sub 808 Bass · Sunken Bells · Super Soover Lead · Supershort Blip · Supersine · Sweeper Saege Pad · Sweeper Saege Pad (Pad) · Sweeper Saege Pad (Synth Pad) · Tempo Steppe Keys · Textural Machine · The Greatest Pad · Thicket Wail Pad · Upright Bass · Vacuum Flute · Vibraphone · Vinyl Siren · Warm Bubbly Pad · Wonk Bass · Zirp Sync Noiseloop
228
+ 808 BNYX Stopper · 808 Selector Rack · Ac Flugelhorn · Ac Strings Orch · Ac Strings Pizz Basic · Ac Strings Pizz Oct · Ac Strings Pizz Stage · Acid Meltdown Bass · Ambient Encounters Bass · Ambient Feeling · Ambient Swells · Ambiente Pad · Analog Stab Lead · Analogue Bass · Arp 5th Lead · Arp Poly Lead · B Bass · B Seven Bass · Big Modules Bass · Biig Saw Pad · Bit Growl Bass · Byte Sized Bass · Celeste · Ceramic Bowl · Ceramic Tiles · Childhood Home Piano · Chill Outzone · Chimes Finger Down · Choir Pad Avalon · Chord Floot Aboot Pad · Chord Soft Keys · Classical Keys · Clay Flute · Click And Finer Cuts · Click Noise · Cnarz FX · Dark Corner Pad · Dark One · Dark Thought Lead · Daysleeper Swells Pad · DnB Tools 1 Lead · DnB Tools 2 Lead · DnB Tools 3 Lead · Downstairs Pad · Drift Pad · Duetta Pad · E-Piano Cheap · Electric Bass Raw · Electric Bass Soft · Electroflow Keys · Fat Heavy Drone Pad · Fine Pulse Bass · Frozen Rings Pad · Galactica Pad · Git Proc Loop · Glide Square Bass · Glidesynth Lead 1 · Glidesynth Lead 2 · Good Old Vintage Phat 1 Lead · Good Old Vintage Phat 2 Lead · Good Old Vintage Phat Bass · Grand Piano · Grand Piano Single Sample · House Stab · Inclement Drone Pad · Independence Day · Indian Flute · Infected Bass · JX Chorus Bass · Jarble Ambience · Jarble Ambience Pad · Jarble Disto Bass · Klickering Lead Modern · LoFi Voodoo · LoFi Warp Drone · Lovely Keys · MPE Alder Waldgeist · MPE Bower Close · MPE Depth Pressure Pad · MPE Dream Grain Drone · MPE Dulcimatica · MPE FM Arp · MPE Inside Angel · MPE Pearlescent Tides Pad · MPE Sci-Fi Flicks · Machine Punk Bass · Mamas Bass · Marimba Concert · Marimba Maple · Megaphatness Pad · Metallic Love Keys · Metallo Shake · Mini 1 OSC Bass · Mini 1 OSC Reso Bass · Mini 2 OSC LFO Bass · Mini 2 OSC Solo Bass · Mini 3 OSC Bass · Mini 3 OSC Xectro Bass · Mini Wobble Bass · Mod Bass · Modular Organ Pad · Music Box · Muugy Bass · No 3O3 FM 1 Lead · No 3O3 FM 2 Lead · Nostalgic VHS Bells · PPP Pad · Panorama Pad · Phantasm Pad · Piano Bass · Pitched Ambience · Pitched Ambiente · Pixelated Bass · Plock Blip · Psycho Tables Pad · Pulse Bass · Reso Clicks · Revenge of Q Pad · Reverberant Keys · Rhyt Mo · Rhythmic Sine Saw Square · Ring Modular Lead · Sandblaster Lead · Saw Filtered Bass · Saw Percussion · Seashore Pad · Seashore Pad (Evolving) · Seashore Pad (Synth Pad) · Simple One Pad · Slow Drown Pad · Smooth Synth Keys · Soft Industry · Soover Lead · Space FlicFlac · Stab Dense · Stab Ibiza · Stab Proga · Stadium Pluck · Steel Pan · Strange Beats 1 · Strange Beats 2 · Strange Space Beats · Sub 808 Bass · Sunken Bells · Super Soover Lead · Supershort Blip · Supersine · Sweeper Saege Pad · Sweeper Saege Pad (Pad) · Sweeper Saege Pad (Synth Pad) · Tempo Steppe Keys · Textural Machine · The Greatest Pad · Thicket Wail Pad · Upright Bass · Vacuum Flute · Vibraphone · Vinyl Siren · Vocal Chop Ah · Vocal Chop Hey · Vocal Chop Oh · Warm Bubbly Pad · Wonk Bass · Zirp Sync Noiseloop
@@ -29,7 +29,7 @@ ranges and units.
29
29
  | [Impulse](devices/impulse.md) | available | 13 | 139 |
30
30
  | [Meld](devices/meld.md) | available | 84 | 221 |
31
31
  | [Operator](devices/operator.md) | tested end to end | 331 | 145 |
32
- | [Sampler](devices/sampler.md) | tested end to end | 161 | 210 |
32
+ | [Sampler](devices/sampler.md) | tested end to end | 164 | 210 |
33
33
  | [Simpler](devices/simpler.md) | tested end to end | 38 | 212 |
34
34
  | [SixOp](devices/sixop.md) | available | 0 | 172 |
35
35
  | [Synth](devices/synth.md) | available | 12 | 10 |
@@ -40,9 +40,12 @@ audio), `code_render` (render and measure) and `code_compare` (compare with
40
40
  a target or an earlier render). Only where the audio is made differs:
41
41
 
42
42
  - **tutticode on your computer** (the default): renders in your own browser
43
- and writes the files to your disk. Free, no account, up to 5 minutes of
44
- audio per render. It also offers `code_open` (open a program here for you to hear)
45
- and `code_reference` (search the language reference).
43
+ and writes the files to your disk. Free, up to 5 minutes of audio per
44
+ render with a free account (`tutticode login`); without sign-in, once the
45
+ limits are switched on (being rolled out), up to 60 seconds, and renders
46
+ over 30 seconds carry a spoken "register at TuttiDAW" tag. It also offers `code_open` (open a program here for you to hear),
47
+ `code_reference` (search the language reference) and `code_account`
48
+ (signed in or not, and the limits).
46
49
  - **TuttiDAW's web MCP** (`https://tuttidaw.com/api/mcp`) and the HTTP API
47
50
  (`/api/code/check`, `/api/code/render`, `/api/code/compare`): for agents
48
51
  that cannot run programs on your computer. Renders on our servers, needs
@@ -99,7 +99,7 @@ n("0 2 4").scale("C:minor")
99
99
 
100
100
  ### `note(notes)`
101
101
 
102
- Plays pitches: note names (c4, eb3) or MIDI numbers (60).
102
+ Plays pitches: note names (c4, eb3), solfège (do re mi, sol4, sib) or MIDI numbers (60).
103
103
 
104
104
  ```js
105
105
  note("c3 e3 g3 b3")
@@ -0,0 +1,59 @@
1
+ # Melodies with do re mi
2
+
3
+ Write notes in solfège (do re mi fa sol la si) wherever a note name goes; strudel.cc gets letters.
4
+
5
+ ## Solfège is a note name
6
+
7
+ Wherever a note name goes, you can write its solfège name instead:
8
+ `do re mi fa sol la si`. TuttiCode uses fixed do: `do` is always C, `re` is D,
9
+ `sol` is G, whatever the key. `so` and `ti` work too (the same as `sol` and
10
+ `si`).
11
+
12
+ ```js
13
+ note("do re mi fa sol la si do4")
14
+ ```
15
+
16
+ Only the name differs: `note("do re mi")` plays exactly what `note("c d e")`
17
+ plays.
18
+
19
+ ## Sharps, flats and octaves
20
+
21
+ Add sharps, flats and octaves as you would to a letter: `do#4`, `mib` (E flat),
22
+ `sib3` (B flat), `fa#`. A name without an octave is in octave 3, like `c`.
23
+ Capitals work too: `Do`, `SOL`.
24
+
25
+ ```js
26
+ note("<do4 mib4 sol4 sib4> [fa#3 la3]").s("piano")
27
+ ```
28
+
29
+ ## Scales and chords
30
+
31
+ Scale roots take solfège: `.scale("re:minor")`. Stack names with commas to
32
+ play a chord.
33
+
34
+ ```js
35
+ n("0 2 4 <7 6>").scale("<re:dorian sol:mixolydian>")
36
+ ```
37
+
38
+ ```js
39
+ note("<[do3,mi3,sol3] [la2,do3,mi3] [fa2,la2,do3] [sol2,si2,re3]>").s("piano")
40
+ ```
41
+
42
+ Chord symbols (`chord("C^7")`, `.voicings()`) keep their letters: there `do`
43
+ already means D diminished (`D` and `o`).
44
+
45
+ ## Where a word is not a note
46
+
47
+ In `s()` and `sound()` words are sound names, so `s("do")` looks for a sound
48
+ called "do". `n()` is also a sample or soundfont index, so `n("do")` is a
49
+ word too: write `note("do")`. Solfège means a pitch only in `note()` /
50
+ `.note()`, `.scale()` roots, `.mode()` and `.anchor()`, and `.add()` /
51
+ `.sub()` / `.transpose()` on notes.
52
+
53
+ ## Opening in strudel.cc
54
+
55
+ strudel.cc reads letter names only. "Open in strudel.cc" rewrites solfège to
56
+ letters for you (`"do re mi"` becomes `"c d e"`), so the program plays the same
57
+ there.
58
+
59
+ Source: https://tuttidaw.com/code/learn/melodies-with-do-re-mi
@@ -11,7 +11,12 @@ the `tutticode` skill (install both: `tutticode skills install`); the tools
11
11
  are `code_check`, `code_render`, `code_compare` from the local `tutticode`
12
12
  MCP server or CLI (default: free, renders in the user's browser, writes
13
13
  files) or TuttiDAW's web MCP (server renders, Muse points, 60 s, no files:
14
- a `listenUrl`).
14
+ a `listenUrl`). Once TuttiDAW switches its limits on (being rolled out),
15
+ the local tools without sign-in render at most 60 s and tag renders over
16
+ 30 s with a spoken "register at TuttiDAW": for a longer delivery, when a
17
+ render hits a limit (`limit` error, `watermark`), suggest
18
+ `tutticode login` (free) to the user (the `tutticode` skill says how an
19
+ agent gets the approval). Never change the program to remove the tag.
15
20
 
16
21
  ## Workflow
17
22
 
@@ -52,19 +57,26 @@ Recipe index:
52
57
  | Broadcast (EBU R128) | -23 |
53
58
  | Short sound effects | -18..-26: peaky, see each recipe |
54
59
 
55
- - True peak ceiling -1 dBTP (the default). `lufs` is one static gain, never
56
- a limiter: a peaky program fails with `clip`. Then lower the target, or
57
- lower the loudest voice's `.gain` and render again. Where loudness
58
- matters (music beds at -14..-17), end the program with
59
- `master.fx("Limiter", {gainDb: 3, ceiling: -3})`: the program's own bus
60
- catches the peaks before the gain, as the music recipes do.
60
+ - True peak ceiling -1 dBTP (the default, `truePeak`). No file is written
61
+ clipped: without `lufs`, a render that would pass the ceiling is lowered
62
+ by one static gain (a negative `gainDb` and a line in `warnings`). `lufs`
63
+ is one static gain: a peaky program (most drum programs at -14..-16)
64
+ fails with `clip`. Then lower the target, lower the loudest voice's
65
+ `.gain` and render again, end the program with
66
+ `master.fx("Limiter", {gainDb: 3, ceiling: -3})` (the program's own bus
67
+ catches the peaks before the gain, as the music recipes do), or add
68
+ `limit: true` (`--limit`): the render's true-peak limiter holds the
69
+ ceiling and reports the most it took off (`limitDb`). More than about
70
+ 6 dB of it flattens the drums: then lower the target instead.
61
71
  - Exact durations: `seconds` cuts exactly. A one-shot effect is one bar
62
72
  long: `setcpm` sets the bar (`setcpm(60)` = 1 s, `setcpm(15)` = 4 s).
63
73
  - Video beds: `fadeIn` 1-3 s, `fadeOut` 2-5 s, `tail` for the reverb.
64
74
  - Loops for apps and games: `loops` N with `tail: 0`, no fades, so the file
65
75
  is exactly N loops and repeats in time; keep the last step short.
66
- - Stems: `stems: true` writes one file per voice (named by the labels); a
67
- `lufs` gain applies to the stems too, so they still sum to the mix.
76
+ - Stems: `stems: true` writes one file per voice (named by the labels); the
77
+ mix's static gain applies to the stems too, so they still sum to the mix.
78
+ A stem that would clip on its own is lowered further (its `gainDb` in
79
+ `voices`, a line in `warnings`); the limiter never touches stems.
68
80
 
69
81
  ## Quality bar: never deliver
70
82
 
@@ -75,7 +87,9 @@ Recipe index:
75
87
  - a length other than the one asked for (check `window.seconds`, plus the
76
88
  tail);
77
89
  - without the `editUrl` (or `listenUrl`): always give it to the user, it
78
- opens the program in TuttiCode to keep editing.
90
+ opens the program in TuttiCode to keep editing;
91
+ - a render with a `watermark` (the anonymous voice tag) without telling
92
+ the user it is there and that `tutticode login` removes it.
79
93
 
80
94
  ## Sound effects
81
95