| Crates.io | rhythm-open-exchange |
| lib.rs | rhythm-open-exchange |
| version | 0.4.1 |
| created_at | 2025-12-10 21:49:18.511808+00 |
| updated_at | 2026-01-19 16:20:49.122769+00 |
| description | A try to create the ffmpeg of vsrg |
| homepage | |
| repository | https://github.com/Glubus/rhythm-open-exchange |
| max_upload_size | |
| id | 1978842 |
| size | 2,421,924 |
A universal, compact binary format for Vertical Scrolling Rhythm Games (VSRG). ROX serves as a pivot format for converting between different rhythm game formats like osu!mania, Quaver, StepMania, Etterna, and BMS.
"so i'm just trying to make a ffmpeg of vsrg game idk where i'm going"
ROX is designed to be:
Add to your Cargo.toml:
[dependencies]
rhythm-open-exchange = "0.4"
dotnet add package RhythmOpenExchange
git clone https://github.com/Glubus/Rhythm-Open-Exchange.git
cd Rhythm-Open-Exchange
cargo build --release
use rhythm_open_exchange::{RoxChart, Note, TimingPoint, Metadata};
// Create a 4K chart
let mut chart = RoxChart::new(4);
// Set metadata
chart.metadata = Metadata {
title: "My Song".into(),
artist: "Artist Name".into(),
creator: "Your Name".into(),
difficulty_name: "Hard".into(),
audio_file: "audio.ogg".into(),
..Default::default()
};
// Add a BPM timing point at the start
chart.timing_points.push(TimingPoint::bpm(0, 180.0));
// Add notes (time in microseconds, column index)
chart.notes.push(Note::tap(1_000_000, 0)); // Tap at 1s, column 0
chart.notes.push(Note::tap(1_500_000, 1)); // Tap at 1.5s, column 1
chart.notes.push(Note::hold(2_000_000, 500_000, 2)); // Hold at 2s, 0.5s duration
use rhythm_open_exchange::{auto_decode, auto_encode, auto_convert};
// Load any supported format (auto-detected from extension)
let chart = auto_decode("chart.osu")?;
// Export to any format
auto_encode(&chart, "chart.sm")?;
// Or convert directly
auto_convert("input.osu", "output.qua")?;
using RhythmOpenExchange;
// Load a chart
byte[] data = File.ReadAllBytes("chart.osu");
using var chart = RoxChart.FromBytes(data);
Console.WriteLine($"{chart.Title} by {chart.Artist}");
Console.WriteLine($"{chart.KeyCount}K - {chart.NoteCount} notes");
// Convert to StepMania
string? sm = chart.ToString(RoxFormat.Sm);
File.WriteAllText("chart.sm", sm);
| Format | Extension | Read | Write |
|---|---|---|---|
| ROX (native binary) | .rox |
✅ | ✅ |
| osu!mania | .osu |
✅ | ✅ |
| osu!taiko | .osu |
✅ | ❌ |
| StepMania / Etterna | .sm |
✅ | ✅ |
| Quaver | .qua |
✅ | ✅ |
| Friday Night Funkin' | .json |
✅ | ✅ |
.mc).bms/.bme/.bml).ojn/.ojm).chart/.mid)# Convert a file
cargo run --bin rox -- convert input.osu output.sm
# Validate a file
cargo run --bin rox -- validate chart.sm
ROX is built for extreme efficiency. Benchmarks on a 50,000 note chart (4K):
| Metric | .osu Format | .rox Format | Improvement |
|---|---|---|---|
| File Size | 1.55 MB | 50 KB | 97% Smaller |
| Decode Speed | ~26 ms | ~2.7 ms | 10x Faster |
| Encode Speed | N/A | ~4.2 ms | Lightning Fast |
cargo build --release
# If you have 'just' installed
just qa
# Or manually
cargo check --all-targets
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test
rhythm-open-exchange/
├── src/
│ ├── lib.rs # Library entry point
│ ├── api.rs # FFI API for C#/native bindings
│ ├── error.rs # Error types
│ ├── codec/
│ │ ├── mod.rs # Codec module
│ │ ├── auto.rs # Auto-detection & conversion
│ │ ├── rox.rs # Native codec (rkyv + zstd)
│ │ └── formats/ # Format converters
│ │ ├── osu/ # osu!mania & osu!taiko
│ │ ├── sm/ # StepMania
│ │ ├── qua/ # Quaver
│ │ └── fnf/ # Friday Night Funkin'
│ └── model/ # Data structures
├── bindings/
│ └── csharp/ # C# NuGet package
├── tests/ # Test suite
├── examples/ # Usage examples
├── assets/ # Test assets
└── justfile # QA automation
Contributions are welcome! Please:
git checkout -b feature/amazing-feature)just qa or manual commands above)git commit -m 'Add amazing feature')This project is licensed under the MIT License.