The Music Workshop is Crusty Studio's portable music editor. It is a four-lane tracker that writes songs against the generic CrustyBasic sound API rather than one machine's sound chip, so the same song can be built for every target Crusty Studio supports.
That portability is the point of it, and it is also its limit. The portable player carries notes, lanes, waveform shapes, and volumes; it does not reach into chip registers. When you want SID registers, filter design, or chip-model-specific composition, use the SID Music Workshop instead — see Help → SID Music Guide.
.crustymusic.json project from the Explorer.music/ folder.A song is data plus a player. Saving the project stores the tune; Export player include writes the MUSIC_* routine your game includes and calls.
Set BPM, Speed, and Rows per beat before entering notes. Speed is the number of ticks per row, so it changes how much time each row has; rows per beat changes where the beat markers fall and therefore how the grid reads rhythmically.
Create one instrument per job rather than one per note: a bass, a lead, a chord or pulse part, and a noise hit is the usual starting set. Each instrument has:
Use the instrument's preview to audition the patch, switch the loop on, and tune it by ear before writing a part with it.
Type a note into a cell and set its instrument number. Blank clears the cell, and OFF stops a held note. The effect column takes a three-character code from the list below.
Add patterns, copy one as a starting point for the next, and put them in the song order. Short, reused patterns are easier to keep musical than one long block.
The Mix tab warns when the arrangement asks for more voices than the target has. A portable song can use four lanes, but targets with fewer channels need channel sharing or muting: a two-channel machine has to alternate or drop lanes. Plan which lanes the target can actually play before the arrangement grows.
Press play to hear the song through system audio. The preview is a plain Web Audio approximation, so treat it as a sketch, not as the target's sound: pulses are played as square waves, the noise lane previews as a sawtooth, ADSR is rendered as gain ramps, and the effect column is not heard at all. It is good enough to check the tune, the arrangement, and the instrument balance.
Save writes <name>.crustymusic.json into music/. Export player include writes a .cbi into src/ — by default named after the song with a -player suffix — using the same include-name and overwrite rules as the other workshops. The generated player contains:
MUSIC_ROWS, MUSIC_SPEED, MUSIC_LOOP, and MUSIC_EVENT_COUNT,MUSIC_INIT, MUSIC_STOP, MUSIC_APPLY, and MUSIC_TICK.Include the file from your game source, call MUSIC_INIT during setup, and call MUSIC_TICK once per frame. Notes are emitted as NOTE_<n><octave> names and shapes as SOUND_SHAPE_TRIANGLE, SOUND_SHAPE_PULSE, SOUND_SHAPE_SAW, or SOUND_SHAPE_NOISE, which the target's CrustyBasic runtime resolves for its own hardware.
What reaches the player matters. Only the note, the lane, the waveform shape, and the volume are exported per event. The instrument's ADSR, gate length, duty, arpeggio, vibrato, and tremolo shape the preview and record your intent, but they are not written into the player, and the effect column is not exported at all. If a sound depends on an envelope or an effect, either bake that into the arrangement or plan to reproduce it in code.
| Code | Meaning |
|---|---|
Axy |
Arpeggio between semitone offsets |
Vxy |
Vibrato depth and speed |
Uxx / Dxx |
Pitch slide up or down |
Txx |
Tempo change |
Wxy |
Pulse-width or waveform movement |
The effect column is an authoring aid and a written record of intent in this workshop. It shapes the preview only in the sense that the instrument settings it refers to also shape the preview; the exported player does not read it.
| Source | What happens |
|---|---|
.crustymusic.json |
The native project format. Tempo, speed, rows per beat, and the pattern shape are restored. |
MIDI (.mid, .midi) |
Notes are quantised to sixteenth notes and at most 64 patterns are built. Lossy: track identity is discarded, notes are sorted into lanes by pitch, every instrument is replaced by one of four fixed patches, notes are clamped to a playable range, and looping is switched off. Only the 64-pattern clip is reported. |
FamiTracker text (.txt) |
2A03 pulse, triangle, and noise material is converted into portable lanes. Duty, a short arpeggio, and a pitch macro survive; other effects are mapped or dropped, and DPCM and expansion-chip data are discarded. The workshop's status message lists what needed approximating. |
There is no ProTracker .mod import. A dropped .mod is stored in music/ and listed in the manifest, but it is not converted, and the editor cannot open it.
| Target | What the Music Workshop gives you |
|---|---|
| Every target | The same editor, the same four lanes, and the same portable player include. |
| NES | Four voices available (two pulse, triangle, noise), so a four-lane arrangement usually fits. |
| C64, C128, Plus/4 | Three SID voices, so four lanes need sharing or muting — the Mix tab warns about it. For register-level work use the SID Music Workshop instead. |
| Other targets | Whatever the target's runtime provides for the generic sound API. Studio does not know the channel count, so treat the Mix warning as advisory and check on the machine. |
The Target API tab's preview selector (Portable, NES, C64) changes the description card only. The generated code is identical for all three; it is the target's CrustyBasic runtime that maps the sound calls onto real hardware.
A song written here plays on any target that implements the API. Where a chip cannot do something the song asks for — a fourth voice on a three-voice machine, for example — the arrangement has to give something up.
OFF to end held notes rather than writing a quiet note; it makes the phrasing auditable.Expected. The preview applies instrument envelopes and ignores the effect column; the player carries only note, lane, shape, and volume. Re-check the part with the settings the player can actually reproduce, or move the movement into the arrangement.
The portable preview has no noise generator, so it approximates the noise lane with a sawtooth. The exported player sends the noise shape to the target, which renders it properly.
That is the documented behaviour of the MIDI import: it is a sketch importer. It keeps the notes and the rhythm, sorts them into lanes by pitch, and replaces every instrument. Expect to re-instrument the result.
The FamiTracker text import converts what maps cleanly onto the portable lanes and reports the rest. Read the status message: anything it could not map is listed, and some of it affects only one channel of the original.
The Mix tab warns when the arrangement needs more channels than are available. Disable a lane, share it between parts, or accept that a target with fewer channels cannot play every lane at once.