exponenta event banner

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

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

Дополнительные сведения о аудиоплагинах в целом см. в разделе Аудиоплагины в MATLAB.

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

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

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

  2. Задает настраиваемые свойства, связанные с параметрами

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

Во время работы стенд аудиотестирования вызывает в цикле метод процесса, а затем 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).

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

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

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

Правильно выполнить сброс

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

  • Состояние очистки

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

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

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

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 на системном object™ компонента после его создания. Построение и настройка объекта-компонента происходит внутри конструктора составного плагина.

  • Если для объекта System компонента требуется информация о частоте дискретизации, он имеет свойство частоты дискретизации. Задайте свойство sample rate в методе сброса.

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

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

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

Следующий фрагмент кода соответствует передовой практике разработки плагинов для обработки изменений в свойствах параметров 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

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

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

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

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

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

Например, dsp.AnalyticSignal не поддерживает сигналы переменного размера. 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 Кодекс

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

Всегда вызывать объект с одним образцом

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

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

Примечание

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

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

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

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

Примечание

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

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

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

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

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

Связанные темы