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 +83 -11
- package/README.zh-CN.md +69 -9
- package/dist/skills/tutticode/SKILL.md +14 -3
- package/dist/skills/tutticode/references/agent-loop.md +43 -7
- package/dist/skills/tutticode/references/devices/sampler.md +1 -1
- package/dist/skills/tutticode/references/devices.md +1 -1
- package/dist/skills/tutticode/references/for-agents.md +6 -3
- package/dist/skills/tutticode/references/functions.md +1 -1
- package/dist/skills/tutticode/references/melodies-with-do-re-mi.md +59 -0
- package/dist/skills/tutticode-sound-for-media/SKILL.md +24 -10
- package/dist/tutticode.cjs +3123 -352
- package/package.json +1 -1
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
|
|
13
|
-
|
|
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`.
|
|
64
|
-
|
|
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
|
|
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.
|
|
150
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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`
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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 |
|
|
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,
|
|
44
|
-
|
|
45
|
-
|
|
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
|
|
@@ -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
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
`
|
|
60
|
-
|
|
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);
|
|
67
|
-
|
|
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
|
|