Учебное руководство: создание простого модуля эффекта с универсальным представлением

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

Формат этой главы позволяет Вам завершить его успешно не считав любой предыдущий материал. Однако для понимания, что Вы делаете необходимо понять информацию в Основных принципах Разработки Аудиоустройства и Аудиоустройстве.

В частности для получения большинства из этой главы необходимо понять:

Обзор

«Простые» модули эффекта воздействуют на отдельные аудиосэмплы, не рассматривая отношения одного аудиосэмпла другому, и не используя буфер обработки. Вы создаете такой модуль эффекта в этой главе, далее упрощенной путем игнорирования некоторых усовершенствованных функций аудиоустройства: пользовательское представление и пользовательские свойства.

Простые модули эффекта могут сделать очень основной DSP, такой как:

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

Рисунок 5-1  Монофоническое тремоло
Monaural tremolo

Тремоло стерео подобно, но включает непрерывное левое/правильное панорамирование в низкой частоте.

В этой главе Вы разрабатываете и создаете монофонический эффект тремоло, использующий универсальное представление. Шаги, описанные подробно в следующих разделах:

  1. Установите комплект разработчика Core Audio, если Вы уже не сделали так.

  2. Выполните некоторую дизайнерскую работу, включая:

    • Укажите вид DSP, который выполнит Ваше аудиоустройство

    • Разработайте интерфейс параметра

    • Разработайте предварительно установленный интерфейс фабрики

    • Определите конфигурационную информацию для своего пакета аудиоустройства, такого как подтип и коды производителя и номер версии

  3. Создайте и сконфигурируйте проект XCode.

  4. Реализуйте свое аудиоустройство:

    • Реализуйте параметр и задайте интерфейсы.

    • Реализуйте обработку сигналов — основа Вашего аудиоустройства.

  5. Наконец, проверьте и протестируйте свое аудиоустройство.

Ваша среда разработки для создания любого аудиоустройства — простой или иначе — должна включать части, описанные под Требуемыми Инструментами для Разработки Аудиоустройства во Введении. Вы не должны посылать к документации XCode или Core Audio документацию SDK выполнить задачи в этой главе.

Установите комплект разработчика Core Audio

  1. Если Вы уже не сделали так, установите новый Core Audio SDK. Это - часть установки Инструментов XCode на OS X DVD. Можно также загрузить его с веб-сайта разработчика Apple в этом расположении:

    http://developer .apple.com/sdk/

    Core Audio установщик SDK помещает суперклассы C++, пример проекты XCode и документация в этом расположении в Вашей системе:

    /Developer/Examples/CoreAudio

    SDK также устанавливает шаблоны проекта XCode для аудиоустройств в этом расположении в Вашей системе:

    /Library/Application Support/Apple/Developer Tools/Project Templates/

  2. После установки SDK подтвердите, что XCode распознает шаблоны аудиоустройства, следующим образом:

    • Запустите XCode и затем выберите File> New Project.

    • В Окне помощника подтвердите, что существует группа Аудиоустройств.

    Рисунок 5-2  , Подтверждающий, что установлены шаблоны аудиоустройства
    Confirming that the audio unit templates are installed

    Подтвердив присутствие группы шаблона Audio Units, нажмите Cancel, и затем выйдите из XCode.

Укажите функцию своего аудиоустройства

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

Затем, выберите тип аудиоустройства на основе функции, которую выполнит аудиоустройство. Просмотрите различные типы стандартных аудиоустройств в AUComponent.h файл в платформе Аудиоустройства. Кроме того, обратитесь к описаниям типов в Спецификации Аудиоустройства. kAudioUnitType_Effect, с четырьмя кодами символа 'aufx', взгляды, надлежащие с этой целью.

Разработайте интерфейс параметра

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

Во-первых, укажите, который приписывает звук, Вы хотели бы, чтобы пользователь был в состоянии управлять. Для этого проекта используйте следующее:

Во-вторых, укажите для каждого параметра:

Следующие таблицы указывают проект параметра. Вы будете использовать большинство этих значений непосредственно в Вашем коде. Указание «Описания» для Вашего преимущества при разработке и расширении аудиоустройства. Можно снова использовать описание позже в онлайн-справке или руководстве пользователя.

Табличная 5-1  Спецификация параметра частоты тремоло

Атрибут параметра

Значение

Имя пользовательского интерфейса

Частота

Описание

Частота эффекта тремоло. Когда этот параметр устанавливается на 2 Гц, существует два цикла эффекта тремоло в секунду. Значение этого параметра непрерывно, таким образом, пользователь может установить любое значение в доступном диапазоне. Пользователь корректирует частоту тремоло с ползунком.

Программируемое имя

kTremolo_Frequency

Единица измерения

Гц

Минимальное значение

0.5

Максимальное значение

10.0

Значение по умолчанию

2.0

Табличная 5-2  Спецификация параметра глубины тремоло

Атрибут параметра

Значение

Имя пользовательского интерфейса

Глубина

Описание

Глубина или интенсивность, эффекта тремоло. Когда установлено в 0%, нет никакого эффекта тремоло. Когда установлено в 100%, эффект тремоло передвигается на каждый цикл от тишины до единичного усиления. Значение этого параметра непрерывно, таким образом, пользователь может установить любое значение в доступном диапазоне. Пользователь корректирует глубину тремоло с ползунком.

Программируемое имя

kTremolo_Depth

Единица измерения

Процент

Минимальное значение

0.0

Максимальное значение

100.0

Значение по умолчанию

50.0

Табличная 5-3  Спецификация параметра формы волны тремоло

Атрибут параметра

Значение

Имя пользовательского интерфейса

Форма волны

Описание

Форма волны, за которой следует эффект тремоло. Этот параметр может взять ряд дискретных значений. Пользователь выбирает форму волны тремоло из меню.

Программируемое имя

kTremolo_Waveform

Единица измерения

Индексируемый

одно значение

Синус

другое значение

Квадрат

Значение по умолчанию

Синус

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

Разработайте предварительные установки фабрики

Теперь, когда Вы указали параметры, можно указать интересные комбинации настроек или предварительных установок фабрики. Для модуля тремоло укажите две предварительных установки фабрики. Эти два, изобретенные для этого учебного руководства, обеспечивают два легко различимых эффекта:

Табличная 5-4  Спецификация Медленной и Нежной фабрики задается

Параметр

Значение

Имя пользовательского интерфейса

Медленный и Нежный

Описание

Нежное колебание

kTremolo_Frequency значение

2.0 Гц

kTremolo_Depth значение

50%

kTremolo_Waveform значение

Синус

Табличная 5-5  Спецификация Быстрой и Твердой фабрики задается

Параметр

Значение

Имя пользовательского интерфейса

Быстро и Трудно

Описание

Лихорадочный, ударный, и интенсивный

kTremolo_Frequency значение

20.0 Гц

kTremolo_Depth значение

90%

kTremolo_Waveform значение

Квадрат

Соберите конфигурационную информацию для пакета аудиоустройства

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

Установите свое название компании в XCode

Установите свое название компании в XCode (с XCode, не работающим), если Вы уже не сделали так. Введите следующую команду в Терминал на одной строке:

defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions '{ORGANIZATIONNAME = "Angry Audio";}'

Теперь, когда Вы установили это так называемое «опытное» предпочтение, XCode помещает имя Вашей компании в уведомление об авторском праве в исходных файлах любого нового проекта.

Создайте и сконфигурируйте проект

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

Запустите XCode и выполните эти шаги:

1. Выберите File> New Project

2. В Новом диалоговом окне Помощника проектного менеджера выберите шаблон Audio Unit Effect и нажмите Далее.

Choose the Xcode template for the project

3. Назовите TremoloUnit проекта и укажите каталог проекта. Тогда нажмите Finish.

../Art/project_name.jpg

XCode создает файлы проекта для Вашего аудиоустройства, и окно проекта XCode открывается.

В этой точке XCode использовал шаблонный файл проекта аудиоустройства для создания подкласса AUEffectBase класс. Ваш пользовательский подкласс называют согласно имени Вашего проекта. Можно найти файл реализации пользовательского подкласса, TremoloUnit.cpp, в Исходной группе AU в области Xcode Groups & Files, показанной затем.

../Art/project_window.jpg

На более поздних шагах Вы отредактируете методы в своем пользовательском подклассе для переопределения методов суперкласса. TremoloUnit.cpp также содержит несколько методов от AUKernelBase класс помощника; это методы, которые Вы позже изменяете для выполнения цифровой обработки сигналов.

4. С Исходной группой AU, открытой как показано на предыдущем шаге, щелкнуть TremoloUnitVersion.h. Тогда нажмите кнопку на панели инструментов Editor, при необходимости, для отображения текстового редактора. Существует три значения для настройки в этом файле: kTremoloUnitVersion, TremoloUnit_COMP_SUBTYPE, и TremoloUnit_COMP_MANF.

Прокрутите вниз в области редактирования к определениям TremoloUnit_COMP_SUBTYPE и TremoloUnit_COMP_MANF. Настройте поле подтипа с кодом подтипа с четырьмя символами, который Вы выбрали. В этом примере, 'tmlo' указывает (разработчикам и пользователям), что аудиоустройство позволяет пользователю добавить тремоло.

../Art/subtype_and_manuf.jpg

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

Теперь установите номер версии для аудиоустройства. В TremoloUnitVersion.h файл, чуть выше определений для подтипа и производителя, Вы будете видеть оператор определения для kTremoloUnitVersion постоянный. По умолчанию шаблон устанавливает значение этой константы в 1.0.0, как представлено шестнадцатеричным числом 0x00010000. Измените это, если Вам нравится. Посмотрите Идентификацию Аудиоустройства для того, как создать шестнадцатеричный номер версии.

Сохраните TremoloUnitVersion.h файл.

5. Щелкните TremoloUnit.r файл ресурсов в «Исходной группе» Источника/AU в области Groups & Files. Существует два значения для настройки в этом файле: NAME и DESCRIPTION.

Работать правильно с универсальным представлением, значением для NAME должен следовать за определенным образцом:

<company name>: <audio unit name>

Для этого примера используйте:

Angry Audio: Tremolo Unit

При установке названия компании с помощью предпочтения эксперта XCode, как описано ранее это будет уже существовать в NAME переменная для этого проекта; чтобы последовать этому примеру, все, что необходимо сделать, добавляет пространство между Тремоло и Модулем на само имя аудиоустройства.

Шаблон Xcode обеспечивает значение по умолчанию для DESCRIPTION. При настройке его сохраните его коротким так, чтобы строка работала хорошо со всплывающими меню. Данные показывают специализированное DESCRIPTION.

../Art/resource_file.jpg

Как Вы видите в числе, файл ресурсов использует a #include оператор для импорта заголовочного файла Версии, который Вы настроили на шаге 4, TremoloUnitVersion.h. Файл ресурсов использует значения от того заголовочного файла для определения некоторых переменных, таких как подтип компонента (COMP_SUBTYPE) и производитель (COMP_MANUF).

Сохраните TremoloUnit.r файл ресурсов.

6. Откройте группу Ресурсов в области Groups & Files в окне проекта XCode и щелкните InfoPlist.strings файл.

../Art/strings.jpg../Art/strings.jpg

Используя редактора, настройте значение для CFBundleGetInfoString с помощью значения Вы выбрали для описания резюме аудиоустройства. Число обеспечивает пример. Эта строка появляется в Поле версии окна Get Info пакета аудиоустройства в Средстве поиска. Сохраните InfoPlist.strings файл.

7. Откройте Целевую группу в области Groups & Files в окне проекта XCode. Дважды щелкните по пакету аудиоустройства, имеющему то же имя как Ваш проект — в этом случае, TremoloUnit.

../Art/target.jpg

Окно Target Info открывается. Щелкните по вкладке Properties.

../Art/target_info.jpg

На вкладке Properties окна Target Info обеспечьте значения для Идентификатора, Создателя, Версии, и, дополнительно, пути к файлу значка Средства поиска для пакета, который Вы помещаете в пакет Resources папка.

Поле идентификатора пакета аудиоустройства должно следовать за образцом:

com.<company_name>.audiounit.<audio_unit_name>

Для этого примера используйте идентификатор:

com.angryaudio.audiounit.TremoloUnit

Для значения Создателя используйте ту же четыре символьных строки, используемые для поля производителя на шаге 4.

XCode передает всю информацию от вкладки Properties в пакет аудиоустройства Info.plist файл. Можно открыться Info.plist файл, если требуется проверить его, непосредственно от этого диалогового окна с помощью кнопки «Open Info.plist as File» у основания окна.

По окончании закройтесь Info.plist файл (при открытии его) или закрывает окно Target Info.

8. Теперь сконфигурируйте процесс сборки проекта XCode для копирования пакета аудиоустройства в надлежащее расположение так, чтобы хост-приложения могли использовать его.

В окне проекта раскройте группу продуктов и Целевую группу, как показано в числе, так, чтобы Вы видели значок для самого пакета аудиоустройства (TremoloUnit.component) а также фазы сборки (под Targets/TremoloUnit).

../Art/copy_files_1.jpg

9. Теперь добавьте новую фазу сборки. Щелкните правой кнопкой (или щелчок управления) по заключительной фазе сборки для TremoloUnit и выберите Add> New Build Phase> New Copy Files Build Phase.

../Art/copy_files_2.jpg../Art/copy_files_2.jpg

Новая фаза сборки Файлов Копии появляется в конце списка, и диалоговое окно открывается, названная Фаза Файлов Копии для Информации «TremoloUnit».

../Art/copy_files_3.jpg

Измените Место назначения, раскрывающееся на Абсолютный путь, как показано в числе.

Введите абсолютный целевой путь для созданного пакета аудиоустройства в поле Full Path.

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

Теперь перетащите TremoloUnit.component значок от группы продуктов к новой фазе сборки.

../Art/copy_files_4.jpg

Если Вы хотите путем двойного щелчка по серому значку фазы сборки Файлов Копии, можно позже изменить местоположение Файлов Копии. Также щелкните по значку Copy Files и затем нажмите кнопку Info на панели инструментов.

В этой точке Вы имеете, имеют создания для рабочего аудиоустройства. Вы еще не настроили его, чтобы сделать независимо от того, что случается так, что у Вас будет он, делают (в нашем данном случае, для обеспечения одноканального эффекта тремоло). Это - хорошая идея гарантировать, что можно создать его без ошибок, что можно проверить его с auval инструментом, и что можно использовать его в хост-приложении. Сделайте это на следующем шаге.

10. Разработайте проект. Можно сделать это любым из стандартных способов: нажмите кнопку Build на панели инструментов, или выберите Build из меню кнопки Build, или выберите Build> Build из главного меню или введите команду-B.

../Art/first_build.jpg

Если все будет в порядке, то Ваш проект создаст без ошибки.

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

Протестируйте неизмененное аудиоустройство

Для тестирования недавно созданного аудиоустройства используйте приложение AU Lab:

Команда Core Audio Apple предоставляет AU Lab в /Developer/Applications/Audio папка, вместе с документацией. Вы не должны обращаться к документации AU Lab для выполнения этой задачи. auval инструмент командной строки является частью стандартной установки OS X.

  1. В Терминале введите команду auval -a. Если OS X распознает Ваш новый пакет аудиоустройства, Вы видите перечисление, подобное этому:

../Art/auval-a.jpg

Если Ваш проект XCode создает без ошибки, но Вы не видите, что новое аудиоустройство связывается в списке, о котором сообщают auval инструмент, двойная проверка, чтобы Вы ввели корректный путь в фазу Файлов Копии, как описано на шаге 8 Набора Ваше Название компании в XCode.

2. Launch AU Lab и создает новый документ AU Lab. Если Вы не сконфигурировали AU Lab для использования стиля документа по умолчанию, Создавание Нового Окна документа открывается. Если AU Lab уже работала, выберите File> New для получения этого окна.

../Art/au_lab_new_doc_1.jpg

Гарантируйте, что конфигурация соответствует настройки, показанные в числе: встроенное Аудио для Аудиоустройства, Строки В для Входного Источника и Стерео для Каналов вывода. Оставьте вкладку Inputs окна несконфигурированной; Вы укажете ввод позже. Нажать «OK».

Новое окно AU Lab открывается, показывая канал вывода, который Вы указали.

../Art/au_lab_new_doc_2.jpg

3. Выберите Edit> Add Audio Unit Generator. Диалоговое окно открывается из окна AU Lab, чтобы позволить Вам указать модуль генератора для служения в качестве источника аудиосигналов.

../Art/au_lab_add_generator.jpg

В диалоговом окне гарантируйте, что модуль AUAudioFilePlayer выбран в раскрывающемся Генераторе. Чтобы последовать этому примеру, измените Название группы на Проигрыватель. Нажать «OK».

Окно AU Lab теперь показывает дорожку стереовхода. Кроме того, окно инспектора открылось для модуля проигрывателя. При закрытии инспектора можно вновь открыть его путем нажимания прямоугольной кнопки «AU» около вершины дорожки Проигрывателя.

../Art/au_lab_file_player_1.jpg

4. Добавьте аудиофайл к списку Аудиофайлов в инспекторе проигрывателя окно. Сделайте это путем перетаскивания аудиофайла от Средства поиска, как показано. При помещении аудиофайла в инспектора проигрывателя окно позволяет Вам отправить аудио через новое аудиоустройство. Примерно любой аудиофайл сделает, несмотря на то, что непрерывный тон полезен для тестирования.

../Art/au_lab_copy_sound_file.jpg

Now AU Lab сконфигурирована и готова протестировать Ваше аудиоустройство.

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

../Art/au_lab_add_effect_1.jpg

Меню открывается, перечисляя все аудиоустройства, доступные в Вашей системе, расположенной по категориям и производитель. Существует Сердитая Аудио группа в раскрывающемся, как показано в следующем числе.

Выберите свое новое аудиоустройство из Эффектов, которые открывает первая строка.

../Art/au_lab_add_effect_2.jpg

AU Lab открывает Какао Вашего аудиоустройства универсальное представление, появляющееся как служебное окно.

../Art/generic_view_1.jpg

Универсальное представление выводит на экран интерфейс Вашего аудиоустройства, как это прибывает непосредственно из параметра и определений свойства, предоставленных шаблоном Xcode. Шаблон определяет аудиоустройство, обеспечивающее корректировку уровня. Его представление, созданное хост-приложением AU Lab, обладает управлением Усилением. Вы изменяете представление на более позднем шаге в этой задаче путем изменения определений параметра аудиоустройства.

Обратитесь к Таблице 3-1 для получения информации о том, где Вы определяете каждый элемент пользовательского интерфейса для универсального представления.

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

7. Сохраните документ AU Lab для использования позже, дав ему имя, такое как “Модуль Тремоло Test.trak”. Вы будете использовать его в заключительном разделе этой главы, Тест Ваше Завершенное Аудиоустройство.

Затем, Вы определите свой интерфейс параметра модуля эффекта тремоло для предоставления контроля за работой пользователей по уровню тремоло, глубине и форме волны.

Реализуйте интерфейс параметра

До этой точки в разработке Вашего аудиоустройства Вы коснулись очень небольшого количества кода. Здесь, Вы определяете параметры аудиоустройства путем редактирования исходных файлов для аудиоустройства пользовательский подкласс: TremoloUnit.h и TremoloUnit.cpp.

Для определения параметров аудиоустройства, Вы делаете три вещи:

Код, который Вы реализуете здесь, не использует параметры по сути. Это - код DSP, который Вы реализуете позже в Обработке сигналов Реализации, использующей параметры. Здесь, Вы просто определяете параметры так, чтобы они появились в аудиоустройстве универсальное представление и так, чтобы они были готовы использовать, когда Вы реализуете код DSP.

Назовите значения набора и параметры

Во-первых, назовите параметры своего аудиоустройства и предоставьте значения им. Сделайте это путем замены определения параметра по умолчанию кодирует в TremoloUnit.h заголовочный файл, предоставленный шаблоном Xcode, со следующим кодом. Это перечисление реализует проект параметра от таблиц в Проекте Интерфейс Параметра.

  Названия параметра перечисления 5-1 и значения (TremoloUnit.h)

#pragma mark ____TremoloUnit Parameter Constants
 
static CFStringRef kParamName_Tremolo_Freq      = CFSTR ("Frequency");    // 1
static const float kDefaultValue_Tremolo_Freq   = 2.0;                    // 2
static const float kMinimumValue_Tremolo_Freq   = 0.5;                    // 3
static const float kMaximumValue_Tremolo_Freq   = 20.0;                   // 4
 
static CFStringRef kParamName_Tremolo_Depth     = CFSTR ("Depth");        // 5
static const float kDefaultValue_Tremolo_Depth  = 50.0;
static const float kMinimumValue_Tremolo_Depth  = 0.0;
static const float kMaximumValue_Tremolo_Depth  = 100.0;
 
static CFStringRef kParamName_Tremolo_Waveform  = CFSTR ("Waveform");     // 6
static const int kSineWave_Tremolo_Waveform     = 1;
static const int kSquareWave_Tremolo_Waveform   = 2;
static const int kDefaultValue_Tremolo_Waveform = kSineWave_Tremolo_Waveform;
 
// menu item names for the waveform parameter
static CFStringRef kMenuItem_Tremolo_Sine       = CFSTR ("Sine");         // 7
static CFStringRef kMenuItem_Tremolo_Square     = CFSTR ("Square");       // 8
 
// parameter identifiers
enum {                                                                    // 9
    kParameter_Frequency  = 0,
    kParameter_Depth      = 1,
    kParameter_Waveform   = 2,
    kNumberOfParameters   = 3
};

Вот то, как работает этот код:

  1. Обеспечивает имя пользовательского интерфейса для Частоты (kParamName_Tremolo_Freq) параметр.

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

  3. Определяет константу для минимального значения для параметра Частоты.

  4. Определяет константу для максимального значения для параметра Частоты.

  5. Обеспечивает имя пользовательского интерфейса для Глубины (kParamName_Tremolo_Depth) параметр. Следующие три строки определяют константы для значения по умолчанию, минимума и максимальных значений для параметра Глубины.

  6. Обеспечивает имя пользовательского интерфейса для Формы волны (kParamName_Tremolo_Waveform) параметр. Следующие три строки определяют константы для минимума, максимума и значений по умолчанию для параметра Формы волны.

  7. Определяет строку пункта меню для синусоидальной опции для параметра Формы волны.

  8. Определяет строку пункта меню для прямоугольной опции для параметра Формы волны.

  9. Определяет константы для идентификации параметров; определяет общее количество параметров.

Для каждого параметра Вы определили в TremoloUnit.h файл, Ваши потребности аудиоустройства:

  • Соответствие SetParameter оператор в методе конструктора, как описано затем в Редактировании Метод конструктора

  • Соответствующее определение параметра в GetParameterInfo метод, как описано позже в Определяют Параметры

Отредактируйте метод конструктора

Затем, замените пользовательский метод конструктора подкласса в TremoloUnit.cpp файл с кодом в этом разделе. Этот код инстанцирует аудиоустройства, включающего установку названий параметра и значений, которые Вы определили в предыдущем разделе.

На данный момент, SetParameter операторы, показанные здесь, являются единственными строками для настройки в методе конструктора. На более позднем шаге Вы добавите код для определения предварительной установки фабрики по умолчанию.

Перечисление 5-2  , Устанавливающее параметры в конструкторе (TremoloUnit.cpp)

TremoloUnit::TremoloUnit (AudioUnit component) : AUEffectBase (component) {
 
    CreateElements ();
    Globals () -> UseIndexedParameters (kNumberOfParameters);
 
    SetParameter (                                       // 1
        kParameter_Frequency,
        kDefaultValue_Tremolo_Freq
    );
 
    SetParameter (                                       // 2
        kParameter_Depth,
        kDefaultValue_Tremolo_Depth
    );
 
    SetParameter (                                       // 3
        kParameter_Waveform,
        kDefaultValue_Tremolo_Waveform
    );
 
    #if AU_DEBUG_DISPATCHER
        mDebugDispatcher = new AUDebugDispatcher (this);
    #endif
}

Вот то, как работает этот код:

  1. Устанавливает первый параметр для аудиоустройства, на основе значений от заголовочного файла. В этом проекте этот параметр управляет частотой тремоло. SetParameter метод наследован от суперклассов в Core Audio SDK.

  2. Устанавливает второй параметр для аудиоустройства, на основе значений от заголовочного файла. В этом проекте этот параметр управляет глубиной тремоло.

  3. Устанавливает третий параметр для аудиоустройства, на основе значений от заголовочного файла. В этом проекте этот параметр управляет формой волны тремоло.

Определите параметры

Замените переопределение по умолчанию GetParameterInfo метод из шаблона Xcode, определяющего всего одно значение по умолчанию (Усиление) параметр. Здесь, используйте проект с тремя параметрами, описанный ранее в Проекте Интерфейс Параметра.

Перечисление 5-3  специализированное GetParameterInfo метод (TremoloUnit.cpp)

#pragma mark ____Parameters
ComponentResult TremoloUnit::GetParameterInfo (
        AudioUnitScope          inScope,
        AudioUnitParameterID    inParameterID,
        AudioUnitParameterInfo  &outParameterInfo
) {
    ComponentResult result = noErr;
 
    outParameterInfo.flags =    kAudioUnitParameterFlag_IsWritable        // 1
                                | kAudioUnitParameterFlag_IsReadable;
 
    if (inScope == kAudioUnitScope_Global) {                              // 2
        switch (inParameterID) {
            case kParameter_Frequency:                                    // 3
                AUBase::FillInParameterName (
                    outParameterInfo,
                    kParamName_Tremolo_Freq,
                    false
                );
                outParameterInfo.unit =                                   // 4
                    kAudioUnitParameterUnit_Hertz;
                outParameterInfo.minValue =                               // 5
                        kMinimumValue_Tremolo_Freq;
                outParameterInfo.maxValue =                               // 6
                        kMaximumValue_Tremolo_Freq;
                outParameterInfo.defaultValue =                           // 7
                        kDefaultValue_Tremolo_Freq;
                outParameterInfo.flags                                    // 8
                        |= kAudioUnitParameterFlag_DisplayLogarithmic;
                break;
 
            case kParameter_Depth:                                        // 9
                AUBase::FillInParameterName (
                    outParameterInfo,
                    kParamName_Tremolo_Depth,
                    false
                );
                outParameterInfo.unit =                                   // 10
                    kAudioUnitParameterUnit_Percent;
                outParameterInfo.minValue =
                    kMinimumValue_Tremolo_Depth;
                outParameterInfo.maxValue =
                    kMaximumValue_Tremolo_Depth;
                outParameterInfo.defaultValue =
                     kDefaultValue_Tremolo_Depth;
                break;
 
            case kParameter_Waveform:                                     // 11
                AUBase::FillInParameterName (
                    outParameterInfo,
                    kParamName_Tremolo_Waveform,
                    false
                );
                outParameterInfo.unit =                                   // 12
                    kAudioUnitParameterUnit_Indexed;
                outParameterInfo.minValue =
                    kSineWave_Tremolo_Waveform;
                outParameterInfo.maxValue =
                    kSquareWave_Tremolo_Waveform;
                outParameterInfo.defaultValue =
                    kDefaultValue_Tremolo_Waveform;
                break;
 
            default:
                result = kAudioUnitErr_InvalidParameter;
                break;
        }
    } else {
        result = kAudioUnitErr_InvalidParameter;
    }
    return result;
}

Вот то, как работает этот код:

  1. Добавляют два флага ко всем параметрам для аудиоустройства, указывая к хост-приложению, что это должно полагать, что параметры всего аудиоустройства читаемы и перезаписываемы.

  2. Все три параметра для этого аудиоустройства находятся в «глобальном» объеме.

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

  4. Устанавливает единицу измерения для параметра Частоты к Герц.

  5. Устанавливает минимальное значение для параметра Частоты.

  6. Устанавливает максимальное значение для параметра Частоты.

  7. Устанавливает значение по умолчанию для параметра Частоты

  8. Добавляет флаг, чтобы указать к узлу, что это должно использовать логарифмическое управление для параметра Частоты.

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

  10. Устанавливает единицу измерения для параметра Глубины к проценту. Следующие три оператора устанавливают минимум, максимум и значения по умолчанию для параметра Глубины.

  11. Третий случай в операторе переключения, вызванном, когда для представления нужна информация для kTremolo_Waveform параметр, определяет, как представлять этот параметр в пользовательском интерфейсе.

  12. Устанавливает единицу измерения для параметра Формы волны к “индексируемому “, позволяя ему быть выведенным на экран как всплывающее меню в универсальном представлении. Следующие три оператора устанавливают минимум, максимум и значения по умолчанию для параметра глубины. Все три требуются для надлежащего функционирования пользовательского интерфейса параметра.

Обеспечьте строки для всплывающего меню формы волны

Теперь Вы реализуете GetParameterValueStrings метод, позволяющий универсальному представлению аудиоустройства вывести на экран параметр формы волны как всплывающее меню.

Удобное расположение для этого кода после GetParameterInfo определение метода. Если Вы добавляете этот метод здесь, как предложено, несомненно, удалят метод заполнителя, предоставленный шаблоном Xcode в другом месте в файле реализации.

Перечисление 5-4  специализированное GetParameterValueStrings метод (TremoloUnit.cpp)

ComponentResult TremoloUnit::GetParameterValueStrings (
    AudioUnitScope          inScope,
    AudioUnitParameterID    inParameterID,
    CFArrayRef              *outStrings
) {
    if ((inScope == kAudioUnitScope_Global) &&             // 1
        (inParameterID == kParameter_Waveform)) {
 
        if (outStrings == NULL) return noErr;              // 2
 
        CFStringRef strings [] = {                         // 3
            kMenuItem_Tremolo_Sine,
            kMenuItem_Tremolo_Square
        };
 
        *outStrings = CFArrayCreate (                      // 4
            NULL,
            (const void **) strings,
            (sizeof (strings) / sizeof (strings [0])),     // 5
            NULL
        );
        return noErr;
    }
    return kAudioUnitErr_InvalidParameter;
}

Вот то, как работает этот код:

  1. Этот метод применяется только к параметру формы волны, который находится в глобальной области видимости.

  2. Когда этот метод вызывают AUBase::DispatchGetPropertyInfo метод, обеспечивающий нулевое значение для outStrings параметра, просто возвращается без ошибки.

  3. Определяет массив, содержащий названия товара всплывающего меню.

  4. Создает новый неизменный массив, содержащий имена пункта меню, и помещает массив в выходной параметр outStrings.

  5. Вычисляет число пунктов меню в массиве.

Реализуйте предварительно установленный интерфейс фабрики

Затем, Вы определяете предварительные установки фабрики аудиоустройства, снова путем редактирования исходных файлов для аудиоустройства пользовательский подкласс, TremoloUnit.h и TremoloUnit.cpp.

Шаги, описанные подробно ниже:

Назовите предварительные установки фабрики и дайте им значения

Определите константы для предварительных установок фабрики. Удобное расположение для этого кода в TremoloUnit.h заголовочный файл ниже раздела констант параметра.

  Фабрика перечисления 5-5 задала имена и значения (TremoloUnit.h)

#pragma mark ____TremoloUnit Factory Preset Constants
static const float kParameter_Preset_Frequency_Slow = 2.0;    // 1
static const float kParameter_Preset_Frequency_Fast = 20.0;   // 2
static const float kParameter_Preset_Depth_Slow     = 50.0;   // 3
static const float kParameter_Preset_Depth_Fast     = 90.0;   // 4
static const float kParameter_Preset_Waveform_Slow            // 5
    = kSineWave_Tremolo_Waveform;
static const float kParameter_Preset_Waveform_Fast            // 6
    = kSquareWave_Tremolo_Waveform;
enum {
    kPreset_Slow    = 0,                                      // 7
    kPreset_Fast    = 1,                                      // 8
    kNumberPresets  = 2                                       // 9
};
 
static AUPreset kPresets [kNumberPresets] = {                 // 10
    {kPreset_Slow, CFSTR ("Slow & Gentle")},
    {kPreset_Fast, CFSTR ("Fast & Hard")}
};
 
static const int kPreset_Default = kPreset_Slow;              // 11

Вот то, как работает этот код:

  1. Определяет константу для значения частоты для “Медленного &amp; Нежная” фабрика задается.

  2. Определяет константу для значения частоты для “Быстрого &amp; Трудно” фабрика задается.

  3. Определяет константу для значения глубины для “Медленного &amp; Нежный; Трудно” фабрика задается.

  4. Определяет константу для значения глубины для “Быстрого &amp; Трудно” фабрика задается.

  5. Определяет константу для значения формы волны для “Медленного &amp; Нежная” фабрика задается.

  6. Определяет константу для значения формы волны для “Быстрого &amp; Трудно” фабрика задается.

  7. Определяет константу для “Медленного &amp; Нежная” фабрика задается.

  8. Определяет константу для “Быстрого &amp; Трудно” фабрика задается.

  9. Определяет постоянное представление общего количества предварительных установок фабрики.

  10. Определяет массив, содержащий два Базовых строковых объекта Основы. Объекты содержат значения для пунктов меню в пользовательском интерфейсе, соответствующем предварительным установкам фабрики.

  11. Определяет постоянное представление предварительной установки фабрики по умолчанию, в этом случае “Медленной и Нежной” предварительной установки.

Добавьте объявления метода для предварительных установок фабрики

Теперь, обеспечьте объявления метода для переопределения GetPresets и NewFactoryPresetSet методы от AUBase суперкласс. Добавьте эти объявления метода к public: часть объявления класса в TremoloUnit.h заголовочный файл. Вы реализуете эти методы на более позднем шаге в этой главе.

  Фабрика перечисления 5-6 задала объявления метода (TremoloUnit.h)

#pragma mark ____TremoloUnit
class TremoloUnit : public AUEffectBase {
 
public:
    TremoloUnit (AudioUnit component);
...
    virtual ComponentResult GetPresets (       // 1
        CFArrayRef        *outData
    ) const;
 
    virtual OSStatus NewFactoryPresetSet (     // 2
        const AUPreset    &inNewFactoryPreset
    );
protected:
...
};

Вот то, как работает этот код:

  1. Объявление для метода GetPresets, переопределяя метод от суперкласса AUBase.

  2. Объявление для метода NewFactoryPresetSet, переопределяя метод от суперкласса AUBase.

Установите предварительную установку фабрики по умолчанию

Теперь Вы возвращаетесь к методу конструктора TremoloUnit, в котором Вы ранее добавили код для установки параметров аудиоустройства. Здесь, Вы добавляете отдельного оператора для установки предварительной установки фабрики по умолчанию, используя kTremoloPreset_Default постоянный.

Перечисление 5-7  , Устанавливающее предварительную установку фабрики по умолчанию в конструкторе (TremoloUnit.cpp)

TremoloUnit::TremoloUnit (AudioUnit component) : AUEffectBase (component) {
 
    CreateElements ();
    Globals () -> UseIndexedParameters (kNumberOfParameters);
    // code for setting default values for the audio unit parameters
    SetAFactoryPresetAsCurrent (                    // 1
        kPresets [kPreset_Default]
    );
    // boilerplate code for debug dispatcher
}

Вот то, как работает этот код:

  1. Устанавливает предварительную установку фабрики по умолчанию.

Реализуйте метод GetPresets

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

Удобное расположение для этого кода в TremoloUnit.cpp файл реализации после GetPropertyInfo и GetProperty методы.

Перечисление 5-8  реализовывая GetPresets метод (TremoloUnit.cpp)

#pragma mark ____Factory Presets
ComponentResult TremoloUnit::GetPresets (                     // 1
    CFArrayRef *outData
) const {
 
    if (outData == NULL) return noErr;                        // 2
 
    CFMutableArrayRef presetsArray = CFArrayCreateMutable (   // 3
        NULL,
        kNumberPresets,
        NULL
    );
 
    for (int i = 0; i < kNumberPresets; ++i) {                // 4
        CFArrayAppendValue (
            presetsArray,
            &kPresets [i]
        );
    }
 
    *outData = (CFArrayRef) presetsArray;                     // 5
    return noErr;
}

Вот то, как работает этот код:

  1. GetPresets метод принимает единственный параметр, указатель на объект CFArrayRef. Этот объект содержит предварительно установленный массив фабрики, сгенерированный этим методом.

  2. Проверки, реализованы ли предварительные установки фабрики для этого аудиоустройства.

  3. Инстанцирует непостоянного Базового массива Основы для содержания предварительных установок фабрики.

  4. Заполняет предварительно установленный массив фабрики значениями из определений в TremoloUnit.h файл.

  5. Хранит предварительно установленный массив фабрики в outData расположение.

Определите предварительные установки фабрики

NewFactoryPresetSet метод определяет все предварительные установки фабрики для аудиоустройства. В основном, для каждой предварительной установки, это вызывает серию SetParameter вызовы.

Удобное расположение для этого кода в TremoloUnit.cpp файл реализации после реализации GetPresets метод.

Перечисление 5-9  , Определяющее фабрику, задает в NewFactoryPresetSet метод (TremoloUnit.cpp)

OSStatus TremoloUnit::NewFactoryPresetSet (                         // 1
    const AUPreset &inNewFactoryPreset
) {
    SInt32 chosenPreset = inNewFactoryPreset.presetNumber;          // 2
 
    if (                                                            // 3
        chosenPreset == kPreset_Slow ||
        chosenPreset == kPreset_Fast
    ) {
        for (int i = 0; i < kNumberPresets; ++i) {                  // 4
            if (chosenPreset == kPresets[i].presetNumber) {
                switch (chosenPreset) {                             // 5
 
                    case kPreset_Slow:                              // 6
                        SetParameter (                              // 7
                            kParameter_Frequency,
                            kParameter_Preset_Frequency_Slow
                        );
                        SetParameter (                              // 8
                            kParameter_Depth,
                            kParameter_Preset_Depth_Slow
                        );
                        SetParameter (                              // 9
                            kParameter_Waveform,
                            kParameter_Preset_Waveform_Slow
                        );
                        break;
 
                    case kPreset_Fast:                             // 10
                        SetParameter (
                            kParameter_Frequency,
                           kParameter_Preset_Frequency_Fast
                        );
                        SetParameter (
                            kParameter_Depth,
                            kParameter_Preset_Depth_Fast
                        );
                        SetParameter (
                            kParameter_Waveform,
                            kParameter_Preset_Waveform_Fast
                        );
                        break;
                }
                SetAFactoryPresetAsCurrent (                        // 11
                    kPresets [i]
                );
                return noErr;                                       // 12
            }
        }
    }
    return kAudioUnitErr_InvalidProperty;                           // 13
}

Вот то, как работает этот код:

  1. Этот метод берет отдельный аргумент типа AUPreset, структура, содержащая фабрику, задала имя и номер.

  2. Получает число желаемой предварительной установки фабрики.

  3. Тесты, определяется ли желаемая предварительная установка фабрики.

  4. Это for цикл, и if оператор, следующий за ним, допускает предварительно установленные числа состоящие из нескольких несмежных участков.

  5. Выбирает надлежащий оператор выбора на основе предварительно установленного числа фабрики.

  6. Настройки для “Медленной и Нежной” фабрики задаются.

  7. Устанавливает параметр аудиоустройства Частоты для “Медленной и Нежной” предварительной установки фабрики.

  8. Устанавливает параметр аудиоустройства Глубины для “Медленной и Нежной” предварительной установки фабрики.

  9. Устанавливает параметр аудиоустройства Формы волны для “Медленной и Нежной” предварительной установки фабрики.

  10. Настройки для “Быстрой и Твердой” фабрики задаются. Три SetParameter операторы, следующие за работой тот же путь что касается другой предварительной установки фабрики.

  11. Обновляет предварительно установленное меню в универсальном представлении для отображения новой предварительной установки фабрики.

  12. На успехе, возвращает значение noErr.

  13. Если хост-приложение попыталось установить неопределенную предварительную установку фабрики, возвратите ошибку.

Реализуйте обработку сигналов

С параметром и предварительно установленный код на месте, Вы теперь добираетесь до сути дела: код цифровой обработки сигналов. Как описано в Синтезе, Обработке и Коде Преобразования формата данных, DSP, выполняемый модулем эффекта канала n-to-n, имеет место в AUKernelBase класс, класс помощника для AUEffectBase класс. Обратитесь к Обработке: Суть дела для больше о том, как DSP работает в аудиоустройствах.

Для реализации обработки сигналов в модуле эффекта канала n-to-n Вы переопределяете два метода от AUKernelBase класс:

По пути Вы вносите изменения в значение по умолчанию TremoloUnitKernel объявление класса в TremoloUnit.h заголовочный файл, и Вы изменяете TremoloUnitKernel метод конструктора в TremoloUnit.cpp.

Проект DSP для эффекта тремоло

Разработка и реализация кода DSP является центральной к разработке аудиоустройства реального мира — но, как упомянуто во Введении, они выходят за рамки этого документа. Тем не менее, этот раздел описывает простой DSP, используемый в этом проекте проиллюстрировать некоторые проблемы, связанные с добавлением такого кода к модулю эффекта.

При создании нового проекта аудиоустройства с шаблоном Xcode Вы получаете аудиоустройство с минимальным DSP. Это состоит из только умножения, применяющего значение параметра усиления к каждой выборке звукового сигнала. Здесь, Вы все еще используете простое умножение — но с немного большим количеством математики передняя сторона, Вы заканчиваете с чем-то немного более интересным; а именно, тремоло. Поскольку Вы добавляете код DSP, Вы видите, куда каждая часть идет и как это вписывается в леса аудиоустройства.

Проект модуля тремоло использует звуковую таблицу для описания одного цикла формы волны тремоло. TremoloUnitKernel класс создает звуковую таблицу во время инстанцирования. Для создания проекта немного более полезным и поучительным класс создает не одну но две звуковых таблицы: одно представление синусоидальной волны и одно представление псевдо прямоугольной волны.

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

После проекта параметра аудиоустройства, описанного ранее в этой главе, существует код для варьирования частоты тремоло, глубины тремоло и формы волны тремоло, все в режиме реального времени.

Определите задействованные переменные в объявлении класса ядра

Для начала реализации DSP для модуля тремоло добавьте некоторые константы как переменные члена парламента, не занимающего официального поста к TremoloUnitKernel объявление класса. Определение их как переменные члена парламента, не занимающего официального поста гарантирует, что они - глобальная переменная к TremolUnitKernel возразите и невидимый в другом месте.

Перечисление 5-10  TremoloUnitKernel задействованные переменные (TremoloUnit.h)

class TremoloUnit : public AUEffectBase
{
public:
    TremoloUnit(AudioUnit component);
 
...
 
protected:
    class TremoloUnitKernel : public AUKernelBase {
        public:
            TremoloUnitKernel (AUEffectBase *inAudioUnit); // 1
 
            virtual void Process (
                const Float32    *inSourceP,
                Float32          *inDestP,
                UInt32           inFramesToProcess,
                UInt32           inNumChannels,   // equal to 1
                bool             &ioSilence
        );
 
        virtual void Reset();
 
        private:
            enum     {kWaveArraySize = 2000};             // 2
            float    mSine [kWaveArraySize];              // 3
            float    mSquare [kWaveArraySize];            // 4
            float    *waveArrayPointer;                   // 5
            Float32  mSampleFrequency;                    // 6
            long     mSamplesProcessed;                   // 7
            enum     {sampleLimit = (int) 10E6};          // 8
            float    mCurrentScale;                       // 9
            float    mNextScale;                          // 10
    };
};

Вот то, как этот код работает (пропустите это объяснение, если Вы не интересуетесь математикой):

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

  2. Число очков в каждой звуковой таблице. Каждая волна содержит один цикл формы волны тремоло.

  3. Звуковая таблица для синусоидальной волны тремоло.

  4. Звуковая таблица для тремоло псевдо прямоугольная волна.

  5. Звуковая таблица для применения к текущему буферу аудиовхода.

  6. Частота дискретизации или «частота дискретизации», как это часто вызывают звукового сигнала, который будет обработан.

  7. Номер выборок, обработанных, так как аудиоустройство начало представлять, или начиная с этой переменной, был в последний раз определен к 0. DSP кодирует дорожки общие выборки, обработанные потому что:

    • Основной цикл обработки основывается на числе выборок, помещенных во входной буфер …

    • Но DSP должен иметь место независимый от размера входного буфера.

  8. Сохранить значение mSamplesProcessed в разумном пределе существует тест в коде для сброса его, когда это достигает этого значения.

  9. Использующийся в настоящее время масштабный коэффициент. DSP использует масштабный коэффициент для корреляции точек в звуковой таблице с частотой дискретизации звукового сигнала для создания желаемой частоты тремоло. Объект ядра отслеживает «текущий» и «следующий» масштабный коэффициент для поддержки изменения от одной частоты тремоло до другого без слышимого незначительного сбоя.

  10. Желаемый масштабный коэффициент для использования, следуя из запроса пользователем для различной частоты тремоло.

Запишите метод конструктора TremoloUnitKernel

В методе конструктора для Вашего пользовательского подкласса AUKernelBase класс, заботьтесь о любой работе DSP, которая может быть выполнена один раз на инстанцирование объекта ядра. В случае модуля тремоло мы создаем, это включает:

  • Инициализация задействованных переменных, требующих инициализации

  • Заполнение этих двух звуковых таблиц

  • Получение частоты дискретизации аудиопотока.

Удобное расположение для конструктора сразу ниже TremoloUnitEffectKernel метка прагмы.

  Модификации перечисления 5-11 к TremoloUnitKernel Конструктор (TremolUnit.cpp)

#pragma mark ____TremoloUnitEffectKernel
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//    TremoloUnit::TremoloUnitKernel::TremoloUnitKernel()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TremoloUnit::TremoloUnitKernel::TremoloUnitKernel (AUEffectBase *inAudioUnit) :
    AUKernelBase (inAudioUnit), mSamplesProcessed (0), mCurrentScale (0) // 1
{
    for (int i = 0; i < kWaveArraySize; ++i) {                           // 2
        double radians = i * 2.0 * pi / kWaveArraySize;
        mSine [i] = (sin (radians) + 1.0) * 0.5;
    }
 
    for (int i = 0; i < kWaveArraySize; ++i) {                           // 3
        double radians = i * 2.0 * pi / kWaveArraySize;
        radians = radians + 0.32;
        mSquare [i] =
            (
                sin (radians) +
                0.3 * sin (3 * radians) +
                0.15 * sin (5 * radians) +
                0.075 * sin (7 * radians) +
                0.0375 * sin (9 * radians) +
                0.01875 * sin (11 * radians) +
                0.009375 * sin (13 * radians) +
                0.8
            ) * 0.63;
    }
    mSampleFrequency = GetSampleRate ();                                 // 4
}

Вот то, как работает этот код:

  1. Оператор объявления метода конструктора и инициализатор конструктора. В дополнение к вызову надлежащих суперклассов этот код инициализирует две задействованных переменные.

  2. Генерирует звуковую таблицу, представляющую один цикл синусоидальной волны, нормализованной так, чтобы он никогда не шел отрицательный и так, чтобы он расположился между 0 и 1.

    Вместе со значением параметра Глубины эта синусоидальная волна указывает, как варьироваться усиление звуковых частот во время одного цикла синусоидального тремоло.

  3. Генерирует звуковую таблицу, представляющую один цикл псевдо прямоугольной волны, нормализованной так, чтобы он никогда не шел отрицательный и так, чтобы он расположился между приблизительно 0 и приблизительно 1.

  4. Заставляет частоту дискретизации для аудиопотока быть обработанной.

Переопределите метод процесса

Поместите свой код DSP в переопределение AUKernelBase класс Process метод. Process метод вызывают один раз каждый раз, когда хост-приложение заполняет входной буфер аудиосэмпла. Метод обрабатывает содержимое буфера, выборку выборкой, и помещает обработанное аудио в буфер вывода аудиосэмпла.

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

  • Объявите все переменные, используемые в методе

  • Получите текущую стоимость всех параметров, как установлено пользователем через представление аудиоустройства

  • Проверьте параметры, чтобы гарантировать, что они находятся в границах и принимающих соответствующих мерах, если они не

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

В цикле обработки действительно только работайте, который должен быть выполнен выборка выборкой:

  • Выполните вычисления, которые должны быть обновлены выборка выборкой. В этом случае это означает вычислять точку в звуковой таблице для использования для усиления тремоло

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

  • Вычислите трансформацию для применения к каждой входной выборке. В этом случае это означает вычислять a) усиление тремоло на основе текущей точки в звуковой таблице и b) текущая стоимость параметра Глубины.

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

  • Усовершенствуйте индексы в буферах ввода и вывода

  • Усовершенствуйте другие индексы, вовлеченные в DSP. В этом случае это означает постепенно увеличиваться mSamplesProcessed переменная.

Перечисление 5-12  Process метод (TremoloUnit.cpp)

void TremoloUnit::TremoloUnitKernel::Process (                        // 1
    const Float32   *inSourceP,                                       // 2
    Float32         *inDestP,                                         // 3
    UInt32          inSamplesToProcess,                               // 4
    UInt32          inNumChannels,                                    // 5
    bool            &ioSilence                                        // 6
) {
    if (!ioSilence) {                                                 // 7
 
        const Float32 *sourceP = inSourceP;                           // 8
 
        Float32  *destP = inDestP,                                    // 9
                 inputSample,                                         // 10
                 outputSample,                                        // 11
                 tremoloFrequency,                                    // 12
                 tremoloDepth,                                        // 13
                 samplesPerTremoloCycle,                              // 14
                 rawTremoloGain,                                      // 15
                 tremoloGain;                                         // 16
 
        int      tremoloWaveform;                                     // 17
 
        tremoloFrequency = GetParameter (kParameter_Frequency);       // 18
        tremoloDepth     = GetParameter (kParameter_Depth);           // 19
        tremoloWaveform  =
            (int) GetParameter (kParameter_Waveform);                 // 20
 
        if (tremoloWaveform != kSineWave_Tremolo_Waveform             // 21
            && tremoloWaveform != kSquareWave_Tremolo_Waveform)
                tremoloWaveform = kSquareWave_Tremolo_Waveform;
 
        if (tremoloWaveform == kSineWave_Tremolo_Waveform)  {         // 22
            waveArrayPointer = &mSine [0];
        } else {
            waveArrayPointer = &mSquare [0];
        }
 
        if (tremoloFrequency < kMinimumValue_Tremolo_Freq)            // 23
            tremoloFrequency = kMinimumValue_Tremolo_Freq;
        if (tremoloFrequency > kMaximumValue_Tremolo_Freq)
            tremoloFrequency = kMaximumValue_Tremolo_Freq;
 
        if (tremoloDepth     < kMinimumValue_Tremolo_Depth)           // 24
            tremoloDepth     = kMinimumValue_Tremolo_Depth;
        if (tremoloDepth     > kMaximumValue_Tremolo_Depth)
            tremoloDepth     = kMaximumValue_Tremolo_Depth;
 
        samplesPerTremoloCycle = mSampleFrequency / tremoloFrequency; // 25
        mNextScale = kWaveArraySize / samplesPerTremoloCycle;         // 26
 
        // the sample processing loop ////////////////
        for (int i = inSamplesToProcess; i > 0; --i) {                // 27
 
            int index =                                               // 28
                static_cast<long>(mSamplesProcessed * mCurrentScale) %
                    kWaveArraySize;
 
            if ((mNextScale != mCurrentScale) && (index == 0)) {      // 29
                mCurrentScale = mNextScale;
                mSamplesProcessed = 0;
            }
 
            if ((mSamplesProcessed >= sampleLimit) && (index == 0))   // 30
                mSamplesProcessed = 0;
 
            rawTremoloGain = waveArrayPointer [index];                // 31
 
            tremoloGain       = (rawTremoloGain * tremoloDepth -      // 32
                                tremoloDepth + 100.0) * 0.01;
            inputSample       = *sourceP;                             // 33
            outputSample      = (inputSample * tremoloGain);          // 34
            *destP            = outputSample;                         // 35
            sourceP           += 1;                                   // 36
            destP             += 1;                                   // 37
            mSamplesProcessed += 1;                                   // 38
        }
    }
}

Вот то, как работает этот код:

  1. Process сигнатура метода. Этот метод объявляется в AUKernelBase класс.

  2. Входной буфер аудиосэмпла.

  3. Буфер вывода аудиосэмпла.

  4. Число выборок во входном буфере.

  5. Число каналов ввода. Это всегда равно 1, потому что всегда существует один объект ядра, который инстанцируют на канал аудио.

  6. Булев флаг, указывающий, состоит ли ввод к аудиоустройству из тишины с a TRUE тишина указания значения.

  7. Игнорирует запрос для выполнения Process метод, если ввод к аудиоустройству является тишиной.

  8. Присваивает переменную указателя запуску входного буфера аудиосэмпла.

  9. Присваивает переменную указателя запуску буфера вывода аудиосэмпла.

  10. Текущий аудиосэмпл для обработки.

  11. Текущая выборка аудиовыхода, следующая из одной итерации цикла обработки.

  12. Частоту тремоло требует пользователь через представление аудиоустройства.

  13. Глубину тремоло требует пользователь через представление аудиоустройства.

  14. Число аудиосэмплов в одном цикле формы волны тремоло.

  15. Усиление тремоло для текущего аудиосэмпла, как сохраненный в звуковой таблице.

  16. Приведенный усиление тремоло в соответствие для текущего аудиосэмпла, рассматривая параметр Глубины.

  17. Тип формы волны тремоло требует пользователь через представление аудиоустройства.

  18. Получает текущую стоимость параметра Частоты.

  19. Получает текущую стоимость параметра Глубины.

  20. Получает текущую стоимость параметра Формы волны.

  21. Выполняет границы, проверяющие параметр Формы волны. Если параметр выходит за пределы, предоставляет рыночную стоимость.

  22. Присваивает переменную указателя звуковой таблице, соответствующей форме волны тремоло, выбранной пользователем.

  23. Выполняет границы, проверяющие параметр Частоты. Если параметр выходит за пределы, предоставляет рыночную стоимость.

  24. Выполняет границы, проверяющие параметр Глубины. Если параметр выходит за пределы, предоставляет рыночную стоимость.

  25. Вычисляет число аудиосэмплов на цикл частоты тремоло.

  26. Вычисляет масштабный коэффициент для использования для применения звуковой таблицы к текущей частоте дискретизации и частоте тремоло.

  27. Цикл, выполняющий итерации по входному буферу аудиосэмпла.

  28. Вычисляет точку в звуковой таблице для использования для текущей выборки. Это, вместе с вычислением mNextScale значение в комментарии, единственная тонкая математика в DSP для этого эффекта.

  29. Тесты, если масштабный коэффициент должен измениться, и если безопасно изменить его при текущей выборке для предотвращения артефактов. Если и условиям удовлетворяют, переключает масштабный коэффициент и сбрасывает mSamplesProcessed переменная.

  30. Тесты, если mSamplesProcessed переменная росла до большого значения, и если безопасно сбросить его при текущей выборке для предотвращения артефактов. Если обоим условиям удовлетворяют, сброс mSamplesProcessed переменная.

  31. Получает усиление тремоло от надлежащей точки в звуковой таблице.

  32. Корректирует усиление тремоло путем применения параметра Глубины. С глубиной 100% применяется полный эффект тремоло. С глубиной 0% нет никакого эффекта тремоло, прикладного вообще.

  33. Получает аудиосэмпл от надлежащего спота во входном буфере аудиосэмпла.

  34. Вычисляет соответствующий выходной аудиосэмпл.

  35. Помещает выходной аудиосэмпл в надлежащем споте в буфере вывода аудиосэмпла.

  36. Постепенно увеличивает счетчик позиции для входного буфера аудиосэмпла.

  37. Постепенно увеличивает счетчик позиции для буфера вывода аудиосэмпла.

  38. Постепенно увеличивает количество обработанных аудиосэмплов.

Переопределите метод сброса

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

Перечисление 5-13  Reset метод (TremoloUnit.cpp)

void TremoloUnit::TremoloUnitKernel::Reset() {
    mCurrentScale        = 0;                    // 1
    mSamplesProcessed    = 0;                    // 2
}

Вот то, как работает этот код:

  1. Сброс mCurrentScale задействованная переменная к ее недавно инициализированному значению.

  2. Сброс mSamplesProcessed задействованная переменная к ее недавно инициализированному значению.

Реализуйте свойство времени хвоста

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

Чтобы сделать это, просто утвердите в Вашем TremoloUnit определение класса, что Ваше аудиоустройство поддерживает свойство путем изменения возвращаемого значения SupportsTail метод к true.

Перечисление 5-14  Реализовывая свойство времени хвоста (TremoloUnit.h)

virtual bool SupportsTail () {return true;}

Учитывая природу DSP Ваше аудиоустройство выполняет, его время хвоста 0 секунды — таким образом, Вы не должны переопределять GetTailTime метод. В AUBase суперкласс, этот метод сообщает о времени хвоста 0 секунды, который является тем, о чем Вы хотите, чтобы Ваше аудиоустройство сообщило.

Проверьте свое Завершенное Аудиоустройство

Теперь Вы реализовали весь код для проекта модуля тремоло. Разработайте проект и исправьте любые ошибки, которые Вы видите. Тогда используйте auval инструмент для проверки аудиоустройства.

1. В Терминале введите команду для проверки модуля тремоло. Это состоит из auval название команды, сопровождаемое -v флаг для вызова проверки, сопровождаемой типом, подтипом и кодами производителя, идентифицирующими модуль тремоло. Полная команда для этого аудиоустройства:

auval -v aufx tmlo Aaud

Если все в порядке, auval должен сообщить, что Ваше новое аудиоустройство действительно допустимо. Данные показывают последний бит журнала, создаваемого auval:

../Art/validation_succeeded.jpg

Протестируйте свое Завершенное Аудиоустройство

Ваше аудиоустройство готово к Вам протестировать в хост-приложении. Apple рекомендует приложение AU Lab для тестирования аудиоустройства. Можно также хотеть протестировать аудиоустройство в других узлах. В этом разделе описываются тестирование с AU Lab. Выполните эти шаги:

1. Откройте документ AU Lab, который Вы сохранили от раздела Test the Unmodified Audio Unit. Если у Вас нет того документа, пробегите шаги в том разделе снова для установки AU Lab для тестирования аудиоустройства.

2. Ваше завершенное аудиоустройство появляется с универсальным представлением как показано в числе:

../Art/tremolo_unit_generic_view.jpg

(Вы, возможно, должны выйти и вновь открыть AU Lab для представления Вашего завершенного аудиоустройства для появления.)

Заметьте ползунки для параметров Частоты и Глубины, всплывающее меню для параметра Формы волны и предварительную установку по умолчанию, выведенную на экран в Предварительно установленном всплывающем меню Фабрики.

3. Щелкните по кнопке воспроизведения в окне утилиты AUAudioFilePlayer. Если все будет в порядке, то файл, который Вы выбрали в проигрывателе, проиграет Ваше аудиоустройство, и Вы услышите эффект тремоло.

4. Эксперимент с диапазоном эффектов, доступных с модулем тремоло: скорректируйте Частоту, Глубину и средства управления Формой волны при слушании вывода от AU Lab.

5. В предварительно установленном меню к верхнему правому из универсального представления выберите Show Presets.

../Art/generic_view_show_presets.jpg

Предварительно установленная секция открывается.

../Art/generic_view_presets_drawer.jpg../Art/generic_view_presets_drawer.jpg

Раскройте предварительные установки в группе Фабрики и проверьте, что предварительные установки, которые Вы добавили к своему аудиоустройству, с помощью NewFactoryPresetSet метод, присутствуют. Дважды щелкните по предварительной установке для загрузки его.

Можно добавить пользовательские предварительные установки к аудиоустройству следующим образом: