@pinkpixel/haku 0.1.0 → 1.0.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.
Files changed (121) hide show
  1. package/README.md +18 -11
  2. package/dist/cli.mjs +38 -4
  3. package/dist/{mcp-DDuNECfs.mjs → mcp-DsSn95Rn.mjs} +3 -2
  4. package/dist/samples/drums/cabasa_v0_r1.ogg +0 -0
  5. package/dist/samples/drums/cabasa_v0_r2.ogg +0 -0
  6. package/dist/samples/drums/cabasa_v1_r1.ogg +0 -0
  7. package/dist/samples/drums/cabasa_v1_r2.ogg +0 -0
  8. package/dist/samples/drums/shaker_v0_r1.ogg +0 -0
  9. package/dist/samples/drums/shaker_v0_r2.ogg +0 -0
  10. package/dist/samples/drums/shaker_v1_r1.ogg +0 -0
  11. package/dist/samples/drums/shaker_v1_r2.ogg +0 -0
  12. package/dist/samples/guitar/v0_31.ogg +0 -0
  13. package/dist/samples/guitar/v0_32.ogg +0 -0
  14. package/dist/samples/guitar/v0_33.ogg +0 -0
  15. package/dist/samples/guitar/v0_34.ogg +0 -0
  16. package/dist/samples/guitar/v0_35.ogg +0 -0
  17. package/dist/samples/guitar/v0_36.ogg +0 -0
  18. package/dist/samples/guitar/v0_37.ogg +0 -0
  19. package/dist/samples/guitar/v0_38.ogg +0 -0
  20. package/dist/samples/guitar/v0_39.ogg +0 -0
  21. package/dist/samples/guitar/v0_40.ogg +0 -0
  22. package/dist/samples/guitar/v0_41.ogg +0 -0
  23. package/dist/samples/guitar/v0_43.ogg +0 -0
  24. package/dist/samples/guitar/v0_45.ogg +0 -0
  25. package/dist/samples/guitar/v0_47.ogg +0 -0
  26. package/dist/samples/guitar/v0_48.ogg +0 -0
  27. package/dist/samples/guitar/v0_50.ogg +0 -0
  28. package/dist/samples/guitar/v0_52.ogg +0 -0
  29. package/dist/samples/guitar/v0_53.ogg +0 -0
  30. package/dist/samples/guitar/v0_54.ogg +0 -0
  31. package/dist/samples/guitar/v0_55.ogg +0 -0
  32. package/dist/samples/guitar/v0_56.ogg +0 -0
  33. package/dist/samples/guitar/v0_57.ogg +0 -0
  34. package/dist/samples/guitar/v0_58.ogg +0 -0
  35. package/dist/samples/guitar/v0_59.ogg +0 -0
  36. package/dist/samples/guitar/v0_60.ogg +0 -0
  37. package/dist/samples/guitar/v0_61.ogg +0 -0
  38. package/dist/samples/guitar/v0_62.ogg +0 -0
  39. package/dist/samples/guitar/v0_63.ogg +0 -0
  40. package/dist/samples/guitar/v0_64.ogg +0 -0
  41. package/dist/samples/guitar/v0_65.ogg +0 -0
  42. package/dist/samples/guitar/v0_66.ogg +0 -0
  43. package/dist/samples/guitar/v0_67.ogg +0 -0
  44. package/dist/samples/guitar/v0_69.ogg +0 -0
  45. package/dist/samples/guitar/v0_70.ogg +0 -0
  46. package/dist/samples/guitar/v0_71.ogg +0 -0
  47. package/dist/samples/guitar/v0_72.ogg +0 -0
  48. package/dist/samples/guitar/v0_73.ogg +0 -0
  49. package/dist/samples/guitar/v0_74.ogg +0 -0
  50. package/dist/samples/guitar/v0_75.ogg +0 -0
  51. package/dist/samples/guitar/v0_76.ogg +0 -0
  52. package/dist/samples/guitar/v0_77.ogg +0 -0
  53. package/dist/samples/guitar/v0_78.ogg +0 -0
  54. package/dist/samples/guitar/v0_79.ogg +0 -0
  55. package/dist/samples/guitar/v0_80.ogg +0 -0
  56. package/dist/samples/guitar/v0_81.ogg +0 -0
  57. package/dist/samples/guitar/v0_82.ogg +0 -0
  58. package/dist/samples/guitar/v0_83.ogg +0 -0
  59. package/dist/samples/guitar/v0_84.ogg +0 -0
  60. package/dist/samples/kalimba/v0_44.ogg +0 -0
  61. package/dist/samples/kalimba/v0_46.ogg +0 -0
  62. package/dist/samples/kalimba/v0_49.ogg +0 -0
  63. package/dist/samples/kalimba/v0_51.ogg +0 -0
  64. package/dist/samples/kalimba/v0_53.ogg +0 -0
  65. package/dist/samples/kalimba/v0_56.ogg +0 -0
  66. package/dist/samples/kalimba/v0_59.ogg +0 -0
  67. package/dist/samples/kalimba/v0_61.ogg +0 -0
  68. package/dist/samples/kalimba/v0_64.ogg +0 -0
  69. package/dist/samples/kalimba/v0_65.ogg +0 -0
  70. package/dist/samples/kalimba/v0_67.ogg +0 -0
  71. package/dist/samples/kalimba/v0_71.ogg +0 -0
  72. package/dist/samples/kalimba/v0_73.ogg +0 -0
  73. package/dist/samples/kalimba/v0_74.ogg +0 -0
  74. package/dist/samples/kalimba/v0_75.ogg +0 -0
  75. package/dist/samples/kalimba/v0_77.ogg +0 -0
  76. package/dist/samples/kalimba/v0_78.ogg +0 -0
  77. package/dist/samples/kalimba/v0_79.ogg +0 -0
  78. package/dist/samples/kalimba/v0_82.ogg +0 -0
  79. package/dist/samples/kalimba/v0_83.ogg +0 -0
  80. package/dist/samples/manifest.json +181 -0
  81. package/dist/samples/vibes/v0_53.ogg +0 -0
  82. package/dist/samples/vibes/v0_57.ogg +0 -0
  83. package/dist/samples/vibes/v0_60.ogg +0 -0
  84. package/dist/samples/vibes/v0_64.ogg +0 -0
  85. package/dist/samples/vibes/v0_67.ogg +0 -0
  86. package/dist/samples/vibes/v0_71.ogg +0 -0
  87. package/dist/samples/vibes/v0_74.ogg +0 -0
  88. package/dist/samples/vibes/v0_77.ogg +0 -0
  89. package/dist/samples/vibes/v0_81.ogg +0 -0
  90. package/dist/samples/vibes/v0_84.ogg +0 -0
  91. package/dist/samples/vibes/v0_88.ogg +0 -0
  92. package/dist/samples/vibes/v1_53.ogg +0 -0
  93. package/dist/samples/vibes/v1_57.ogg +0 -0
  94. package/dist/samples/vibes/v1_60.ogg +0 -0
  95. package/dist/samples/vibes/v1_64.ogg +0 -0
  96. package/dist/samples/vibes/v1_67.ogg +0 -0
  97. package/dist/samples/vibes/v1_71.ogg +0 -0
  98. package/dist/samples/vibes/v1_74.ogg +0 -0
  99. package/dist/samples/vibes/v1_77.ogg +0 -0
  100. package/dist/samples/vibes/v1_81.ogg +0 -0
  101. package/dist/samples/vibes/v1_84.ogg +0 -0
  102. package/dist/samples/vibes/v1_88.ogg +0 -0
  103. package/dist/{src-D5fW7AC1.mjs → src-Bz-0ulVm.mjs} +179 -23
  104. package/dist/{src-JrRbTOJC.mjs → src-DNP73wX3.mjs} +60 -3
  105. package/dist/{version-DoZ2etXG.mjs → tools-CO-tdB7d.mjs} +321 -82
  106. package/dist/web/assets/esm-J-U37_Wq.js +210 -0
  107. package/dist/web/assets/figtree-latin-ext-wght-normal-DCwSJGxG.woff2 +0 -0
  108. package/dist/web/assets/figtree-latin-wght-normal-D_ZTVpCC.woff2 +0 -0
  109. package/dist/web/assets/fraunces-latin-ext-wght-normal-Ca2vKHc0.woff2 +0 -0
  110. package/dist/web/assets/fraunces-latin-wght-normal-ukD16Tqj.woff2 +0 -0
  111. package/dist/web/assets/fraunces-vietnamese-wght-normal-CnvboYUG.woff2 +0 -0
  112. package/dist/web/assets/index-BkzOde44.js +65 -0
  113. package/dist/web/assets/index-D0m3L8JK.css +1 -0
  114. package/dist/web/assets/rolldown-runtime-BWaJ3C7D.js +1 -0
  115. package/dist/web/assets/src-m48ItyJA.js +1 -0
  116. package/dist/web/icon-192.png +0 -0
  117. package/dist/web/icon-512.png +0 -0
  118. package/dist/web/index.html +19 -0
  119. package/dist/web/manifest.webmanifest +24 -0
  120. package/dist/web/sw.js +37 -0
  121. package/package.json +2 -2
package/README.md CHANGED
@@ -11,7 +11,7 @@ The `haku` command gives you (or your agent) a tool for every drawing command, p
11
11
  - Node 22.18 or newer
12
12
  - For listening without the browser: one of `pw-play`, `paplay`, `aplay`, `afplay`, or `ffplay` (Windows uses PowerShell, so nothing extra there)
13
13
 
14
- The package is about 7 MB, mostly because the instrument samples come with it.
14
+ The package is about 9 MB, mostly because the instrument samples come with it. The web app is in there too.
15
15
 
16
16
  ## Install
17
17
 
@@ -93,7 +93,7 @@ Every drawing and editing command is its own tool (`draw_line`, `set_mood`, `add
93
93
  | `new_project` | Makes a new `.haku.json` from a mood |
94
94
  | `batch` | Runs a list of commands as one step. All or nothing |
95
95
  | `describe` | Reads the project back as text, with a little piano roll per layer |
96
- | `snapshot` | A PNG of a scene: chords, notes, strokes, and a legend. `--out` saves it as `.png` or `.svg` |
96
+ | `snapshot` | A PNG of a scene: chords, notes, strokes, and a legend. `--scope song` draws the whole arrangement instead: the song order, then each scene's chords and notes. `--out` saves it as `.png` or `.svg` |
97
97
  | `analyze` | Notes per layer, how many strong-beat notes are chord tones, notes outside the key, half-step clashes between layers, and loudness in LUFS |
98
98
  | `play` / `stop` | Renders the scene (or the whole song) and plays it through your speakers |
99
99
  | `export` | WAV, MIDI, or the project file, for one scene or the whole song |
@@ -102,21 +102,23 @@ Every drawing and editing command is its own tool (`draw_line`, `set_mood`, `add
102
102
 
103
103
  ## Working live in the browser
104
104
 
105
- Haku also has a web app with the actual drawing canvas. When it's open, leave out `-f` and the tools work on that tab instead of a file, so you see and hear every change, and Ctrl+Z still undoes it. The MCP server hosts a small bridge on `127.0.0.1:5179` for this, and the tab connects on its own. Without an MCP server, run `haku bridge` in another terminal.
106
-
107
- Right now the web app isn't hosted anywhere, so live mode means running it from the repo:
105
+ Haku also has a web app with the actual drawing canvas, and it ships in this package. Open it with:
108
106
 
109
107
  ```bash
110
- git clone https://github.com/pinkpixel-dev/haku.git
111
- cd haku
112
- pnpm install
113
- pnpm --filter @haku/web dev
108
+ haku web
114
109
  ```
115
110
 
116
- Then open http://localhost:5178. A few things to know:
111
+ That serves the app on http://127.0.0.1:5177, hosts the agent bridge, and opens your default browser. Leave out `-f` and the tools work on that tab instead of a file, so you see and hear every change, and Ctrl+Z still undoes it. The MCP server also hosts the bridge on `127.0.0.1:5179`, and the tab connects to whichever one is running on its own.
112
+
113
+ You don't have to open it first. When a tool needs the tab and none is connected, Haku starts `haku web` in the background (it quits after 30 minutes with no tab connected), opens the browser, and waits for the tab. Set `HAKU_NO_LAUNCH=1` if you'd rather get an error instead.
114
+
115
+ In Chrome or Edge you can install Haku as an app from the install icon in the address bar. It gets its own window, and since the app and samples are cached after the first visit, it opens fine even when `haku web` isn't running. Agents only reach it while a bridge is up, though, so start `haku web` or your MCP client first if you want that.
116
+
117
+ A few things to know:
117
118
 
118
119
  - Browsers won't let a page make sound until you've clicked in it once. If `play` says so, click anywhere in the tab and try again.
119
120
  - With more than one Haku tab open, tools drive the one you clicked into most recently.
121
+ - Your projects are saved in the browser for `127.0.0.1:5177`. Changing `HAKU_WEB_PORT` gives you a separate, empty project list, so use the folder button to export and import if you move.
120
122
  - The bridge only accepts tabs from `localhost` pages and only accepts tools from outside the browser. `HAKU_ALLOW_ORIGINS` (comma separated) adds other page origins, and `HAKU_BRIDGE_PORT` changes the port.
121
123
 
122
124
  ## Environment variables
@@ -125,19 +127,24 @@ Then open http://localhost:5178. A few things to know:
125
127
  |---|---|
126
128
  | `HAKU_PROJECT` | Default project file for commands that take `-f` |
127
129
  | `HAKU_BRIDGE_PORT` | Bridge port. Default `5179` |
130
+ | `HAKU_WEB_PORT` | Port `haku web` serves the app on. Default `5177` |
131
+ | `HAKU_NO_LAUNCH` | Set it to stop tools from opening Haku when no tab is connected |
128
132
  | `HAKU_ALLOW_ORIGINS` | Extra page origins allowed to connect as a Haku tab |
129
133
  | `HAKU_SAMPLES` | Use a different sample folder (one with a `manifest.json`) |
130
134
 
131
135
  ## Credits
132
136
 
133
- Haku's code is Apache 2.0 (see `dist/LICENSE`). The bundled samples are edited versions of the originals: trimmed, shortened, faded, level-adjusted, and re-encoded to Ogg Vorbis. The Wurlitzer also has its sfz mapping's tuning and level fixes baked in, and the rain recordings are cut into seamless loops.
137
+ Haku's code is Apache 2.0 (see `dist/LICENSE`). The bundled samples are edited versions of the originals: trimmed, shortened, faded, level-adjusted, and re-encoded to Ogg Vorbis. The Wurlitzer also has its sfz mapping's tuning and level fixes baked in, the kalimba and a few guitar notes are retuned to the nearest note, and the rain recordings are cut into seamless loops.
134
138
 
135
139
  | Sound | Source | Author | License |
136
140
  |---|---|---|---|
137
141
  | Upright piano | [VSCO 2 Community Edition](https://github.com/sgossner/VSCO-2-CE) | Simon Dalzell of Ivy Audio, distributed by Versilian Studios | CC0 1.0 |
138
142
  | Glockenspiel, marimba, harp | [VSCO 2 Community Edition](https://github.com/sgossner/VSCO-2-CE) | Versilian Studios | CC0 1.0 |
143
+ | Vibraphone, kalimba | [Versilian Community Sample Library](https://github.com/sgossner/VCSL) | Versilian Studios | CC0 1.0 |
144
+ | Nylon guitar | [Spanish classical guitar](https://freepats.zenvoid.org/Guitar/acoustic-guitar.html) from FreePats | roberto@zenvoid.org, for the FreePats project | CC0 1.0 |
139
145
  | Wurlitzer EP200 | [Greg Sullivan's E-Pianos](https://github.com/sfzinstruments/GregSullivan.E-Pianos) | [Greg Sullivan](http://www.sullivang.net/), sfz mapping by kinwie | [CC-BY 3.0](https://creativecommons.org/licenses/by/3.0/) |
140
146
  | Drums | [Big Rusty Drums](https://github.com/sfzinstruments/karoryfer.big-rusty-drums) | Karoryfer Samples | CC0 1.0 |
147
+ | Shaker, cabasa | [Versilian Community Sample Library](https://github.com/sgossner/VCSL) | Versilian Studios | CC0 1.0 |
141
148
  | Rain on the roof | [Soft rain on roof window](https://freesound.org/people/Metadex/sounds/235827/) | Metadex | CC0 1.0 |
142
149
  | Rain on the window | [January rain on a window](https://freesound.org/people/mmorgaine/sounds/333510/) | mmorgaine | CC0 1.0 |
143
150
 
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { a as BridgeClient, c as bridgePort, i as GUIDE, n as TOOLS, o as BridgeHost, r as Player, t as VERSION } from "./version-DoZ2etXG.mjs";
2
+ import { a as webRunning, c as Player, d as BridgeHost, f as SharedLink, i as webPort, l as GUIDE, n as openBrowser, o as webUrl, p as bridgePort, r as serveWeb, s as VERSION, t as TOOLS, u as BridgeClient } from "./tools-CO-tdB7d.mjs";
3
3
  import { readFile } from "node:fs/promises";
4
4
  import { resolve } from "node:path";
5
5
  import { Command, Option } from "commander";
@@ -8,10 +8,11 @@ import { z } from "zod";
8
8
  const kebab = (s) => s.replace(/_/g, "-");
9
9
  let client = null;
10
10
  const ctx = {
11
- link: () => client ??= BridgeClient.connect(),
11
+ link: async () => await client ?? await (client = BridgeClient.connect()),
12
12
  player: new Player(),
13
13
  waitForPlayback: true,
14
- cwd: process.env.INIT_CWD ?? process.cwd()
14
+ cwd: process.env.INIT_CWD ?? process.cwd(),
15
+ autoLaunch: !process.env.HAKU_NO_LAUNCH
15
16
  };
16
17
  function fail(message) {
17
18
  console.error(`haku: ${message}`);
@@ -110,6 +111,39 @@ program.command("exec").argument("[commands]", "JSON file of commands (an array,
110
111
  }
111
112
  await runTool(batch, parsed.data);
112
113
  });
114
+ /** How long an auto-launched `haku web` keeps running with no tab connected. */
115
+ const IDLE_MS = 18e5;
116
+ program.command("web").description("Open Haku in your browser. Serves the app on localhost and hosts the bridge, so agents can drive it too.").option("--no-open", "Just serve, don't open a browser").addOption(new Option("--exit-when-idle").hideHelp()).action(async (opts) => {
117
+ const port = webPort();
118
+ const url = webUrl(port);
119
+ let server;
120
+ try {
121
+ server = await serveWeb(port);
122
+ } catch (err) {
123
+ if (err.code !== "EADDRINUSE") fail(err instanceof Error ? err.message : String(err));
124
+ if (!await webRunning(port)) fail(`port ${port} is taken by something else. Set HAKU_WEB_PORT to use another one.`);
125
+ console.log(`Haku is already running at ${url}`);
126
+ if (opts.open) await openBrowser(url);
127
+ return;
128
+ }
129
+ const link = new SharedLink();
130
+ await link.ensure().catch(() => null);
131
+ console.log(`Haku is running at ${url}. Ctrl+C to stop.`);
132
+ if (opts.open && !await openBrowser(url)) console.log(`Couldn't open a browser. Open ${url} yourself.`);
133
+ const shutdown = () => {
134
+ server.close();
135
+ link.close().finally(() => process.exit(0));
136
+ };
137
+ process.once("SIGINT", shutdown);
138
+ process.once("SIGTERM", shutdown);
139
+ if (opts.exitWhenIdle) {
140
+ let lastTab = Date.now();
141
+ setInterval(async () => {
142
+ if ((await link.request({ op: "ping" }).catch(() => null))?.tab) lastTab = Date.now();
143
+ else if (Date.now() - lastTab > IDLE_MS) shutdown();
144
+ }, 6e4);
145
+ }
146
+ });
113
147
  program.command("bridge").description("Run the localhost bridge on its own, so the CLI can reach the open Haku tab.").action(async () => {
114
148
  const port = bridgePort();
115
149
  let host;
@@ -124,7 +158,7 @@ program.command("bridge").description("Run the localhost bridge on its own, so t
124
158
  process.once("SIGINT", () => void host.close().then(() => process.exit(0)));
125
159
  });
126
160
  program.command("mcp").description("Start the MCP server on stdio. It also hosts the bridge to the Haku tab.").action(async () => {
127
- const { startMcp } = await import("./mcp-DDuNECfs.mjs");
161
+ const { startMcp } = await import("./mcp-DsSn95Rn.mjs");
128
162
  await startMcp();
129
163
  });
130
164
  const argv = [...process.argv];
@@ -1,4 +1,4 @@
1
- import { i as GUIDE, n as TOOLS, r as Player, s as SharedLink, t as VERSION } from "./version-DoZ2etXG.mjs";
1
+ import { c as Player, f as SharedLink, l as GUIDE, s as VERSION, t as TOOLS } from "./tools-CO-tdB7d.mjs";
2
2
  import { McpServer } from "@modelcontextprotocol/server";
3
3
  import { serveStdio } from "@modelcontextprotocol/server/stdio";
4
4
  // src/mcp.ts
@@ -17,7 +17,8 @@ async function startMcp() {
17
17
  link: () => link.ensure().catch(() => null),
18
18
  player,
19
19
  waitForPlayback: false,
20
- cwd: process.cwd()
20
+ cwd: process.cwd(),
21
+ autoLaunch: !process.env.HAKU_NO_LAUNCH
21
22
  };
22
23
  const handle = serveStdio(() => {
23
24
  const server = new McpServer({
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -189,6 +189,149 @@
189
189
  }
190
190
  }
191
191
  ]
192
+ },
193
+ "vibes": {
194
+ "credit": {
195
+ "name": "Vibraphone, soft mallets (VCSL)",
196
+ "author": "Versilian Studios",
197
+ "license": "CC0-1.0",
198
+ "url": "https://github.com/sgossner/VCSL"
199
+ },
200
+ "release": 1.5,
201
+ "layers": [
202
+ {
203
+ "maxVelocity": 0.6,
204
+ "zones": {
205
+ "53": "vibes/v0_53.ogg",
206
+ "57": "vibes/v0_57.ogg",
207
+ "60": "vibes/v0_60.ogg",
208
+ "64": "vibes/v0_64.ogg",
209
+ "67": "vibes/v0_67.ogg",
210
+ "71": "vibes/v0_71.ogg",
211
+ "74": "vibes/v0_74.ogg",
212
+ "77": "vibes/v0_77.ogg",
213
+ "81": "vibes/v0_81.ogg",
214
+ "84": "vibes/v0_84.ogg",
215
+ "88": "vibes/v0_88.ogg"
216
+ }
217
+ },
218
+ {
219
+ "maxVelocity": 1,
220
+ "zones": {
221
+ "53": "vibes/v1_53.ogg",
222
+ "57": "vibes/v1_57.ogg",
223
+ "60": "vibes/v1_60.ogg",
224
+ "64": "vibes/v1_64.ogg",
225
+ "67": "vibes/v1_67.ogg",
226
+ "71": "vibes/v1_71.ogg",
227
+ "74": "vibes/v1_74.ogg",
228
+ "77": "vibes/v1_77.ogg",
229
+ "81": "vibes/v1_81.ogg",
230
+ "84": "vibes/v1_84.ogg",
231
+ "88": "vibes/v1_88.ogg"
232
+ }
233
+ }
234
+ ]
235
+ },
236
+ "guitar": {
237
+ "credit": {
238
+ "name": "Spanish classical guitar (FreePats)",
239
+ "author": "roberto@zenvoid.org, for the FreePats project",
240
+ "license": "CC0-1.0",
241
+ "url": "https://freepats.zenvoid.org/Guitar/acoustic-guitar.html"
242
+ },
243
+ "release": 0.8,
244
+ "layers": [
245
+ {
246
+ "maxVelocity": 1,
247
+ "zones": {
248
+ "31": "guitar/v0_31.ogg",
249
+ "32": "guitar/v0_32.ogg",
250
+ "33": "guitar/v0_33.ogg",
251
+ "34": "guitar/v0_34.ogg",
252
+ "35": "guitar/v0_35.ogg",
253
+ "36": "guitar/v0_36.ogg",
254
+ "37": "guitar/v0_37.ogg",
255
+ "38": "guitar/v0_38.ogg",
256
+ "39": "guitar/v0_39.ogg",
257
+ "40": "guitar/v0_40.ogg",
258
+ "41": "guitar/v0_41.ogg",
259
+ "43": "guitar/v0_43.ogg",
260
+ "45": "guitar/v0_45.ogg",
261
+ "47": "guitar/v0_47.ogg",
262
+ "48": "guitar/v0_48.ogg",
263
+ "50": "guitar/v0_50.ogg",
264
+ "52": "guitar/v0_52.ogg",
265
+ "53": "guitar/v0_53.ogg",
266
+ "54": "guitar/v0_54.ogg",
267
+ "55": "guitar/v0_55.ogg",
268
+ "56": "guitar/v0_56.ogg",
269
+ "57": "guitar/v0_57.ogg",
270
+ "58": "guitar/v0_58.ogg",
271
+ "59": "guitar/v0_59.ogg",
272
+ "60": "guitar/v0_60.ogg",
273
+ "61": "guitar/v0_61.ogg",
274
+ "62": "guitar/v0_62.ogg",
275
+ "63": "guitar/v0_63.ogg",
276
+ "64": "guitar/v0_64.ogg",
277
+ "65": "guitar/v0_65.ogg",
278
+ "66": "guitar/v0_66.ogg",
279
+ "67": "guitar/v0_67.ogg",
280
+ "69": "guitar/v0_69.ogg",
281
+ "70": "guitar/v0_70.ogg",
282
+ "71": "guitar/v0_71.ogg",
283
+ "72": "guitar/v0_72.ogg",
284
+ "73": "guitar/v0_73.ogg",
285
+ "74": "guitar/v0_74.ogg",
286
+ "75": "guitar/v0_75.ogg",
287
+ "76": "guitar/v0_76.ogg",
288
+ "77": "guitar/v0_77.ogg",
289
+ "78": "guitar/v0_78.ogg",
290
+ "79": "guitar/v0_79.ogg",
291
+ "80": "guitar/v0_80.ogg",
292
+ "81": "guitar/v0_81.ogg",
293
+ "82": "guitar/v0_82.ogg",
294
+ "83": "guitar/v0_83.ogg",
295
+ "84": "guitar/v0_84.ogg"
296
+ }
297
+ }
298
+ ]
299
+ },
300
+ "kalimba": {
301
+ "credit": {
302
+ "name": "Kalimba, Tanzania (VCSL)",
303
+ "author": "Versilian Studios",
304
+ "license": "CC0-1.0",
305
+ "url": "https://github.com/sgossner/VCSL"
306
+ },
307
+ "release": 1.2,
308
+ "layers": [
309
+ {
310
+ "maxVelocity": 1,
311
+ "zones": {
312
+ "44": "kalimba/v0_44.ogg",
313
+ "46": "kalimba/v0_46.ogg",
314
+ "49": "kalimba/v0_49.ogg",
315
+ "51": "kalimba/v0_51.ogg",
316
+ "53": "kalimba/v0_53.ogg",
317
+ "56": "kalimba/v0_56.ogg",
318
+ "59": "kalimba/v0_59.ogg",
319
+ "61": "kalimba/v0_61.ogg",
320
+ "64": "kalimba/v0_64.ogg",
321
+ "65": "kalimba/v0_65.ogg",
322
+ "67": "kalimba/v0_67.ogg",
323
+ "71": "kalimba/v0_71.ogg",
324
+ "73": "kalimba/v0_73.ogg",
325
+ "74": "kalimba/v0_74.ogg",
326
+ "75": "kalimba/v0_75.ogg",
327
+ "77": "kalimba/v0_77.ogg",
328
+ "78": "kalimba/v0_78.ogg",
329
+ "79": "kalimba/v0_79.ogg",
330
+ "82": "kalimba/v0_82.ogg",
331
+ "83": "kalimba/v0_83.ogg"
332
+ }
333
+ }
334
+ ]
192
335
  }
193
336
  },
194
337
  "drums": {
@@ -198,6 +341,12 @@
198
341
  "license": "CC0-1.0",
199
342
  "url": "https://github.com/sfzinstruments/karoryfer.big-rusty-drums"
200
343
  },
344
+ "percussionCredit": {
345
+ "name": "Shaker and cabasa (VCSL)",
346
+ "author": "Versilian Studios",
347
+ "license": "CC0-1.0",
348
+ "url": "https://github.com/sgossner/VCSL"
349
+ },
201
350
  "pieces": {
202
351
  "kick": [
203
352
  {
@@ -342,6 +491,38 @@
342
491
  "drums/tom_v1_r2.ogg"
343
492
  ]
344
493
  }
494
+ ],
495
+ "shaker": [
496
+ {
497
+ "maxVelocity": 0.6,
498
+ "files": [
499
+ "drums/shaker_v0_r1.ogg",
500
+ "drums/shaker_v0_r2.ogg"
501
+ ]
502
+ },
503
+ {
504
+ "maxVelocity": 1,
505
+ "files": [
506
+ "drums/shaker_v1_r1.ogg",
507
+ "drums/shaker_v1_r2.ogg"
508
+ ]
509
+ }
510
+ ],
511
+ "cabasa": [
512
+ {
513
+ "maxVelocity": 0.6,
514
+ "files": [
515
+ "drums/cabasa_v0_r1.ogg",
516
+ "drums/cabasa_v0_r2.ogg"
517
+ ]
518
+ },
519
+ {
520
+ "maxVelocity": 1,
521
+ "files": [
522
+ "drums/cabasa_v1_r1.ogg",
523
+ "drums/cabasa_v1_r2.ogg"
524
+ ]
525
+ }
345
526
  ]
346
527
  }
347
528
  },
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file