【新卒 / 中途採用】サーバー / クラウドエンジニア 募集中!【大阪】

【新卒 / 中途採用】サーバー / クラウドエンジニア 募集中!【大阪】

【導入実績300社以上】AWS 構築・運用保守サービス

【導入実績300社以上】AWS 構築・運用保守サービス

【ECサイト構築】Shopify カスタムアプリ開発サービス

【ECサイト構築】Shopify カスタムアプリ開発サービス

【100URLの登録が0円】Webサイト監視サービス「Appmill」

【100URLの登録が0円】Webサイト監視サービス「Appmill」

【音声アプリ開発】Twilio アプリ開発サービス』

【音声アプリ開発】Twilio アプリ開発サービス』

【メッセージアプリ】LINE アプリ開発サービス

【メッセージアプリ】LINE アプリ開発サービス

【対談記事】「やっぱクラウド移設っていいですよね」マイネット × ビヨンド エンジニア対談

【対談記事】「やっぱクラウド移設っていいですよね」マイネット × ビヨンド エンジニア対談

ビヨンド公式YouTubeチャンネル「びよまるチャンネル」

ビヨンド公式YouTubeチャンネル「びよまるチャンネル」

オーディオエフェクトの話


お疲れ様です。
システム開発室、松山です。

ふと、オーディオフィルターってあるけど、リバーブくらいしか使った事ないなと思いたち、
他のフィルター(エフェクト)について確認してみました。

Audio Filter

まずはどんなフィルターがあるか確認しましょう。
公式のドキュメントはこちら

Low Pass Filter

Low Pass なので、高い周波数をカットするフィルターです。
壁など遮蔽物の向こう側や、スピーカーの裏側など高周波が減衰した状態の聴こえ方になります。

High Pass Filter

Low Pass とは逆に、低い周波数をカットするフィルターです。
物理現象としては高周波数から減衰するはずなので、安いイヤホンなどで低い周波数が再生できない感じの聴こえ方でしょうか。
チャカチャカした感じの音になります。

Echo Filter

エコーですね。同じ音を減衰させながら繰り返してくれます。
カラオケボックスでエコーかけて歌ってるイメージです。
間隔を広げると、山彦みたいになるかもです。

Distortion Filter

ボリュームとは関係なしに音を大きくします。
低品質なので音割れみたいな感じに歪みます。

Reverb Filter

個人的には、一番使う機会が多いフィルターです。
ホールや地下道など、閉じた空間で反響した感じに聞こえます。
あと、マイクを通して聞こえてくる音声のようなイメージでしょうか。
設定できるパラメータが一番多く、素人の自分には調整仕切れない感があります。

Chorus Filter

合唱のような感じに、変調された音声を合わせて再生するフィルターです。
サンプルで試したのですが、何かうまく効いてくれませんでした。
知っている方いたら教えてください…

要件

いつものように、Unity でサンプルを作成して実際に試していきます。
① Audio Listener に各種フィルターを設定
② 各フィルターをチェックボックスで on / off できるようにする
③ Low Pass と High Pass フィルターは、スライダーで周波数を指定
④ bgm, se, ジングルをそれぞれ再生できるようにする
⑤ オーディオスペクトラム的なものを表示してみる

こんな感じ。
各フィルターのパラメータはデフォルト状態。
いくつかの音声を再生する UI を作るくらいです。
オーディオスペクトラムはそれっぽく動いてくれれば OK とします。

Audio Listener にフィルターを設定する

MainCamera の Component に Audio Listener があるので、その下に各フィルターを追加していきます。
Low / High Pass Filter 以外はチェックボックスで切り替えるので、デフォルトはオフにしておきます。

各フィルターをチェックボックスで on / off できるようにする

UI.Toggle を使って作成。(こんな感じ↓)

トリガー用のメソッドを用意して、

// Filter 用トグル
public void OnClickToggleFilter(int no)
{
    switch ((FilterNo)no)
    {
        case FilterNo.Chorus:
            fltChorus.enabled = tglChorus.isOn;
            break;
        case FilterNo.Distortion:
            fltDistortion.enabled = tglDistotion.isOn;
            break;
        case FilterNo.Echo:
            fltEcho.enabled = tglEcho.isOn;
            break;
        case FilterNo.Reverv:
            fltReverb.enabled = tglReverv.isOn;
            break;
    }
}

OnValueChanged で設定してあげれば OK。

Low Pass と High Pass フィルターは、スライダーで周波数を指定

Low Pass と High Pass フィルターはスライダーで設定できるようにする。
ついでに、ボリュームとピッチも作ってしまう。

スライダーのj反映はこんな感じで。

① イベントリスナーを設定

// 低音通過
sldLoPass.onValueChanged.AddListener((value) =>
{
    setLoPass(value);
});

② フィルターに値を設定

// 低域通過フィルター設定
private void setLoPass(float val)
{
    var loPassHz = ExpHz(val);
    fltLoPass.cutoffFrequency = loPassHz;
    txtLoPass.text = string.Format("{0:#}", loPassHz);
}

※ ExpHz で 0.0 〜 1.0 の値を、10 〜 22000 Hz に変換してます

float ExpHz(float logHz)
{
    var t = Mathf.Log(LowHz) - Mathf.Log(HighHz);
    return Mathf.Exp(logHz * t) * 10f;
}

bgm, se, jingle をそれぞれ再生できるようにする

UI.Button を使って、音声を再生できるようにします。

イベントリスナーを設定して、再生 / 停止を切り替えます。
AudioSource.Play(), Stop() を使用します。

// BGM 再生・停止
btnBgmPlay.onClick.AddListener(() =>
{
    if (!bgmSource.isPlaying) bgmSource.Play();
    else bgmSource.Stop();
});

オーディオスペクトラム的なものを表示してみる

最後に波形データを表示してみます。
タイトル画像に出てるやつです。

AudioListener のGetSpectrumData() を使用します。

実装は、こちらを参考にさせていただきました。(感謝です)
スマホ実機でサウンドのスペクトル解析を見たい

GetSpectrumData() で取得したオーディオサンプルを、UI 表示用に 512 分割した周波数帯に分けます。

AudioListener.GetSpectrumData(spectrumData, 0, FFTWindow.Hanning);
var outputF = AudioSettings.outputSampleRate;
// 全binを初期化
for (int i=0; i<bins.Length; i++)
{
    bins[i] = 0f;
}

var logMaxF = Mathf.Log(graphMaxFrequency); // 上のbinの周波数のlog
var logMinF = Mathf.Log(graphMinFrequency);
var logRange = logMaxF - logMinF;
if (logRange <= 0f)
{
    logRange = 8f;
}
// まず周波数分類
for (int i=0; i<spectrumData.Length; i++)
{
    var f = outputF * 0.5f * (float)i / (float)spectrumData.Length;
    if (f == 0f)
    {
        f = float.Epsilon;
    }
    // 対数を取ってどのビンに入るか確定
    float binValue = (float)bins.Length * (Mathf.Log(f) - logMinF) / logRange;
    int binIndex = Mathf.FloorToInt(binValue);
    if ((binIndex >= 0) && (binIndex < bins.Length))
    {
        // そのビンにデータを加算
        bins[binIndex] += spectrumData[i];
    }
}

各ブロックで表示するためのベースとなる Prefab を作成します。
Width : 3, Height:0 の UI.Image です。
これを画面左から順に並べ、値の大きさに合わせて高さを設定します。

// バーに反映
for(int i=0; i<BinCount; i++)
{
    float v = bins[i];
    float y = Mathf.Min(v * 8000f, 420f);
    Vector2 sd = new Vector2(BarWidth, y);
    spectrumBars[i].sizeDelta = sd;
}

これで音声を再生すると波形データがそれっぽく表示されるようになると思います。

まとめ

一通りのオーディオフィルターを試してみました。
Chorus は上手く効いてくれませんでした(涙)
やはり、リバーブと Low Pass 以外は使いどころ難しい感じがします。
Unity には Audio Mixer もあるので、より細かい設定をしたい場合はこちらを使うと良いかもしれません。
正直、素人が手を出して良い領域ではない気がしますが…
それでは、今回のお話はこれまでになります。

今回も、Git に上げておきます。
何かの参考にでもなれば幸いです。
Unity サンプル

また、音声データは以下から使用させていただきました。
OtoLogic 様
音の森 様
ありがとうございます。


この記事をかいた人

About the author

松山賢勝

2019年8月から横浜オフィスに勤務。
経歴としてはクライアント開発が多いため、クライアント寄りの記事が多いかも。
趣味は自転車(ロード)と競馬。