Integrating Processing
This guide explains how to add a custom Audio Processing component with MimiCore
inside MimiSDK, providing your users with Mimified audio.
Activation
As the MimiProcessingController
owns the MimiProcessingSession
; it is the location where processing can be “activated” or “deactivated”.
Note: Activation refers to the ability for parameters values to be transferred and not whether the physical processing effect is enabled or disabled.
Before activating a MimiProcessingSession
, you will need to create a preset parameter data source. The SDK currently provides two preset parameter data sources which are explained in Preset Parameter Data Sources.
A MimiProcessingSession
can be activated as follows:
do {
let fitting = MimiPersonalization.Fitting.techLevel(3) // An example fitting, yours will be defined by your Processing system
let presetDataSource = MimiDefaultPresetParameterDataSource(fitting: fitting)
_ = try MimiCore.shared.processing.activate(presetDataSource: .default(presetDataSource))
} catch {
// Handle activation failure
}
Once there is an activated MimiProcessingSession
, it is possible to access the processing parameters and configure them appropriately.
- Activating a session will set the
session.value
property on theMimiProcessingController
allowing the session to be easily referenced. - Only a single session can be activated at one time.
MimiProcessingController.session
is aCurrentValueSubject
and can be subscribed for changes that occur during the activation & deactivation of a session.
Tip: Most partner integrations will only need to use a single, long-lived MimiProcessingSession
that roughly aligns with the application lifecycle.
Parameter Value Operations
Observing the current value
The value
property of the MimiProcessingParameter
is published var and can be subscribed to as follows.
cancellable = parameter.$value
.sink { value in
// Do something with value
}
Value application sequence summary
The internal process of updating a MimiProcessingParameter
value or sending value updates to the associated applicators follows a specific sequence as executed by the MimiProcessingParameter
:
- Value update is triggered with the
apply(value:)
method. - Based on the delivery mode, the update is handled either immediately (
continous
) or debounced (discrete
). - The out-of-date applicators are filtered out from the list of associated applicators. If no out-of-date applicators are found, then the parameter is immediately updated with the value and the subscribers are notified of the success.
- If any out-of-date applicators are found, they are then asked to verify that they are capable of applying the value via their
canApply
method. - If any out-of-date applicator fails the
canApply
verification (i.e. by returningfalse
), the value application sequence is abandoned with an error and subscribers are notified of the failure. - After all out-of-date applicators pass the
canApply
verification (i.e. by returningtrue
), the applicators are requested to apply the new value via theirapply
method. - If any applicator fails to apply the value (by returning a
failure(Error)
), the application sequence is abandoned with an error and the subscribers are notified of the failure. - If the applicator applies the value successfully (by returning a
success
), the parameter value is updated and the subscribers are notified of the success.
Updating the value
The parameter value can be updated via the apply(value:)
method. This method will attempt to apply the provided value on all registered applicators that are out-of-date. For the application to succeed, success
must be reported by all applicators that the application is attempted on. If any of the applicators fail to report this, the overall application is considered a failure and will escape.
cancellable = parameter.apply(value)
.sink { completion in
// Do something with completion
} receiveValue: { value in
// Do something with value
}
Note: For remote parameters, please use the reload()
method which will attempt to reload a new parameter value from a remote data source and then apply it on all registered applicators.
Delivery Mode
The delivery mode of a MimiProcessingParameter
describes how it handles requests to update the parameter value.
By default, the updates are handled in a continuous manner, meaning they are delivered to the applicators immediately when the parameter is updated via the apply(value:)
method. This can be customized to an alternate delivery mode if preferred:
.continuous
(Default) - Executes parameter updates immediately..discrete(seconds:)
- Debounces parameter updates for a specified time interval before executing them.swift // Sets the delivery mode to discrete with a debounce interval of 200ms. parameter.deliveryMode = .discrete(seconds: 0.2)
Defining an Applicator
An applicator can be defined and added using the MimiProcessingParameter.applicator()
method. Since the applicator is held weakly by the parameter, you will need to maintain a strong reference to it.
// Make sure to hold on to the applicator strongly.
let applicator = parameter.applicator()
.canApply { value in
// Verify if value can be applied
return true // or false
}
.apply { value, result in
// Apply the value and execute result handler
result(.success) // or result(.failure(error))
}
Alternatively, an applicator can also be created while synchronizing an existing value to the parameter. This method returns a tuple containing the newly registered applicator and a Publisher
that wraps the application task for applying the synchronized value
.
// Make sure to hold on to the applicator strongly.
var (applicator, resultPublisher) = parameter.applicator(synchronizing: aValue)
applicator = applicator
.canApply { value in
// Verify if value can be applied
return true // or false
}
.apply { value, result in
// Apply the value and execute result handler
result(.success) // or result(.failure(error))
}
cancellable = resultPublisher
.sink { completion in
// Do something with completion
} receiveValue: { value in
// Do something with value
}
Application timeout
It is also possible to set a timeout for the application of a value on the MimiProcessingApplicator
. If the value application exceeds this timeout, it will cause the entire value application sequence to fail.
// Make sure to hold on to the applicator strongly.
let applicator = parameter.applicator()
.timeout(0.5) // A timeout of 500 milliseconds
.canApply { value in
// Verify if value can be applied
return true // or false
}
.apply { value, result in
// Apply the value and execute result handler
// If the timeout expires before the result handler is executed
// the value application will be considered a failure.
result(.success) // or result(.failure(error))
}
Removing an Applicator
Since the applicator is held weakly by its associated parameter, simply setting the applicator to nil
is enough to remove it from the parameter’s list of applicators.
Session Interruptions
The processing session provides the ability to be interrupted via the MimiProcessingSession.interrupt(reason:)
method. Interrupting a session leads to its isEnabled
parameter to be set to false
. This value cannot be changed until all the session interruptions are resolved via the MimiProcessingSession.resolve(interruption:)
method. Once all the interruptions have been resolved, the value of the isEnabled
parameter is set back to its pre-interruption value.
// Interrupting a session
let interruption = "MySessionInterruption"
cancellable = session.interrupt(reason: interruption)
.sink { completion in
// Do something with completion
} receiveValue: { isInterrupted in
// Do something with isInterrupted
}
// Resolving session interruption
cancellable = session.resolve(interruption: interruption)
.sink { completion in
// Do something with completion
} receiveValue: { isInterrupted in
// Do something with isInterrupted
}
Note: Certain events in MimiSDK
such as launching of the test flow also lead to the session being temporarily interrupted.
Parameter Recommendations
Based on certain events in MimiSDK
e.g. user authentication, hearing test submission etc, the processing parameters are automatically set to recommended values.