Разработка аудиоустройства - обрабатывающий события аудиоустройства
Этот technote описывает, как использовать События Аудиоустройства, чтобы отправить и получить уведомления о состоянии изменения Аудиоустройства, являются ли те изменения вследствие «жестов» или изменений в значениях параметров или свойств.
Используя Событие Аудиоустройства API, Аудиоустройства, Узлы Аудиоустройства и их UIs теперь имеют объединенный метод отправки и получения уведомлений о событиях. Уведомления о событиях могут быть отправлены и получены без потребности различных реализаций и для Углерода и для Какао UIs. Это значительно упрощает взаимодействие между Аудиоустройствами, их узлами и их UIs.
Существует три различных типов событий, которые могут упасть в AudioUnitEvent категория:
Изменения значения параметра.
Изменения в Значении свойства Аудиоустройства.
Начинание или конец Параметра Аудиоустройства изменяют жесты.
Событие Аудиоустройства API является просто механизмом для отправки уведомления об этих типах изменений. Эта новая реализация создает поверх существующего Core Audio API для свойства Audio Unit и слушания параметра. Эта новая реализация позволяет лучшему сотрудничеству среди клиентов при помощи AudioUnitEvents знать о том, что делает другой клиент. Теперь, когда узел Аудиоустройства изменяет параметр Аудиоустройства (или значение свойства), то изменение может быть отражено в GUI узла, и наоборот.
Этот API также обеспечивает универсальное уведомление о начинании или жестах изменения параметра конца. Примером жеста был бы пользователь, перетаскивающий ползунок на UI. Начать жест в этом случае был бы пользователями, сначала щелкают, тогда как жест конца состоял бы в том когда разъединения абонентом кнопка мыши. Это во многом как события нажатия мыши Углерода, но теперь разработчик может развернуть определение жестов к событиям кроме просто щелчков мышью (таких как нажатие клавиши на клавиатуре).
AudioUnitEvents и AUEventListeners
AudioUnitEvent состоит AudioUnitEventType и возможно параметр, который может относиться к любому AudioUnitParameter или AudioUnitProperty.
Перечисление 1 AudioUnitEvent структура, как определено в AudioUnitUtilities.h
/*! |
@struct AudioUnitEvent |
@abstract Describes a change to an Audio Unit's state. |
@field mEventType |
The type of event. |
@field mArgument |
Specifies the parameter or property which has changed. |
*/ |
typedef struct AudioUnitEvent { |
AudioUnitEventType mEventType; |
union { |
AudioUnitParameter mParameter; // for parameter value change, begin and end gesture |
AudioUnitProperty mProperty; // for kAudioUnitEvent_PropertyChange |
} mArgument; |
} AudioUnitEvent; |
AudioUnitEventType опишет AudioUnitEvent. Типы событий ограничиваются следующими четырьмя типами событий: начните и закончите жесты, изменения параметра и изменения свойства. Если надлежащее использование AudioUnitEvent должен отправить уведомление о AudioUnitParameter действие, тогда единственные типы событий, которые могут использоваться, kAudioUnitEvent_ParameterValueChange, kAudioUnitEvent_BeginParameterChangeGesture, или kAudioUnitEvent_EndParameterChangeGesture. Точно так же AudioUnitProperty может только использовать kAudioUnitEvent_PropertyChange как тип события.
Перечисление 2 AudioUnitEventType как определено в AudioUnitUtilities.h
/*! |
@enum AudioUnitEventType |
@abstract Types of Audio Unit Events. |
@constant kAudioUnitEvent_ParameterValueChange |
The event is a change to a parameter value |
@constant kAudioUnitEvent_BeginParameterChangeGesture |
The event signifies a gesture (e.g. mouse-down) beginning a potential series of |
related parameter value change events. |
@constant kAudioUnitEvent_EndParameterChangeGesture |
The event signifies a gesture (e.g. mouse-up) ending a series of related |
parameter value change events. |
@constant kAudioUnitEvent_PropertyChange |
The event is a change to a property value. |
*/ |
enum { // typedef UInt32 AudioUnitEventType |
kAudioUnitEvent_ParameterValueChange = 0, |
kAudioUnitEvent_BeginParameterChangeGesture = 1, |
kAudioUnitEvent_EndParameterChangeGesture = 2, |
kAudioUnitEvent_PropertyChange = 3 |
}; |
typedef UInt32 AudioUnitEventType; |
Слушатели могут быть созданы для наблюдения изменений в параметрах или свойствах Аудиоустройства. AUEventListenerCreate метод (определенный в <AudioToolbox/AudioUnitUtilities.h>) создаст AUEventListener для Вашего Аудиоустройства. Правильно создать слушателя события с AUEventListenerCreate метод, необходимо включать CFRunLoop и CFRunLoop режим, на котором Вы намереваетесь получить AudioUnitEvent уведомления.
В то время как эти уведомления могут быть выпущены от приоритетных потоков в реальном времени, они могут быть получены на другом цикле выполнения, который может быть указан, когда создается слушатель события. При использовании AUEventListenerCreate, необходимо также указать интервал между вызовами к AUEventListenerProc обратный вызов, а также гранулярность, с которой изменения значения параметра будут поставленный в очередь обратным вызовом слушателя. Это улучшит производительность, потому что она определяет корректную частоту для уведомлений для появления, который позволяет Аудиоустройствам и узлам реагировать более соответственно на событие. Например, когда событие следует за предыдущим меньшим временным интервалом, чем гранулярность, тогда слушатель будет только уведомлен для второго изменения параметра. Это может быть очень полезно в зависимости от типа Аудиоустройства или создаваемого узла. См. <AudioToolbox/AudioUnitUtilities.h> для получения дополнительной информации и примеры интервалов уведомления и значения изменяют гранулярность.
После того, как слушатель события создается, можно добавить события, при помощи которых это прислушается AUEventListenerAddEventType. AUEventListenerAddEventType требует AUEventListenerRef и AudioUnitEvent.
Перечисление 3 AUEventListenerProc обратный вызов, как определено в <AudioToolbox/AudioUnitUtilities.h>
/*! |
@typedef AUParameterListenerProc |
@abstract A function called when an Audio Unit event occurs. |
@param inCallbackRefCon |
The value passed to AUListenerCreate when the callback function was installed. |
@param inObject |
The object which generated the parameter change. |
@param inEvent |
The event which occurred. |
@param inEventHostTime |
The host time at which the event occurred. |
@param inParameterValue |
If the event is parameter change, the parameter's new value (otherwise, undefined). |
*/ |
typedef void (*AUEventListenerProc)(void * inCallbackRefCon, |
void * inObject, |
const AudioUnitEvent * inEvent, |
UInt64 inEventHostTime, |
AudioUnitParameterValue inParameterValue); |
Перечисление 4 AUEventListenerCreate объявление, как определено в <AudioToolbox/AudioUnitUtilities.h>
/*! |
@functiongroup AUEventListener |
*/ |
/*! |
@function AUEventListenerCreate |
@abstract Creates an Audio Unit event listener. |
@param inProc |
Function called when an event occurs. |
@param inCallbackRefCon |
A reference value for the use of the callback function. |
@param inRunLoop |
The run loop on which the callback is called. If NULL, |
CFRunLoopGetCurrent() is used. |
@param inRunLoopMode |
The run loop mode in which the callback's underlying run loop source will be |
attached. If NULL, kCFRunLoopDefaultMode is used. |
@param inNotificationInterval |
The minimum time interval, in seconds, at which the callback will be called. |
@param inValueChangeGranularity |
Determines how parameter value changes occuring within this interval are |
queued; when an event follows a previous one by a smaller time interval than |
the granularity, then the listener will only be notified for the second |
parameter change. |
@param outListener |
On succcessful return, an AUEventListenerRef. |
@discussion |
AUEventListener is a specialization of AUParameterListener; use AUListenerDispose to |
dispose of an AUEventListener. You may use AUListenerAddParameter and |
AUListenerRemoveParameter with AUEventListerRef's, in addition to |
AUEventListenerAddEventType / AUEventListenerRemoveEventType. |
Some examples illustrating inNotificationInterval and inValueChangeGranularity: |
[1] a UI receiver: inNotificationInterval = 100 ms, inValueChangeGranularity = 100 ms. |
User interfaces almost never care about previous values, only the current one, |
and don't wish to perform redraws too often. |
[2] An automation recorder: inNotificationInterval = 200 ms, inValueChangeGranularity = 10 ms. |
Automation systems typically wish to record events with a high degree of timing precision, |
but do not need to be woken up for each event. |
In case [1], the listener will be called within 100 ms (the notification interval) of an |
event. It will only receive one notification for any number of value changes to the |
parameter concerned, occurring within a 100 ms window (the granularity). |
In case [2], the listener will be received within 200 ms (the notification interval) of |
an event It can receive more than one notification per parameter, for the last of each |
group of value changes occurring within a 10 ms window (the granularity). |
In both cases, thread scheduling latencies may result in more events being delivered to |
the listener callback than the theoretical maximum (notification interval / |
granularity). |
*/ |
extern OSStatus |
AUEventListenerCreate(AUEventListenerProc inProc, |
void * inCallbackRefCon, |
CFRunLoopRef inRunLoop, |
CFStringRef inRunLoopMode, |
Float32 inNotificationInterval, // seconds |
Float32 inValueChangeGranularity, // seconds |
AUEventListenerRef * outListener) |
Перечисление 5 , создающее слушателя события аудиоустройства
// The inObject parameter should specify an object interested in the event type. |
// This object is passed as the inObject parameter to the listener callback function. |
OSStatus createListener(void *inObject) |
{ |
AudioUnitEvent myPropertyEvent; |
AudioUnitProperty myProperty; |
AUEventListenerRef MyListener; |
OSStatus result = noErr; |
//this may be a run loop of your choosing |
CFRunLoopRef runLoop = (CFRunLoopRef)GetCFRunLoopFromEventLoop(GetCurrentEventLoop()); |
CFStringRef loopMode = kCFRunLoopDefaultMode; |
myPropertyEvent.mEventType = kAudioUnitEvent_PropertyChange; |
myProperty.mAudioUnit = mAudioUnit; |
myProperty.mPropertyID = kAudioUnitCustomProperty_FilterFrequencyResponse; |
myProperty.mScope = kAudioUnitScope_Global; |
myProperty.mElement = 0; |
myPropertyEvent.mArgument.mProperty = myProperty; |
result = AUEventListenerCreate(MyPropertyListener, |
NULL, |
runLoop, |
loopMode, |
0.05, |
0.05, |
&MyListener); |
if (noErr == result) { |
result = AUEventListenerAddEventType(MyListener, inObject, &myPropertyEvent); |
} |
return result; |
} |
Обработка изменений параметра
Параметры Аудиоустройства используются для изменения поведения процесса рендеринга Аудиоустройства. Параметры могут использоваться для изменения объема, усиления, задержки и многих других способов поведения, которые имели бы эффект на Аудиоустройство. Эти изменения часто применяются в режиме реального времени, и уведомления об этих изменениях могут быть отправлены и получены через AudioUnitEvent.
Уведомления изменения параметра могут быть отправлены использованием узла или Аудиоустройством AUEventListenerNotify. AudioUnitEvent должен иметь kAudioUnitEvent_ParameterValueChange как тип и AudioUnitParameter для параметра. События поставлены последовательно слушателю, вкрапленному изменениями параметра, сохранив порядок времени изменений параметра и событий. Это во многом как какой AUParameterListener уже делает, но в более общем случае. AUParameterListener может генерировать уведомления тезисов при помощи AUParameterSet и AUParameterListenerNotify.
AUEventListener API's расширяет вышеупомянутое AUParameterListener API's путем добавления семантического из событий кроме изменений параметра.
Перечисление 6 , создающее AudioUnitEvent (kAudioUnitEvent_ParameterValueChange) и уведомление AUEventListener
AudioUnitEvent myEvent; |
myEvent.mEventType = kAudioUnitEvent_ParameterValueChange; |
myEvent.mArgument.mParameter.mAudioUnit = mAudioUnit; |
myEvent.mArgument.mParameter.mParameterID = kFilterParam_CutoffFrequency; |
myEvent.mArgument.mParameter.mScope = kAudioUnitScope_Global; |
myEvent.mArgument.mParameter.mElement = 0; |
AUEventListenerNotify(NULL, NULL, &myEvent); |
Обработка изменений свойства
Свойства представляют общий и расширяемый механизм для передающей информации к и от Аудиоустройств. Типом информации, переданной свойствами, можно управлять путем прислушивания к Событиям Аудиоустройства. Действия, и внутренние и внешние к Аудиоустройству, могут изменить значение свойств.
Например, выходное аудиоустройство, отслеживающее устройство, которое пользователь выбирает в области Sound Preferences, является Устройством вывода По умолчанию. Устройство может быть изменено в любое время посредством взаимодействия с пользователем. Если программа имеет экземпляр открытого Устройства вывода По умолчанию, слушатель свойства для kAudioOutputUnitProperty_CurrentDevice свойство может быть установлено, чтобы позволить программе обнаруживать то изменение. Также программа может не заботиться об определенном устройстве, что Устройство вывода По умолчанию подключено с, но может заботиться о формате того устройства, например, частоты дискретизации устройства. Обнаружить то свойство изменилось, слушатель может также быть установлен заранее, чтобы уведомить, что изменилось значение свойства. Тогда узел или Аудиоустройство могут принять любые соответствующие меры, что это должно.
Уведомления изменения свойства могут быть реализованы при помощи AudioUnitEvent. AudioUnitEvent должен иметь AudioUnitProperty и kAudioUnitEvent_PropertyChange как тип. После того, как слушатель создается с помощью AUEventListenerCreate, Аудиоустройство или узел могут получить эти уведомления безопасно на потоке, где это будет самым применимым вместо потока, где фактически произошло изменение. Это особенно полезно для уведомлений, сгенерированных на потоке рендеринга аудио (такие потоки, обычно выполненные с приоритетом в реальном времени).
Перечисление 7 , создающее AudioUnitEvent (kAudioUnitEvent_PropertyChange) и уведомление AUEventListener
AudioUnitEvent myEvent; |
myEvent.mEventType = kAudioUnitEvent_PropertyChange; |
myEvent.mArgument.mProperty.mAudioUnit = mAudioUnit; |
myEvent.mArgument.mProperty.mPropertyID = kAudioUnitCustomProperty_FilterFrequencyResponse; |
myEvent.mArgument.mProperty.mScope = kAudioUnitScope_Global; |
myEvent.mArgument.mProperty.mElement = 0; |
AUEventListenerNotify(NULL, NULL, &myEvent); |
Уведомления о Начинают/Заканчивают Жесты
Аудиоустройства имеют общий метод отправки, начинают и заканчивают уведомления жеста. Начните и закончитесь, уведомления жеста отправляют событие, чтобы сказать, что параметр собирается быть измененным или закончил изменяться. Это включает и Углероду и Какао UIs, чтобы отправить и получить эти типы уведомлений о событии от взаимодействия с пользователем, затем решите, что сделать с той информацией. Этот механизм обобщает определение жестов так, чтобы любое взаимодействие с GUI могло быть интерпретировано как жест, поэтому удалив ограничение щелчков мышью (мышь, мышь вниз) как единственный допустимый жест, который может быть интерпретирован.
Например, пользователь может хотеть перетащить кнопку параметра на GUI Аудиоустройства для изменения его значения. Пользовательский интерфейс может быть сделан реагировать на выбор пользователя путем изменения цвета кнопки для обеспечения обратной связи для пользователя, что значение параметра собирается быть измененным. После того, как кнопка параметра отпускается, уведомление жеста изменения параметра конца может быть отослано для возвращения цвета кнопки.
Начните и закончитесь, уведомления жеста не имеют никаких данных, связанных с ними. Используя AUEventListenerNotify с типами событий kAudioUnitEvent_BeginParameterChangeGesture, или kAudioUnitEvent_EndParameterChangeGesture проигнорирует значение аргумента параметра, если Вы будете существовать. AudioUnitParameter через данные только пройдут AudioUnitEvent если событие имеет kAudioUnitEvent_ParameterValueChange ввести.
Перечисление 8 , Управляющее использованием изменений значения параметра, начинает и заканчивает жесты
void CreateAudioUnitEventForParameterID(AudioUnitEvent *myEvent, AudioUnitParameterID inParameterID) |
{ |
myEvent->mArgument.mParameter.mAudioUnit = mAudioUnit; |
myEvent->mArgument.mParameter.mParameterID = inParameterID; |
myEvent->mArgument.mParameter.mScope = kAudioUnitScope_Global; |
myEvent->mArgument.mParameter.mElement = 0; |
} |
void HandleMouseDown(AudioUnitEvent *myEvent) |
{ |
myEvent->mEventType = kAudioUnitEvent_BeginParameterChangeGesture; |
AUEventListenerNotify(NULL, NULL, myEvent); |
} |
void HandleParameterChange(AudioUnitEvent *myEvent) |
{ |
myEvent->mEventType =kAudioUnitEvent_ParameterValueChange; |
AUEventListenerNotify(NULL, NULL, myEvent); |
} |
void HandleMouseUp(AudioUnitEvent *myEvent) |
{ |
myEvent->mEventType = kAudioUnitEvent_EndParameterChangeGesture; |
AUEventListenerNotify(NULL, NULL, myEvent); |
} |
Сводка - выборка FilterDemo
Следующий раздел обсуждает Обработку событий Аудиоустройства с помощью Аудиоустройства демонстрационный проект FilterDemo в качестве основания для обсуждения. Фрагменты кода от AppleDemoFilter_UIView.m и AppleDemoFilter_GraphView.m файлы. В то время как некоторые более важные функции выделяются, нет никакой замены для установки выборки, установки некоторые точки останова и работы вместе с кодом для понимания логики события.
Когда параметр аудиоустройства изменяется, слушатели События Аудиоустройства используются Представлением Аудиоустройства для получения уведомлений. Существует несколько различных уведомлений (AudioUnitEventType), с одним из более важных быть kAudioUnitEvent_ParameterValueChange. Слушатели используются для разъединения Аудиоустройства от его Пользовательского интерфейса, так как Аудиоустройство может работать на различном процессе, процессоре, или даже различной машине, чем Представление, делающее непосредственное управление Аудиоустройством от Представления плохая идея.
Существует много причин изменения параметра: значение параметра могло быть программно установлено, изменено предварительной установкой, измененной другим представлением и т.д.
Аудиоустройство выборка FilterDemo использует понятие Контроллера представления Модели для разъединения Аудиоустройства от его Представления. Когда управление изменяется в Представлении, оно устанавливает значение соответствующего параметра. Это заставляет Слушателя События быть уволенным, который тогда уведомляет Представление для обновления его дисплея. Это гарантирует, что Представление и Аудиоустройство никогда не вне синхронизации.
Жесты используются узлами к автоматизации. Средства управления должны быть в состоянии сказать узел, когда они сначала тронуты, и с другой стороны когда они выпущены. Если узел перезаписывает существующую автоматизацию, он должен знать, когда управление затронуто так, чтобы, если он перемещается, могли быть перезаписаны предыдущие значения. Это сделано через kAudioUnitEvent_BeginParameterChangeGesture и kAudioUnitEvent_EndParameterChangeGesture.
В выборке FilterDemo, AppleDemoFilter_UIView действия как Контроллер, в то время как AppleDemoFilter_GraphView действия как Представление.

setAU: когда GraphView (как замечено на рисунке 1) инстанцируют, показанный в Перечислении 9 вызывается. Этот метод ответственен за установку различных слушателей события как требуется Представлением. Уведомления Какао являются связующим звеном контроллера, используемым для передачи между GraphView и Контроллером Представления поэтому, когда GraphView изменяется, уведомление Какао отправляются в Контроллер.
Перечисление 9 , настраивающее представление
- (void)setAU:(AudioUnit)inAU { |
// remove previous listeners |
if (mAU) |
[self priv_removeListeners]; |
if (!mData) // only allocate the data once |
mData = malloc(kNumberOfResponseFrequencies * sizeof(FrequencyResponse)); |
mData = [graphView prepareDataForDrawing: mData]; // fill out the initial |
//frequency values for the data displayed by the graph |
// register for resize notification and data changes for the graph view |
[[NSNotificationCenter defaultCenter] addObserver: self |
selector: @selector(handleGraphDataChanged:) |
name: kGraphViewDataChangedNotification |
object: graphView]; |
[[NSNotificationCenter defaultCenter] addObserver: self |
selector: @selector(handleGraphSizeChanged:) |
name: NSViewFrameDidChangeNotification |
object: graphView]; |
[[NSNotificationCenter defaultCenter] addObserver: self |
selector: @selector(beginGesture:) |
name: kGraphViewBeginGestureNotification |
object: graphView]; |
[[NSNotificationCenter defaultCenter] addObserver: self |
selector: @selector(endGesture:) |
name: kGraphViewEndGestureNotification |
object: graphView]; |
mAU = inAU; |
// add new listeners |
[self priv_addListeners]; |
// initial setup |
[self priv_synchronizeUIWithParameterValues]; |
} |
priv_addListeners от метода, показанного в Перечислении 10, вызывают setAU: создание слушателя События Аудиоустройства и добавление типов событий.
Перечисление 10 , создающее слушателя события аудиоустройства и добавляющее типы событий
void addParamListener (AUEventListenerRef listener, void* refCon, AudioUnitEvent *inEvent) |
{ |
inEvent->mEventType = kAudioUnitEvent_BeginParameterChangeGesture; |
verify_noerr (AUEventListenerAddEventType(listener, refCon, inEvent)); |
inEvent->mEventType = kAudioUnitEvent_EndParameterChangeGesture; |
verify_noerr (AUEventListenerAddEventType(listener, refCon, inEvent)); |
inEvent->mEventType = kAudioUnitEvent_ParameterValueChange; |
verify_noerr (AUEventListenerAddEventType(listener, refCon, inEvent)); |
} |
- (void)priv_addListeners |
{ |
if (mAU) { |
verify_noerr(AUEventListenerCreate(EventListenerDispatcher, self, |
CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0.05, 0.05, |
&mAUEventListener)); |
AudioUnitEvent auEvent; |
AudioUnitParameter parameter = {mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0 }; |
auEvent.mArgument.mParameter = parameter; |
addParamListener (mAUEventListener, self, &auEvent); |
auEvent.mArgument.mParameter.mParameterID = kFilterParam_Resonance; |
addParamListener (mAUEventListener, self, &auEvent); |
/* Add a listener for the changes in our custom property */ |
/* The Audio unit will send a property change when the unit is initialized */ |
auEvent.mEventType = kAudioUnitEvent_PropertyChange; |
auEvent.mArgument.mProperty.mAudioUnit = mAU; |
auEvent.mArgument.mProperty.mPropertyID = kAudioUnitCustomProperty_FilterFrequencyResponse; |
auEvent.mArgument.mProperty.mScope = kAudioUnitScope_Global; |
auEvent.mArgument.mProperty.mElement = 0; |
verify_noerr (AUEventListenerAddEventType (mAUEventListener, self, &auEvent)); |
} |
} |
События Аудиоустройства обрабатываются через EventListenerDispatcher функция (установленный вызовом на AUEventListenerCreate в Перечислении 10) и priv_eventListener:event: метод так GraphView может обновить как требуется.
Перечисление 11 слушатель события аудиоустройства.
void EventListenerDispatcher (void *inRefCon, void *inObject, const AudioUnitEvent *inEvent, |
UInt64 inHostTime, Float32 inValue) |
{ |
AppleDemoFilter_UIView *SELF = (AppleDemoFilter_UIView *)inRefCon; |
[SELF priv_eventListener:inObject event: inEvent value: inValue]; |
} |
- (void)priv_eventListener:(void *) inObject event:(const AudioUnitEvent *)inEvent value:(Float32)inValue { |
switch (inEvent->mEventType) { |
case kAudioUnitEvent_ParameterValueChange: // Parameter Changes |
switch (inEvent->mArgument.mParameter.mParameterID) { |
case kFilterParam_CutoffFrequency: // handle cutoff frequency parameter |
[cutoffFrequencyField setFloatValue: inValue]; // update the frequency text field |
[graphView setFreq: inValue]; // update the graph's frequency visual state |
break; |
case kFilterParam_Resonance: // handle resonance parameter |
[resonanceField setFloatValue: inValue]; // update the resonance text field |
[graphView setRes: inValue]; // update the graph's gain visual state |
break; |
} |
// get the curve data from the audio unit |
[self updateCurve]; |
break; |
case kAudioUnitEvent_BeginParameterChangeGesture: // Begin gesture |
[graphView handleBeginGesture]; // notify graph view to update visual state |
break; |
case kAudioUnitEvent_EndParameterChangeGesture: // End gesture |
[graphView handleEndGesture]; // notify graph view to update visual state |
break; |
case kAudioUnitEvent_PropertyChange: // custom property changed |
if (inEvent->mArgument.mProperty.mPropertyID == kAudioUnitCustomProperty_FilterFrequencyResponse) |
[self updateCurve]; |
break; |
} |
} |
Когда пользователь вводит новое значение в поле Cutoff Frequency, вот основной поток управления:
Пользователь вводит новое значение в поле Cutoff Frequency.
Контроллер UIView
cutoffFrequencyChanged:действие вызывают, см. перечисление 12.Вызов к
AUParameterSetсделан дляkFilterParam_CutoffFrequencyпараметр с новым значением.Значение параметра установлено в Аудиоустройстве.
Аудиоустройство уведомляет слушателей изменения значения параметра.
UIView contoller
priv_eventListener:event:value:метод вызывают.Контроллер UIView устанавливает значение в поле и говорит GraphView перерисовывать.
Перечисление 12 , обрабатывающее изменение значения в поле частоты отсечки.
- (IBAction) cutoffFrequencyChanged:(id)sender { |
float floatValue = [sender floatValue]; |
AudioUnitParameter cutoffParameter = {mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0 }; |
NSAssert(AUParameterSet(mAUEventListener, sender, &cutoffParameter, (Float32)floatValue, 0) == noErr, |
@"[AppleDemoFilter_UIView cutoffFrequencyChanged:] AUParameterSet()"); |
} |
Вызов к AUParameterSet изменяет значение параметра Аудиоустройства и заставляет Аудиоустройство выходить, параметр изменил сообщение. Вы видите, что экземпляр аудиоустройства передается, как первый элемент в AudioUnitParameter структура.
1) Устанавливает значение параметра AudioUnit.
2) Выполняет/планирует обратные вызовы уведомления всем слушателям параметра для параметра - отмечают, что никакой обратный вызов не сгенерирован для inListener / inObject пара.
Когда пользователь вводит новое значение в Управление GraphView, вот основного потока управления:
Пользователь перемещает Управление GraphView.
GraphView
mouseDown:сообщения akGraphViewBeginGestureNotificationУведомление какао.Контроллер UIView получает уведомление Какао через
beginGesture:метод.Вызовы Контроллера UIView
AUEventListenerNotifyуведомлять всех слушателей (Узел, например)kAudioUnitEvent_BeginParameterChangeGestureСобытие аудиоустройства.GraphView реагирует на событие от нажатия мыши путем вызова
handleMouseEventAtLocation:тогда сообщения akGraphViewDataChangedNotificationУведомление какао.Контроллер UIView обрабатывает это уведомление в
handleGraphDataChanged:и вызовыAUParameterSetодин раз для каждого параметра.Значения параметров установлены в Аудиоустройстве.
Аудиоустройство уведомляет слушателей изменения значения параметра.
UIView contoller
priv_eventListener:event:value:метод вызывают.Контроллер UIView устанавливает значение в полях и говорит GraphView перерисовывать.
GraphView mouseUp: сообщения a
kGraphViewEndGestureNotificationУведомление какао.Контроллер UIView получает уведомление Какао через
endGesture:метод.Вызовы Контроллера UIView
AUEventListenerNotifyуведомлять всех слушателей (Узел, например)kAudioUnitEvent_EndParameterChangeGestureСобытие аудиоустройства.
Перечисление 13 , отправляющее kAudioUnitEvent_BeginParameterChangeGesture Событие аудиоустройства.
- (void) beginGesture:(NSNotification *) aNotification { |
AudioUnitEvent event; |
AudioUnitParameter parameter = {mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0 }; |
event.mArgument.mParameter = parameter; |
event.mEventType = kAudioUnitEvent_BeginParameterChangeGesture; |
AUEventListenerNotify (mAUEventListener, self, &event); |
event.mArgument.mParameter.mParameterID = kFilterParam_Resonance; |
AUEventListenerNotify (mAUEventListener, self, &event); |
} |
Перечисление 14 , обрабатывающее изменения значения.
- (void) handleGraphDataChanged:(NSNotification *) aNotification { |
float resonance = [graphView getRes]; |
float cutoff = [graphView getFreq]; |
AudioUnitParameter cutoffParameter = {mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0 }; |
AudioUnitParameter resonanceParameter = {mAU, kFilterParam_Resonance, kAudioUnitScope_Global, 0 }; |
NSAssert(AUParameterSet(mAUEventListener, cutoffFrequencyField, &cutoffParameter, (Float32)cutoff, 0) == |
noErr, @"[AppleDemoFilter_UIView cutoffFrequencyChanged:] AUParameterSet()"); |
NSAssert(AUParameterSet(mAUEventListener, resonanceField, &resonanceParameter, (Float32)resonance, 0) == |
noErr, @"[AppleDemoFilter_UIView resonanceChanged:] AUParameterSet()"); |
} |
Перечисление 15 , отправляющее kAudioUnitEvent_EndParameterChangeGesture Событие аудиоустройства.
- (void) endGesture:(NSNotification *) aNotification { |
AudioUnitEvent event; |
AudioUnitParameter parameter = {mAU, kFilterParam_CutoffFrequency, kAudioUnitScope_Global, 0 }; |
event.mArgument.mParameter = parameter; |
event.mEventType = kAudioUnitEvent_EndParameterChangeGesture; |
AUEventListenerNotify (mAUEventListener, self, &event); |
event.mArgument.mParameter.mParameterID = kFilterParam_Resonance; |
AUEventListenerNotify (mAUEventListener, self, &event); |
} |
priv_removeListeners от метода вызывают dealloc когда GraphView уничтожается и вызывает AUListenerDispose расположить слушателя.
Перечисление 16 , удаляющее слушателя.
- (void)priv_removeListeners |
{ |
if (mAUEventListener) verify_noerr (AUListenerDispose(mAUEventListener)); |
mAUEventListener = NULL; |
mAU = NULL; |
} |
Ссылки
Аудиоустройство Выборка FilterDemo установлено со Средствами разработки XCode.
История версии документа
| Дата | Примечания |
|---|---|
| 27.10.2011 | Передовая статья |
| 10.12.2009 | Передовая статья |
| 18.05.2009 | Редакционные исправления и добавленный сводный раздел. |
| 29.04.2005 | Разъяснение уведомлений AUEvent. |
| 16.02.2004 | Новый документ, который объясняет этот technote, как обработать События AudioUnit |