synthizer 0.5.4

bindings to Synthizer, a library for 3D audio and effects
Documentation
//! Implement the media player example from the Python tutorial, but in Rust.
use std::io::Write;
use std::str::FromStr;

use synthizer as syz;

fn help() {
    print!(
        r#"Commands:
pause, play: pause and/or play the media.
pos x y z: move the source to the position x y z.
seek pos: seek to position pos in seconds.
gain value: control the gain of the generator in db
quit: exit.
"#
    );
}

fn main_impl(input_file: &str) -> syz::Result<()> {
    let mut init_cfg = syz::LibraryConfig::new();
    init_cfg.log_to_stderr();
    init_cfg.log_level(syz::LogLevel::Debug);
    let _guard = init_cfg.initialize()?;

    let ctx = syz::Context::new()?;
    ctx.default_panner_strategy()
        .set(syz::PannerStrategy::Hrtf)?;

    let src = syz::Source3D::new(&ctx, syz::PannerStrategy::Delegate, (0.0, 0.0, 0.0))?;
    let gen = syz::BufferGenerator::new(&ctx)?;
    let syz_buf = syz::Buffer::from_file(input_file)?;
    gen.buffer().set(&syz_buf)?;
    src.add_generator(&gen)?;

    let mut looping = false;
    let stdin = std::io::stdin();
    let mut stdout = std::io::stdout();
    loop {
        print!("> ");
        stdout.flush().expect("Should flush");

        let mut line = String::new();
        stdin.read_line(&mut line).expect("Should always read");
        let line = line.trim();

        if line == "quit" {
            break;
        }

        let parts = line.split_whitespace().collect::<Vec<_>>();
        if parts.is_empty() {
            continue;
        }

        match parts[0] {
            "help" => {
                help();
            }
            "pause" => {
                src.pause()?;
            }
            "play" => {
                src.play()?;
            }
            "loop" => {
                looping = !looping;
                gen.looping().set(looping)?;
            }
            "seek" => {
                if parts.len() != 2 {
                    println!("Usage: seek <pos>");
                }
                let pos = match f64::from_str(parts[1]) {
                    Ok(f) => f,
                    Err(_) => {
                        println!("Invalid position");
                        continue;
                    }
                };
                gen.playback_position().set(pos)?;
            }
            "pos" => {
                if parts.len() != 4 {
                    println!("Usage: pos x y z");
                    continue;
                }
                let m_x = f64::from_str(parts[1]);
                let m_y = f64::from_str(parts[2]);
                let m_z = f64::from_str(parts[3]);
                let pos = match (m_x, m_y, m_z) {
                    (Ok(x), Ok(y), Ok(z)) => (x, y, z),
                    _ => {
                        println!("Unable to parse position");
                        continue;
                    }
                };
                src.position().set(pos)?;
            }
            "gain" => {
                if parts.len() != 2 {
                    println!("Usage: gain <db>");
                    continue;
                }
                let gain_db = match f64::from_str(parts[1]) {
                    Ok(g) => g,
                    Err(_) => {
                        println!("Unable to parse gain");
                        continue;
                    }
                };
                let gain = 10.0f64.powf(gain_db / 20.0);
                src.gain().set(gain)?;
            }
            _ => {
                println!("Invalid command. Type help for usage");
            }
        }
    }

    Ok(())
}

fn main() -> std::result::Result<(), &'static str> {
    let args = std::env::args().collect::<Vec<_>>();
    if args.len() != 2 {
        println!("Usage: {} <file>", args[0]);
        return Err("Failed");
    }

    main_impl(args[1].as_str()).expect("Should succeed");
    Ok(())
}