【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【25卒向け】AI×バーチャル面接の募集を開始いたしました!

【25卒向け】AI×バーチャル面接の募集を開始いたしました!

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

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

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【WordPress 専用】クラウドサーバー『ウェブスピード』

【WordPress 専用】クラウドサーバー『ウェブスピード』

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

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

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

【中国現地企業に対応】中国クラウド / サーバー構築・運用保守

【中国現地企業に対応】中国クラウド / サーバー構築・運用保守

【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 様
音の森 様

最後に

私が所属するシステム開発のサービスサイト「SEKARAKU Lab(セカラク ラボ)」を開設しました。
ビヨンドは、サーバーの設計・構築から運用までをワンストップでお任せいただけますので、サーバーサイド開発でお困りの方はお気軽にお問い合わせください。
SEKARAKU Lab:[https://sekarakulab.beyondjapan.com/](https://sekarakulab.beyondjapan.com/)

ありがとうございます。

この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
1
読み込み中...
1 票, 平均: 1.00 / 11
693
X facebook はてなブックマーク pocket
【2024.6.30 CentOS サポート終了】CentOS サーバー移行ソリューション

【2024.6.30 CentOS サポート終了】CentOS サーバー移行ソリューション

【25卒向け】AI×バーチャル面接の募集を開始いたしました!

【25卒向け】AI×バーチャル面接の募集を開始いたしました!

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

この記事をかいた人

About the author

松山賢勝

長くゲーム開発会社でプログラムやプロジェクトマネージメントなどの業務に従事。
2019年より株式会社ビヨンド に入社。横浜オフィスに勤務。
サーバーサイド開発業務のプロジェクトマネージメントを中心に担当。(時々、プログラミング)
趣味は自転車(ロードレーサー)と競馬観戦。