Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ jobs:
with:
workspaces: src-tauri -> target

- name: Verify Tauri default binary
run: cargo metadata --no-deps --format-version 1 | grep -q '"default_run":"scorebench"'

- name: Check formatting
run: cargo fmt --check

Expand All @@ -52,6 +55,46 @@ jobs:
- name: Run tests
run: cargo test

scorekit-contract:
name: ScoreKit 0.6 contract
runs-on: ubuntu-latest
steps:
- name: Check out scorebench
uses: actions/checkout@v5

- name: Check out pinned ScoreKit
uses: actions/checkout@v5
with:
repository: talkincode/scorekit
# v0.6.0 release commit; pin the immutable contract, not a moving branch.
ref: 5cea04fb75764480e18759674aae4cb8d917a518
path: .scorekit-contract

- name: Install native dependencies
run: |
sudo apt-get update
sudo apt-get install --no-install-recommends -y \
ffmpeg \
fluidsynth \
libwebkit2gtk-4.1-dev \
libgtk-3-dev \
libayatana-appindicator3-dev \
librsvg2-dev

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Build pinned ScoreKit
run: cargo build --locked --manifest-path .scorekit-contract/Cargo.toml

- name: Run non-skippable ScoreKit contract
env:
SCOREBENCH_SCOREKIT: ${{ github.workspace }}/.scorekit-contract/target/debug/scorekit
SCOREBENCH_REQUIRE_SCOREKIT_CONTRACT: "1"
run: >-
cargo test --manifest-path src-tauri/Cargo.toml
scorekit_06_contract_tools_query_live_capabilities -- --nocapture

frontend:
name: Frontend
runs-on: ubuntu-latest
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ vite.config.ts.timestamp-*
/examples/mood-demo/main.js
/examples/armor-material-lab/main.js
/examples/voyage-demo/main.js

# Per-machine workspace path overrides (see scorekit-workspace.json in the scorekit repo)
scorekit-workspace.local.json
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Install scorebench from [Releases](https://github.com/talkincode/scorebench/rele
- Linux: use the `.deb` or `.AppImage` artifact.
- Windows: use the `.msi` or `-setup.exe` artifact.

Install ScoreKit 0.3.x–0.4.x separately (for example with Homebrew `brew install talkincode/tap/scorekit`, or from [ScoreKit Releases](https://github.com/talkincode/scorekit/releases)), then confirm:
Install ScoreKit 0.5.x separately (for example with Homebrew `brew install talkincode/tap/scorekit`, or from [ScoreKit Releases](https://github.com/talkincode/scorekit/releases)), then confirm:

```bash
brew trust --tap talkincode/tap # when installing ScoreKit via Homebrew tap
Expand All @@ -98,6 +98,11 @@ npm install
npm run tauri dev # requires Rust toolchain + scorekit on PATH
```

Working across the whole constellation (scorekit, samples, forge, ScoreData)?
The committed multi-repo map is [`scorekit-workspace.json` in the scorekit
repo](https://github.com/talkincode/scorekit/blob/main/scorekit-workspace.json);
run `python3 scripts/workspace.py doctor` there to check/bootstrap the layout.

## Documentation

The English user guide covers the ScoreKit scene protocol, practical
Expand Down
2 changes: 1 addition & 1 deletion docs-site/src/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This chapter takes the shortest path through the complete loop: install the depe

## 1. Install scorebench and ScoreKit

scorebench needs the ScoreKit CLI at runtime. The desktop app does not bundle the CLI. This version is tested with ScoreKit 0.3.x–0.4.x.
scorebench needs the ScoreKit CLI at runtime. The desktop app does not bundle the CLI. This version is tested with ScoreKit 0.5.x.

### macOS (Homebrew, recommended)

Expand Down
6 changes: 4 additions & 2 deletions docs-site/src/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
| Arrangement | Assigning melody, harmony, bass, rhythm, color, and form to instruments. |
| Texture | How simultaneous voices are organized, from sparse solo writing to dense layers. |
| Register | Whether material sits in a low, middle, or high pitch range. |
| Section | A named suite cue that can change length, tempo, looping, overall intensity, and muted tracks. |
| Section | A named suite cue that can change length, tempo, looping, overall intensity, and tracks muted by stable `id`. |

## Performance and space

Expand All @@ -55,7 +55,9 @@
| Renderer | Software that converts MIDI plus a sound source into PCM audio, such as FluidSynth, TiMidity++, or sfizz. |
| SoundFont / SF2 | A file that packages samples and mappings for multiple, often GM-compatible, instruments. |
| SFZ | A text instrument format that maps external WAV or FLAC samples. |
| Renderer profile | YAML that maps ScoreKit instruments and articulations to local SFZ files. |
| Renderer profile | YAML that maps ScoreKit instruments and articulations to local SFZ files; a leaf bound into an orchestration's palettes. |
| Orchestration profile | YAML routing each scene track's logical `palette` (or the orchestration's `default_palette`) to a renderer profile; only meaningful for `--renderer sfizz`. |
| Palette | A named logical role (for example `default`, `solo`) an orchestration binds to one renderer profile; scene tracks select one via `palette`. |
| General MIDI / GM | Standard program and drum-channel conventions used to map scene instruments into compatible SoundFonts. |
| Sample | A digital recording used by a sampled instrument. |
| Sample rate | Audio samples per second, commonly 44,100 or 48,000 Hz. |
Expand Down
12 changes: 6 additions & 6 deletions docs-site/src/rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ MIDI
├── FluidSynth + SF2
├── TiMidity++ + SF2
└── sfizz_render + SFZ profile
└── sfizz_render + orchestration (palette → renderer profile) + SFZ
synth audio ──┐
Expand All @@ -30,24 +30,24 @@ ScoreKit launches the tools, checks their results, and writes artifacts atomical
| --- | --- | --- | --- |
| `fluidsynth` | One GM-compatible SF2 | Default sketches, fast iteration, easy setup | Every instrument comes from one SoundFont; `articulation` has no effect |
| `timidity` | One GM-compatible SF2 | An alternate SF2 path or cross-check | Mixing and controller response can differ; `articulation` has no effect |
| `sfizz` | SFZ files plus a renderer profile | Detailed sample libraries and multiple articulations | Requires a profile and a mapping for every scene instrument |
| `sfizz` | SFZ files plus an orchestration profile | Detailed sample libraries and multiple articulations | Requires an orchestration mapping every track's palette; single-instrument renders can use `--sfz` directly |

FluidSynth is the default. Switch to sfizz only when the musical structure is stable and you are ready to manage sample libraries, file paths, compatibility, and licensing.

## Render-panel controls

| Control | Meaning | Guidance |
| --- | --- | --- |
| Renderer | The MIDI-to-PCM synthesis backend | Start with FluidSynth; sfizz requires a profile |
| Renderer | The MIDI-to-PCM synthesis backend | Start with FluidSynth; sfizz requires an orchestration profile |
| Sample rate | 44,100 or 48,000 samples per second | 44.1 kHz is common for music; 48 kHz is common in video and some game pipelines |
| Format | `OGG` or `WAV` | OGG is compact; WAV is lossless and better for later production |
| Gain | Overall renderer amplitude, from 0 to 2 in the UI | Start at 0.8; reduce clipping here, but do not use gain to fix arrangement balance |
| Quality | Vorbis quality from 0 to 10 | Primarily affects OGG size and encoding quality; default 5 |
| Stems | Render every track as aligned audio | Enable for adaptive playback or downstream mixing |
| SFZ profile | Maps instruments and articulations to `.sfz` files | Used only by sfizz; missing mappings fail the build |
| Orchestration profile | Routes each track's logical `palette` to a leaf renderer profile mapping instruments and articulations to `.sfz` files | Used only by sfizz; a missing palette or unmapped instrument fails the build |
| Texture profile | Maps portable texture source names to local audio files | Renderer-independent; required only when the scene declares `textures` |

The renderer, SFZ profile, and texture profile are stored in the project's `bench.json`, allowing the Agent to check instrument and texture-source compatibility while writing a scene. The other controls are immediate Render-panel choices.
The renderer, orchestration profile, and texture profile are stored in the project's `bench.json`, allowing the Agent to check per-track palette and texture-source compatibility while writing a scene. The other controls are immediate Render-panel choices.

## Output files

Expand Down Expand Up @@ -79,5 +79,5 @@ A suite with `sections` emits separate audio assets per section. Every stem is s

1. Still changing melody, harmony, or form? Use FluidSynth.
2. Want to compare a second SF2 renderer? Try TiMidity++.
3. Need detailed samples or multiple articulations? Prepare and certify an SFZ profile, then use sfizz.
3. Need detailed samples or multiple articulations? Prepare and certify a renderer profile, bind it into an orchestration palette, then use sfizz.
4. Need commercial plugins, a DAW effect chain, or mastering? Export WAV or stems and continue in an external production workflow.
47 changes: 32 additions & 15 deletions docs-site/src/scene-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,21 @@ motifs:
- { degree: 0, beats: 4 }

tracks:
- instrument: flute
- id: lead
instrument: flute
pattern: melody
motif: forest_call
intensity: 0.45
- instrument: slow_strings
- id: harmony
instrument: slow_strings
pattern: sustain
intensity: 0.35
- instrument: harp
- id: motion
instrument: harp
pattern: arpeggio
intensity: 0.3
- instrument: bass
- id: foundation
instrument: bass
pattern: bass
intensity: 0.3
```
Expand All @@ -74,9 +78,9 @@ tracks:

ScoreKit currently builds diatonic triads from the scene scale. Roman-numeral case is conventional: `VI` and `vi` select the same scale degree in the current protocol. This field is not a complete classical-harmony notation system.

## Tracks and the five patterns
## Tracks and the six patterns

Every track selects an `instrument` and a `pattern`:
Every track selects an `instrument` and a `pattern`, and carries a stable scene-local `id`:

| Pattern | Generated material | Typical role |
| --- | --- | --- |
Expand All @@ -85,9 +89,12 @@ Every track selects an `instrument` and a `pattern`:
| `arpeggio` | Eighth notes in root–third–fifth–third order | Motion, piano or harp figures |
| `bass` | Low roots derived from the current chord | Low-frequency foundation |
| `drums` | A fixed kick, snare, and hi-hat groove | Basic pulse; must use `instrument: drums` |
| `tabla` | A deterministic tabla groove | World-percussion pulse; must use `instrument: tabla` and still obey the single-percussion-track rule |

Tracks can also define:

- `id`: a stable identifier matching `[a-z][a-z0-9_-]{0,63}`. Required; referenced by section `mute` lists, stems, and MIDI's `--solo` selector — never a positional index, so reordering tracks never breaks a reference.
- `palette`: an optional logical orchestration palette name. Absent uses the active orchestration's `default_palette`; irrelevant when not building with `--renderer sfizz --orchestration ...`. Routing metadata only — it never changes compiled MIDI.
- `intensity`: velocity scaling from 0.0 to 1.0.
- `articulation`: `sustain`, `staccato`, `spiccato`, `pizzicato`, `tremolo`, or `mute`. It selects SFZ samples only; SF2 backends ignore it.
- `pan`: 0.0 hard left, 0.5 center, 1.0 hard right, compiled to MIDI CC10.
Expand All @@ -108,7 +115,7 @@ A melody repeats or truncates its motif to fill the scene or section exactly. Sp

## Sound textures

ScoreKit 0.3 adds deterministic non-instrument layers:
ScoreKit provides deterministic non-instrument layers:

```yaml
textures:
Expand All @@ -127,12 +134,22 @@ textures:
```yaml
name: forest-recordings
root: recordings
schema_version: 1
sources:
river: river.flac
birds: birds.wav
river:
path: river.flac
description: Steady close river
category: organic
tags: [water, flowing]
playback:
modes: [loop]
default_mode: loop
use_cases: [forest]
provenance:
library: field-recordings@1.0.0
```

The Agent receives the active profile's source keys and the observation panel reports missing mappings before build. ScoreKit still performs the authoritative validation and mixing. Enabling stems produces aligned texture stems alongside instrument stems.
ScoreKit 0.6 also accepts the old path-only binding for build compatibility, but discovery and certification require the structured form. The Agent queries the active profile with exact `inspect_textures` filters before choosing a source; `no_match` means it must change the plan, not invent a key. The observation panel reports missing mappings and a `loop`/`one_shot` mode not declared by the source before build. ScoreKit still performs authoritative validation and mixing. Enabling stems produces aligned texture stems alongside instrument stems.

## Performance

Expand All @@ -158,17 +175,17 @@ performance:

```yaml
sections:
- { name: intro, bars: 4, loop: false, mute: [2, 3], intensity: 0.7 }
- { name: explore, bars: 8, loop: true, mute: [3], intensity: 0.9 }
- { name: intro, bars: 4, loop: false, mute: [motion, foundation], intensity: 0.7 }
- { name: explore, bars: 8, loop: true, mute: [foundation], intensity: 0.9 }
- { name: combat, bars: 8, loop: true, intensity: 1.25, tempo: 108 }
- { name: victory, bars: 4, loop: false, mute: [3], intensity: 1.1 }
- { name: victory, bars: 4, loop: false, mute: [foundation], intensity: 1.1 }
```

A section can change `bars`, `tempo`, `loop`, and overall `intensity`, or silence tracks through the **zero-based** `mute` indexes. Sections inherit the top-level key, harmony, motifs, tracks, and performance. The current protocol cannot replace harmony or motif contents per section.
A section can change `bars`, `tempo`, `loop`, and overall `intensity`, or silence tracks through the **stable track `id`s** listed in `mute`. Sections inherit the top-level key, harmony, motifs, tracks, and performance. The current protocol cannot replace harmony or motif contents per section.

## What does not belong in the scene protocol

- SoundFont, SFZ, renderer, and recording paths. They belong in build parameters, renderer profiles, or texture profiles; scene textures use portable source keys.
- SoundFont, SFZ, renderer, orchestration, and recording paths. They belong in build parameters, orchestration/renderer profiles, or texture profiles; scene textures use portable source keys.
- Arbitrary `mood`, `danger`, or `avoid` fields without compile semantics. Keep them in the conversation or `story`.
- Plugin chains, mastering, equalization, or post-processing instructions.
- Arbitrary MIDI events, automation curves, or free-form per-note editing outside the schema.
Expand Down
24 changes: 22 additions & 2 deletions docs-site/src/sound-sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ Before adopting a custom SF2, remember:
- `articulation` does not switch an SF2 to pizzicato, spiccato, or another sample set. Only SFZ profiles use that field.
- A license may permit music made with a library while forbidding redistribution of the original samples or instrument file.

ScoreKit 0.6's scene vocabulary includes world identities such as `erhu`, `pipa`, `guzheng`, `dizi`, `tabla`, `oud`, `ney`, and `duduk`. They validate as musical identities but do not have an exact General MIDI program, so an SF2 fallback is intentionally rejected. `shakuhachi`, `shamisen`, and `sitar` do have exact GM programs. Run `scorekit inspect-instruments scene.yaml --json` before promising any world identity; use an orchestration with an exact source when the default SF2 cannot provide one.

The current scorebench Render panel does not expose a custom-SoundFont picker, although the Agent/backend build interface supports a `soundfont` parameter. For a fixed project source, configure the ScoreKit sound directory or make the build workflow pass an explicit path rather than copying a large library into the repository.

## SFZ files and samples

SFZ is a text format that describes how samples are mapped into an instrument. A `.sfz` commonly references WAV or FLAC files beside it or elsewhere in the library. Copying the `.sfz` without its referenced samples cannot produce sound.

ScoreKit uses a renderer profile to map protocol instruments onto local SFZ files:
ScoreKit uses a renderer profile to map protocol instruments onto local SFZ files, and a multi-profile **orchestration** to route each scene track's logical `palette` to one of these renderer profiles:

```yaml
name: open-orchestra
Expand All @@ -59,7 +61,7 @@ instruments:

Every instrument needs a `sustain` mapping. When a dedicated articulation is absent, ScoreKit falls back to that instrument's `sustain`. This keeps machine-specific paths out of portable scene YAML, but teams still need an installation convention for the profile and its sample root.

Certify a profile before use:
Certify a renderer profile before use:

```bash
scorekit profile check profile.yaml
Expand All @@ -68,6 +70,24 @@ scorekit --json profile check profile.yaml

The check covers paths, render probes, silence, warnings, and repeat-render behavior. One successful patch does not prove that every patch in the same library is compatible with sfizz.

Bind one or more certified profiles into an orchestration, then validate the whole routing (palette bindings, leaf profiles, and every referenced SFZ file):

```yaml
schema_version: 1
name: hybrid-cinematic
default_palette: default
palettes:
default: { profile: ../renderers/scoredata-open.yaml }
solo: { profile: ../renderers/scoredata-chamber.yaml }
```

```bash
scorekit orchestration check hybrid-cinematic.yaml
scorekit build scene.yaml --renderer sfizz --orchestration hybrid-cinematic.yaml -o out/scene.ogg
```

A scene track without a `palette` uses `default_palette`; a track with `palette: solo` routes through the `scoredata-chamber` profile instead, without any DSL field naming a sound source.

## Open sources worth evaluating

ScoreKit's example profiles and research have used or evaluated sources such as:
Expand Down
Loading
Loading