1.1.0 - TOML

This commit is contained in:
2025-06-23 23:54:23 -06:00
parent 8d86d1cbfb
commit 944a33eb95
10 changed files with 550 additions and 1720 deletions

37
Cargo.lock generated
View File

@ -684,7 +684,7 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "musicgen"
version = "1.0.0"
version = "1.1.0"
dependencies = [
"clap",
"cpal 0.16.0",
@ -693,7 +693,7 @@ dependencies = [
"rand",
"rodio",
"serde",
"serde_json",
"toml",
]
[[package]]
@ -1148,6 +1148,15 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_spanned"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
dependencies = [
"serde",
]
[[package]]
name = "shlex"
version = "1.3.0"
@ -1265,11 +1274,26 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "toml"
version = "0.8.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
@ -1278,10 +1302,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"toml_write",
"winnow",
]
[[package]]
name = "toml_write"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "unicode-ident"
version = "1.0.18"

View File

@ -1,6 +1,6 @@
[package]
name = "musicgen"
version = "1.0.0"
version = "1.1.0"
edition = "2024"
authors = ["Atridad Lahiji <me@atri.dad>"]
description = "Generate electronic music without AI"
@ -15,7 +15,7 @@ hound = "3.5"
rand = "0.8"
clap = { version = "4.5", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml = "0.8"
# Real-time audio
rodio = "0.20"

145
README.md
View File

@ -14,47 +14,45 @@ cd music
cargo build --release
```
## JSON Configuration
## TOML Configuration
Create declaritive songs with structured JSON:
Create declaritive songs with structured TOML:
```bash
cargo run --bin musicgen json examples/fantasy.json
cargo run --bin musicgen toml examples/enchanted.toml
```
### From Binary
```bash
./target/release/musicgen json examples/fantasy.json
./target/release/musicgen toml examples/enchanted.toml
```
### Basic JSON Structure
### Basic TOML Structure
```json
{
"composition": {
"key": 60,
"scale": "minor",
"tempo": 85.0,
"measures": 16
},
"tracks": [
{
"name": "bass",
"instrument": "sine",
"volume": 0.8,
"pattern": {
"type": "custom",
"steps": [
{ "time": 0.0, "note": "C2", "duration": 0.75, "velocity": 0.9 }
]
}
}
],
"export": {
"filename": "my_song",
"format": "wav"
}
}
```toml
[composition]
key = 60
scale = "minor"
tempo = 85.0
measures = 16
[[tracks]]
name = "bass"
instrument = "sine"
volume = 0.8
[tracks.pattern]
type = "custom"
[[tracks.pattern.steps]]
time = 0.0
note = "C2"
duration = 0.75
velocity = 0.9
[export]
filename = "my_song"
format = "wav"
```
### Definitions
@ -85,46 +83,55 @@ cargo run --bin musicgen json examples/fantasy.json
### Track Configuration
```json
{
"tracks": [
{
"name": "bass",
"instrument": "sine",
"volume": 0.8,
"pattern": {
"type": "custom",
"steps": [
{ "time": 0.0, "note": "C2", "duration": 0.75, "velocity": 0.9 },
{ "time": 2.0, "note": "G2", "duration": 0.75, "velocity": 0.8 }
],
"loop_length": 4.0
},
"effects": [
{
"type": "lowpass",
"cutoff": 400.0,
"resonance": 1.8
}
]
},
{
"name": "drums",
"instrument": "noise",
"volume": 0.6,
"pattern": {
"type": "custom",
"steps": [
{ "time": 0.0, "note": "C1", "duration": 0.1, "velocity": 1.0 },
{ "time": 1.0, "note": "E3", "duration": 0.05, "velocity": 0.7 }
]
}
}
]
}
```toml
[[tracks]]
name = "bass"
instrument = "sine"
volume = 0.8
[tracks.pattern]
type = "custom"
loop_length = 4.0
[[tracks.pattern.steps]]
time = 0.0
note = "C2"
duration = 0.75
velocity = 0.9
[[tracks.pattern.steps]]
time = 2.0
note = "G2"
duration = 0.75
velocity = 0.8
[[tracks.effects]]
type = "lowpass"
cutoff = 400.0
resonance = 1.8
[[tracks]]
name = "drums"
instrument = "noise"
volume = 0.6
[tracks.pattern]
type = "custom"
[[tracks.pattern.steps]]
time = 0.0
note = "C1"
duration = 0.1
velocity = 1.0
[[tracks.pattern.steps]]
time = 1.0
note = "E3"
duration = 0.05
velocity = 0.7
```
See `examples` for complete examples and the full schema.
See `composition-schema` for a complete example and the full schema.
## Output

385
composition-schema.toml Normal file
View File

@ -0,0 +1,385 @@
# MusicGen TOML Configuration Schema
# Complete reference for all available fields and options
# ============================================================================
# METADATA SECTION
# Optional information about your composition
# ============================================================================
[metadata]
title = "My Composition" # Title of the track
artist = "Artist Name" # Your name or band name
description = "An electronic song" # Description of the composition
tags = ["electronic", "ambient", "chill"] # Genre tags or keywords
# ============================================================================
# COMPOSITION SECTION
# Core musical settings that define the overall structure
# ============================================================================
[composition]
# Musical key - can be MIDI note number (60 = C4) or note name
key = "C4" # Options: MIDI numbers 0-127 OR note names like "C4", "F#3", "Bb5"
# Scale type - defines which notes are used
scale = "major" # Options: "major", "minor", "dorian", "phrygian", "lydian",
# "mixolydian", "aeolian", "locrian", "pentatonic",
# "blues", "chromatic"
# Tempo in beats per minute
tempo = 120.0 # Range: 40.0 - 300.0 BPM
# Time signature - how many beats per measure
[composition.time_signature]
numerator = 4 # Beats per measure (1-16)
denominator = 4 # Note value for one beat (2, 4, 8, or 16)
# Composition length and complexity
measures = 32 # Number of measures (1-1000)
complexity = 0.7 # Overall complexity (0.0-1.0, default: 0.6)
harmony_density = 0.8 # How much harmony/chords (0.0-1.0, default: 0.7)
rhythmic_density = 0.6 # How busy the rhythm is (0.0-1.0, default: 0.8)
seed = 12345 # Random seed for reproducible generation (optional)
# ============================================================================
# TRACKS SECTION
# Each track is like one instrument in your band
# ============================================================================
# Example 1: Custom melody track
[[tracks]]
name = "main_melody"
instrument = "piano" # Options: "sine", "square", "sawtooth", "triangle", "noise", "piano"
volume = 0.8 # Track volume (0.0-1.0)
[tracks.pattern]
type = "custom" # Pattern type: "custom", "chord", "arpeggio", "sequence"
loop_length = 16.0 # How long before pattern repeats (in beats)
# Individual notes in the pattern
[[tracks.pattern.steps]]
time = 0.0 # When to play (in beats from start of loop)
note = "C5" # MIDI number or note name
duration = 1.5 # How long to hold the note (in beats)
velocity = 0.7 # How loud to play this note (0.0-1.0)
[[tracks.pattern.steps]]
time = 2.0
note = "E5"
duration = 1.0
velocity = 0.6
[[tracks.pattern.steps]]
time = 4.0
note = "G5"
duration = 2.0
velocity = 0.8
# Effects for this track
[[tracks.effects]]
type = "reverb"
room_size = 0.7 # Size of the reverb space (0.0-1.0)
damping = 0.5 # How much high frequencies are absorbed (0.0-1.0)
mix = 0.3 # How much effect to blend in (0.0-1.0)
[[tracks.effects]]
type = "delay"
time = 0.25 # Delay time in seconds (0.01-2.0)
feedback = 0.3 # How much delay repeats (0.0-0.95)
mix = 0.2 # How much effect to blend in (0.0-1.0)
# Example 2: Chord progression track
[[tracks]]
name = "harmony"
instrument = "sawtooth"
volume = 0.6
[tracks.pattern]
type = "chord"
loop_length = 16.0
voicing = "spread" # Options: "close", "spread", "drop2", "drop3"
octave = 3 # Which octave to play chords in (0-8)
# Chord progression
[[tracks.pattern.chord_progression]]
time = 0.0
chord = "Cmaj7" # Chord name (e.g., "C", "Am", "F#dim", "Bbmaj7")
duration = 4.0
[[tracks.pattern.chord_progression]]
time = 4.0
chord = "Am7"
duration = 4.0
[[tracks.pattern.chord_progression]]
time = 8.0
chord = "Fmaj7"
duration = 4.0
[[tracks.pattern.chord_progression]]
time = 12.0
chord = "G7"
duration = 4.0
# Effects for chord track
[[tracks.effects]]
type = "lowpass"
cutoff = 2000.0 # Cutoff frequency in Hz (20-20000)
resonance = 1.2 # Filter resonance (0.1-10.0)
# Example 3: Bass track
[[tracks]]
name = "bass"
instrument = "sine"
volume = 0.9
[tracks.pattern]
type = "custom"
loop_length = 8.0
[[tracks.pattern.steps]]
time = 0.0
note = "C2"
duration = 1.0
velocity = 0.9
[[tracks.pattern.steps]]
time = 2.0
note = "G2"
duration = 1.0
velocity = 0.8
[[tracks.pattern.steps]]
time = 4.0
note = "A2"
duration = 1.0
velocity = 0.8
[[tracks.pattern.steps]]
time = 6.0
note = "F2"
duration = 1.0
velocity = 0.9
# Bass effects
[[tracks.effects]]
type = "highpass"
cutoff = 80.0 # Remove very low frequencies
resonance = 0.7
# Example 4: Percussion track
[[tracks]]
name = "drums"
instrument = "noise"
volume = 0.7
[tracks.pattern]
type = "custom"
loop_length = 4.0
# Kick drum
[[tracks.pattern.steps]]
time = 0.0
note = "C1" # Low note for kick
duration = 0.1
velocity = 1.0
[[tracks.pattern.steps]]
time = 2.0
note = "C1"
duration = 0.1
velocity = 1.0
# Snare/hi-hat
[[tracks.pattern.steps]]
time = 1.0
note = "D4" # Higher note for snare
duration = 0.05
velocity = 0.7
[[tracks.pattern.steps]]
time = 3.0
note = "D4"
duration = 0.05
velocity = 0.7
# Drum effects
[[tracks.effects]]
type = "distortion"
drive = 1.5 # Amount of distortion (1.0-10.0)
tone = 0.6 # Tone control (0.0-1.0)
[[tracks.effects]]
type = "chorus"
rate = 1.2 # Modulation rate in Hz (0.1-10.0)
depth = 0.4 # Modulation depth (0.0-1.0)
layers = 3 # Number of chorus layers (1-8)
mix = 0.3
# ============================================================================
# SECTIONS SECTION (Optional)
# For structured compositions with different parts
# ============================================================================
[[sections]]
name = "intro"
measures = 8
tempo = 100.0 # Optional tempo change for this section
complexity = 0.3 # Lower complexity for intro
repeat = 1 # How many times to repeat this section
[[sections]]
name = "verse"
measures = 16
complexity = 0.6
repeat = 2
[[sections]]
name = "chorus"
measures = 16
tempo = 125.0 # Faster tempo for chorus
complexity = 0.8
key = "F4" # Optional key change
scale = "major" # Optional scale change
repeat = 2
[[sections]]
name = "bridge"
measures = 8
complexity = 0.9
key = "Am" # Relative minor
repeat = 1
[[sections]]
name = "outro"
measures = 8
tempo = 90.0 # Slower outro
complexity = 0.2
repeat = 1
# ============================================================================
# EXPORT SECTION
# How to save your finished composition
# ============================================================================
[export]
filename = "my_song" # Output filename (without extension)
format = "wav" # Only "wav" currently supported
sample_rate = 44100 # Options: 22050, 44100, 48000, 96000
bit_depth = 24 # Options: 16, 24, 32
stereo = true # true for stereo, false for mono
max_duration = 180.0 # Maximum length in seconds (optional)
# Optional: Generate variations of your composition
[export.variations]
count = 3 # Number of variations to generate
vary_complexity = true # Vary the complexity between versions
vary_rhythm = true # Vary the rhythmic patterns
vary_harmony = false # Vary the chord progressions
vary_tempo = false # Vary the tempo
# ============================================================================
# EFFECT TYPES REFERENCE
# Complete list of all available effects and their parameters
# ============================================================================
# FILTERS
# [[tracks.effects]]
# type = "lowpass" # Removes high frequencies (makes sound warmer/duller)
# cutoff = 1000.0 # Frequency cutoff in Hz (20-20000)
# resonance = 1.0 # Emphasis at cutoff frequency (0.1-10.0)
# [[tracks.effects]]
# type = "highpass" # Removes low frequencies (makes sound thinner/brighter)
# cutoff = 100.0 # Frequency cutoff in Hz (20-20000)
# resonance = 1.0 # Emphasis at cutoff frequency (0.1-10.0)
# TIME-BASED EFFECTS
# [[tracks.effects]]
# type = "delay" # Echo effect
# time = 0.25 # Delay time in seconds (0.01-2.0)
# feedback = 0.3 # How much delay feeds back (0.0-0.95)
# mix = 0.3 # Wet/dry mix (0.0-1.0)
# [[tracks.effects]]
# type = "reverb" # Spatial reverb
# room_size = 0.5 # Size of reverb space (0.0-1.0)
# damping = 0.5 # High frequency absorption (0.0-1.0)
# mix = 0.3 # Wet/dry mix (0.0-1.0)
# [[tracks.effects]]
# type = "chorus" # Thickening/modulation effect
# rate = 1.0 # Modulation rate in Hz (0.1-10.0)
# depth = 0.5 # Modulation depth (0.0-1.0)
# layers = 3 # Number of voices (1-8)
# mix = 0.3 # Wet/dry mix (0.0-1.0)
# DISTORTION
# [[tracks.effects]]
# type = "distortion" # Hard clipping distortion
# drive = 2.0 # Amount of distortion (1.0-10.0)
# tone = 0.5 # Tone control (0.0-1.0, 0=dark, 1=bright)
# LO-FI EFFECTS
# [[tracks.effects]]
# type = "vinyl" # Vinyl crackle and surface noise
# intensity = 0.5 # Crackle intensity (0.0-1.0)
# frequency = 0.5 # Crackle frequency (0.0-1.0)
# mix = 0.3 # Wet/dry mix (0.0-1.0)
# [[tracks.effects]]
# type = "tape" # Tape saturation and warmth
# drive = 2.0 # Saturation amount (1.0-10.0)
# warmth = 0.7 # Warmth/color (0.0-1.0)
# mix = 0.5 # Wet/dry mix (0.0-1.0)
# [[tracks.effects]]
# type = "bitcrusher" # Digital degradation
# bit_depth = 8.0 # Bit depth reduction (1.0-16.0)
# sample_rate_reduction = 2.0 # Sample rate reduction factor (1.0-10.0)
# mix = 0.5 # Wet/dry mix (0.0-1.0)
# ============================================================================
# INSTRUMENT TYPES REFERENCE
# ============================================================================
# instrument = "sine" # Pure sine wave - smooth, warm, flute-like
# instrument = "square" # Square wave - classic video game sound, punchy
# instrument = "sawtooth" # Sawtooth wave - bright, buzzy, good for leads
# instrument = "triangle" # Triangle wave - mellow, soft, like filtered square
# instrument = "noise" # White noise - for percussion and texture
# instrument = "piano" # Natural piano with harmonics
# ============================================================================
# PATTERN TYPES REFERENCE
# ============================================================================
# type = "custom" # Specify exact notes and timing
# type = "chord" # Play chord progressions
# type = "arpeggio" # Arpeggiate chords (play notes one after another)
# type = "sequence" # Step sequencer patterns
# ============================================================================
# CHORD NAMES REFERENCE
# ============================================================================
# Basic triads: "C", "Dm", "E", "F#", "Bb"
# Seventh chords: "Cmaj7", "Dm7", "E7", "F#m7b5", "Bbmaj7"
# Extended chords: "C9", "Dm11", "E13"
# Altered chords: "C7#11", "Dm7b5", "E7alt"
# Diminished/Augmented: "Cdim", "Caug", "C°7", "C+7"
# ============================================================================
# NOTE NAMES REFERENCE
# ============================================================================
# Format: [Note][Accidental][Octave]
# Notes: C, D, E, F, G, A, B
# Accidentals: # (sharp), b (flat), ♯, ♭
# Octaves: 0-9 (C4 = middle C = MIDI 60)
# Examples: "C4", "F#3", "Bb5", "A0", "G9"
# MIDI equivalents:
# C4 = 60, C#4 = 61, D4 = 62, D#4 = 63, E4 = 64, F4 = 65
# F#4 = 66, G4 = 67, G#4 = 68, A4 = 69, A#4 = 70, B4 = 71
# Add/subtract 12 for different octaves

View File

@ -1,666 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://example.com/schemas/composition-config.json",
"title": "Generate electronic music without AI",
"description": "JSON schema for configuring musicgen",
"type": "object",
"properties": {
"metadata": {
"type": "object",
"description": "Metadata about the composition",
"properties": {
"title": {
"type": "string",
"description": "Composition title",
"default": ""
},
"artist": {
"type": "string",
"description": "Artist or composer name",
"default": ""
},
"description": {
"type": "string",
"description": "Description of the composition",
"default": ""
},
"tags": {
"type": "array",
"description": "Tags or genres",
"items": {
"type": "string"
},
"default": []
}
},
"additionalProperties": false
},
"composition": {
"type": "object",
"description": "Global composition settings",
"required": ["key", "scale", "tempo", "measures"],
"properties": {
"key": {
"description": "Musical key",
"oneOf": [
{
"type": "integer",
"minimum": 0,
"maximum": 127,
"description": "MIDI note number (60 = C4)"
},
{
"type": "string",
"pattern": "^[A-G][#b♯♭]?[0-9]$",
"description": "Note name (e.g., 'C4', 'F#3', 'Bb5')"
}
]
},
"scale": {
"type": "string",
"description": "Scale type",
"enum": [
"major",
"minor",
"dorian",
"phrygian",
"lydian",
"mixolydian",
"aeolian",
"locrian",
"pentatonic",
"blues",
"chromatic"
]
},
"tempo": {
"type": "number",
"description": "Tempo in beats per minute (BPM)",
"minimum": 40,
"maximum": 300
},
"time_signature": {
"type": "object",
"properties": {
"numerator": {
"type": "integer",
"minimum": 1,
"maximum": 16,
"description": "Number of beats per measure"
},
"denominator": {
"type": "integer",
"enum": [2, 4, 8, 16],
"description": "Note value that gets one beat"
}
},
"required": ["numerator", "denominator"],
"additionalProperties": false,
"default": {
"numerator": 4,
"denominator": 4
}
},
"measures": {
"type": "integer",
"description": "Number of measures in the composition",
"minimum": 1,
"maximum": 1000
},
"complexity": {
"type": "number",
"description": "Musical complexity level (0.0 = simple, 1.0 = complex)",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.6
},
"harmony_density": {
"type": "number",
"description": "Harmonic density (0.0 = sparse, 1.0 = dense)",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.7
},
"rhythmic_density": {
"type": "number",
"description": "Rhythmic density (0.0 = sparse, 1.0 = dense)",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.8
},
"seed": {
"type": "integer",
"description": "Random seed for reproducible generation",
"minimum": 0,
"maximum": 18446744073709551615
}
},
"additionalProperties": false
},
"tracks": {
"type": "array",
"description": "Individual track definitions",
"items": {
"type": "object",
"required": ["name", "instrument", "pattern"],
"properties": {
"name": {
"type": "string",
"description": "Track name (e.g., 'bass', 'kick', 'hihat', 'pad')"
},
"instrument": {
"type": "string",
"description": "Instrument/waveform type",
"enum": ["sine", "square", "sawtooth", "triangle", "noise", "piano"]
},
"volume": {
"type": "number",
"description": "Track volume level (0.0 = silent, 1.0 = full)",
"minimum": 0.0,
"maximum": 1.0,
"default": 1.0
},
"pattern": {
"type": "object",
"description": "Pattern definition for this track",
"required": ["type"],
"properties": {
"type": {
"type": "string",
"description": "Pattern type",
"enum": ["custom", "chord", "arpeggio", "sequence"]
},
"loop_length": {
"type": "number",
"description": "Pattern loop length in beats",
"minimum": 0.1,
"maximum": 64.0,
"default": 4.0
}
},
"allOf": [
{
"if": {
"properties": {
"type": {
"const": "custom"
}
}
},
"then": {
"properties": {
"steps": {
"type": "array",
"description": "Individual pattern steps",
"items": {
"type": "object",
"required": ["time", "note", "duration", "velocity"],
"properties": {
"time": {
"type": "number",
"description": "Time in beats when note starts",
"minimum": 0.0
},
"note": {
"description": "Note to play",
"oneOf": [
{
"type": "integer",
"minimum": 0,
"maximum": 127,
"description": "MIDI note number"
},
{
"type": "string",
"pattern": "^[A-G][#b♯♭]?[0-9]$",
"description": "Note name (e.g., 'C4', 'F#3')"
}
]
},
"duration": {
"type": "number",
"description": "Note duration in beats",
"minimum": 0.01,
"maximum": 16.0
},
"velocity": {
"type": "number",
"description": "Note velocity/volume (0.0 to 1.0)",
"minimum": 0.0,
"maximum": 1.0
}
},
"additionalProperties": false
}
}
},
"required": ["steps"]
}
},
{
"if": {
"properties": {
"type": {
"const": "chord"
}
}
},
"then": {
"properties": {
"chord_progression": {
"type": "array",
"description": "Chord progression steps",
"items": {
"type": "object",
"required": ["time", "chord", "duration"],
"properties": {
"time": {
"type": "number",
"description": "Time in beats when chord starts",
"minimum": 0.0
},
"chord": {
"type": "string",
"description": "Chord name (e.g., 'Cm7', 'F', 'G#maj7')"
},
"duration": {
"type": "number",
"description": "Chord duration in beats",
"minimum": 0.1,
"maximum": 16.0
}
},
"additionalProperties": false
}
},
"voicing": {
"type": "string",
"description": "Chord voicing style",
"enum": ["close", "spread", "drop2", "drop3"],
"default": "close"
},
"octave": {
"type": "integer",
"description": "Base octave for chord",
"minimum": 0,
"maximum": 8,
"default": 4
}
},
"required": ["chord_progression"]
}
}
],
"additionalProperties": false
},
"effects": {
"type": "array",
"description": "Audio effects to apply to this track",
"items": {
"type": "object",
"required": ["type"],
"properties": {
"type": {
"type": "string",
"description": "Effect type",
"enum": [
"lowpass",
"highpass",
"bandpass",
"delay",
"reverb",
"chorus",
"distortion",
"compressor"
]
}
},
"allOf": [
{
"if": {
"properties": {
"type": {
"const": "lowpass"
}
}
},
"then": {
"properties": {
"cutoff": {
"type": "number",
"description": "Cutoff frequency in Hz",
"minimum": 20,
"maximum": 20000,
"default": 1000
},
"resonance": {
"type": "number",
"description": "Resonance factor",
"minimum": 0.1,
"maximum": 10.0,
"default": 1.0
}
}
}
},
{
"if": {
"properties": {
"type": {
"const": "highpass"
}
}
},
"then": {
"properties": {
"cutoff": {
"type": "number",
"description": "Cutoff frequency in Hz",
"minimum": 20,
"maximum": 20000,
"default": 100
},
"resonance": {
"type": "number",
"description": "Resonance factor",
"minimum": 0.1,
"maximum": 10.0,
"default": 1.0
}
}
}
},
{
"if": {
"properties": {
"type": {
"const": "delay"
}
}
},
"then": {
"properties": {
"time": {
"type": "number",
"description": "Delay time in seconds",
"minimum": 0.001,
"maximum": 2.0,
"default": 0.25
},
"feedback": {
"type": "number",
"description": "Feedback amount",
"minimum": 0.0,
"maximum": 0.95,
"default": 0.3
},
"mix": {
"type": "number",
"description": "Wet/dry mix",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.3
}
}
}
},
{
"if": {
"properties": {
"type": {
"const": "reverb"
}
}
},
"then": {
"properties": {
"room_size": {
"type": "number",
"description": "Room size",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.5
},
"damping": {
"type": "number",
"description": "High frequency damping",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.5
},
"mix": {
"type": "number",
"description": "Wet/dry mix",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.3
}
}
}
},
{
"if": {
"properties": {
"type": {
"const": "chorus"
}
}
},
"then": {
"properties": {
"rate": {
"type": "number",
"description": "LFO rate in Hz",
"minimum": 0.1,
"maximum": 10.0,
"default": 1.0
},
"depth": {
"type": "number",
"description": "Modulation depth",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.5
},
"layers": {
"type": "integer",
"description": "Number of chorus layers",
"minimum": 1,
"maximum": 4,
"default": 2
},
"mix": {
"type": "number",
"description": "Wet/dry mix",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.5
}
}
}
},
{
"if": {
"properties": {
"type": {
"const": "distortion"
}
}
},
"then": {
"properties": {
"drive": {
"type": "number",
"description": "Distortion amount",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.5
},
"tone": {
"type": "number",
"description": "Tone control (0.0 = dark, 1.0 = bright)",
"minimum": 0.0,
"maximum": 1.0,
"default": 0.5
}
}
}
}
],
"additionalProperties": false
}
}
},
"additionalProperties": false
}
},
"sections": {
"type": "array",
"description": "Section definitions for structured compositions",
"items": {
"type": "object",
"required": ["name", "measures"],
"properties": {
"name": {
"type": "string",
"description": "Section name (e.g., 'intro', 'verse', 'chorus', 'bridge', 'outro')"
},
"measures": {
"type": "integer",
"description": "Number of measures in this section",
"minimum": 1,
"maximum": 1000
},
"tempo": {
"type": "number",
"description": "Tempo override for this section",
"minimum": 40,
"maximum": 300
},
"key": {
"description": "Key change for this section",
"oneOf": [
{
"type": "integer",
"minimum": 0,
"maximum": 127
},
{
"type": "string",
"pattern": "^[A-G][#b♯♭]?[0-9]$"
}
]
},
"scale": {
"type": "string",
"description": "Scale override for this section",
"enum": [
"major",
"minor",
"dorian",
"phrygian",
"lydian",
"mixolydian",
"aeolian",
"locrian",
"pentatonic",
"blues",
"chromatic"
]
},
"complexity": {
"type": "number",
"description": "Complexity override for this section",
"minimum": 0.0,
"maximum": 1.0
},
"repeat": {
"type": "integer",
"description": "Number of times to repeat this section",
"minimum": 1,
"maximum": 100,
"default": 1
}
},
"additionalProperties": false
}
},
"export": {
"type": "object",
"description": "Export settings",
"properties": {
"filename": {
"type": "string",
"description": "Output filename (without extension)",
"default": "output"
},
"format": {
"type": "string",
"description": "Export format",
"enum": ["wav", "mp3", "flac"],
"default": "wav"
},
"sample_rate": {
"type": "integer",
"description": "Sample rate in Hz",
"enum": [22050, 44100, 48000, 88200, 96000],
"default": 44100
},
"bit_depth": {
"type": "integer",
"description": "Bit depth",
"enum": [16, 24, 32],
"default": 16
},
"stereo": {
"type": "boolean",
"description": "Export in stereo (true) or mono (false)",
"default": false
},
"max_duration": {
"type": "number",
"description": "Maximum duration in seconds (null for full composition)",
"minimum": 1.0,
"maximum": 3600.0
},
"variations": {
"type": "object",
"description": "Variation generation settings",
"properties": {
"count": {
"type": "integer",
"description": "Number of variations to generate",
"minimum": 1,
"maximum": 100
},
"vary_complexity": {
"type": "boolean",
"description": "Vary complexity between variations",
"default": false
},
"vary_rhythm": {
"type": "boolean",
"description": "Vary rhythm between variations",
"default": false
},
"vary_harmony": {
"type": "boolean",
"description": "Vary harmony between variations",
"default": false
},
"vary_tempo": {
"type": "boolean",
"description": "Vary tempo between variations",
"default": false
}
},
"required": ["count"],
"additionalProperties": false
}
},
"additionalProperties": false
}
},
"required": ["composition"],
"additionalProperties": false
}

View File

@ -1,697 +0,0 @@
{
"metadata": {
"title": "Enchanted",
"artist": "Enchanted",
"description": "A waltx in 3/4 time."
},
"composition": {
"key": "Bb3",
"scale": "major",
"tempo": 132,
"time_signature": {
"numerator": 3,
"denominator": 4
},
"measures": 64,
"complexity": 0.8,
"harmony_density": 0.9,
"rhythmic_density": 0.6
},
"tracks": [
{
"name": "piano_melody",
"instrument": "piano",
"volume": 0.8,
"pattern": {
"type": "custom",
"loop_length": 96.0,
"steps": [
{
"time": 0.0,
"note": "D5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 1.5,
"note": "Eb5",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 2.5,
"note": "F5",
"duration": 0.5,
"velocity": 0.6
},
{
"time": 3.0,
"note": "G5",
"duration": 2.0,
"velocity": 0.7
},
{
"time": 5.0,
"note": "F5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 6.0,
"note": "Eb5",
"duration": 1.5,
"velocity": 0.5
},
{
"time": 7.5,
"note": "D5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 9.0,
"note": "C5",
"duration": 2.0,
"velocity": 0.6
},
{
"time": 11.0,
"note": "Bb4",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 12.0,
"note": "C5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 13.5,
"note": "D5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 14.5,
"note": "Eb5",
"duration": 0.5,
"velocity": 0.5
},
{
"time": 15.0,
"note": "F5",
"duration": 2.0,
"velocity": 0.7
},
{
"time": 17.0,
"note": "G5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 18.0,
"note": "A5",
"duration": 1.5,
"velocity": 0.7
},
{
"time": 19.5,
"note": "Bb5",
"duration": 1.5,
"velocity": 0.8
},
{
"time": 21.0,
"note": "A5",
"duration": 1.0,
"velocity": 0.7
},
{
"time": 22.0,
"note": "G5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 23.0,
"note": "F5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 24.0,
"note": "Eb5",
"duration": 2.0,
"velocity": 0.6
},
{
"time": 26.0,
"note": "D5",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 27.0,
"note": "C5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 28.5,
"note": "Bb4",
"duration": 1.5,
"velocity": 0.5
},
{
"time": 30.0,
"note": "C5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 31.0,
"note": "D5",
"duration": 2.0,
"velocity": 0.6
},
{
"time": 36.0,
"note": "G5",
"duration": 1.5,
"velocity": 0.7
},
{
"time": 37.5,
"note": "A5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 38.5,
"note": "Bb5",
"duration": 0.5,
"velocity": 0.7
},
{
"time": 39.0,
"note": "C6",
"duration": 2.0,
"velocity": 0.8
},
{
"time": 41.0,
"note": "Bb5",
"duration": 1.0,
"velocity": 0.7
},
{
"time": 42.0,
"note": "A5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 43.5,
"note": "G5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 45.0,
"note": "F5",
"duration": 2.0,
"velocity": 0.7
},
{
"time": 47.0,
"note": "Eb5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 48.0,
"note": "F5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 49.5,
"note": "G5",
"duration": 1.0,
"velocity": 0.7
},
{
"time": 50.5,
"note": "A5",
"duration": 0.5,
"velocity": 0.6
},
{
"time": 51.0,
"note": "Bb5",
"duration": 2.0,
"velocity": 0.8
},
{
"time": 53.0,
"note": "C6",
"duration": 1.0,
"velocity": 0.7
},
{
"time": 54.0,
"note": "D6",
"duration": 1.5,
"velocity": 0.8
},
{
"time": 55.5,
"note": "C6",
"duration": 1.5,
"velocity": 0.7
},
{
"time": 57.0,
"note": "Bb5",
"duration": 1.0,
"velocity": 0.7
},
{
"time": 58.0,
"note": "A5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 59.0,
"note": "G5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 60.0,
"note": "F5",
"duration": 2.0,
"velocity": 0.6
},
{
"time": 62.0,
"note": "Eb5",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 63.0,
"note": "D5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 64.5,
"note": "C5",
"duration": 1.5,
"velocity": 0.5
},
{
"time": 66.0,
"note": "Bb4",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 67.0,
"note": "C5",
"duration": 2.0,
"velocity": 0.6
},
{
"time": 72.0,
"note": "F5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 73.5,
"note": "G5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 74.5,
"note": "A5",
"duration": 0.5,
"velocity": 0.7
},
{
"time": 75.0,
"note": "Bb5",
"duration": 2.0,
"velocity": 0.7
},
{
"time": 77.0,
"note": "A5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 78.0,
"note": "G5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 79.5,
"note": "F5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 81.0,
"note": "Eb5",
"duration": 2.0,
"velocity": 0.6
},
{
"time": 83.0,
"note": "D5",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 84.0,
"note": "Eb5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 85.5,
"note": "F5",
"duration": 1.0,
"velocity": 0.6
},
{
"time": 86.5,
"note": "G5",
"duration": 0.5,
"velocity": 0.7
},
{
"time": 87.0,
"note": "A5",
"duration": 2.0,
"velocity": 0.7
},
{
"time": 89.0,
"note": "Bb5",
"duration": 1.0,
"velocity": 0.7
},
{
"time": 90.0,
"note": "G5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 91.5,
"note": "F5",
"duration": 1.5,
"velocity": 0.6
},
{
"time": 93.0,
"note": "Eb5",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 94.0,
"note": "D5",
"duration": 2.0,
"velocity": 0.6
}
]
},
"effects": [
{
"type": "reverb",
"room_size": 0.8,
"damping": 0.7,
"mix": 0.4
},
{
"type": "delay",
"time": 0.25,
"feedback": 0.15,
"mix": 0.2
}
]
},
{
"name": "string_harmony",
"instrument": "sawtooth",
"volume": 0.4,
"pattern": {
"type": "chord",
"loop_length": 48.0,
"chord_progression": [
{
"time": 0.0,
"chord": "Bb",
"duration": 6.0
},
{
"time": 6.0,
"chord": "F",
"duration": 6.0
},
{
"time": 12.0,
"chord": "Gm",
"duration": 6.0
},
{
"time": 18.0,
"chord": "Eb",
"duration": 6.0
},
{
"time": 24.0,
"chord": "Bb",
"duration": 6.0
},
{
"time": 30.0,
"chord": "F",
"duration": 6.0
},
{
"time": 36.0,
"chord": "Gm",
"duration": 6.0
},
{
"time": 42.0,
"chord": "Bb",
"duration": 6.0
}
],
"voicing": "spread",
"octave": 3
},
"effects": [
{
"type": "lowpass",
"cutoff": 4000,
"resonance": 0.6
},
{
"type": "reverb",
"room_size": 0.9,
"damping": 0.8,
"mix": 0.6
}
]
},
{
"name": "waltz_bass",
"instrument": "sine",
"volume": 0.6,
"pattern": {
"type": "custom",
"loop_length": 12.0,
"steps": [
{
"time": 0.0,
"note": "Bb2",
"duration": 1.0,
"velocity": 0.7
},
{
"time": 1.0,
"note": "F2",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 2.0,
"note": "F2",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 3.0,
"note": "F2",
"duration": 1.0,
"velocity": 0.7
},
{
"time": 4.0,
"note": "C3",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 5.0,
"note": "C3",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 6.0,
"note": "G2",
"duration": 1.0,
"velocity": 0.7
},
{
"time": 7.0,
"note": "D3",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 8.0,
"note": "D3",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 9.0,
"note": "Eb2",
"duration": 1.0,
"velocity": 0.7
},
{
"time": 10.0,
"note": "Bb2",
"duration": 1.0,
"velocity": 0.5
},
{
"time": 11.0,
"note": "Bb2",
"duration": 1.0,
"velocity": 0.5
}
]
},
"effects": [
{
"type": "lowpass",
"cutoff": 2000,
"resonance": 0.8
}
]
},
{
"name": "gentle_percussion",
"instrument": "triangle",
"volume": 0.25,
"pattern": {
"type": "custom",
"loop_length": 3.0,
"steps": [
{
"time": 0.0,
"note": "C4",
"duration": 0.1,
"velocity": 0.4
},
{
"time": 1.0,
"note": "C4",
"duration": 0.1,
"velocity": 0.3
},
{
"time": 2.0,
"note": "C4",
"duration": 0.1,
"velocity": 0.3
}
]
},
"effects": [
{
"type": "highpass",
"cutoff": 2000,
"resonance": 0.5
},
{
"type": "reverb",
"room_size": 0.6,
"damping": 0.9,
"mix": 0.5
}
]
},
{
"name": "atmospheric_pad",
"instrument": "sine",
"volume": 0.15,
"pattern": {
"type": "chord",
"loop_length": 24.0,
"chord_progression": [
{
"time": 0.0,
"chord": "Bbmaj7",
"duration": 12.0
},
{
"time": 12.0,
"chord": "Gm7",
"duration": 12.0
}
],
"voicing": "spread",
"octave": 2
},
"effects": [
{
"type": "lowpass",
"cutoff": 1500,
"resonance": 0.4
},
{
"type": "reverb",
"room_size": 1.0,
"damping": 0.9,
"mix": 0.8
}
]
}
],
"export": {
"filename": "enchanted",
"format": "wav",
"sample_rate": 44100,
"bit_depth": 24,
"stereo": true,
"max_duration": 88.0
}
}

View File

@ -1,231 +0,0 @@
{
"metadata": {
"title": "Fantasy",
"artist": "Atridad Lahiji",
"description": "A generic fantasy beat."
},
"composition": {
"key": 60,
"scale": "minor",
"tempo": 85.0,
"time_signature": {
"numerator": 4,
"denominator": 4
},
"measures": 18
},
"tracks": [
{
"name": "deep_bass",
"instrument": "sine",
"volume": 0.7,
"pattern": {
"type": "custom",
"steps": [
{ "time": 0.0, "note": "C2", "duration": 0.75, "velocity": 0.9 },
{ "time": 1.0, "note": "C2", "duration": 0.75, "velocity": 0.8 },
{ "time": 2.0, "note": "G1", "duration": 0.75, "velocity": 0.85 },
{ "time": 3.0, "note": "G1", "duration": 0.75, "velocity": 0.8 }
],
"loop_length": 4.0
},
"effects": [
{
"type": "lowpass",
"cutoff": 400.0,
"resonance": 1.8
}
]
},
{
"name": "sub_bass",
"instrument": "square",
"volume": 0.5,
"pattern": {
"type": "custom",
"steps": [
{ "time": 0.5, "note": "C3", "duration": 0.25, "velocity": 0.6 },
{ "time": 1.5, "note": "Eb3", "duration": 0.25, "velocity": 0.6 },
{ "time": 2.5, "note": "G3", "duration": 0.25, "velocity": 0.6 },
{ "time": 3.5, "note": "F3", "duration": 0.25, "velocity": 0.6 }
],
"loop_length": 4.0
},
"effects": [
{
"type": "lowpass",
"cutoff": 800.0,
"resonance": 2.0
}
]
},
{
"name": "lofi_kick",
"instrument": "sine",
"volume": 0.6,
"pattern": {
"type": "custom",
"steps": [
{ "time": 0.0, "note": "C1", "duration": 0.1, "velocity": 1.0 },
{ "time": 1.0, "note": "C1", "duration": 0.1, "velocity": 0.8 },
{ "time": 2.0, "note": "C1", "duration": 0.1, "velocity": 0.9 },
{ "time": 3.0, "note": "C1", "duration": 0.1, "velocity": 0.7 }
],
"loop_length": 4.0
},
"effects": [
{
"type": "lowpass",
"cutoff": 200.0,
"resonance": 1.0
},
{
"type": "distortion",
"drive": 0.3,
"tone": 0.2
}
]
},
{
"name": "lofi_snare",
"instrument": "noise",
"volume": 0.3,
"pattern": {
"type": "custom",
"steps": [
{ "time": 1.0, "note": "E3", "duration": 0.05, "velocity": 0.7 },
{ "time": 3.0, "note": "E3", "duration": 0.05, "velocity": 0.8 }
],
"loop_length": 4.0
},
"effects": [
{
"type": "highpass",
"cutoff": 200.0,
"resonance": 1.0
},
{
"type": "lowpass",
"cutoff": 600.0,
"resonance": 1.5
}
]
},
{
"name": "lofi_hihat",
"instrument": "noise",
"volume": 0.2,
"pattern": {
"type": "custom",
"steps": [
{ "time": 0.5, "note": "A4", "duration": 0.02, "velocity": 0.4 },
{ "time": 1.5, "note": "A4", "duration": 0.02, "velocity": 0.4 },
{ "time": 2.5, "note": "A4", "duration": 0.02, "velocity": 0.5 },
{ "time": 3.5, "note": "A4", "duration": 0.02, "velocity": 0.3 }
],
"loop_length": 4.0
},
"effects": [
{
"type": "highpass",
"cutoff": 1000.0,
"resonance": 1.0
},
{
"type": "lowpass",
"cutoff": 2000.0,
"resonance": 1.0
}
]
},
{
"name": "warm_pad",
"instrument": "sine",
"volume": 0.2,
"pattern": {
"type": "chord",
"chord_progression": [
{ "time": 0.0, "chord": "Cm7", "duration": 4.0 },
{ "time": 4.0, "chord": "Fm7", "duration": 4.0 },
{ "time": 8.0, "chord": "Gm7", "duration": 4.0 },
{ "time": 12.0, "chord": "Cm7", "duration": 4.0 }
],
"voicing": "spread",
"octave": 3
},
"effects": [
{
"type": "lowpass",
"cutoff": 600.0,
"resonance": 1.2
},
{
"type": "reverb",
"room_size": 0.8,
"damping": 0.8,
"mix": 0.4
}
]
},
{
"name": "peaceful_melody",
"instrument": "sine",
"volume": 0.9,
"pattern": {
"type": "custom",
"steps": [
{ "time": 16.0, "note": "Eb4", "duration": 1.0, "velocity": 0.6 },
{ "time": 17.5, "note": "G4", "duration": 1.0, "velocity": 0.5 },
{ "time": 19.0, "note": "C5", "duration": 1.5, "velocity": 0.7 },
{ "time": 21.0, "note": "Bb4", "duration": 0.75, "velocity": 0.5 },
{ "time": 22.0, "note": "Ab4", "duration": 1.0, "velocity": 0.6 },
{ "time": 23.5, "note": "F4", "duration": 0.75, "velocity": 0.5 },
{ "time": 24.0, "note": "G4", "duration": 2.0, "velocity": 0.6 },
{ "time": 26.5, "note": "Bb4", "duration": 0.75, "velocity": 0.5 },
{ "time": 27.5, "note": "D5", "duration": 1.0, "velocity": 0.7 },
{ "time": 29.0, "note": "C5", "duration": 1.5, "velocity": 0.6 },
{ "time": 31.0, "note": "G4", "duration": 1.0, "velocity": 0.5 },
{ "time": 32.5, "note": "Eb4", "duration": 1.5, "velocity": 0.6 },
{ "time": 34.5, "note": "C5", "duration": 1.0, "velocity": 0.7 },
{ "time": 36.0, "note": "G4", "duration": 2.0, "velocity": 0.5 },
{ "time": 38.5, "note": "Eb4", "duration": 1.0, "velocity": 0.4 },
{ "time": 40.0, "note": "C5", "duration": 1.5, "velocity": 0.6 },
{ "time": 42.0, "note": "Bb4", "duration": 0.75, "velocity": 0.5 },
{ "time": 43.0, "note": "Ab4", "duration": 1.0, "velocity": 0.6 },
{ "time": 44.5, "note": "F4", "duration": 1.25, "velocity": 0.5 },
{ "time": 46.0, "note": "G4", "duration": 1.0, "velocity": 0.6 },
{ "time": 47.5, "note": "Bb4", "duration": 0.75, "velocity": 0.5 },
{ "time": 48.5, "note": "D5", "duration": 1.0, "velocity": 0.7 },
{ "time": 50.0, "note": "C5", "duration": 1.5, "velocity": 0.6 },
{ "time": 52.0, "note": "G4", "duration": 1.0, "velocity": 0.5 },
{ "time": 53.5, "note": "Eb4", "duration": 1.5, "velocity": 0.6 },
{ "time": 55.5, "note": "C5", "duration": 1.0, "velocity": 0.7 },
{ "time": 57.0, "note": "G4", "duration": 2.0, "velocity": 0.5 },
{ "time": 60.0, "note": "Eb4", "duration": 1.0, "velocity": 0.4 },
{ "time": 62.0, "note": "C5", "duration": 2.0, "velocity": 0.6 },
{ "time": 65.0, "note": "G4", "duration": 2.0, "velocity": 0.5 },
{ "time": 68.0, "note": "Eb4", "duration": 4.0, "velocity": 0.4 }
],
"loop_length": 72.0
},
"effects": [
{
"type": "highpass",
"cutoff": 2000.0,
"resonance": 1.1
},
{
"type": "reverb",
"room_size": 0.9,
"damping": 0.7,
"mix": 0.5
}
]
}
],
"export": {
"filename": "fantasy",
"format": "wav",
"stereo": true
}
}

View File

@ -1,6 +1,6 @@
//! JSON configuration module for composition specifications
//! TOML configuration module for composition specifications
//!
//! This module provides structures and parsing for JSON-based composition definitions,
//! This module provides structures and parsing for TOML-based composition definitions,
//! allowing users to specify complete compositions in a declarative format.
use crate::core::{CompositionParams, CompositionStyle};
@ -235,7 +235,7 @@ pub struct PatternConfig {
/// Pattern-specific parameters
#[serde(flatten)]
pub params: serde_json::Value,
pub params: toml::Value,
}
/// Effect configuration
@ -255,7 +255,7 @@ pub struct EffectConfig {
/// Effect parameters
#[serde(flatten)]
pub params: serde_json::Value,
pub params: toml::Value,
}
/// Export settings
@ -409,29 +409,28 @@ fn parse_note_name(name: &str) -> Result<u8, String> {
}
impl CompositionConfig {
/// Load configuration from a JSON file
/// Load configuration from a TOML file
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, String> {
let content =
fs::read_to_string(path).map_err(|e| format!("Failed to read config file: {}", e))?;
Self::from_json(&content)
Self::from_toml(&content)
}
/// Parse configuration from JSON string
pub fn from_json(json: &str) -> Result<Self, String> {
serde_json::from_str(json).map_err(|e| format!("Failed to parse JSON: {}", e))
/// Parse configuration from TOML string
pub fn from_toml(toml_str: &str) -> Result<Self, String> {
toml::from_str(toml_str).map_err(|e| format!("Failed to parse TOML: {}", e))
}
/// Save configuration to a JSON file
/// Save configuration to a TOML file
pub fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), String> {
let json = self.to_json_pretty()?;
fs::write(path, json).map_err(|e| format!("Failed to write config file: {}", e))
let toml_str = self.to_toml_pretty()?;
fs::write(path, toml_str).map_err(|e| format!("Failed to write config file: {}", e))
}
/// Serialize configuration to pretty JSON
pub fn to_json_pretty(&self) -> Result<String, String> {
serde_json::to_string_pretty(self)
.map_err(|e| format!("Failed to serialize to JSON: {}", e))
/// Serialize configuration to pretty TOML
pub fn to_toml_pretty(&self) -> Result<String, String> {
toml::to_string_pretty(self).map_err(|e| format!("Failed to serialize to TOML: {}", e))
}
/// Convert to composition parameters (deprecated - use track-based generation instead)
@ -534,8 +533,8 @@ mod tests {
#[test]
fn test_config_serialization() {
let config = CompositionConfig::example();
let json = config.to_json_pretty().unwrap();
let parsed = CompositionConfig::from_json(&json).unwrap();
let toml_str = config.to_toml_pretty().unwrap();
let parsed = CompositionConfig::from_toml(&toml_str).unwrap();
assert_eq!(parsed.composition.tempo, config.composition.tempo);
}

View File

@ -19,16 +19,16 @@ struct Cli {
#[derive(Subcommand)]
enum Commands {
/// Generate composition from JSON configuration file
Json {
/// Path to JSON configuration file
/// Generate composition from TOML configuration file
Toml {
/// Path to TOML configuration file
config: PathBuf,
/// Override output filename
#[arg(short, long)]
output: Option<String>,
/// Print example JSON configuration
/// Print example TOML configuration
#[arg(long)]
example: bool,
},
@ -53,11 +53,11 @@ fn main() {
let cli = Cli::parse();
let result = match cli.command {
Commands::Json {
Commands::Toml {
config,
output,
example,
} => handle_json_command(config, output, example),
} => handle_toml_command(config, output, example),
Commands::Info {
scales,
@ -126,16 +126,16 @@ fn show_info(scales: bool, instruments: bool, all: bool) -> Result<(), Box<dyn s
Ok(())
}
fn handle_json_command(
fn handle_toml_command(
config_path: PathBuf,
output_override: Option<String>,
show_example: bool,
) -> Result<(), Box<dyn std::error::Error>> {
if show_example {
let example = CompositionConfig::example();
println!("{}", example.to_json_pretty()?);
println!("\n# Save this to a .json file and run:");
println!("# cargo run --bin musicgen json your_config.json");
println!("{}", example.to_toml_pretty()?);
println!("\n# Save this to a .toml file and run:");
println!("# cargo run --bin musicgen toml your_config.toml");
return Ok(());
}

View File

@ -87,12 +87,12 @@ impl TrackState {
let cutoff = effect_config
.params
.get("cutoff")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(1000.0) as f32;
let resonance = effect_config
.params
.get("resonance")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(1.0) as f32;
Box::new(LowPassFilter::new(cutoff, resonance))
}
@ -100,12 +100,12 @@ impl TrackState {
let cutoff = effect_config
.params
.get("cutoff")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(1000.0) as f32;
let resonance = effect_config
.params
.get("resonance")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(1.0) as f32;
Box::new(HighPassFilter::new(cutoff, resonance))
}
@ -113,17 +113,17 @@ impl TrackState {
let time = effect_config
.params
.get("time")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.3) as f32;
let feedback = effect_config
.params
.get("feedback")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.3) as f32;
let mix = effect_config
.params
.get("mix")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.3) as f32;
Box::new(Delay::new(time, feedback, mix))
}
@ -131,17 +131,17 @@ impl TrackState {
let room_size = effect_config
.params
.get("room_size")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.5) as f32;
let damping = effect_config
.params
.get("damping")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.5) as f32;
let mix = effect_config
.params
.get("mix")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.3) as f32;
Box::new(Reverb::new(room_size, damping, mix))
}
@ -149,12 +149,12 @@ impl TrackState {
let drive = effect_config
.params
.get("drive")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(2.0) as f32;
let tone = effect_config
.params
.get("tone")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.5) as f32;
Box::new(Distortion::new(drive, tone))
}
@ -162,22 +162,22 @@ impl TrackState {
let rate = effect_config
.params
.get("rate")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(1.0) as f32;
let depth = effect_config
.params
.get("depth")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.5) as f32;
let mix = effect_config
.params
.get("mix")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.3) as f32;
let layers = effect_config
.params
.get("layers")
.and_then(|v| v.as_u64())
.and_then(|v| v.as_integer())
.unwrap_or(3) as usize;
Box::new(Chorus::new(rate, depth, mix, layers))
}
@ -185,17 +185,17 @@ impl TrackState {
let intensity = effect_config
.params
.get("intensity")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.5) as f32;
let frequency = effect_config
.params
.get("frequency")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.5) as f32;
let mix = effect_config
.params
.get("mix")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.3) as f32;
Box::new(VinylCrackle::new(intensity, frequency, mix))
}
@ -203,17 +203,17 @@ impl TrackState {
let drive = effect_config
.params
.get("drive")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(2.0) as f32;
let warmth = effect_config
.params
.get("warmth")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.7) as f32;
let mix = effect_config
.params
.get("mix")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.5) as f32;
Box::new(TapeSaturation::new(drive, warmth, mix))
}
@ -221,17 +221,17 @@ impl TrackState {
let bit_depth = effect_config
.params
.get("bit_depth")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(8.0) as f32;
let sample_rate_reduction = effect_config
.params
.get("sample_rate_reduction")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(2.0) as f32;
let mix = effect_config
.params
.get("mix")
.and_then(|v| v.as_f64())
.and_then(|v| v.as_float())
.unwrap_or(0.5) as f32;
Box::new(BitCrusher::new(bit_depth, sample_rate_reduction, mix))
}