Creating custom audio effects
At a glance
| Item | Summary |
|---|---|
| Purpose | Add custom audio-effect processing to apps like Logic Pro X and GarageBand by creating Audio Unit (AU) plug-ins. |
| App architecture | A C/Objective-C header, Objective-C++, Swift sample bundle with entry-bearing project variants iOS, macOS, each leading to AUv3FilterFramework / CoreAudioKit APIs. |
| Main patterns | View-controller organization, Protocol-oriented abstraction, Delegate or data-source callbacks, Adapter |
| Project style | 25 scanned source file(s) across C/Objective-C header, Objective-C++, Swift, organized around ranked entry, type, and file boundaries. |
| Execution model | Source-visible boundaries: DispatchQueue.main.async, DispatchQueue(label:), DispatchQueue.global.async; none alone proves a background thread. |
| State/event model | No structured observation or publisher-scheduling marker indexed. |
| Key frameworks/packages | AUv3FilterFramework, CoreAudioKit, AudioToolbox, AVFoundation, Foundation; these are source dependencies, not architecture labels. |
Project structure
Source bundle/
├── Shared/
│ ├── Support/
│ │ ├── User Interface/
│ │ │ └── FilterView.swift
│ │ └── Audio/
│ │ └── SimplePlayEngine.swift
│ ├── AudioUnitManager.swift
│ ├── AUv3FilterDemoViewController.swift
│ └── AudioUnit/
│ ├── Support/
│ │ ├── FilterDSPKernelAdapter.h
│ │ ├── FilterDSPKernelAdapter.mm
│ │ └── AUv3Base.mm
│ └── AUv3FilterDemoParameters.swift
├── iOS/
│ └── AUv3Filter/
│ ├── AppDelegate.swift
│ └── MainViewController.swift
└── macOS/
└── AUv3Filter/
├── AppDelegate.swift
└── MainViewController.swift
Structure observations
- Architecturally prominent files are ranked from entry points and role-named declarations; resource-only paths are omitted.
- Primary languages: C/Objective-C header, Objective-C++, Swift.
- The verified tree contains 17 project/configuration file(s) and 18 source declaration(s).
Overall architecture
flowchart LR
Bundle["Sample bundle"]
V1["iOS"]
V2["macOS"]
Boundary["AUv3FilterFramework / CoreAudioKit APIs"]
Bundle --> V1
V1 --> Boundary
Bundle --> V2
V2 --> Boundary
Reference code
iOS/AUv3Filter/AppDelegate.swift:10 — architecture anchor
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
}Interpretation
The branches represent separate entry-bearing project variants in the downloaded bundle, not runtime calls between those variants. Each branch is intentionally collapsed at the documented framework boundary; the detailed target-local flow remains in the cited files. Ownership is claimed only where the next section cites a stored property or assignment.
Ownership and state
classDiagram
FilterView *-- Float : defaultMinHertz
FilterView *-- Float : defaultMaxHertz
FilterView *-- CGFloat : leftMargin
FilterView *-- CGFloat : rightMargin
Ownership evidence
Shared/Support/User Interface/FilterView.swift:8 — stored dependency or nearest verified ownership anchor
public let defaultMinHertz: Float = 12.0| Owner | Object or state | Relationship | Mutation authority |
|---|---|---|---|
FilterView |
Float (defaultMinHertz) |
owns value state | Initialized by the owner; the binding is immutable |
FilterView |
Float (defaultMaxHertz) |
owns value state | Initialized by the owner; the binding is immutable |
FilterView |
CGFloat (leftMargin) |
owns value state | Initialized by the owner; the binding is immutable |
FilterView |
CGFloat (rightMargin) |
owns value state | Initialized by the owner; the binding is immutable |
Composition arrows indicate a source-visible construction expression or locally owned value state; aggregation means the owner stores or receives a dependency without proving exclusive lifetime ownership.
Concurrency, scheduling, and thread safety
Evidence limit: actor isolation, async/await, or Task creation does not by itself prove background-thread execution; Sendable conformance alone does not prove thread-safe mutation.
| Concern | Source mechanism | Verified placement or handoff | Evidence |
|---|---|---|---|
| Queue scheduling | DispatchQueue.main.async |
The source addresses the main dispatch queue. | Shared/AUv3FilterDemoViewController.swift:124 |
| Queue scheduling | DispatchQueue(label:) |
The source constructs a dispatch queue; its label alone does not prove a thread. | Shared/Support/Audio/SimplePlayEngine.swift:18 |
| Queue scheduling | DispatchQueue.global.async |
The source addresses a global dispatch queue; no stable thread identity is implied. | Shared/Support/Audio/SimplePlayEngine.swift:293 |
@MainActor/MainActor.run, DispatchQueue.main, and RunLoop.main are reported as distinct isolation, queue, and event-loop mechanisms. A plain Task is kept separate from Task.detached; neither is labeled as a background thread.
Reference code
Shared/AUv3FilterDemoViewController.swift:124 — representative execution boundary
DispatchQueue.main.async {
self.updateUI()
}State propagation, frameworks, and dependencies
Evidence limit: an import proves a source-level compilation dependency at the cited line; it does not prove runtime use, architectural adoption, or whether a Swift package is a direct application dependency.
| Category | Mechanism or module | Verified role | Evidence |
|---|---|---|---|
| Source import | AUv3FilterFramework |
The cited file imports this module; runtime use and architectural role are not inferred. | Shared/AudioUnit/Support/AUv3Base.h:10 |
| Source import | CoreAudioKit |
The cited file imports this module; runtime use and architectural role are not inferred. | Shared/AUv3FilterDemoViewController.swift:8 |
| Source import | AudioToolbox |
The cited file imports this module; runtime use and architectural role are not inferred. | Shared/AudioUnit/AUv3FilterDemo.swift:9 |
| Source import | AVFoundation |
The cited file imports this module; runtime use and architectural role are not inferred. | Shared/AudioUnit/AUv3FilterDemo.swift:10 |
| Source import | Foundation |
The cited file imports this module; runtime use and architectural role are not inferred. | Shared/AudioUnit/AUv3FilterDemo.swift:8 |
| Source import | UIKit |
The cited file imports this module; runtime use and architectural role are not inferred. | Shared/Support/User Interface/TypeAliases.swift:9 |
receive(on:) describes downstream delivery scheduling, while subscribe(on:) describes upstream subscription/request/cancel scheduling. An import Combine alone establishes neither behavior nor a Store, reducer, Redux, or other application architecture.
Class and protocol design
Shared/Support/User Interface/FilterView.swift:12 — representative type boundary
protocol FilterViewDelegate: AnyObject {
func filterViewTouchBegan(_ filterView: FilterView)
// ...
}| Type | Responsibility | Depends on or conforms to |
|---|---|---|
AppDelegate |
Receives callback-driven events | UIResponder, UIApplicationDelegate |
AppDelegate |
Receives callback-driven events | NSObject, NSApplicationDelegate |
FilterViewDelegate |
Defines a capability or collaboration contract | AnyObject |
AUManagerDelegate |
Defines a capability or collaboration contract | AnyObject |
FilterView |
User-interface presentation and input forwarding | View |
AudioUnitManager |
Long-lived feature or framework coordination | Concrete collaborators/imported frameworks |
SimplePlayEngine |
Owns processing or simulation work | Concrete collaborators/imported frameworks |
InstrumentPlayer |
Owns media or timeline playback | Concrete collaborators/imported frameworks |
AUv3FilterDemoViewController |
View lifecycle, callbacks, and feature coordination | AUViewController |
FilterDSPKernelAdapter |
Translates one interface or representation into another | NSObject |
The source explicitly defines local protocol relationships: AUv3FilterDemoViewController → FilterViewDelegate, MainViewController → AUManagerDelegate, MainViewController → AUManagerDelegate.
Access control
| Symbol | Access | Verified effect | Likely rationale |
|---|---|---|---|
viewConfig (Shared/AUv3FilterDemoViewController.swift:15) |
private |
Use is restricted to the lexical declaration and same-file extensions allowed by Swift. | Inference: keep state mutation or dependency lifetime inside the owning implementation. |
cutoffParameter (Shared/AUv3FilterDemoViewController.swift:17) |
private |
Use is restricted to the lexical declaration and same-file extensions allowed by Swift. | Inference: keep state mutation or dependency lifetime inside the owning implementation. |
resonanceParameter (Shared/AUv3FilterDemoViewController.swift:18) |
private |
Use is restricted to the lexical declaration and same-file extensions allowed by Swift. | Inference: keep state mutation or dependency lifetime inside the owning implementation. |
parameterObserverToken (Shared/AUv3FilterDemoViewController.swift:19) |
private |
Use is restricted to the lexical declaration and same-file extensions allowed by Swift. | Inference: keep state mutation or dependency lifetime inside the owning implementation. |
Reference code
Shared/AUv3FilterDemoViewController.swift:15 — representative boundary
public class AUv3FilterDemoViewController: AUViewController {
// ...
private var viewConfig: AUAudioUnitViewConfiguration!
// ...
}Swift declarations without a modifier are internal; explicit private, fileprivate, private(set), public, or open entries above are interpreted by language semantics. Objective-C/C samples instead rely on header and implementation boundaries, which are not equivalent to Swift lexical privacy.
Logic ownership and placement
| Logic | Owning type or file | Placement rationale |
|---|---|---|
| Translates one interface or representation into another | FilterDSPKernelAdapter |
The source’s Adapter suffix makes this role explicit. |
| View lifecycle, callbacks, and feature coordination | AUv3FilterDemoViewController, MainViewController |
The source’s Controller suffix makes this role explicit. |
| Receives callback-driven events | AUManagerDelegate, AppDelegate, FilterViewDelegate |
The source’s Delegate suffix makes this role explicit. |
| Owns processing or simulation work | SimplePlayEngine |
The source’s Engine suffix makes this role explicit. |
| Long-lived feature or framework coordination | AudioUnitManager |
The source’s Manager suffix makes this role explicit. |
| Owns media or timeline playback | InstrumentPlayer |
The source’s Player suffix makes this role explicit. |
| User-interface presentation and input forwarding | FilterView |
The source’s View suffix makes this role explicit. |
Design patterns
| Pattern | Source evidence | Purpose or tradeoff |
|---|---|---|
| View-controller organization | Shared/AUv3FilterDemoViewController.swift:10 |
A controller is the verified coordination boundary; this is MVC-style only where a separate model is present. |
| Protocol-oriented abstraction | Shared/AUv3FilterDemoViewController.swift:225 |
A local protocol and concrete conformance create an explicit capability boundary. |
| Delegate or data-source callbacks | iOS/AUv3Filter/AppDelegate.swift:11 |
Callback protocols invert event delivery back into the sample’s owner. |
| Adapter | Shared/AudioUnit/Support/FilterDSPKernelAdapter.h:14 |
An adapter-named type translates interfaces or representations. |
Naming conventions
- Types: Adapter: FilterDSPKernelAdapter; Controller: AUv3FilterDemoViewController, MainViewController; Delegate: AUManagerDelegate, AppDelegate, FilterViewDelegate; Engine: SimplePlayEngine; Manager: AudioUnitManager; Player: InstrumentPlayer; View: FilterView.
- Protocols:
FilterViewDelegate,AUManagerDelegate. - Methods:
filterViewTouchBegan,filterView,filterViewTouchEnded,filterViewDataDidChange,clamp,noAnimation,valueAtGridIndex,logValueForNumber. - Files:
Shared/Support/User Interface/FilterView.swift,iOS/AUv3Filter/AppDelegate.swift,macOS/AUv3Filter/AppDelegate.swift,Shared/AudioUnitManager.swift,Shared/Support/Audio/SimplePlayEngine.swift,Shared/AUv3FilterDemoViewController.swift.
Architecture takeaways
AppDelegateis the main source-visible entry or composition anchor for this sample.- Framework work reaches AUv3FilterFramework, CoreAudioKit, AVFoundation, AudioToolbox through a deliberately small high-level chain; the detailed API graph remains inside the cited implementation files.
- Stored-property evidence identifies lifecycle collaboration; it does not by itself prove exclusive object ownership.
- Access-control conclusions separate verified language visibility from the likely design rationale.
- Local protocol relationships provide an explicit substitution boundary.
Source map
| Source file | Relevant symbols |
|---|---|
iOS/AUv3Filter/AppDelegate.swift |
Cited implementation, AppDelegate |
Shared/Support/User Interface/FilterView.swift |
Cited implementation, FilterViewDelegate, func, FilterView, ColorLayer |
Shared/AUv3FilterDemoViewController.swift |
Cited implementation, AUv3FilterDemoViewController, DispatchQueue.main.async, CoreAudioKit |
Shared/AudioUnit/Support/FilterDSPKernelAdapter.h |
FilterDSPKernelAdapter |
Shared/Support/Audio/SimplePlayEngine.swift |
DispatchQueue(label:), DispatchQueue.global.async, SimplePlayEngine, InstrumentPlayer |
Shared/AudioUnit/Support/AUv3Base.h |
AUv3FilterFramework, AUv3Base |
Shared/AudioUnit/AUv3FilterDemo.swift |
AudioToolbox, AVFoundation, Foundation, AUv3FilterDemo |
Shared/Support/User Interface/TypeAliases.swift |
UIKit, Feature implementation |
macOS/AUv3Filter/AppDelegate.swift |
AppDelegate |
Shared/AudioUnitManager.swift |
Preset, AUManagerDelegate, AudioUnitManager |
Shared/AudioUnit/Support/FilterDSPKernelAdapter.mm |
FilterDSPKernelAdapter |
iOS/AUv3Filter/MainViewController.swift |
MainViewController |
macOS/AUv3Filter/MainViewController.swift |
MainViewController |
Shared/AudioUnit/AUv3FilterDemoParameters.swift |
AUv3FilterDemoParameters, AUv3FilterParam |
Shared/AudioUnit/Support/AUv3Base.mm |
AUv3Base |
Shared/AudioUnit/Support/DSPKernel.mm |
Feature implementation |