Configuration and Parameterization#
Configuration is central to the quartet work. The repository uses TOML because it is readable, easy to version, and structured enough to separate different kinds of choices. In the quartet packages, configuration controls three main areas. The first is output and metadata. The second is rendering. The third is musical generation.
The output section controls naming and filename construction. The render section controls SoundFonts and sample rate. The generation section controls measure count, note and rest durations, leap bounds, density, tempo, and seed. The materials section defines the pitch-class pool. The parts section defines instrumentation, ranges, MIDI channel assignments, clefs, and roles.
This design is important for two reasons. First, it makes generated scores reproducible. Second, it turns the quartet packages into research interfaces rather than fixed scripts. The config is the place where an experiment can be defined, rerun, and compared.
No. 2 extends this model rather than replacing it. The second quartet adds hand-specific piano parameters, separate piano occupancy, and more detailed chord controls. This is one of the best examples in the project of how technical design and musical design work together.
The first quartet config is compact enough to show the overall model:
title = "Algo Rhythms Quartet No. 1"
composer = "George K. Thiruvathukal"
[output]
basename = "algo-rhythms-quartet-no-1"
label = ""
include_measures = true
include_tempo = true
include_seed = true
include_timestamp = true
timestamp_format = "%Y-%m-%d@%H-%M"
[render]
# Dual-soundfont render setup:
# piano -> ~/.soundfonts/SalamanderGrandPiano-V3+20200602.sf2
# strings -> ~/.soundfonts/AegeanSymphonicOrchestra.sf2
piano_soundfont = "~/.soundfonts/SalamanderGrandPiano-V3+20200602.sf2"
strings_soundfont = "~/.soundfonts/AegeanSymphonicOrchestra.sf2"
sample_rate = 44100
[generation]
measures = 32
time_signature = [4, 4]
min_note_duration = "1/16"
max_note_duration = "1"
min_rest_duration = "1/16"
max_rest_duration = "1/4"
max_simultaneous_tones_per_quantum = 4
max_pitch_leap = 5
tempo_bpm = 50
seed = 42
[materials]
pitch_classes = [0, 1, 3, 6, 8, 10]
[[parts]]
id = "violin"
name = "Violin"
short_name = "Vln."
family = "strings"
clef = "treble"
role = "melodic"
midi_channel = 1
midi_program = 41
midi_instrument = "violin"
range = ["G3", "A7"]
[[parts]]
id = "viola"
name = "Viola"
short_name = "Vla."
family = "strings"
clef = "alto"
role = "melodic"
midi_channel = 2
midi_program = 42
midi_instrument = "viola"
range = ["C3", "E6"]
[[parts]]
id = "cello"
name = "Cello"
short_name = "Vc."
The second quartet config shows how the same structure can grow to support more detailed piano behavior:
title = "Algorithmic Piano Quartet No. 2"
composer = "George K. Thiruvathukal"
[output]
basename = "algorithmic-piano-quartet-no-2"
label = ""
include_measures = true
include_tempo = true
include_seed = true
include_timestamp = true
timestamp_format = "%Y-%m-%d@%H-%M"
[render]
# Dual-soundfont render setup:
# piano -> ~/.soundfonts/SalamanderGrandPiano-V3+20200602.sf2
# strings -> ~/.soundfonts/AegeanSymphonicOrchestra.sf2
piano_soundfont = "~/.soundfonts/SalamanderGrandPiano-V3+20200602.sf2"
strings_soundfont = "~/.soundfonts/AegeanSymphonicOrchestra.sf2"
sample_rate = 44100
[generation]
measures = 32
time_signature = [4, 4]
min_note_duration = "1/16"
max_note_duration = "1"
min_rest_duration = "1/16"
max_rest_duration = "1/4"
max_simultaneous_tones_per_quantum = 4
piano_max_simultaneous_events = 6
max_pitch_leap = 5
tempo_bpm = 50
seed = 42
piano_chord_probability = 0.45
piano_min_chord_tones = 2
piano_max_chord_tones = 4
piano_rh_min_chord_tones = 2
piano_rh_max_chord_tones = 3
piano_lh_min_chord_tones = 2
piano_lh_max_chord_tones = 3
piano_chord_span = 12