9 releases (4 breaking)
Uses new Rust 2024
| new 0.6.2 | Feb 3, 2026 |
|---|---|
| 0.4.1 | Jan 19, 2026 |
| 0.3.3 | Jan 10, 2026 |
| 0.2.2 | Dec 12, 2025 |
| 0.1.3 | Dec 10, 2025 |
#143 in Configuration
73 downloads per month
Used in minacalc-rs
2.5MB
6.5K
SLoC
Rhythm Open Exchange (ROX)
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"
Overview
ROX is designed to be:
- Compact — Uses rkyv zero-copy serialization with zstd compression
- Precise — Microsecond timestamp precision (i64) for accurate timing
- Universal — Supports all common VSRG features across different games
- Verifiable — BLAKE3 content hashing for integrity verification
Features
- Support for any key count (4K, 7K, 9K, etc.)
- Multiple note types: Tap, Hold (LN), Burst/Roll, Mine
- BPM changes and Scroll Velocity (SV) modifications
- Keysound support for BMS/O2Jam style charts
- Comprehensive metadata (title, artist, difficulty, tags, etc.)
- Content-based hashing for chart identification
- C# bindings for Unity/Godot/.NET integration
Installation
Rust
Add to your Cargo.toml:
[dependencies]
rhythm-open-exchange = "0.5"
C# / .NET
dotnet add package RhythmOpenExchange --version 0.5.0
From Source
git clone https://github.com/Glubus/Rhythm-Open-Exchange.git
cd Rhythm-Open-Exchange
cargo build --release
Quick Start
Creating a Chart
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
Auto-Converting Formats
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")?;
C# Usage
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);
Supported Formats
| ROX (native binary) | .rox | ✅ | ✅ |
| osu!mania | .osu | ✅ | ✅ |
| osu!taiko | .osu | ✅ | ❌ |
| StepMania / Etterna | .sm/.ssc | ✅ | ✅ |
| Quaver | .qua | ✅ | ✅ |
| Friday Night Funkin' | .json | ✅ | ✅ | (Experimental) |
Planned
- Malody (
.mc) - BMS (
.bms/.bme/.bml) - O2Jam (
.ojn/.ojm) - Clone Hero (
.chart/.mid)
Multi-Language Support
- C# / .NET - Full feature parity, located in
bindings/ffi/csharp. - Python - High-performance bindings in
bindings/ffi/python. - WebAssembly - Optimized for browser-based tools, located in
bindings/wasm. - C/C++ - Stable C-API via UniFFI in
bindings/ffi.
CLI Tool
# Convert a file
cargo run --bin rox -- convert input.osu output.sm
# Validate a file
cargo run --bin rox -- validate chart.sm
Performance
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 | ~0.82 ms | 30x Faster |
| Encode Speed | N/A | ~1.69 ms | Lightning Fast |
Development
Prerequisites
- Rust 1.85+ (2024 edition)
- Cargo
- (Optional) just - for running QA checks
Building
cargo build --release
Running QA Checks
# If you have 'just' installed
just qa
# Or manually
cargo check --all-targets --all-features
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-features
Project Structure
rhythm-open-exchange/
├── src/ # Core library (Rust)
├── bindings/
│ ├── api/ # Stable C-API / FFI (Native)
│ ├── csharp/ # C# Bindings
│ ├── python/ # Python Bindings
│ └── wasm/ # WebAssembly Bindings
├── tests/ # Integration tests
├── assets/ # Test assets
└── justfile # QA automation
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Run QA checks (
just qaor manual commands above) - Commit your changes (
git commit -m 'Add amazing feature') - Push and open a Pull Request
License
This project is licensed under the MIT License.
See Also
Dependencies
~11–15MB
~218K SLoC