Das NEGONE SDK ist ein Werkzeug für Forscher, mit dem sie ihre eigenen Audiomodelle einwickeln und mit unserem Neuton -Plugin in einer DAW ausführen können. Wir bieten Funktionen für sowohl das Laden der Modelle lokal im Plugin als auch für die Standardliste der Modelle, die für alle verfügbar sind, die das Plugin ausführen. Wir hoffen, dass dies den Forschern es ermöglichen wird, ihre Modelle problemlos in einer DAW auszuprobieren, aber auch die Ersteller eine Sammlung interessanter Modelle zur Verfügung stellen.
Juce ist der Branchenstandard für den Aufbau von Audio -Plugins. Aus diesem Grund ist Kenntnis von C ++ erforderlich, um auch sehr einfache Audio -Plugins erstellen zu können. Es ist jedoch selten, dass KI -Audioforscher umfangreiche Erfahrung mit C ++ haben und ein solches Plugin erstellen können. Darüber hinaus ist es eine ernsthafte Zeitinvestition, die für die Entwicklung besserer Algorithmen ausgegeben werden könnte. Neutone ermöglicht es, Modelle mit bekannten Tools wie Pytorch und mit nur einer minimalen Menge an Python -Code zu erstellen, die diese Modelle so umwickeln, dass sie vom Neutone -Plugin ausgeführt werden können. Ein Modell in eine DAW zu bringen, kann in weniger als einem Tag ohne C ++ - Code oder Wissen erforderlich sein.
Das SDK unterstützt die automatische Pufferung von Eingängen und Ausgängen für Ihr Modell sowie die Probenrate und die Stereo-Mono-Konvertierung in der Fliege. Es ermöglicht ein Modell, das nur mit einer vordefinierten Anzahl von Stichproben in der DAW in jeder Stichprobenrate und jeder Puffergröße nahtlos in der DAW verwendet werden kann. Darüber hinaus sind innerhalb der SDK -Tools für Benchmarking und Profiling leicht verfügbar, sodass Sie die Leistung Ihrer Modelle problemlos debuggen und testen können.
Sie können neutone_sdk mit PIP installieren:
pip install neutone_sdk
Das Neutone -Plugin ist unter https://neutone.space erhältlich. Wir bieten derzeit VST3- und Au -Plugins an, mit denen die mit diesem SDK erstellten Modelle geladen werden können. Bitte besuchen Sie die Website für weitere Informationen.
Wenn Sie nur ein Modell einwickeln möchten, ohne eine detaillierte Beschreibung dessen zu durchlaufen, was alles tut, haben wir diese Beispiele für Sie vorbereitet.
Das SDK bietet Funktionen für das Einwickeln vorhandener Pytorch -Modelle auf eine Weise, die sie im VST -Plugin ausführbar machen kann. Im Kern sendet das Plugin die Stücke von Audio -Proben mit einer bestimmten Stichprobenrate als Eingabe und erwartet die gleiche Menge an Proben am Ausgang. Der Benutzer des SDK kann angeben, welche Beispielrate (en) und Puffergröße (en) ihre Modelle optimal abschneiden. Der SDK garantiert dann, dass der Vorwärtspass des Modells in einer dieser (Sample_Rate, Buffer_Size) -Kombinationen Audio erhält. Es stehen vier Knöpfe zur Verfügung, mit denen die Benutzer des Plugins zur Laufzeit zusätzliche Parameter zum Modell einfügen können. Sie können nach Bedarf über das SDK aktiviert oder deaktiviert werden.
Mit der mitgelieferten Exportfunktion wird automatisch eine Reihe von Tests ausgeführt, um sicherzustellen, dass sich die Modelle wie erwartet verhalten und vom Plugin geladen werden können.
Benchmarking- und Profiling -CLI -Tools finden Sie für ein weiteres Debuggen und Testen von Wickelmodellen. Es ist möglich, die Geschwindigkeit und Latenz eines Modells auf einem Bereich der simulierten gemeinsamen DAW (Sample_Rate, Buffer_size) -Kombinationen sowie das Profil der Speicher- und CPU -Verwendung zu verhindern.
Wir bieten mehrere Modelle im Beispielverzeichnis. Wir werden eines der einfachsten Modelle, ein Verzerrungsmodell, durchlaufen, um zu veranschaulichen.
Angenommen, wir haben das folgende Pytorch -Modell. Die Parameter werden später abgedeckt. Wir werden uns vorerst auf die Eingänge und Ausgänge konzentrieren. Angenommen, dieses Modell empfängt einen Tensor der Form (2, buffer_size) als Eingabe, bei dem buffer_size ein Parameter ist, der angegeben werden kann.
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 )Um dies in der VST zu führen, können Sie die einfachste Wrapper, die wir schreiben können, durch die Unterklasse der BaseClass der Wellenformtowaveformbase besteht.
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 Die Methode, die den größten Teil der Arbeit erledigt, ist do_forward_pass . In diesem Fall ist es nur ein einfaches Durchgang, aber wir werden es verwenden, um die Parameter später zu verarbeiten.
Standardmäßig wird der VST als stereo-stereo ausgeführt, aber wenn Mono für das Modell erwünscht ist, können wir die SDK is_input_mono und is_output_mono verwenden und die Eingänge und Ausgänge automatisch konvertiert werden. Wenn is_input_mono ein gemittelter (1, buffer_size) geformter Tensor umgeschaltet ist, wird als Eingabe anstelle von (2, buffer_size) übergeben. Wenn is_output_mono umgeschaltet ist, wird erwartet, dass do_forward_pass einen Mono -Tensor (Form (1, buffer_size) ) zurückgibt, der dann über beide Kanäle am Ausgang der VST dupliziert wird. Dies geschieht innerhalb des SDK, um unnötige Speicherzuweisungen während jedes Durchgangs zu vermeiden.
get_native_sample_rates und get_native_buffer_sizes kann verwendet werden, um alle bevorzugten Beispielraten oder Puffergrößen anzugeben. In den meisten Fällen wird erwartet, dass diese nur ein Element haben, aber für komplexere Modelle wird zusätzliche Flexibilität bereitgestellt. Falls mehrere Optionen bereitgestellt werden, versucht der SDK, das Beste für die aktuelle Einstellung der DAW zu finden. Immer wenn sich die Stichprobenrate oder die Puffergröße von der DAW unterscheidet, wird automatisch ein Wrapper ausgelöst, der in die richtige Abtastrate umwandelt oder eine FIFO -Warteschlange für die angeforderte Puffergröße oder beides implementiert. Dies führt zu einer geringen Leistungsstrafe und erhöht eine gewisse Verzögerung. Falls ein Modell mit jeder Stichprobenrate und/oder der Puffergröße kompatibel ist, können diese Listen leer gelassen werden.
Dies bedeutet, dass der Tensor x in der Methode do_forward_pass garantiert ist (1 if is_input_mono else 2, buffer_size) wobei buffer_size zur Laufzeit aus der in der Methode get_native_buffer_sizes bereitgestellten Liste ausgewählt wird. Der Tensor x befindet sich auch in einer der Stichprobenraten aus der in der Methode get_native_sample_rates angegebenen Liste.
Wir bieten eine save_neutone_model -HELPER -Funktion, mit der Modelle für die Festplatte gespeichert werden. Standardmäßig werden Modelle in Torchscript umwandelt und durch eine Reihe von Schecks ausgeführt, um sicherzustellen, dass sie vom Plugin geladen werden können. Die resultierende model.nm -Datei kann mit der Schaltfläche load your own im Plugin geladen werden. Lesen Sie unten, wie Sie Modelle an die Standardsammlung einreichen, die für alle verwendet werden, die das Plugin verwenden.
Für Modelle, die Konditionierungssignale verwenden können, liefern wir derzeit vier konfigurierbare Knopfparameter. Innerhalb des oben definierten ClipperModelWrapper können wir Folgendes einschließen:
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 Während des Vorwärtsgabers ist die Variable params wie folgt ein Wörterbuch wie folgt:
{
"min" : torch . Tensor ([ 0.5 ] * buffer_size ),
"max" : torch . Tensor ([ 1.0 ] * buffer_size ),
"gain" : torch . Tensor ([ 1.0 ] * buffer_size )
} Die Schlüssel des Wörterbuchs sind in der Funktion get_parameters angegeben.
Die Parameter nehmen immer Werte zwischen 0 und 1 und die Funktion do_forward_pass können verwendet werden, um die erforderliche Neu neu zu skalieren, bevor die interne Vorwärtsmethode des Modells ausgeführt wird.
Darüber hinaus werden die vom Plugin gesendeten Parameter auf einer Granularität der Probenebene eingesetzt. Standardmäßig nehmen wir den Mittelwert jedes Puffers ein und geben einen einzelnen Float (als Tensor) zurück, aber die aggregate_param -Methode kann verwendet werden, um die Aggregationsmethode zu überschreiben. In der vollständigen Clipper -Exportdatei finden Sie ein Beispiel für die Erhaltung dieser Granularität.
Einige Audiomodelle verzögern das Audio für eine bestimmte Anzahl von Proben. Dies hängt von der Architektur jedes bestimmten Modells ab. Damit das nasses und trockene Signal das Plugin durchläuft, um ausgerichtete Benutzer zu übermitteln, müssen Benutzer berichten, wie viele Stichproben der Verzögerung ihr Modell induzieren. Die calc_model_delay_samples können verwendet werden, um die Anzahl der Verzögerungsproben anzugeben. Rave -Modelle haben im Durchschnitt einen Verzögerungspuffer (2048 Proben), der statisch in der Methode calc_model_delay_samples kommuniziert wird und in den Beispielen zu sehen ist. Modelle mit Überlappungs-ADD haben eine Verzögerung, die der Anzahl der Proben entspricht, die für das Crossfading verwendet werden, wie im Demucs-Modellverpackung oder im Beispiel des Spektralfilters zu sehen ist.
Berechnung der Verzögerung, die Ihr Modell hinzugefügt hat, kann schwierig sein, zumal es mehrere verschiedene Verzögerungsquellen geben kann, die kombiniert werden müssen (z. B. Verzögerungsverzögerung der Filter, Verzögerung von Lookahead -Puffer und / oder neuronale Netzwerke, die auf nicht ausgerichteten trockenen und nassen Audio ausgebildet sind) . Es lohnt sich, zusätzliche Zeit damit zu verbringen, das Modell in Ihrer DAW zu testen, um sicherzustellen, dass die Verzögerung korrekt gemeldet wird.
Das Hinzufügen eines LookBehind -Puffers zu Ihrem Modell kann für Modelle nützlich sein, die einen bestimmten zusätzlichen Kontext erfordern, um nützliche Ergebnisse auszuführen. Ein LookBehind -Puffer kann leicht aktiviert werden, indem angibt, wie viele Proben von LookBehind Sie in der Methode get_look_behind_samples benötigen. Wenn diese Methode eine Zahl mehr als Null zurückgibt, empfängt die Methode do_forward_pass immer einen Tensor der Form (in_n_ch, look_behind_samples + buffer_size) , muss jedoch weiterhin einen Tensor der Form (out_n_ch, buffer_size) der neuesten Samples zurückgeben.
Wir empfehlen, wenn möglich ein Puffer zu verwenden, da Ihr Modell weniger effizient ist und während jedes Vorwärtspasses zu verschwendeten Berechnungen führen kann. Wenn Sie ein reines Faltungsmodell verwenden, wechseln Sie stattdessen alle Konvolutionen auf zwischengespeicherte Konvolutionen.
Es ist üblich, dass KI -Modelle auf unerwartete Weise handeln, wenn sie mit Eingaben außerhalb der in ihrer Trainingsverteilung vorhandenen Eingaben präsentiert werden. Wir bieten eine Reihe gemeinsamer Filter (niedriger Bass, Hochpass, Bandpass, Bandstopp) in der Datei neutone_sdk/filters.py. Diese können während des Vorwärtspasses verwendet werden, um die Domäne der Eingänge einzuschränken, die in das Modell eingehen. Einige von ihnen können eine kleine Verzögerung induzieren. Schauen Sie sich die Beispiele/Beispiel_Clipper_Prefilter.py -Datei an, um ein einfaches Beispiel zum Einrichten eines Filters zu erhalten.
Das Plugin enthält eine Standardliste von Modellen, die sich an Macher richten, die sie während ihres kreativen Prozesses verwenden möchten. Wir ermutigen Benutzer, ihre Modelle einzureichen, sobald sie mit den Ergebnissen zufrieden sind, damit sie von der Community insgesamt verwendet werden können. Für die Einreichung benötigen wir einige zusätzliche Metadaten, mit denen Informationen über das Modell sowohl für Ersteller als auch andere Forscher angezeigt werden. Dies wird sowohl auf der Neutone -Website als auch im Plugin angezeigt.
Wenn Sie das vorherige Clipper-Modell überspringen, ist hier ein realistischeres Beispiel, das auf einem zufälligen TCN-Overdrive-Modell basiert, das von Micro-TCN inspiriert ist.
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."Schauen Sie sich die Dokumentation der Methoden in Core.py sowie das zufällige Overdrive -Modell auf der Website und im Plugin an, um zu verstehen, wo jedes Feld angezeigt wird.
Um ein Modell einzureichen, öffnen Sie bitte ein Problem im Github -Repository. Wir brauchen derzeit Folgendes:
model.nm -Datei, der von der Funktion save_neutone_model HELPER ausgegeben wurde Das SDK bietet drei CLI -Tools, mit denen umgehickte Modelle debuggen und getestet werden können.
Beispiel:
$ 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]
Durch das Ausführen des Speed -Benchmarks werden zufällige Eingaben automatisch über das Modell mit einer Stichprobenrate von 48000 und Puffergrößen von (128, 256, 512, 1024, 2048) ausgeführt und melden die durchschnittliche Zeit, die zur Durchführung eines Puffers benötigt wurde. Daraus wird die 1/RTF berechnet, die darstellt, wie viel schneller das Modell ist. Wenn diese Zahl höher wird, verwendet das Modell weniger Ressourcen innerhalb der DAW. Es ist notwendig, dass diese Zahl größer als 1 ist, damit das Modell in Echtzeit auf dem Computer, auf dem der Benchmark ausgeführt wird, in Echtzeit ausgeführt werden kann.
Die Probenraten und Puffergrößen werden sowie die Häufigkeit des Benchmarks intern wiederholt, um die Durchschnittswerte zu berechnen, und die Anzahl der für die Berechnung verwendeten Threads sind als Parameter verfügbar. Führen Sie python -m neutone_sdk.benchmark benchmark-speed --help für weitere Informationen. Bei spezifizieren benutzerdefinierten Beispielraten oder Puffergrößen muss jeder einzelne einzeln an die CLI weitergegeben werden. Zum Beispiel: --sample_rate 48000 --sample_rate 44100 --buffer_size 32 --buffer_size 64 .
Während der Speed -Benchmark schnell sein sollte, da die Modelle im Allgemeinen in Echtzeit sind, ist es möglich, hängen zu bleiben, wenn das Modell zu langsam ist. Stellen Sie sicher, dass Sie eine angemessene Anzahl von Stichprobenraten und Puffergrößen für die Prüfung auswählen.
Beispiel:
$ 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) Durch Ausführen des Speed -Benchmarks berechnet automatisch die Latenz des Modells bei Kombinationen von sample_rate=(44100, 48000) und buffer_size=(128, 256, 512, 1024, 2048) . Dies gibt einen allgemeinen Überblick darüber, was für gemeinsame DAW -Einstellungen passieren wird. Die Gesamtverzögerung wird in Pufferverzögerung und Modellverzögerung unterteilt. Die Modellverzögerung wird vom Ersteller des Modells im Modellverpackung wie oben erläutert angegeben. Die Pufferverzögerung wird von der SDK automatisch berechnet, unter Berücksichtigung der Kombination von (sample_rate, buffer_size) die durch den Wrapper (die nativen) und die von der DAW zur Laufzeit angegebenen DAW angegeben sind. Das Ausführen des Modells in seiner nativen Kombination (sample_rate, buffer_size) entsteht eine minimale Verzögerung.
Ähnlich wie bei der oben genannten Geschwindigkeitsbenchmark können die getesteten Kombinationen von (sample_rate, buffer_size) aus der CLI angegeben werden. Führen Sie python -m neutone_sdk.benchmark benchmark-latency --help für weitere Informationen.
$ 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.
Das Profiling -Tool wird das Modell mit einer Stichprobenrate von 48000 und einer Puffergröße von 128 unter dem Pytorch -Profiler ausführen und eine Reihe von Erkenntnissen ausgeben, wie z. (pro Gruppe von Funktionsaufrufen). Dies kann verwendet werden, um Engpässe in Ihrem Modellcode zu identifizieren (auch innerhalb des Modellaufrufs im Aufruf do_forward_pass ).
Ähnlich wie beim Benchmarking kann es in verschiedenen Kombinationen von Stichprobenraten und Puffergrößen sowie in unterschiedlicher Anzahl von Fäden ausgeführt werden. Führen Sie python -m neutone_sdk.benchmark profile --help für weitere Informationen aus.
Wir begrüßen alle Beiträge zum SDK. Bitte fügen Sie nach Möglichkeit Typen hinzu und verwenden Sie das black Formatierer zur Lesbarkeit.
Die aktuelle Roadmap ist:
Das Audacitorch -Projekt war eine wichtige Inspiration für die Entwicklung des SDK. Schau es dir hier an