use tunes::prelude::*;
use tunes::theory::core::ChordPattern;
fn main() -> anyhow::Result<()> {
let mut comp = Composition::new(Tempo::new(120.0));
let engine = AudioEngine::new()?;
println!("๐ฏ Complete Generator API Demo\n");
println!("๐ผ GENERATOR NAMESPACE (50+ methods total):");
println!(" CHORDS: chord, chord_inverted, chord_voice_lead, chord_over_bass, chords, chords_from");
println!(" SCALES: scale, scale_reverse, scale_updown, scale_downup");
println!(" ARPEGGIOS: arpeggiate, arpeggiate_reverse, arpeggiate_updown, arpeggiate_downup");
println!(" CLASSICAL: alberti_bass, waltz_bass, broken_chord, walking_bass, tremolo_strings, ostinato");
println!(" ORNAMENTS: trill, cascade, tremolo_note, strum, mordent, inverted_mordent, turn, inverted_turn");
println!(" TUPLETS: tuplet, triplet, quintuplet, sextuplet, septuplet");
println!(" MUSICAL: octaves, pedal, sequence_from");
println!(" PORTAMENTO: slide");
println!(" ALGORITHMIC: orbit, bounce, scatter, stream, random_notes, sprinkle");
println!(" TIME-BASED: wholes, halves, quarters, eighths, sixteenths\n");
comp.instrument("chords", &Instrument::electric_piano())
.generator(|g| g
.chord(C4, &ChordPattern::MAJOR, 0.5)
.chord(F4, &ChordPattern::MAJOR, 0.5)
.chord(G4, &ChordPattern::MAJOR, 0.5)
.chord(C4, &ChordPattern::MAJOR, 0.5)
);
comp.instrument("arpeggios", &Instrument::synth_lead())
.wait(2.0)
.generator(|g| g
.arpeggiate(&[C5, E5, G5, C6], 0.125)
);
comp.instrument("alberti", &Instrument::electric_piano())
.wait(3.0)
.generator(|g| g
.alberti_bass(&[C4, E4, G4], 0.125)
);
comp.instrument("ornaments", &Instrument::synth_lead())
.wait(4.0)
.generator(|g| g
.trill(C5, D5, 8, 0.0625)
);
comp.instrument("tuplets", &Instrument::synth_lead())
.wait(5.0)
.generator(|g| g
.triplet(&[C5, E5, G5], 0.5)
);
comp.instrument("scales", &Instrument::electric_piano())
.wait(6.0)
.generator(|g| g
.scale(&[C4, D4, E4, F4, G4, A4, B4, C5], 0.125)
);
comp.instrument("orbit", &Instrument::synth_lead())
.wait(7.0)
.generator(|g| g
.orbit(A4, 7.0, 16, 0.0625, 1.5, true) );
comp.instrument("bounce", &Instrument::pluck())
.wait(8.5)
.generator(|g| g
.bounce(523.25, 261.63, 0.6, 3, 6, 0.0833) );
comp.instrument("scatter", &Instrument::synth_lead())
.wait(10.0)
.generator(|g| g
.scatter(300.0, 900.0, 16, 0.0625) );
comp.instrument("stream", &Instrument::electric_piano())
.wait(11.0)
.generator(|g| g
.stream(440.0, 16, 0.0625) );
comp.instrument("random", &Instrument::synth_lead())
.wait(12.0)
.generator(|g| g
.random_notes(&[C5, E5, G5, C6], 16, 0.0625) );
comp.instrument("sprinkle", &Instrument::synth_lead())
.wait(13.0)
.generator(|g| g
.sprinkle(250.0, 850.0, 16, 0.0625) );
println!("๐ COMBINED - Generators + Transforms:");
println!(" Chain generators with transforms for complete control\n");
comp.instrument("combined", &Instrument::synth_lead())
.wait(14.0)
.generator(|g| g
.chord(C5, &ChordPattern::MAJOR, 0.25)
.chord(F5, &ChordPattern::MAJOR, 0.25)
)
.transform(|t| t
.shift(12)
.humanize(0.01, 0.05)
);
println!("๐ CHAINING - Multiple generator blocks:");
println!(" Create complex musical phrases in stages\n");
comp.instrument("chained", &Instrument::electric_piano())
.wait(15.0)
.generator(|g| g
.chord(C4, &ChordPattern::MAJOR, 0.5)
.chord(A4, &ChordPattern::MINOR, 0.5)
)
.generator(|g| g
.arpeggiate(&[E5, G5, B5], 0.125)
);
println!("โฎ๏ธ OLD SYNTAX STILL WORKS:");
println!(" Direct method calls for quick live coding\n");
comp.instrument("old_style", &Instrument::electric_piano())
.wait(16.0)
.chord(G4, &ChordPattern::MAJOR7, 0.5)
.arpeggiate(&[G4, B4, D5, F5], 0.125);
println!("\nโถ๏ธ Playing generator API demo...\n");
let mixer = comp.into_mixer();
engine.play_mixer(&mixer)?;
println!("โ
Demo complete!\n");
println!("๐ก Benefits of generator namespace:");
println!(" ๐ฆ Organized - 50+ note generators clearly grouped");
println!(" ๐ Discoverable - Type .generator() to see all note-producing methods");
println!(" ๐งน Clean autocomplete - Only see generator methods in this namespace");
println!(" ๐ Readable - Visual boundaries clarify intent");
println!(" ๐ Backward compatible - Old direct-call syntax still works!");
println!(" ๐ต Chainable - Combine with .transform() and .effects() for complete control");
println!("\n Use whichever style fits your workflow! ๐ต");
Ok(())
}