@hraness/dawg 0.5.0 → 0.6.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 (88) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/DAWG.md +269 -13
  3. package/README.md +4 -4
  4. package/core/diff.ts +4 -0
  5. package/core/fx.ts +437 -2
  6. package/core/granular.ts +528 -0
  7. package/core/instruments.ts +281 -0
  8. package/core/keys.ts +386 -0
  9. package/core/resonators.ts +574 -0
  10. package/core/score.ts +181 -6
  11. package/core/sdk/eval-child.ts +2 -0
  12. package/core/sdk/print.ts +169 -13
  13. package/core/sdk/sync-instruments.ts +58 -0
  14. package/core/sdk/v1.ts +1114 -21
  15. package/core/sections.ts +34 -8
  16. package/core/strings.ts +845 -0
  17. package/guides/effects.md +3 -1
  18. package/guides/sounds.md +4 -0
  19. package/guides/tempo.md +1 -0
  20. package/package.json +1 -1
  21. package/src/agent/agent.ts +7 -0
  22. package/src/agent/granular-tools.ts +138 -0
  23. package/src/agent/models.ts +4 -4
  24. package/src/agent/ops.ts +39 -2
  25. package/src/agent/preview-tool.ts +6 -1
  26. package/src/agent/tools.ts +538 -14
  27. package/src/agent/xcb-agent.ts +7 -0
  28. package/src/audio/arrange.ts +21 -3
  29. package/src/audio/dsp/bank.ts +233 -0
  30. package/src/audio/dsp/fft.ts +6 -0
  31. package/src/audio/dsp/filters.ts +57 -0
  32. package/src/audio/dsp/interp.ts +112 -0
  33. package/src/audio/dsp/modal.ts +684 -0
  34. package/src/audio/dsp/onset.ts +197 -0
  35. package/src/audio/dsp/oversample.ts +202 -0
  36. package/src/audio/dsp/rng.ts +37 -0
  37. package/src/audio/dsp/shape.ts +81 -0
  38. package/src/audio/dsp/stft.ts +73 -0
  39. package/src/audio/dsp/window.ts +77 -0
  40. package/src/audio/effects/chain.ts +6 -1
  41. package/src/audio/effects/rig/cab.ts +99 -0
  42. package/src/audio/effects/rig/filters.ts +152 -0
  43. package/src/audio/effects/rig/gate.ts +39 -0
  44. package/src/audio/effects/rig/head.ts +487 -0
  45. package/src/audio/effects/rig/index.ts +170 -0
  46. package/src/audio/effects/rig/section.ts +78 -0
  47. package/src/audio/effects/rig/stomp.ts +238 -0
  48. package/src/audio/engine.ts +10 -1
  49. package/src/audio/fit.ts +402 -0
  50. package/src/audio/granular.ts +664 -0
  51. package/src/audio/instrument-check.ts +133 -0
  52. package/src/audio/instruments.ts +111 -0
  53. package/src/audio/keys/dsp.ts +323 -0
  54. package/src/audio/keys/engine.ts +361 -0
  55. package/src/audio/keys/piano.ts +432 -0
  56. package/src/audio/live-worker.ts +54 -0
  57. package/src/audio/live.ts +231 -12
  58. package/src/audio/loudness.ts +65 -20
  59. package/src/audio/preview.ts +2 -0
  60. package/src/audio/resonators.ts +287 -0
  61. package/src/audio/sampler.ts +163 -17
  62. package/src/audio/samples.ts +30 -7
  63. package/src/audio/strings/body.ts +250 -0
  64. package/src/audio/strings/engine.ts +369 -0
  65. package/src/audio/strings/loop.ts +119 -0
  66. package/src/audio/strings/measure.test-helpers.ts +198 -0
  67. package/src/audio/strings/pluck.ts +354 -0
  68. package/src/audio/warp.ts +61 -0
  69. package/src/audio/wav.ts +78 -6
  70. package/src/commands/expression.ts +9 -2
  71. package/src/commands/fit.ts +135 -0
  72. package/src/commands/fx.ts +31 -0
  73. package/src/commands/granular.ts +427 -0
  74. package/src/commands/help.ts +74 -3
  75. package/src/commands/keys.ts +353 -0
  76. package/src/commands/modal.ts +247 -0
  77. package/src/commands/rig.ts +260 -0
  78. package/src/commands/sample.ts +3 -0
  79. package/src/commands/string.ts +175 -0
  80. package/src/commands/time.ts +4 -1
  81. package/src/main.ts +210 -8
  82. package/src/project/check.ts +13 -0
  83. package/src/render.ts +33 -4
  84. package/src/tui/audition.ts +2 -2
  85. package/src/tui/granular-menu.ts +278 -0
  86. package/src/tui/menu.ts +332 -9
  87. package/src/tui/modal-menu.ts +118 -0
  88. package/src/tui/play-session.ts +45 -2
package/core/sections.ts CHANGED
@@ -13,8 +13,11 @@
13
13
  */
14
14
  import { DRUM_VOICES, isDrumInstrument } from "./drums.ts";
15
15
  import { FX_LANES } from "./fx.ts";
16
+ import { resolveString } from "./strings.ts";
17
+ import { modalSettings } from "./resonators.ts";
16
18
  import {
17
19
  SCORE_LIMITS,
20
+ withNoteCap,
18
21
  ScoreValidationError,
19
22
  TrackScore,
20
23
  isSamplerInstrument,
@@ -121,8 +124,12 @@ export function sliceSongTime(
121
124
  * Later repetitions get `~p2`, `~p3` ids. Without timed tracks, or without
122
125
  * sections, the score comes back unchanged.
123
126
  */
124
- export function bakeTrackTime(score: TrackScore): TrackScore {
125
- if (score.sections.length === 0 || !hasTrackTime(score)) return score;
127
+ export function bakeTrackTime(
128
+ score: TrackScore,
129
+ options: { always?: boolean } = {},
130
+ ): TrackScore {
131
+ if (!hasTrackTime(score)) return score;
132
+ if (score.sections.length === 0 && !options.always) return score;
126
133
  const seen = new Map<string, number>();
127
134
  const notes = performedNotes(score).map((note) => {
128
135
  const count = (seen.get(note.id) ?? 0) + 1;
@@ -134,13 +141,24 @@ export function bakeTrackTime(score: TrackScore): TrackScore {
134
141
  durationTicks: Math.max(1, Math.round(note.durationTicks)),
135
142
  };
136
143
  });
137
- return new TrackScore({
138
- ...score.toJSON(),
139
- tracks: score.tracks.map(({ time: _time, ...track }) => track),
140
- notes,
141
- });
144
+ return withNoteCap(
145
+ BAKED_NOTE_CAP,
146
+ () =>
147
+ new TrackScore({
148
+ ...score.toJSON(),
149
+ tracks: score.tracks.map(({ time: _time, ...track }) => track),
150
+ notes,
151
+ }),
152
+ );
142
153
  }
143
154
 
155
+ /**
156
+ * Most notes a baked or arranged score may hold while it renders: a cycled
157
+ * or phasing track repeats its notes across the song, past the stored
158
+ * score's limit.
159
+ */
160
+ export const BAKED_NOTE_CAP = SCORE_LIMITS.maxNotes * 64;
161
+
144
162
  /** Conventional section names, offered first by `nextSectionName`. */
145
163
  export const SECTION_KINDS = Object.freeze([
146
164
  "intro",
@@ -1302,12 +1320,20 @@ function laneFallback(track: Track, lane: string): number | undefined {
1302
1320
  }
1303
1321
  const spec = FX_LANES.find((candidate) => candidate.lane === lane);
1304
1322
  if (!spec) return undefined;
1323
+ if (spec.effect === "string") {
1324
+ const value = resolveString(track.string)[spec.param];
1325
+ return typeof value === "number" ? value : spec.spec.default;
1326
+ }
1305
1327
  const source = (
1306
1328
  spec.effect === "reverb"
1307
1329
  ? track.reverb
1308
1330
  : spec.effect === "synth"
1309
1331
  ? track.synth
1310
- : (track.fx as Record<string, unknown> | undefined)?.[spec.effect]
1332
+ : spec.effect === "keys"
1333
+ ? track.keys
1334
+ : spec.effect === "modal"
1335
+ ? track.modal && modalSettings(track.modal)
1336
+ : (track.fx as Record<string, unknown> | undefined)?.[spec.effect]
1311
1337
  ) as Record<string, unknown> | undefined;
1312
1338
  const stored = source?.[spec.param];
1313
1339
  return typeof stored === "number" ? stored : spec.spec.default;