🎵

Rustでリバーブを実装する

2024/06/17に公開

Parakeet株式会社でResearcherをしている金子(nadare)です。CPUで動く軽量AIボイスチェンジャーParavoにおいて、リバーブやイコライザといったエフェクターをかける機能をRustで実装しました。本記事ではRustで実装した理由や用いたライブラリについて説明します。

エフェクトに追加されたルームリバーブ(ホール)

リバーブについて

リバーブは音に残響音や反射音を加える空間的エフェクトで、通常の音をホールで演奏した音や狭い空間で鳴らした音のように加工します。リバーブの実装にはハードウェア・ソフトウェア等様々な手法がありますが、今回は畳み込み演算を用いたリバーブの実装を行いました。
畳み込み演算で実装するリバーブには、Room Impulse Response(RIR)という音の信号を用います。これは再現したい空間で拍手をしたときに得られるような音で、様々な環境で収録したRIRを集めたデータセットや、pyroomacouticsといったライブラリでシミュレーションして得ることができます。
長い音声に対するRIRであればフーリエ変換を用いた畳み込みの方が効率的なため採用されますが、Paravoではリアルタイムにリバーブをかける必要があるので、Conv1dのような計算でリバーブを掛けました。

Paravoで採用しているライブラリについて

Paravoではtauriというフレームワークを用いてアプリケーションを実装しています。tauriについては同じ会社のだだっこぱんださんも記事を書いているのでこちらも読んでみてください。

tauriはRustで書かれたデスクトップアプリを作るためのフレームワークで、フロントをHTMLやTypeScript、バックエンドをRustで書くことでWindows、Mac、ios、Android等に対応したアプリケーションを作ることができます。Paravoではpythonで学習を行ったモデルをonnxに出力し、ONNX RuntimeのRust版ラッパーのortを用いて動かしています。

onnxruntimeの弱点

ONNX Runtimeを用いることでTensorFlowやPyTorchに実装されている様々な関数をRustから呼び出すことができます。しかし、ONNXへの変換では複素数が使えない、可変長のfor loopの扱いが面倒等といった制約もあります。今回リバーブの実装にあたって、まずortからconv1d関数を呼び出しinputとweightを渡そうと試したのですが、ONNXでのconv1dはweightの長さが一定である必要がありました。RIRは広い空間ほど長くなる傾向にあり、可変長のRIRで畳み込む必要がある今回は使えません。そのためRustで直接実装を行いました。

Rayon crateによる並列計算の実装

1dの畳み込み計算にあたって、weightは24kHzのRIRでは1秒でも24000点あるため、計算の高速化が必要でした。Rustで並列計算を手軽に実装するため、Rayonというライブラリを用いデータ並列による高速化を行いました。
Rayonの使い方はシンプルで、iter_mat()をpar_iter_mut()に置き換えるだけで手軽に並列化が可能です。Rayonを用いた1次元の畳み込みの関数は下記のように実装しました。

use rayon::prelude::*;
fn parallel_conv1d(input: &Vec<f32>, kernel: &Vec<f32>) -> Vec<f32> {
    let n = input.len();
    let m = kernel.len();
    let mut result = vec![0.0; n - m + 1];

    result.par_iter_mut().enumerate().for_each(|(i, res)| {
        for j in 0..m {
            *res += input[i + m - j - 1] * kernel[j];
        }
    });
    result
}

実装した感想

今回のエフェクターの実装は、今後Paravo単体で音声変換を用いる際に必要な機能を入れるための練習として行いました。RustもTypeScriptも初めて触ったのですが、だだっこぱんださんの優秀な設計と、VSCodeのrust-analyzerやGitHub Copilot、ChatGPTとの相談により比較的躓くことなく実装できました。(一方で言語以外の部分では畳み込みの実装の添字をバグらせすぎたので、Jupyter Notebook上で先にサイン波に対してpythonで畳み込みの関数を実装し、matplotlibで可視化し上手く計算できているかで検算をしました。)RustやTypeScriptはコード解析が優秀になった現代のIDEで輝く言語に感じています。

Paravoでは最先端のAI技術とプログラム実装を用いて、誰でもクリーンで高品質な音声変換ができるよう研究開発を進めています。ぜひ、公式ページよりDLしてみてください。

Parakeet 株式会社

Discussion