Нейтон SDK - это инструмент для исследователей, который позволяет им обернуть свои собственные аудио -модели и запускать их в DAW, используя наш плагин с нейтоном. Мы предлагаем функциональность как для загрузки моделей локально в плагин, так и для их вклад в список моделей по умолчанию, которые доступны для всех, кто работает за плагином. Мы надеемся, что это позволит исследователям легко попробовать свои модели в DAW, но также предоставит создателям коллекцию интересных моделей.
Juce является отраслевым стандартом для создания аудио плагинов. Из -за этого необходимо знание C ++, чтобы иметь возможность создавать даже очень простые аудио плагины. Тем не менее, исследователи из ИИ редко имеют обширный опыт работы с C ++ и иметь возможность создавать такой плагин. Более того, это серьезные инвестиции времени, которые можно потратить на разработку лучших алгоритмов. Neutone позволяет создавать модели, используя знакомые инструменты, такие как Pytorch, и с минимальным количеством кода Python, обертывая эти модели, чтобы их можно было выполнять с помощью плагина Neutone. Получение модели и запуска внутри DAW может быть сделано менее чем за день без необходимости в коде C ++ или знаниях.
SDK обеспечивает поддержку автоматической буферизации входов и выходов в вашу модель и скорость дискретизации на лету и преобразование стереомоно. Он позволяет выполнять модель, которая может быть выполнена только с предопределенным количеством образцов, которые будут использоваться в DAW с любой скоростью отбора проб и любого размера буфера. Кроме того, в рамках инструментов SDK для сравнительного анализа и профилирования легко доступны, чтобы вы могли легко отлаживать и проверить производительность своих моделей.
Вы можете установить neutone_sdk с помощью PIP:
pip install neutone_sdk
Нейтонский плагин доступен по адресу https://neutone.space. В настоящее время мы предлагаем плагины VST3 и AU, которые можно использовать для загрузки моделей, созданных с помощью этой SDK. Пожалуйста, посетите веб -сайт для получения дополнительной информации.
Если вы просто хотите обернуть модель, не просматривая подробное описание того, что все мы подготовили эти примеры для вас.
SDK обеспечивает функциональность для обертывания существующих моделей Pytorch таким образом, чтобы они могли сделать их исполняемыми в плагина VST. В своем ядре плагин отправляет кусочки образцов аудио с определенной скоростью дискретизации в качестве входа и ожидает одинакового количества выборок на выходе. Пользователь SDK может указать, какой скорость дискретизации (ы) и размер буфера (ы) их модели работают оптимально. Затем SDK гарантирует, что прямой проход модели будет получать аудио в одной из этих комбинаций (sample_rate, buffer_size). Доступны четыре ручки, которые позволяют пользователям плагина подавать дополнительные параметры для модели во время выполнения. Они могут быть включены или отключены по мере необходимости через SDK.
Используя включенную функцию экспорта, серия тестов автоматически выполняется, чтобы гарантировать, что модели ведут себя так же, как и ожидалось, и готовы к загрузке плагином.
Бенчмаркинг и профилирование инструментов CLI доступны для дальнейшей отладки и тестирования обернутых моделей. Можно сравнить скорость и задержку модели на диапазоне моделируемых комбинаций Common DAW (образец_Рате, buffere_size), а также профилировать память и использование ЦП.
Мы предоставляем несколько моделей в каталоге примеров. Мы пройдем одну из самых простых моделей, модель искажения, чтобы проиллюстрировать.
Предположим, что у нас есть следующая модель Pytorch. Параметры будут рассмотрены позже, мы сейчас сосредоточимся на входах и выходах. Предположим, что эта модель получает тензор формы (2, buffer_size) в качестве входа, где 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, простая обертка, которую мы можем написать, - это подклассный базовый базовый базовый базовый.
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 вернет моно -тензор (форма (1, buffer_size) ), который затем будет дублироваться по обоим каналам на выходе VST. Это делается в SDK, чтобы избежать ненужных распределений памяти во время каждого прохода.
get_native_sample_rates и get_native_buffer_sizes можно использовать для указания любых предпочтительных скоростей дискретизации или размеров буферов. В большинстве случаев они должны иметь только один элемент, но для более сложных моделей обеспечивается дополнительная гибкость. В случае, если будут предоставлены несколько вариантов, SDK попытается найти лучший для текущего настройки DAW. Всякий раз, когда скорость дискретизации или размер буфера отличается от одной из DAW, запускается автоматически обертка, которая преобразуется в правильную скорость выборки или реализует очередь FIFO для запрошенного размера буфера или обоих. Это понесет небольшой штраф за производительность и добавит некоторую задержку. В случае, если модель совместима с любой скоростью дискретизации и/или размером буфера, эти списки могут быть пустыми.
Это означает, что тензор x в методе do_forward_pass гарантированно имеет форму (1 if is_input_mono else 2, buffer_size) , где buffer_size будет выбран во время выполнения из списка, указанного в методе get_native_buffer_sizes . Тенсор x также будет находиться на одной из скоростей отбора проб из списка, указанного в методе get_native_sample_rates .
Мы предоставляем вспомогательную функцию save_neutone_model , которая сохраняет модели на диск. По умолчанию это будет конвертировать модели в TorchScript и запустить их через серию чеков, чтобы убедиться, что они могут быть загружены плагином. Полученный файл model.nm может быть загружен в плагин, используя кнопку load your own . Прочитайте ниже, чтобы отправить модели в коллекцию по умолчанию, видимые для всех, используя плагин.
Для моделей, которые могут использовать сигналы кондиционирования, мы в настоящее время предоставляем четыре параметра настраиваемой ручки. Внутри 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 может использоваться для переопределения метода агрегации. См. Полный файл экспорта Clipper для примера сохранения этой гранулярности.
Некоторые звуковые модели задержит аудио для определенного количества образцов. Это зависит от архитектуры каждой конкретной модели. Для того, чтобы влажный и сухой сигнал, который проходит через плагин, чтобы быть выровненными, пользователи должны сообщать, сколько выборок задержки индуцирует их модель. calc_model_delay_samples можно использовать для указания количества образцов задержки. В среднем модели Rave имеют один буфер задержки (2048 образцов), который статически сообщается в методе calc_model_delay_samples и можно увидеть в примерах. Модели, реализованные с помощью перекрытия, будут иметь задержку, равную количеству выборок, используемых для перекрестного фарма, как видно в обертке модели DeMUCS или примере спектрального фильтра.
Расчет задержки, которую добавляет ваша модель, может быть трудным, тем более что может быть несколько различных источников задержки, которые необходимо объединить (например, задержка с касфейдированием, задержка фильтра, задержка буфера на лайнере и / или нейронные сети, обученные безоцененному сухому и влажному звуку) Полем Стоит потратить дополнительное время на тестирование модели в вашей DAW, чтобы убедиться, что задержка сообщается правильно.
Добавление буфера LookBehind в вашу модель может быть полезно для моделей, которые требуют определенного количества дополнительного контекста для вывода полезных результатов. Буфер Lookbehind может быть включен легко, указав, сколько образцов Lookbehind вам нужно в методе get_look_behind_samples . Когда этот метод возвращает число больше нуля, метод do_forward_pass всегда будет получать тензор формы (in_n_ch, look_behind_samples + buffer_size) , но должен вернуть тензор формы (out_n_ch, buffer_size) последних образцов.
Мы рекомендуем избегать использования буфера-подразделения, когда это возможно, поскольку он делает вашу модель менее эффективной и может привести к потраченным впустую вычислениям во время каждого прямого прохода. При использовании чисто сверточной модели попробуйте переключить все сверкания на кэшированные свертыватели вместо этого.
Модели искусственного интеллекта обычно действуют неожиданно, когда они представляются с вкладами за пределами того, что присутствует в их обучающем распределении. Мы предоставляем серию общих фильтров (низкий бас, высокий проход, полосовый проход, полосовая остановка) в файле Neutone_sdk/filters.py. Они могут быть использованы во время прямого прохода, чтобы ограничить домен входов, входящих в модель. Некоторые из них могут вызвать небольшой объем задержки, ознакомьтесь с примерами/exater_clipper_prefilter.py File, чтобы получить простой пример того, как настроить фильтр.
Плагин содержит список моделей по умолчанию, направленных на создателей, которые хотят использовать их в ходе творческого процесса. Мы призываем пользователей представлять свои модели, как только они довольны результатами, которые они получают, чтобы их можно было использовать сообществом в целом. Для представления нам требуются дополнительные метаданные, которые будут использоваться для отображения информации о модели, предназначенной как для создателей, так и для других исследователей. Это будет отображаться как на веб -сайте Neutone, так и внутри плагина.
Пропустив предыдущую модель Clipper, вот более реалистичный пример, основанный на случайной модели Overdrive TCN, вдохновленной Micro-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, а также случайную модель перегрузки на веб -сайте и в плагине, чтобы понять, где будет отображаться каждое поле.
Чтобы отправить модель, откройте проблему в репозитории GitHub. Нам в настоящее время нужно следующее:
model.nm , выведенный функцией вспомогательной save_neutone_model SDK предоставляет три инструмента 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/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. Общая задержка разделена на задержку буферизации и задержку модели. Задержка модели сообщается создателем модели в модельной обертке, как объяснено выше. Задержка буферизации автоматически вычисляется SDK с учетом комбинации (sample_rate, buffer_size) указанной оберткой (нативными) и указанной DAW во время выполнения. Запуск модели в его нативной комбинации (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.
Инструмент профилирования запустит модель с частотой дискретизации 48000 и размером буфера 128 под профилировщиком пирога (по группе функциональных вызовов). Это может быть использовано для идентификации узких мест в вашем коде модели (даже в модельном вызове в вызове do_forward_pass ).
Подобно сравнительному сравнению, его можно запустить с различными комбинациями скоростей дискретистов и размеров буфера, а также различного количества потоков. Запустите python -m neutone_sdk.benchmark profile --help для получения дополнительной информации.
Мы приветствуем любой вклад в SDK. Пожалуйста, добавьте типы везде, где это возможно, и используйте black форматер для читаемости.
Нынешняя дорожная карта:
Проект Audacitorch был основным вдохновением для развития SDK. Проверьте это здесь