Neutone SDKは、研究者が独自のオーディオモデルをラップし、Neutoneプラグインを使用してDAWで実行できるようにするためのツールです。プラグインにモデルをローカルにロードし、プラグインを実行している人が利用できるモデルのデフォルトリストに貢献する両方の機能を提供します。これにより、研究者がDAWでモデルを簡単に試すことができることを願っていますが、クリエイターに興味深いモデルのコレクションを提供します。
Juceは、オーディオプラグインを構築するための業界標準です。このため、非常にシンプルなオーディオプラグインも構築できるようにするには、C ++の知識が必要です。ただし、AIオーディオ研究者がC ++で豊富な経験を持ち、そのようなプラグインを構築できることはまれです。さらに、より良いアルゴリズムの開発に費やすことができる深刻な時間投資です。 Neutoneを使用すると、Pytorchなどの馴染みのあるツールを使用してモデルを構築し、Pythonコードを最小限の量のPythonコードラップで構築して、Neutoneプラグインで実行できるようにします。 DAW内でモデルを起動して実行することは、C ++コードや知識を必要とせずに1日以内に実行できます。
SDKは、モデルへの入力と出力の自動バッファリング、およびオンザフライサンプルレートとステレオモノ変換のサポートを提供します。これにより、定義された数のサンプルでのみ実行できるモデルが、任意のサンプリングレートとバッファサイズでシームレスに使用される可能性があります。さらに、ベンチマークとプロファイリング用のSDKツール内はすぐに利用でき、モデルのパフォーマンスを簡単にデバッグしてテストできます。
PIPを使用してneutone_sdkをインストールできます。
pip install neutone_sdk
Neutoneプラグインはhttps://neutone.spaceで入手できます。現在、このSDKで作成されたモデルをロードするために使用できるVST3およびAUプラグインを提供しています。詳細については、ウェブサイトをご覧ください。
これらの例を準備していることを詳細に説明せずにモデルをラップしたい場合。
SDKは、VSTプラグイン内で実行可能にすることができる方法で既存のPytorchモデルをラッピングする機能を提供します。そのコアでは、プラグインは特定のサンプルレートでオーディオサンプルのチャンクを入力として送信しており、出力で同じ量のサンプルを期待しています。 SDKのユーザーは、モデルが最適に機能するサンプルレートとバッファサイズを指定できます。 SDKは、モデルのフォワードパスがこれらの1つ(sample_rate、buffer_size)の組み合わせでオーディオを受信することを保証します。プラグインのユーザーが実行時にモデルに追加のパラメーターをフィードできるようにする4つのノブが利用可能です。 SDKを介して必要に応じて有効または無効にすることができます。
含まれたエクスポート機能を使用して、一連のテストが自動的に実行され、モデルが期待どおりに動作するようにし、プラグインによってロードされる準備ができています。
ベンチマークとプロファイリングCLIツールは、ラップモデルのさらなるデバッグとテストに利用できます。シミュレートされた共通DAW(sample_rate、buffere_size)の組み合わせの範囲でモデルの速度とレイテンシをベンチマークし、メモリとCPUの使用をプロファイルすることができます。
例ディレクトリにいくつかのモデルを提供します。説明するために、最も単純なモデルの1つである歪みモデルを使用します。
次のPytorchモデルがあると仮定します。パラメーターは後でカバーされ、今のところ入力と出力に焦点を当てます。このモデルは、 buffer_size指定できるパラメーターである入力として、形状のテンソル(2, buffer_size)を受け取ると仮定します。
class ClipperModel ( nn . Module ):
def forward ( self , x : Tensor , min_val : float , max_val : float , gain : float ) -> Tensor :
return torch . clip ( x , min = min_val * gain , max = max_val * gain )これをVST内で実行するために、私たちが書くことができる最も単純なラッパーは、WaveformTowaveFormBase Baseclassをサブクラス化することです。
class ClipperModelWrapper ( WaveformToWaveformBase ):
@ torch . jit . export
def is_input_mono ( self ) -> bool :
return False
@ torch . jit . export
def is_output_mono ( self ) -> bool :
return False
@ torch . jit . export
def get_native_sample_rates ( self ) -> List [ int ]:
return [] # Supports all sample rates
@ torch . jit . export
def get_native_buffer_sizes ( self ) -> List [ int ]:
return [] # Supports all buffer sizes
def do_forward_pass ( self , x : Tensor , params : Dict [ str , Tensor ]) -> Tensor :
# ... Parameter unwrap logic
x = self . model . forward ( x , min_val , max_val , gain )
return xほとんどの作業を行う方法は、 do_forward_passです。この場合、それは単純なパススルーですが、後でパラメーターを処理するために使用します。
デフォルトではVSTはstereo-stereoとして実行されますが、モデルにMonoが必要な場合は、 is_input_monoおよびis_output_monoを使用してSDKを通知し、入力と出力を自動的に変換することができます。 is_input_monoが切り替えられた場合、平均化された(1, buffer_size)形状のテンソルは(2, buffer_size)ではなく入力として渡されます。 is_output_monoが切り替えられた場合、 do_forward_passモノテンソル(shape (1, buffer_size) )を返すと予想されます。これは、VSTの出力で両方のチャネルで複製されます。これは、各パス中の不要なメモリの割り当てを避けるために、SDK内で行われます。
get_native_sample_ratesおよびget_native_buffer_sizesを使用して、優先されるサンプルレートまたはバッファサイズを指定できます。ほとんどの場合、これらは1つの要素しかないと予想されますが、より複雑なモデルには特別な柔軟性が提供されます。複数のオプションが提供された場合、SDKはDAWの現在の設定に最適なオプションを見つけようとします。サンプルレートまたはバッファサイズがDAWの1つとは異なる場合はいつでも、ラッパーが自動的にトリガーされ、正しいサンプリングレートに変換されるか、要求されたバッファサイズまたはその両方のFIFOキューを実装します。これにより、パフォーマンスのペナルティが少なくなり、ある程度の遅延が追加されます。モデルが任意のサンプルレートおよび/またはバッファサイズと互換性がある場合、これらのリストは空のままにすることができます。
これは、 do_forward_passメソッドのテンソルx (1 if is_input_mono else 2, buffer_size) get_native_buffer_sizesメソッドで提供されているリストからbuffer_sizeが選択されます。テンソルx 、 get_native_sample_ratesメソッドで提供されるリストのサンプリングレートの1つでもあります。
モデルをディスクに保存するsave_neutone_modelヘルパー関数を提供します。デフォルトでは、これによりモデルをTorchScriptに変換し、一連のチェックを使用してプラグインでロードできることを確認します。結果のmodel.nmファイルはload your ownボタンを使用してプラグイン内にロードできます。プラグインを使用して、すべての人に見えるデフォルトコレクションにモデルを送信する方法については、以下をお読みください。
コンディショニング信号を使用できるモデルの場合、現在4つの構成可能なノブパラメーターを提供しています。上記のClipperModelWrapper内には、以下を含めることができます。
class ClipperModelWrapper ( WaveformToWaveformBase ):
...
def get_neutone_parameters ( self ) -> List [ NeutoneParameter ]:
return [ NeutoneParameter ( name = "min" , description = "min clip threshold" , default_value = 0.5 ),
NeutoneParameter ( name = "max" , description = "max clip threshold" , default_value = 1.0 ),
NeutoneParameter ( name = "gain" , description = "scale clip threshold" , default_value = 1.0 )]
def do_forward_pass ( self , x : Tensor , params : Dict [ str , Tensor ]) -> Tensor :
min_val , max_val , gain = params [ "min" ], params [ "max" ], params [ "gain" ]
x = self . model . forward ( x , min_val , max_val , gain )
return xフォワードパス中、 params変数は次のような辞書になります。
{
"min" : torch . Tensor ([ 0.5 ] * buffer_size ),
"max" : torch . Tensor ([ 1.0 ] * buffer_size ),
"gain" : torch . Tensor ([ 1.0 ] * buffer_size )
}辞書のキーは、 get_parameters関数で指定されています。
パラメーターは常に0と1の間の値を取得し、 do_forward_pass関数を使用して、モデルの内部フォワードメソッドを実行する前に必要な再スケーリングを行うことができます。
さらに、プラグインによって送信されたパラメーターは、サンプルレベルの粒度で入ります。デフォルトでは、各バッファーの平均を取得し、単一のフロート(テンソルとして)を返しますが、 aggregate_paramメソッドを使用して集約方法をオーバーライドできます。この粒度を保存する例については、完全なクリッパーエクスポートファイルを参照してください。
一部のオーディオモデルでは、一定量のサンプルに対してオーディオを遅らせます。これは、特定の各モデルのアーキテクチャに依存します。プラグインを通過しているウェットおよびドライの信号が整列されるためには、モデル誘導の遅延サンプルの数を報告するためにユーザーが必要です。 calc_model_delay_samples使用して、遅延のサンプル数を指定できます。 Raveモデルは、平均して、 calc_model_delay_samplesメソッドで静的に通信され、例で見ることができる遅延(2048サンプル)のバッファー(2048サンプル)を持っています。オーバーラップADDで実装されたモデルは、DEMUCSモデルラッパーまたはスペクトルフィルターの例で見られるように、クロスフェードに使用されるサンプルの数に等しい遅延があります。
特に、組み合わせる必要がある複数の異なる遅延ソースがある可能性があるため、モデルの追加の遅延を計算することは困難です(例:フィルター遅延、Lookaheadバッファー遅延、および /または整形のないドライおよびウェットオーディオでトレーニングされたニューラルネットワーク) 。遅延が正しく報告されていることを確認するために、DAWのモデルのテストに余分な時間を費やす価値があります。
Lookbehindバッファーをモデルに追加することは、有用な結果を出力するために一定量の追加コンテキストを必要とするモデルに役立ちます。 get_look_behind_samplesメソッドで必要なLookbehindのサンプルの数を示すことにより、LookBehindバッファーを簡単に有効にすることができます。このメソッドがゼロより大きい数を返す場合、 do_forward_passメソッドは常に形状(in_n_ch, look_behind_samples + buffer_size)のテンソルを受け取りますが、最新サンプルの形状(out_n_ch, buffer_size)のテンソルを返す必要があります。
モデルが効率が低下し、各フォワードパス中に無駄な計算をもたらす可能性があるため、見た目バッファーを使用することを避けることをお勧めします。純粋に畳み込みモデルを使用する場合は、代わりにすべての畳み込みをキャッシュされた畳み込みに切り替えてみてください。
AIモデルは、トレーニング分布に存在する入力の外側に提示された場合、予期せぬ方法で行動することが一般的です。 Neutone_sdk/filters.pyファイルに一連の共通フィルター(低バス、ハイパス、バンドパス、バンドストップ)を提供します。これらは、モデルに入る入力のドメインを制限するために、フォワードパス中に使用できます。それらのいくつかは、少量の遅延を誘導することができます。フィルターのセットアップ方法に関する簡単な例については、例/example_clipper_prefilter.pyファイルをチェックしてください。
プラグインには、創造的なプロセス中にそれらを利用したいクリエイターを対象としたモデルのデフォルトリストが含まれています。コミュニティ全体で使用できるように、結果に満足したら、ユーザーがモデルを提出することをお勧めします。提出には、作成者と他の研究者の両方を対象としたモデルに関する情報を表示するために使用される追加のメタデータが必要です。これは、Neutone Webサイトとプラグインの両方に表示されます。
以前のクリッパーモデルをスキップして、Micro-TCNに触発されたランダムTCNオーバードライブモデルに基づいたより現実的な例を次に示します。
class OverdriveModelWrapper ( WaveformToWaveformBase ):
def get_model_name ( self ) -> str :
return "conv1d-overdrive.random"
def get_model_authors ( self ) -> List [ str ]:
return [ "Nao Tokui" ]
def get_model_short_description ( self ) -> str :
return "Neural distortion/overdrive effect"
def get_model_long_description ( self ) -> str :
return "Neural distortion/overdrive effect through randomly initialized Convolutional Neural Network"
def get_technical_description ( self ) -> str :
return "Random distortion/overdrive effect through randomly initialized Temporal-1D-convolution layers. You'll get different types of distortion by re-initializing the weight or changing the activation function. Based on the idea proposed by Steinmetz et al."
def get_tags ( self ) -> List [ str ]:
return [ "distortion" , "overdrive" ]
def get_model_version ( self ) -> str :
return "1.0.0"
def is_experimental ( self ) -> bool :
return False
def get_technical_links ( self ) -> Dict [ str , str ]:
return {
"Paper" : "https://arxiv.org/abs/2010.04237" ,
"Code" : "https://github.com/csteinmetz1/ronn"
}
def get_citation ( self ) -> str :
return "Steinmetz, C. J., & Reiss, J. D. (2020). Randomized overdrive neural networks. arXiv preprint arXiv:2010.04237."Core.py内のメソッドのドキュメントと、Webサイトおよびプラグインのランダムオーバードライブモデルのドキュメントをチェックして、各フィールドがどこに表示されるかを理解してください。
モデルを送信するには、GitHubリポジトリで問題を開きます。現在、以下が必要です。
save_neutone_modelヘルパー関数によって出力されたmodel.nmファイルへのリンクSDKは、ラップされたモデルをデバッグおよびテストするために使用できる3つのCLIツールを提供します。
例:
$ python -m neutone_sdk.benchmark benchmark-speed --model_file model.nm
INFO:__main__:Running benchmark for buffer sizes (128, 256, 512, 1024, 2048) and sample rates (48000,). Outliers will be removed from the calculation of mean and std and displayed separately if existing.
INFO:__main__:Sample rate: 48000 | Buffer size: 128 | duration: 0.014±0.002 | 1/RTF: 5.520 | Outliers: [0.008]
INFO:__main__:Sample rate: 48000 | Buffer size: 256 | duration: 0.028±0.003 | 1/RTF: 5.817 | Outliers: []
INFO:__main__:Sample rate: 48000 | Buffer size: 512 | duration: 0.053±0.003 | 1/RTF: 6.024 | Outliers: []
INFO:__main__:Sample rate: 48000 | Buffer size: 1024 | duration: 0.106±0.000 | 1/RTF: 6.056 | Outliers: []
INFO:__main__:Sample rate: 48000 | Buffer size: 2048 | duration: 0.212±0.000 | 1/RTF: 6.035 | Outliers: [0.213]
速度ベンチマークを実行すると、サンプルレート48000およびバッファサイズ(128、256、512、1024、2048)のサンプルレートでモデルを介してランダム入力を自動的に実行し、1つのバッファーの推論を実行するのにかかった平均時間を報告します。このことから、モデルのリアルタイムよりも速いかを表す1/RTFが計算されます。この数値が高くなると、モデルはDAW内のリソースが少なくなります。モデルがベンチマークが実行されるマシンでリアルタイムで実行できるようにするには、この数値が1よりも大きくなる必要があります。
テスト対象のサンプルレートとバッファサイズ、およびベンチマークが内部的に繰り返される回数は、平均を計算し、計算に使用されるスレッドの数をパラメーターとして計算します。 python -m neutone_sdk.benchmark benchmark-speed --help実行してください。個々の個々のサイズをカスタムサンプルレートまたはバッファサイズを指定する場合、個別に渡す必要があります。例: --sample_rate 48000 --sample_rate 44100 --buffer_size 32 --buffer_size 64 。
モデルは一般的にリアルタイムである必要があるため、速度ベンチマークは高速である必要がありますが、モデルが遅すぎると止まることが可能です。テストするために、サンプルレートとバッファサイズの適用数を選択することを確認してください。
例:
$ python -m neutone_sdk.benchmark benchmark-latency model.nm
INFO:__main__:Native buffer sizes: [2048], Native sample rates: [48000]
INFO:__main__:Model exports/ravemodel/model.nm has the following delays for each sample rate / buffer size combination (lowest delay first):
INFO:__main__:Sample rate: 48000 | Buffer size: 2048 | Total delay: 0 | (Buffering delay: 0 | Model delay: 0)
INFO:__main__:Sample rate: 48000 | Buffer size: 1024 | Total delay: 1024 | (Buffering delay: 1024 | Model delay: 0)
INFO:__main__:Sample rate: 48000 | Buffer size: 512 | Total delay: 1536 | (Buffering delay: 1536 | Model delay: 0)
INFO:__main__:Sample rate: 48000 | Buffer size: 256 | Total delay: 1792 | (Buffering delay: 1792 | Model delay: 0)
INFO:__main__:Sample rate: 44100 | Buffer size: 128 | Total delay: 1920 | (Buffering delay: 1920 | Model delay: 0)
INFO:__main__:Sample rate: 48000 | Buffer size: 128 | Total delay: 1920 | (Buffering delay: 1920 | Model delay: 0)
INFO:__main__:Sample rate: 44100 | Buffer size: 256 | Total delay: 2048 | (Buffering delay: 2048 | Model delay: 0)
INFO:__main__:Sample rate: 44100 | Buffer size: 512 | Total delay: 2048 | (Buffering delay: 2048 | Model delay: 0)
INFO:__main__:Sample rate: 44100 | Buffer size: 1024 | Total delay: 2048 | (Buffering delay: 2048 | Model delay: 0)
INFO:__main__:Sample rate: 44100 | Buffer size: 2048 | Total delay: 2048 | (Buffering delay: 2048 | Model delay: 0)速度ベンチマークを実行するとsample_rate=(44100, 48000)とbuffer_size=(128, 256, 512, 1024, 2048)の組み合わせでモデルの遅延が自動的に計算されます。これにより、一般的なDAW設定で何が起こるかについての一般的な概要が得られます。総遅延は、バッファリング遅延とモデルの遅延に分割されます。モデルの遅延は、上記のようにモデルラッパーのモデルの作成者によって報告されます。バッファリング遅延は、ラッパー(ネイティブのもの)によって指定された(sample_rate, buffer_size)の組み合わせを考慮して、SDKによって自動的に計算されます。ネイティブ(sample_rate, buffer_size)の組み合わせでモデルを実行すると、最小の遅延が発生します。
上記の速度ベンチマークと同様に、 (sample_rate, buffer_size)のテストされた組み合わせをCLIから指定できます。 python -m neutone_sdk.benchmark benchmark-latency --help詳細については、ヘルプ。
$ python -m neutone_sdk.benchmark profile --model_file exports/ravemodel/model.nm
INFO:__main__:Profiling model exports/ravemodel/model.nm at sample rate 48000 and buffer size 128
STAGE:2023-09-28 14:34:53 96328:4714960 ActivityProfilerController.cpp:311] Completed Stage: Warm Up
30it [00:00, 37.32it/s]
STAGE:2023-09-28 14:34:54 96328:4714960 ActivityProfilerController.cpp:317] Completed Stage: Collection
STAGE:2023-09-28 14:34:54 96328:4714960 ActivityProfilerController.cpp:321] Completed Stage: Post Processing
INFO:__main__:Displaying Total CPU Time
INFO:__main__:-------------------------------- ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------
Name Self CPU % Self CPU CPU total % CPU total CPU time avg CPU Mem Self CPU Mem # of Calls
-------------------------------- ------------ ------------ ------------ ------------ ------------ ------------ ------------ ------------
forward 98.54% 799.982ms 102.06% 828.603ms 26.729ms 0 b -918.17 Kb 31
aten::convolution 0.12% 963.000us 0.95% 7.739ms 175.886us 530.62 Kb -143.50 Kb 44
...
...
Full output removed from GitHub.
プロファイリングツールは、Pytorch Profilerの下で48000のサンプルレートと128のバッファサイズでモデルを実行し、合計CPU時間、合計CPUメモリ使用(関数ごと)、グループ化されたCPUメモリ使用量などの一連の洞察を出力します。 (関数呼び出しのグループごと)。これを使用して、モデルコードでボトルネックを識別できます( do_forward_passコール内のモデルコール内であっても)。
ベンチマークと同様に、サンプルレートとバッファサイズのさまざまな組み合わせ、およびさまざまな数のスレッドで実行できます。詳細についてはpython -m neutone_sdk.benchmark profile --helpを実行します。
SDKへの貢献を歓迎します。可能な限りタイプを追加し、読みやすくするためにblackフォーマッタを使用してください。
現在のロードマップは次のとおりです。
Audacitorchプロジェクトは、SDKの開発の大きなインスピレーションでした。ここでそれをチェックしてください