audiorustalto

Rust: How to create sounds programmatically using alto crate


I'm new to Rust and I stitched together a program for playing sounds based on a sequence which will be generated by the secret sauce algorithm.

However, I hear no sound being played with a sequence of integers as test data.

I have no clue what values are valid in the number sequence, and which values are audible and which values are awful as in loosing my hearing by playing them.

I'm also struggling with the Result wrapper concept of Rust; In my code I'm using three different ways to unwrap some of which probably are inappropriate.

Here is my code:

fn main() {
    use std::process::exit;

    if let Err(e) = run() {
        println!("Failed to run basic example: {}", e);
        exit(1);
    }
}

extern crate alto;

use alto::{Alto, AltoResult, Mono, Source}; 

fn run() -> AltoResult<()> {
    use std::sync::Arc;

    let alto = Alto::load_default()?;

    for s in alto.enumerate_outputs() {
        println!("Found device: {}", s.to_str().unwrap());
    }

    let device = alto.open(None)?; // Opens the default audio device
    let context = device.new_context(None)?; // Creates a default context

    // Configure listener
    context.set_position([1.0, 4.0, 5.0])?;
    context.set_velocity([2.5, 0.0, 0.0])?;
    context.set_orientation(([0.0, 0.0, 1.0], [0.0, 1.0, 0.0]))?;

    let mut _source = context.new_static_source()?;

    // Now you can load your samples and store them in a buffer with
    // `context.new_buffer(samples, frequency)`;

    let data: Vec<_> = (10..200u32).map(|i| i as i16).collect();
    let buffer = context.new_buffer::<Mono<i16>, _>(data, 44_100);
    let buf = Arc::new(buffer.unwrap());

    let good_result = _source.set_buffer(buf);
    assert!(good_result.is_ok() && !good_result.is_err());

    _source.play();

    Ok(())
}

Desired result: Play some sounds from a sequence of integers (not from an audio file). I also would like to know how to append to a Vec(vector).


Solution

  • Looks like this is very close to working, just a couple issues:

    Here is a modification of your example which is working for me, generating a 220 Hz sinusoid for 2 seconds:

    use alto::{Alto, AltoResult, Mono, Source};
    use std::{thread, time};
    
    fn main() {
        use std::process::exit;
    
        if let Err(e) = run() {
            println!("Failed to run basic example: {}", e);
            exit(1);
        }
    }
    
    fn run() -> AltoResult<()> {
        use std::sync::Arc;
    
        let alto = Alto::load_default()?;
    
        for s in alto.enumerate_outputs() {
            println!("Found device: {}", s.to_str().unwrap());
        }
    
        let device = alto.open(None)?; // Opens the default audio device
        let context = device.new_context(None)?; // Creates a default context
    
        // Configure listener
        context.set_position([1.0, 4.0, 5.0])?;
        context.set_velocity([2.5, 0.0, 0.0])?;
        context.set_orientation(([0.0, 0.0, 1.0], [0.0, 1.0, 0.0]))?;
    
        let mut _source = context.new_static_source()?;
    
        // Now you can load your samples and store them in a buffer with
        // `context.new_buffer(samples, frequency)`;
    
        let pi = std::f32::consts::PI;
        let data: Vec<_> = (0..88200u32)
            .map(|i| ((i16::MAX as f32) * f32::sin(2.0 * pi * (i as f32) * 220.0 / 44100.0)) as i16)
            .collect();
        let buffer = context.new_buffer::<Mono<i16>, _>(data, 44_100);
        let buf = Arc::new(buffer.unwrap());
    
        let good_result = _source.set_buffer(buf);
        assert!(good_result.is_ok() && !good_result.is_err());
    
        _source.play();
    
        thread::sleep(time::Duration::from_millis(2000));
        Ok(())
    }
    

    To answer your question about the range of valid values in the sequence, any i16 values are valid, so you'd want to provide values between i16::MIN and i16::MAX, i.e., between -32768 and +32767. For highest quality, you probably want your audio to be normalized such that at its loudest parts it hits (or come close to hitting) that maximum value of 32767, and you can adjust your system volume level to prevent this from causing discomfort/hearing loss.