2021/05/04

LFO のテンポシンク

 

LFO のテンポシンクを読む (github.io) 

LFO を滑らかにテンポシンクする方法について調べました。 magnetophon さんによる LFO の同期についての issue が発端となっています。

VST 3 や LV2 プラグインでは、ユーザが指定した同期間隔のほかに、ホストのテンポ (BPM) と再生開始からの経過拍数が取得できます。適当に実装するなら経過拍数を同期間隔で割った余りを使えばいいのですが、使い方によってはポップノイズが出てしまいます。そこで経過拍数の変化を検知して、位相の速度を調整することで滑らかに同期を続ける方法を紹介しています。

画像は LFO の位相が滑らかに新しい同期間隔へと移行する様子を表した図です。

2021/05/09追記: リンク先の記事の C++ 実装のバグを修正。

2021/01/24

ウェーブテーブルのピッチベンド

ウェーブテーブルのピッチベンドを読む (github.io)

Laurent de Soras さんによる The Quest For The Perfect Resampler を参考にして、ウェーブテーブルをピッチベンドしたときにエイリアシングノイズを出さないようにする方法を試しました。 

オクターブごとにウェーブテーブルを用意して、線形補間と2倍のオーバーサンプリングを組み合わせることでエイリアシングノイズは消せました。ただしピッチベンド中にウェーブテーブルが切り替わるとポップノイズが出ます。ポップノイズを抑えたいときは4倍以上にオーバーサンプリングするとよさそうです。

De Soras さんの資料ではミップマップとアップサンプラを組み合わせていますが、フィルタ係数の補間と FIR の畳み込みが重たそうだったので今回は実装していません。

画像の上は今回実装したオーバーサンプリングを行うウェーブテーブルオシレータでのこぎり波を出力したときのスペクトログラムです。下はウェーブテーブルが切り替わるタイミングを示しています。

2021/02/24追記: リンク先の記事を大幅に加筆修正しました。

2021/01/11

ステレオパンニング

ステレオパンニングを読む (github.io)

ステレオ → ステレオパンニングの計算式をいくつか作りました。ステレオ → モノラルパンニングについては Loudness Concepts & Panning Laws を参考にしました。

画像はステレオ → ステレオパンニングのブロック線図です。

2021/01/08

リミッタの実装

リミッタの実装を読む (github.io)

リミッタの実装についてまとめました。「ステップ応答が S 字を描くフィルタ」と「ピークホールドによるエンベロープ」で作った部品を使っています。

今回作ったリミッタは musicdsp.orgLookahead Limiter の記事で紹介されているレシピとほとんど同じです。この記事の翻訳版もあります。レシピにはピークホールドの詳細が書いていなかったので、そこだけ試行錯誤しました。

画像は実装したリミッタの大まかなブロック線図です。

2021/01/06

ダウンサンプリング

ダウンサンプリングを読む (github.io) 

今まで適当にやっていたダウンサンプリングについて調べたことをまとめました。

画像は FIR フィルタのポリフェイズ分解を表したブロック線図です。

ピークホールドによるエンベロープ

 

ピークホールドによるエンベロープを読む (github.io)

リミッタで使うためのピークホールドを使ったエンベロープの実装について調べました。

画像は理想的なピークホールドの出力です。

2020/12/03

GitHub Actions による VST 3 SDK のビルド

かなりはまったのでまとめておきます。

build.yml

以下は Windows のジョブだけを抜き出した `.github/workflows/build.yml` の内容です。

name: CI

on: [push]

jobs:
  build-windows:
    runs-on: windows-latest
    steps:
    - uses: actions/checkout@v2
      with:
        path: VSTPlugins
        submodules: recursive
    - name: Run script
      run: VSTPlugins/ci/ci_windows.ps1
    - name: Upload
      uses: actions/upload-artifact@v1
      with:
        name: vst_windows
        path: vst_windows

actions/checkout で自前のプラグインのリポジトリをクローン、細かいビルド作業を `ci_windows.ps1` で実行、 actions/upload-artifact でビルドしたプラグインをアップロードする、という単純な CI (continuous integration) です。 GitHub Actions では CI の終了後にアップロードするデータのことをアーティファクトと言います。

以下は実際のコードへのリンクです。

`build.yml` の macOS と Ubuntu のジョブは、ほとんどコピペです。スクリプトは `ci_windows.ps1` へのリンクをたどってディレクトリを一つ登ったところに置いています。

ビルドスクリプト

以下は `ci_windows.ps1` からアーティファクトのアップロードの前処理を省いた抜粋です。言語は PowerShell です。

git clone --recursive $VST3SDK_REPOSITORY_URL
mkdir build
mkdir target
$SRC_ROOT = (Get-Item .).FullName

cmake `
  -S vst3sdk `
  -B build `
  -G "Visual Studio 16 2019" `
  -A x64 `
  -DSMTG_MYPLUGINS_SRC_PATH="$SRC_ROOT\VSTPlugins" `
  -DSMTG_PLUGIN_TARGET_PATH="$SRC_ROOT\target" `
  -DSMTG_ADD_VST3_HOSTING_SAMPLES=FALSE `
  -DSMTG_ADD_VST3_PLUGINS_SAMPLES=FALSE `
  -DSMTG_CREATE_PLUGIN_LINK=FALSE
  
cmake --build build -j --config Release
if (!$?) { Exit $LASTEXITCODE }

VST 3 SDK 固有の cmake オプションの意味は以下の通りです。

  • SMTG_MYPLUGINS_SRC_PATH: 自分のプラグインのソースコードへのパス。
  • SMTG_PLUGIN_TARGET_PATH: プラグインのインストールパス。
  • SMTG_ADD_VST3_HOSTING_SAMPLES: サンプルホストのビルド。
  • SMTG_ADD_VST3_PLUGINS_SAMPLES: サンプルプラグインのビルド。
  • SMTG_CREATE_PLUGIN_LINK: ビルドしたプラグインのリンクをインストールパスに作る。

SMTG_ADD_VST3_HOSTING_SAMPLES 、 SMTG_ADD_VST3_PLUGINS_SAMPLES 、 SMTG_CREATE_PLUGIN_LINK は CI では不要なので FALSE に設定しています。

最後の行の `if (!$?) { Exit $LASTEXITCODE }` は cmake がビルドに失敗したときにエラーコードを出してスクリプトを終了する PowerShell 固有の処理です。 bash ではスクリプトの先頭に `set -e` と書けば似たような効果があります。これらの行が無いとビルドに失敗してもスクリプトが止まらず、問題が残ったまま CI が成功してしまいます。このワークアラウンドは以下のリンクのコメントを参考にしました。

Windows PowerShell failed still marks job successful (#3194) · Issues · GitLab.org / gitlab-runner · GitLab

アーティファクトの消去

何回もビルドしているとアーティファクトが増えてストレージの容量が圧迫されることがあります。アーティファクトは手でも消せますが、時間がかかるので GitHub の提供する REST API を使うと楽です。 GitHub の REST API の詳細は以下のマニュアルを参照してください。マニュアルの Guides のページを前から順に試せばだいたい理解できます。

GitHub REST API - GitHub Docs

まずは以下のページの手順に従ってアクセストークンを取得します。アクセストークンがあればアカウントを乗っ取れてしまうので、何があっても誰にも公開しないでください。

Creating a personal access token - GitHub Docs

以降ではアクセストークンを `GITHUB_TOKEN` 、ユーザ名を `GITHUB_USER` とします。

以下のコマンドを実行すれば curl を使ってアーティファクトの一覧を取得します。

curl \
  -H "Accept: application/vnd.github.v3+json"\
  -u "$GITHUB_USER:$GITHUB_TOKEN" \
  "$REPOSITORY_URL/actions/artifacts?per_page=100" \
  > artifacts.json

実行前に `$GITHUB_USER` と `$GITHUB_TOKEN` にそれぞれ適切な値を代入しておいてください。 `$REPOSITORY_URL` は GitHub リポジトリのトップページの URL です。 `https://github.com//` の形式になっています。 `` と `` の部分は自分のリポジトリに合わせて置き換えてください。

`$REPOSITORY_URL` のあとに続く `actions/artifacts?per_page=100` の部分が REST API です。アーティファクトに関する API は以下のリンクに載っています。

Actions - GitHub Docs

取得したアーティファクトの一覧を保存した `artifacts.json` を使って以下の Python3 のスクリプトでまとめてアーティファクトを消します。

import json
import subprocess

github_user = # ユーザ名
github_token = # アクセストークン
repository_name = # リポジトリ名

with open("artifacts.json", "r", encoding="utf-8") as fi:
    data = json.load(fi)

for artifact in data["artifacts"]:
    print(f"████ Deleting {artifact['id']}")
    subprocess.run([
        "curl",
        "-i",
        "-X",
        "DELETE",
        "-u",
        f"{github_user}:{github_token}",
        f"https://api.github.com/repos/{github_user}/{repository_name}/actions/artifacts/{artifact['id']}",
    ])

ユーザ名、アクセストークン、リポジトリ名は文字列で指定してください。

この方法では一度に 100 個のアーティファクトまでしか消せません。アーティファクトが多いときはスクリプト側で curl コマンドを呼び出すことが考えられます。ただし接続回数の制限には注意してください。

また、任意のアーティファクトだけ残すような処理も行っていません。この辺はマニュアルや `artifacts.json` を読んで個別に対応してください。

その他

今は解決しましたが、昨日までは Windows の CI スクリプトの最初の cmake が `C:\Users\RUNNER~1\AppData\Local\Temp` とだけ出力して止まっていました。この問題は GitHub Actions では VST 3 SDK のデフォルトのインストールパスである `C:/Program Files/Common Files/VST3` を作成できないことが原因だったようです。上のスクリプトでは適当なディレクトリ `target` を作って cmake のオプションから `SMTG_PLUGIN_TARGET_PATH` に設定するというワークアラウンドを使っています。

ここからは解決策が見つかるまでの道のりを書いています。まずは "github actions cmake C:\Users\RUNNER~1\AppData\Local\Temp" でグーグル検索したところ以下の issue が出てきました。

%TEMP% is broken on Windows · Issue #712 · actions/virtual-environments · GitHub

この issue に書いてあるワークアラウンドを試しても問題が解決しなかったので、 `vst3sdk/cmake` ディレクトリ内で "TEMP" という文字列を検索したところ SMTG_Platform_Windows.cmake が引っかかりました。 SMTG_Platform_Windows.cmake の中に唯一書いてある関数 "smtg_create_directory_as_admin_win" でもう一度 `vst3sdk/cmake` 内を検索したところ SMTG_AddVST3Options.cmake の以下の行が引っかかりました。

if(SMTG_WIN)
    smtg_create_directory_as_admin_win (${SMTG_PLUGIN_TARGET_PATH})
else()

ここでようやく SMTG_PLUGIN_TARGET_PATH が原因になっていそうなことが分かりました。

2020/11/20

トゥルーピークの計算

 

トゥルーピークの計算を読む (github.io)

ITU-R BS.1770 で触れられているトゥルーピークの計算について調べました。いろいろな分数ディレイフィルタを試したところ、以前に調べた群遅延が平坦になるように凸最適化によって設計した FIR フィルタを使うと良さそうなことがわかりました。

画像は今回設計した FIR の分数ディレイフィルタの特性です。 Sinc 補間と比べたときの誤差は BS.1770 の Annex 2 に掲載されているフィルタと同程度ですが、フィルタのタップ数が 7 なので、より速く計算できます。

EBU TECH 3341 に掲載されているトゥルーピークのテストを通ればいいだけならフィルタのタップ数は 5 まで減らせます。

2020/10/15

ステップ応答が S 字を描くフィルタ

ステップ応答が S 字を描くフィルタを読む (github.io)

リミッタのエンベロープのスムーシングに使うためにステップ応答が S 次を描くフィルタについて調べました。移動平均の重ね掛け、バイリニア変換した Bessel フィルタ、 Thiran ローパスフィルタを比べています。画像は 3 つのフィルタのステップ応答です。

S 字のステップ応答にこだわったのは、リミッタのエンベロープが矩形波に近い波形になったときでもサイン波に近い波形にスムーシングできるような気がしたからです。

2020/08/19

CollidingCombSynth


ダウンロードとマニュアル (github.io)
ソースコード (github.com)

CollidingCombSynth は Karplus-Strong アルゴリズムによる弦 (K-S弦) をぶつけ合うというアイデアに基づいた実験的なシンセサイザです。たまに擦弦楽器のような音が出ます。

以前に作った KSCymbal を元にしています。

弦の衝突の実装はかなり適当です。まず隣り合う 2 つの K-S 弦の出力の差をとって、ユーザが指定した弦と弦の間の距離 (distance パラメータ) を超えているかどうかを判定します。出力の差が距離を超えているときは、出力の差と距離の間でさらに差をとって次の入力に足し合わせています。

今回の実装では、一方の K-S 弦から、もう一方の K-S 弦だけに衝撃が伝わるので、オシレータシンクのような挙動をします。衝撃を伝える側の弦は一定の周期で距離を縮めるのに対して、衝撃を伝えられる側の弦は自身の周期によらず距離が縮まる影響を受けるからです。

衝撃は UI 上の表記で言うと Strings -> Frequency の 0 から 23 に向かって伝わります。

2020/06/04

L4Reverb


ダウンロードとマニュアル (github.io)
ソースコード (github.com)

L4Reverb は格子構造を使ったステレオリバーブです。

LatticeReverb と比べると 1 チャンネルあたりのディレイの数が 16 から 256 に増えています。また LatticeReverb では 16 セクションの格子構造が 1 つだけでしたが、 L4Reverb は 4 セクションの格子構造が 4 重の入れ子になっています (4 * 4 * 4 * 4 = 256) 。

ローパスフィルタを使っていないので、明るく長いリバーブが得意です。ショートリバーブは金属的な質感になることが多いです。ここでの金属的な質感とはショートディレイをたくさんつないだときのような音を指しています。