Soundtrack expanded to 35 pieces with a leitmotif variant generator and 8 new instruments

- generator: leitmotif as scale degrees, keys/modes, augmentation, diminution, inversion,
  fragment sequences, accompaniment and drum styles; hand-written title 2, boss themes, victory 2
- organ, bell, choir, sub bass, tom, crash, harp, timpani; 8-bit samples, unused instruments stripped
- src/tracks.rs generated with categories; music director with boss themes and room moods
- all pieces validated with libopenmpt; notes checked to stay in key

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-03 08:09:15 +01:00
1 parent 1e92e19089
commit 5158075d7b
42 files changed
+721 -98

No files matched your search

+5 -18
View File
@@ -1126,23 +1126,11 @@ mod tests {
use super::*;
use std::rc::Rc;
const SONGS: [&[u8]; 8] = [
include_bytes!("../assets/music/title.xm"),
include_bytes!("../assets/music/build1.xm"),
include_bytes!("../assets/music/build2.xm"),
include_bytes!("../assets/music/build3.xm"),
include_bytes!("../assets/music/battle1.xm"),
include_bytes!("../assets/music/battle2.xm"),
include_bytes!("../assets/music/victory.xm"),
include_bytes!("../assets/music/defeat.xm"),
];
#[test]
fn render_all_songs() {
for (k, data) in SONGS.iter().enumerate() {
for (k, (name, _, data)) in crate::tracks::TRACKS.iter().enumerate() {
let m = Rc::new(load(data).expect("load"));
assert_eq!(m.channels, 8);
assert_eq!(m.instruments.len(), 8);
assert_eq!(m.channels, 8, "{}", name);
let mut p = Player::new(m, 48000.0);
let mut buf = vec![0.0f32; 48000 * 2];
let mut peak = 0.0f32;
@@ -1157,8 +1145,8 @@ mod tests {
}
}
let rms = (sum / (20.0 * 96000.0)).sqrt();
println!("song {}: peak {:.3} rms {:.4} loops {}", k, peak, rms, p.loops);
assert!(rms > 0.005, "song {} is silent", k);
println!("{:2} {:14}: peak {:.3} rms {:.4} loops {}", k, name, peak, rms, p.loops);
assert!(rms > 0.005, "song {} is silent", name);
}
}
}
@@ -1173,8 +1161,7 @@ mod render_dump {
#[test]
fn dump_renders() {
let Ok(dir) = std::env::var("DC_RENDER_DIR") else { return };
let names = ["title", "build1", "build2", "build3", "battle1", "battle2", "victory", "defeat"];
for n in names {
for (n, _, _) in crate::tracks::TRACKS.iter() {
let data = std::fs::read(format!("assets/music/{}.xm", n)).unwrap();
let mut p = Player::new(Rc::new(load(&data).unwrap()), 48000.0);
let mut buf = vec![0.0f32; 48000 * 2 * 30];