Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ales-tsurko/midi-player


https://github.com/ales-tsurko/midi-player

audio midi midi-player soundfont

Last synced: 22 days ago
JSON representation

Awesome Lists containing this project

README

        

midi-player
===========

A MIDI file player library with integrated synthesizer ([`rustysynth`](https://crates.io/crates/rustysynth)).

It's independent from audio library, that means you should provide your own
audio loop and run the render function within it.

The player has play/stop, position, volume and tempo parameters, and position
observer, which allows you to track the play position in the real-time.

## Example usage (with `cpal`)

```rust
use std::{thread, time::Duration};

use cpal::{
traits::{DeviceTrait, HostTrait, StreamTrait},
StreamConfig,
};
use midi_player::player::{Player, Settings};

fn main() {
let settings = Settings::builder().build();
let (player, mut controller) =
Player::new("examples/Nice-Steinway-Lite-v3.0.sf2", settings).unwrap();

thread::spawn(|| {
start_audio_loop(player);
});

thread::sleep(Duration::from_secs(2));

controller
.set_file(Some("examples/Sibelius_The_Spruce.mid"))
.unwrap();

controller.play();

loop {}
}

fn start_audio_loop(mut player: Player) {
let host = cpal::default_host();
let device = host
.default_output_device()
.expect("No output device available");
let channels = 2 as usize;
let config = StreamConfig {
channels: channels as u16,
sample_rate: cpal::SampleRate(player.settings().sample_rate),
buffer_size: cpal::BufferSize::Fixed(player.settings().audio_buffer_size),
};

let err_fn = |err| eprintln!("An error occurred on the output audio stream: {}", err);

let mut left = vec![0f32; player.settings().audio_buffer_size as usize];
let mut right = vec![0f32; player.settings().audio_buffer_size as usize];

let stream = device
.build_output_stream(
&config.into(),
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
let sample_count = data.len() / channels;

player.render(&mut left, &mut right);

if !left.is_empty() {
for i in 0..sample_count {
data[channels * i] = left[i];
data[channels * i + 1] = right[i];
}
}
},
err_fn,
None,
)
.unwrap();

stream.play().expect("cannot run audio stream");

std::thread::park();
}
```