commit aa9356ab1d5b33eb288cc791e716d0bf131ad94f Author: Andrea Date: Sun Feb 16 16:12:13 2025 +0100 first commit diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..eb00925 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,135 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "ryu" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "trkconverter" +version = "0.1.0" +dependencies = [ + "regex", + "serde", + "serde_json", +] + +[[package]] +name = "unicode-ident" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..401a760 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "trkconverter" +version = "0.1.0" +edition = "2024" + +[dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +regex = "1.5" diff --git a/README.md b/README.md new file mode 100644 index 0000000..6d04a71 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# trkconverter + +tool to convert old trk format to new trk format for just dance + +# usage + +``` +trkconverter +``` diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..217149b --- /dev/null +++ b/src/main.rs @@ -0,0 +1,159 @@ +use std::env; +use std::fs; +use serde::{Deserialize, Serialize}; +use regex::Regex; + +#[derive(Serialize, Deserialize, Debug)] +struct BuuTrack { + #[serde(rename = "$format")] + format: i32, + Markers: Vec, + Signatures: Vec, + Sections: Vec, + Comments: Vec, + Ambiances: Vec, + AudioFilePath: String, + StartBeat: i32, + EndBeat: i32, + VideoStartTime: String, + Volume: f32, + PreviewEntry: f32, + PreviewLoopStart: f32, + PreviewLoopEnd: f32, + FadeInDuration: f32, + FadeOutDuration: f32, + FadeStartBeat: f32, + FadeEndBeat: f32, + UseFadeStartBeat: bool, + UseFadeEndBeat: bool, + FadeInType: i32, + FadeOutType: i32, +} + +#[derive(Serialize, Deserialize, Debug)] +struct Signature { + Comment: String, + Marker: f32, + Beat: i32, +} + +fn parse_drum_trk(content: &str) -> Result> { + // Extract markers + let re_markers = Regex::new(r"\{\s*VAL\s*=\s*(\d+)\s*\}")?; + let markers: Vec = re_markers + .captures_iter(content) + .map(|cap| cap[1].parse().unwrap()) + .collect(); + + // Extract signature data + let re_signature = Regex::new(r#"MusicSignature\s*=\s*\{\s*beats\s*=\s*(\d+),\s*marker\s*=\s*([0-9.]+),\s*comment\s*=\s*"(.*?)"\s*\}"#)?; + let mut signatures = Vec::new(); + + for cap in re_signature.captures_iter(content) { + let beat = cap[1].parse()?; + let marker = cap[2].parse()?; + let comment = cap[3].to_string(); + + signatures.push(Signature { + Comment: comment, + Marker: marker, + Beat: beat, + }); + } + + // Extract start and end beats + let re_beats = Regex::new(r"startBeat\s*=\s*(\d+),\s*endBeat\s*=\s*(\d+)")?; + let (start_beat, end_beat) = if let Some(cap) = re_beats.captures(content) { + (cap[1].parse()?, cap[2].parse()?) + } else { + (0, 0) + }; + + // Extract video start time + let re_video_time = Regex::new(r"videoStartTime\s*=\s*([0-9.]+)")?; + let video_time = if let Some(cap) = re_video_time.captures(content) { + cap[1].parse::()? + } else { + 0.0 + }; + + // Format video time as HH:MM:SS + let hours = (video_time / 3600.0) as i32; + let minutes = ((video_time % 3600.0) / 60.0) as i32; + let seconds = (video_time % 60.0) as i32; + let video_time_str = format!("{:02}:{:02}:{:02}", hours, minutes, seconds); + + // Extract volume + let re_volume = Regex::new(r"volume\s*=\s*([0-9.]+)")?; + let volume = if let Some(cap) = re_volume.captures(content) { + cap[1].parse()? + } else { + 0.0 + }; + + // Extract preview values + let re_preview = Regex::new(r"previewEntry\s*=\s*([0-9.]+),\s*previewLoopStart\s*=\s*([0-9.]+),\s*previewLoopEnd\s*=\s*([0-9.]+)")?; + let (preview_entry, preview_loop_start, preview_loop_end) = if let Some(cap) = re_preview.captures(content) { + (cap[1].parse()?, cap[2].parse()?, cap[3].parse()?) + } else { + (0.0, 0.0, 0.0) + }; + + // Construct the BuuTrack + let buu_track = BuuTrack { + format: 0, + Markers: markers, + Signatures: signatures, + Sections: Vec::new(), + Comments: Vec::new(), + Ambiances: Vec::new(), + AudioFilePath: "maps\\Drum\\audio\\Drum.wav".to_string(), // Default path + StartBeat: start_beat, + EndBeat: end_beat, + VideoStartTime: video_time_str, + Volume: volume, + PreviewEntry: preview_entry, + PreviewLoopStart: preview_loop_start, + PreviewLoopEnd: preview_loop_end, + FadeInDuration: 0.0, + FadeOutDuration: 0.0, + FadeStartBeat: 0.0, + FadeEndBeat: 0.0, + UseFadeStartBeat: false, + UseFadeEndBeat: false, + FadeInType: 0, + FadeOutType: 0, + }; + + Ok(buu_track) +} + +fn main() -> Result<(), Box> { + let args: Vec = env::args().collect(); + + if args.len() != 3 { + eprintln!("Usage: {} ", args[0]); + std::process::exit(1); + } + + let input_path = &args[1]; + let output_path = &args[2]; + + // Read the input file + let content = fs::read_to_string(input_path) + .map_err(|e| format!("Failed to read input file: {}", e))?; + + // Parse the Drum.trk content + let buu_track = parse_drum_trk(&content)?; + + // Serialize to JSON + let json = serde_json::to_string_pretty(&buu_track)?; + + // Write to output file + fs::write(output_path, json) + .map_err(|e| format!("Failed to write output file: {}", e))?; + + println!("Successfully converted {} to {}", input_path, output_path); + + Ok(()) +} \ No newline at end of file