5 个版本 (3 个重大更新)

0.4.0 2024年2月6日
0.3.0 2022年10月17日
0.2.0 2022年10月16日
0.1.1 2022年2月4日
0.1.0 2022年2月4日

#113音频

每月下载 34

CC0 许可证

100KB
2.5K SLoC

Rocoder

用 Rust 编写的可实时编码的相位声码器。

Rocoder 是一个数字乐器命令行程序,通过放慢或加速音频并应用可实时编码的频率核来转换音频。它可以

  • 改变音频速度
  • 音调转换(尽管只沿谐波和亚谐波进行)
  • 将任意代码转换应用于频域音频表示(仅限 Mac 和 Linux)
  • 实时编译和重新加载转换代码
  • 读取和写入音频文件
  • 直接音频输入和播放

安装

  1. 如果您还没有,请在 https://rustup.rs/ 安装 Rust 工具链
  2. 通过运行 cargo install rocoder 来安装此工具
  3. 运行 rocoder -h 开始使用!

工作原理

rocoder 是一个相当简单的,可能并不完全正确的 相位声码器。它使用 3 个步骤处理音频,了解基础知识对于高级使用是必要的,特别是与频率核一起工作。

  1. 分析:输入音频在重叠的 汉宁窗口 中使用 FFT 分析。每个窗口分析发出其音频窗口的频域表示,编码为复数缓冲区。
  2. 处理:如果提供了频率核,则将每个频域窗口缓冲区传递给它进行任意代码定义的处理。
  3. 再合成:然后将处理过的频域缓冲区传递给逆 FFT 以进行再合成。再合成以允许音高转换和速度变化的方式进行。

使用方法

rocoder 使用一系列命令行参数进行控制。运行 rocoder -h 以列出它们。

-r, --record

从默认音频输入设备获取音频输入。设置后,rocoder 将开始记录输入,直到您按下 Enter 键。它将自动尝试修剪音频的开始/结束部分,以去除静音。

--rotate-channels

将输入音频通道旋转 1 次。对于立体声输入,这将交换左右通道。

-a, --amplitude <amplitude>

输出振幅乘数。默认为 1;

-b, --buffer <buffer-dur>

处理音频的最大持续时间。这主要用于您想更改实时代码更改的响应时间时。值以秒为单位指定,例如,-b 1.5 表示 1.5 秒。

-d, --duration <duration>

从输入源读取的音频量,如果提供了起始时间,则从起始时间开始。指定为持续时间字符串 hh:mm:ss.ss,较大的部分可以省略,例如,1:0:0 表示 1 小时,1:30 表示 90 秒,1.5 表示 1.5 秒。

-f, --factor <factor>

拉伸因子;例如,5 表示减速 5 倍,0.2 表示加速 5 倍。默认为 1(无速度变化)。

-x, --fade <fade>

应用于输出音频的淡入/淡出持续时间。有关指定格式,请参阅 --duration。默认为 1(1 秒)。

--freq-kernel <freq-kernel>

rust 频率内核的路径。

-, --input <input>

要从中读取音频文件的路径。目前支持 .wav(8、16、24、32 位整数和 32 位浮点格式)和 .mp3

-, --output <output>

音频输出文件的路径。如果设置,则不会将输出播放到设备;相反,rocoder 将尽可能快地运行并将输出持久化到磁盘。

此功能仅支持以32位浮点格式输出的 .wav

由于实现方式有缺陷,需要将整个输出文件放入内存中才能写入磁盘。

-p--pitch-multiple <pitch-multiple>

非零整数音高倍数。大于1的正数用于音高移位,沿着谐波系列,而小于-1的负数用于沿着次谐波系列移位。

arg result
1 无音高移位
2 升八度
3 升八度和五度
4 升两八度
5 升两八度和纯五度
-1 无音高移位
-2 降八度
-3 降八度和五度
0 [无效]

默认为 1(无音高移位)。

-s--start <start>

输入音频中的起始时间。(关于参数格式,请参阅 --duration

-w--window <window-len>

处理窗口的大小。小值会导致失真,而大值会导致模糊。推荐使用2的幂次以获得最佳性能。默认为 16384

现场编码

频率核仅在Mac和Linux上受支持。欢迎为支持Windows做出贡献。

频率核在重新合成之前修改频域数据,允许你对声音进行非常强大的转换。内核定义在Rust文件中,必须符合以下签名

#[no_mangle]
pub fn apply(elapsed_ms: usize, input: Vec<(f32, f32)>) -> Vec<(f32, f32)> {
    todo!() // Your code here
}

需要 no_mangle 指令和 apply 名称。

输入是表示给定音频窗口频域的复数缓冲区。默认情况下,窗口长度约为16k个样本。函数的输出是输入的转换副本。

以下是一个简单的内核,它简单地通过乘以一个常数来增加输入音频的幅度

#[no_mangle]
pub fn apply(elapsed_ms: usize, input: Vec<(f32, f32)>) -> Vec<(f32, f32)> {
    return input
        .iter()
        .map(|(real, im)| (real * 2.0, im * 2.0))
        .collect();
}

如果将其保存到文件 kernel.rs 中,它可以与以下内容一起使用

cargo run --release -- \
    -r -f 1 --freq-kernel path/to/kernel.rs

当rocoder正在运行并播放音频(不写入文件)时,它将监视此文件的变化,并自动在飞行中编译和热交换到进程。只需编辑文件并保存到你的内核中的现场代码即可!

此工具的各种功能都在crate库中公开,但此API目前尚未文档化且非常不稳定。

致谢

相位声码器算法的基本实现已从Paulstretch改编。

依赖关系

约10-41MB
约655K SLoC