Советы и рекомендации по разработке плагинов

Чтобы написать свой алгоритм в качестве аудиоплагина, вы должны соответствовать API аудиоплагина. При создании аудиоплагинов в MATLAB® окружение, имейте в виду эти общие подводные камни и лучшие практики.

Чтобы узнать больше о аудиоплагинах в целом, смотрите Audio Plugins в MATLAB.

Избегайте срыва очереди событий в MATLAB

Когда Audio Test Bench запускает аудиоплагин, он последовательно:

  1. Вызывает метод сброса

  2. Устанавливает настраиваемые свойства, сопоставленные с параметрами

  3. Вызывает метод процесса

Во время выполнения Audio Test Bench вызывает в цикле метод процесса, а затем set методы для настроенных свойств. Плагин API не задает порядок установки настроенных свойств.

Возможно прервать установление времени для обычных методов путем прерывания очереди событий. Общие способы случайно прервать очередь событий включают использование plot или drawnow функция.

Примечание

plot и drawnow доступны только в среде MATLAB. plot и drawnow не может быть включен в сгенерированные плагины. Для получения дополнительной информации смотрите Отдельный код для функций, не поддерживаемых для генерации плагинов.

В следующем фрагменте кода коэффициент усиления, приложенный к левому и правому каналам, не совпадает, если связанный Gain параметр настраивается во время вызова для обработки:

...
L = plugin.Gain*in(:,1);
drawnow
R = plugin.Gain*in(:,2);
out = [L,R];
...

 См. Полный код

Автор прерывает очередь событий в фрагменте кода, вызывая set методы свойств, связанных с параметрами, которые будут вызываться в то время, когда метод процесса находится в середине выполнения.

В зависимости от вашего алгоритма обработки, прерывание очереди событий может привести к несогласованному и багги поведению. Кроме того, set метод может быть неявным, что может затруднить отслеживание проблемы. Возможные решения проблемы прерывания очереди событий включают сохранение свойств к локальным переменным и перемещение прерывания очереди в начало или конец метода процесса.

Сохраните свойства в локальные переменные

Вы можете сохранить значения настраиваемых свойств в локальных переменных в начале обработки. Этот метод гарантирует, что значения, используемые во время метода процесса, не обновляются в рамках одного вызова для обработки. Поскольку доступ к значению локальной переменной дешевле, чем к значению свойства, сохранение свойств к локальным переменным, к которым обращаются несколько раз, является наилучшей практикой.

...
gain = plugin.Gain;
L = gain*in(:,1);
drawnow
R = gain*in(:,2);
out = [L,R];
...

 См. Полный код

Перемещение прерывания очереди в нижнюю или верхнюю часть метода процесса

Можно переместить прерывание в очередь событий в нижнюю или верхнюю часть метода процесса. Этот метод гарантирует, что значения свойств не будут обновлены в середине вызова.

...
L = plugin.Gain*in(:,1);
R = plugin.Gain*in(:,2);
out = [L,R];
drawnow
...

 См. Полный код

Отдельный код для функций, не поддерживаемых для генерации плагинов

Окружение MATLAB предлагает функциональность, не поддерживаемую для генерации плагинов. Можно пометить код, который нужно игнорировать во время генерации плагина, поместив его внутрь условного оператора при помощи coder.target (MATLAB Coder).

...
    if coder.target('MATLAB')
    ...
    end
...
Если вы генерируете плагин используя generateAudioPlugin, код внутри оператора if coder.target('MATLAB') игнорируется.

Для примера, timescope не включен для генерации кода. Если вы запускаете следующий плагин в MATLAB, можно использовать функцию визуализации, чтобы открыть временные возможности, которая строит графики входа и выхода степени по системе координат.

 Смотрите Полный пример кода

Реализация сброса правильно

Распространенная ошибка при разработке аудио плагинов - неправильное использование метода сброса. Допустимое использование метода сброса включает:

  • Состояние выравнивания

  • Передача обратных вызовов для сброса к объектам компонента

  • Обновление свойств, которые зависят от частоты дискретизации

Недопустимое использование метода сброса включает в себя установку значения любых свойств, сопоставленных с параметрами. Не используйте метод сброса, чтобы задать свойства, сопоставленные с параметрами, их начальным условиям. Прямая установка свойства, сопоставленного с параметром, приводит к тому, что свойство не синхронизируется с параметром. Например, следующий плагин является примером неправильного использования метода сброса.

classdef badReset < audioPlugin
    properties
        Gain = 1;
    end
    properties (Constant)
        PluginInterface = audioPluginInterface(audioPluginParameter('Gain'));
    end
    methods
        function out = process(plugin,in)
            out = in*plugin.Gain;
        end
        function reset(plugin) % <-- Incorrect use of reset method.
            plugin.Gain = 1;   % <-- Never set values of a property that is
        end                    %     associated with a plugin parameter.
    end
end

Правильно реализуйте композицию плагина

Если ваш плагин состоит из других плагинов, то вы должны передать вниз частоту дискретизации и вызовы, чтобы сбросить к плагинам компонента. Функции setSampleRate в методе сброса, чтобы передать частоту дискретизации в плагины компонента. Чтобы настроить параметры плагинов компонента, создайте интерфейс аудиоплагина в составном плагине для настраиваемых параметров плагинов компонента. Затем передайте значения в set методы для связанных свойств. Ниже приведен пример композиции плагина, которая была сконструирована с использованием лучших практик.

 Композиция плагина с использованием базовых плагинов

Композиция плагина с использованием Системных объектов имеет эти ключевые различия от композиции плагина с использованием базовых плагинов.

  • Немедленный вызов setup на вашем компоненте System object™ после его создания. Конструкция и настройка объекта компонента происходит внутри конструктора составного плагина.

  • Если ваш компонент Системный объект требует информации о скорости дискретизации, то он имеет свойство частоты дискретизации. Установите свойство скорости дискретизации в методе сброса.

 Композиция плагина с использованием системных объектов

Адрес «Метод набора для свойства, не являющегося зависимым, не должен обращаться к другому свойству» Предупреждение в плагине

Рекомендуется подавлять предупреждение при разработке аудиоплагинов.

Следующий фрагмент кода следует лучшей практике разработки плагина для обработки изменений свойства параметра Cutoff.

classdef highpassFilter < audioPlugin
...
    properties (Constant)
        PluginInterface = audioPluginInterface( ...
            audioPluginParameter('Cutoff', ...
            'Label','Hz',...
            'Mapping',{'log',20,2000}));
    end
    methods
        function y = process(plugin,x)
            [y,plugin.State] = filter(plugin.B,plugin.A,x,plugin.State);
        end

        function set.Cutoff(plugin,val)
            plugin.Cutoff = val;
            [plugin.B,plugin.A] = highpassCoeffs(plugin,val,getSampleRate(plugin)); % <<<< warning occurs here
        end
    end
...
end

 См. пример полного кода

The highpassCoeffs функция может быть дорогостоящей и должна вызываться только при необходимости. Вы не хотите звонить highpassCoeffs в методе процесса, который запускается в цикле обработки аудио в реальном времени. Логическое место для вызова highpassCoeffs находится в set.Cutoff. Однако, mlint показывает предупреждение для этой практики. Предупреждение призвано помочь вам избежать проблем с порядком инициализации при сохранении и загрузке классов. Дополнительные сведения см. в разделе «Избегайте зависимости порядка инициализации свойств». Решение, рекомендуемое предупреждением, состоит в том, чтобы создать зависимое свойство с get метод и вычислите значение там. Однако выполнение рекомендации усложняет проект и отталкивает расчет назад в метод обработки в реальном времени, которого вы пытаетесь избежать.

Вы также можете понести предупреждение при правильной реализации композиции плагина. Для примера правильной реализации композиции смотрите Реализуйте Композицию плагина Правильно.

Используйте системный объект, который не поддерживает сигналы переменного размера

Для API аудиоплагина требуются аудиоплагины для поддержки входов и выходов переменного размера. Для получения частичного списка системных объектов, которые поддерживают сигналы переменного размера, смотрите Объекты системы DSP поддержки сигнала переменного размера. Вы можете столкнуться с проблемами, если попытаетесь использовать объекты, которые не поддерживают сигналы переменного размера в плагине.

Для примера, dsp.AnalyticSignal не поддерживает сигналы переменного размера. The BrokenAnalyticSignalTransformer плагин использует dsp.AnalyticSignal объект неправильно и не работает validateAudioPlugin испытательный стенд:

validateAudioPlugin BrokenAnalyticSignalTransformer
Checking plug-in class 'BrokenAnalyticSignalTransformer'... passed.
Generating testbench file 'testbench_BrokenAnalyticSignalTransformer.m'... done.
Running testbench... 
Error using dsp.AnalyticSignal/parenReference
Changing the size on input 1 is not allowed without first calling the release() method.

Error in BrokenAnalyticSignalTransformer/process (line 13)
                analyticSignal = plugin.Transformer(in);

Error in testbench_BrokenAnalyticSignalTransformer (line 61)
        o1 = process(plugin, in(:,1));

Error in validateAudioPlugin

 См. BrokenAnalyticSignalTransformer Код

Если вы хотите использовать функциональность Системного объекта, которая не поддерживает сигналы переменного размера, можно буферизировать вход и выход Системного объекта или всегда вызывать объект с помощью одной выборки.

Всегда вызывайте объект с одной выборкой

Вы можете создать цикл вокруг вашего вызова объекта. Цикл итератирует количество выборок в вашем переменном формате кадра. Вызов объекта в цикле всегда является одной выборкой.

 См. пример полного кода

Примечание

В зависимости от вашей реализации и конкретного объекта, вызов выборки объектов по выборкам в цикле может привести к значительным вычислительным затратам.

Буферный вход и выход объекта

Можно буферизировать вход к объекту до допустимого формата кадра, а затем буферизировать выход вашего объекта до исходного формата кадра. The dsp.AsyncBuffer Системный объект хорошо подходит для этой задачи.

 См. пример полного кода

Примечание

Использование объекта асинхронной буферизации приводит к минимальной задержке вашего заданного формата кадра.

Использование отображения параметров перечисления

Часто полезно связать свойство с набором строк или векторов символов. Однако ограничения на генерацию плагинов требуют, чтобы кэшированные значения, такие как значения свойств, имели статический размер. Чтобы обойти эту проблему, можно использовать отдельный класс перечисления, который сопоставляет строки с перечислениями, как описано в audioPluginParameter документация.

Кроме того, если вы хотите избежать записи класса перечисления и сохранить весь ваш код в одном файле, можно использовать зависимое свойство, чтобы сопоставить имена параметров с множеством значений. В этом сценарии значение перечисления сопоставляется со значением, которое можно кэшировать.

 См. пример полного кода

Похожие темы