mirror of
https://github.com/RustAudio/rodio
synced 2024-11-10 06:04:16 +00:00
Initial commit
This commit is contained in:
commit
824b4f0041
8 changed files with 149 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
target
|
||||
Cargo.lock
|
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "rodio"
|
||||
version = "0.1.0"
|
||||
authors = ["Pierre Krieger <pierre.krieger1708@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
cpal = "0.1.1"
|
||||
hound = "1.0.0"
|
||||
lazy_static = "0.1.12"
|
9
examples/basic.rs
Normal file
9
examples/basic.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
extern crate rodio;
|
||||
|
||||
fn main() {
|
||||
let file = std::fs::File::open("examples/beep.wav").unwrap();
|
||||
|
||||
rodio::play_once(file);
|
||||
|
||||
std::thread::sleep_ms(10000);
|
||||
}
|
BIN
examples/beep.wav
Normal file
BIN
examples/beep.wav
Normal file
Binary file not shown.
16
src/decoder/mod.rs
Normal file
16
src/decoder/mod.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
use std::io::Read;
|
||||
use cpal::Voice;
|
||||
|
||||
mod wav;
|
||||
|
||||
pub trait Decoder {
|
||||
fn write(&mut self, &mut Voice);
|
||||
}
|
||||
|
||||
pub fn decode<R>(data: R) -> Box<Decoder + Send> where R: Read + Send + 'static {
|
||||
if let Ok(decoder) = wav::WavDecoder::new(data) {
|
||||
return Box::new(decoder);
|
||||
}
|
||||
|
||||
panic!("Invalid format");
|
||||
}
|
49
src/decoder/wav.rs
Normal file
49
src/decoder/wav.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use std::io::Read;
|
||||
use super::Decoder;
|
||||
|
||||
use cpal::{self, Voice};
|
||||
use hound::WavReader;
|
||||
use hound::WavSpec;
|
||||
|
||||
pub struct WavDecoder<R> where R: Read {
|
||||
reader: WavReader<R>,
|
||||
spec: WavSpec,
|
||||
}
|
||||
|
||||
impl<R> WavDecoder<R> where R: Read {
|
||||
pub fn new(data: R) -> Result<WavDecoder<R>, ()> {
|
||||
let reader = match WavReader::new(data) {
|
||||
Err(_) => return Err(()),
|
||||
Ok(r) => r
|
||||
};
|
||||
|
||||
let spec = reader.spec();
|
||||
|
||||
Ok(WavDecoder {
|
||||
reader: reader,
|
||||
spec: spec,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> Decoder for WavDecoder<R> where R: Read {
|
||||
fn write(&mut self, voice: &mut Voice) {
|
||||
let mut samples = self.reader.samples::<i16>();
|
||||
let samples_left = samples.len();
|
||||
if samples_left == 0 { return; }
|
||||
|
||||
// TODO: hack because of a bug in cpal
|
||||
let samples_left = if samples_left > 512 { 512 } else { samples_left };
|
||||
|
||||
let mut buffer: cpal::Buffer<u16> =
|
||||
voice.append_data(self.spec.channels,
|
||||
cpal::SamplesRate(self.spec.sample_rate),
|
||||
samples_left);
|
||||
|
||||
for (dest, src) in buffer.iter_mut().zip(&mut samples) {
|
||||
// TODO: There is a bug in cpal that handles signed samples in the
|
||||
// wrong manner, so we cast it to `u16` for now.
|
||||
*dest = src.unwrap() as u16;
|
||||
}
|
||||
}
|
||||
}
|
45
src/engine.rs
Normal file
45
src/engine.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use std::thread;
|
||||
use std::sync::mpsc::{self, Sender, Receiver};
|
||||
use std::sync::Mutex;
|
||||
|
||||
use cpal::Voice;
|
||||
use decoder::Decoder;
|
||||
|
||||
pub enum Command {
|
||||
Play(Box<Decoder + Send>)
|
||||
}
|
||||
|
||||
pub struct Engine {
|
||||
commands: Mutex<Sender<Command>>,
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
pub fn new() -> Engine {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
thread::spawn(move || background(rx));
|
||||
Engine { commands: Mutex::new(tx) }
|
||||
}
|
||||
|
||||
pub fn play_once(&self, decoder: Box<Decoder + Send>) {
|
||||
let commands = self.commands.lock().unwrap();
|
||||
commands.send(Command::Play(decoder)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn background(rx: Receiver<Command>) {
|
||||
let mut sounds = Vec::new();
|
||||
|
||||
loop {
|
||||
// polling for new sounds
|
||||
if let Ok(command) = rx.try_recv() {
|
||||
match command {
|
||||
Command::Play(decoder) => sounds.push((Voice::new(), decoder)),
|
||||
}
|
||||
}
|
||||
|
||||
for &mut (ref mut voice, ref mut decoder) in sounds.iter_mut() {
|
||||
decoder.write(voice);
|
||||
voice.play();
|
||||
}
|
||||
}
|
||||
}
|
19
src/lib.rs
Normal file
19
src/lib.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
extern crate cpal;
|
||||
extern crate hound;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
use std::io::Read;
|
||||
|
||||
mod decoder;
|
||||
mod engine;
|
||||
|
||||
lazy_static! {
|
||||
static ref ENGINE: engine::Engine = engine::Engine::new();
|
||||
}
|
||||
|
||||
/// Plays a sound once. There's no way to stop the sound except by exiting the program.
|
||||
pub fn play_once<R>(input: R) where R: Read + Send + 'static {
|
||||
let decoder = decoder::decode(input);
|
||||
ENGINE.play_once(decoder);
|
||||
}
|
Loading…
Reference in a new issue