audio - Rust:如何使用 alto crate 以编程方式创建声音
问题描述
我是 Rust 的新手,我根据秘密酱算法生成的序列拼接了一个播放声音的程序。
但是,我没有听到使用整数序列作为测试数据播放的声音。
我不知道数字序列中哪些值是有效的,哪些值是可听的,哪些值是可怕的,就像通过播放它们失去了我的听力一样。
我也在为 Rust 的结果包装器概念而苦苦挣扎;在我的代码中,我使用了三种不同的方法来解开其中一些可能不合适的方法。
这是我的代码:
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(())
}
期望的结果:从整数序列(而不是音频文件)播放一些声音。我也想知道如何附加到 Vec(vector)。
解决方案
看起来这非常接近工作,只有几个问题:
看起来调用
_source.play()
是非阻塞的,这意味着进程在启动音频后几乎立即退出。您可以通过插入对 的调用来防止这种情况thread::sleep
。样本数据 (10..200) 只有 190 个样本长,在 44100 Hz 下只能持续 190 / 44100 秒,或大约 0.004 秒。此外,此处的波形可能听不见,因为其中没有振荡,扬声器的位置/压力只有一个线性斜坡。您可以通过创建正弦曲线或其他一些重复波形来获得声音。
这是对您的示例的修改,它对我有用,生成 220 Hz 正弦波持续 2 秒:
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(())
}
要回答有关序列中有效值范围的问题,任何i16
值都是有效的,因此您需要提供介于i16::MIN
和之间的值i16::MAX
,即介于 -32768 和 +32767 之间的值。为了获得最高质量,您可能希望对音频进行标准化,以便在其最响亮的部分达到(或接近达到)最大值 32767,并且您可以调整系统音量以防止这引起不适/听力损失.
推荐阅读
- php - 展平 laravel 关系集合/数组
- reactjs - 如何修复材料表(React)中的分页图标(将其重置为默认值)?
- python - 减少python中字典上带有关键字参数的函数列表
- javascript - Vue JS Vuetify $emit is not working on first time
- java - Spring Boot JPA - Define a One to Many relationship
- android - 如何在android中获取仅包含音频文件(.mp3)的文件夹
- mongodb - mongodb 中的 find() 方法返回未定义
- .htaccess - 如何使用 htaccess 使网页像子目录一样
- azure-iot-hub - 有没有办法在 java [Azure-IoT-Hub] 边缘模块中实例化没有连接字符串的 DeviceClient?
- coldfusion - 锚标签不能正常工作,而是在 cfemail 内容中显示完整的字符串