# rsnbs
[](https://github.com/omninbs/rsnbs/actions)
[](https://crates.io/crates/rsnbs)
[](https://crates.io/crates/rsnbs)
[](https://github.com/rust-lang/rustfmt)
> A simple rust library to read and write [.nbs files](https://opennbs.org/nbs)
> from [Open Note Block Studio](https://opennbs.org/).
`rsnbs` has all the functionality `pynbs` has, like iterating over Note Block Studio songs
```rust
use rsnbs::read_nbs;
let song = read_nbs("song.nbs");
for note in song.notes {
println!("tick: {}, instrument: {}", note.tick.unwrap(), note.instrument.unwrap())
}
```
or generating new songs programmatically
```rust
use rsnbs::{Song, Note};
let song = Song::default();
for i in 0..10 {
Song.notes.push(Note {
tick: Some(i), layer: None, instrument: None,
velocity: 30, panning: None, pitch: None, key: Some(i+35)
})
}
```
the main difference is that every field is an option (for version differences sake) where None acts as 0/"".
## Installation
The package can be installed with `cargo`
```bash
$ cargo install rsnbs
```
## Reading / Writing
You can use the read_nbs function to read an parse a specific NBS file of any version.
```rust
let song = rsnbs::read_nbs("song.nbs");
```
This returns a rsnbs::Song object wich can then be written using Song::save
```rust
song.save("song.nbs", version);
```
## Song struct
Song implements the Default trait so you can instance a default with 1 layer and all None fields
```rust
let song = Song::default();
```
### Fields
#### Header
the first field is `header`, the file header, of type struct `Header`
`header.version` | `i8` | The NBS version this file was saved on.
`header.default_instruments`| `i8` | The amount of instruments from vanilla Minecraft in the song.
`header.song_length` | `i16` | The length of the song, measured in ticks.
`header.song_layers` | `i16` | The ID of the last layer with at least one note block in it.
`header.song_name` | `String` | The name of the song.
`header.song_author` | `String` | The author of the song.
`header.original_author` | `String` | The original song author of the song.
`header.description` | `String` | The description of the song.
`header.tempo` | `i16` | The tempo of the song multiplied by 100.
`header.auto_save` | `bool` | Whether auto-saving has been enabled.
`header.auto_save_duration` | `i8` | The amount of minutes between each auto-save.
`header.time_signature` | `i8` | The time signature of the song.
`header.minutes_spent` | `i32` | The amount of minutes spent on the project.
`header.left_clicks` | `i32` | The amount of times the user has left-clicked.
`header.right_clicks` | `i32` | The amount of times the user has right-clicked.
`header.blocks_added` | `i32` | The amount of times the user has added a block.
`header.blocks_removed` | `i32` | The amount of times the user has removed a block.
`header.song_origin` | `String` | The file name of the original MIDI or schematic.
`header.loop` | `bool` | Whether the song should loop back to the start after ending.
`header.max_loop_count` | `i8` | The amount of times to loop. 0 = infinite.
`header.loop_start` | `i16` | The tick the song will loop back to at the end of playback.
#### Notes
the `notes` field has all the notes of type struct `Note` stored in a vec in order
`note.tick` | `i32` | The tick at which the note plays.
`note.layer` | `i32` | The ID of the layer in which the note is placed.
`note.instrument` | `i8` | The ID of the instrument.
`note.key` | `i8` | The key of the note. (between 0 and 87)
`note.velocity` | `i8` | The velocity of the note. (between 0 and 100)
`note.panning` | `u8` | The stereo panning of the note. (between -100 and 100)
`note.pitch` | `i16` | The detune of the note, in cents. (between -1200 and 1200)
#### Layers
the `layers` field is a vec of all layers of type struct `Layer` in order
`layer.name` | `String` | The name of the layer.
`layer.lock` | `bool`| Whether the layer is locked.
`layer.volume` | `i8` | The volume of the layer.
`layer.panning` | `u8` | The stereo panning of the layer.
#### Instruments
the `instruments` field stores all the custom instruments of the song in order in a vec
`instrument.name` | `String` | The name of the instrument.
`instrument.file` | `String` | The name of the sound file of the instrument.
`instrument.pitch` | `i8` | The pitch of the instrument. (between 0 and 87)
`instrument.press_key` | `bool` | Whether the piano should automatically press keys with the instrument when the marker passes them.