SimplyCoreAudio
(formerly known as AMCoreAudio
) is a Swift framework that aims to make Core Audio use less tedious in macOS.
- Enumerating audio devices (see SimplyCoreAudio)
- Getting/setting default input, output and system device (see SimplyCoreAudio)
- Creating and destroying aggregate devices (see SimplyCoreAudio)
- Querying audio device properties such as: name, manufacturer, UID, volume, mute, sample rate, clock source, etc. (see AudioDevice)
- Managing (physical and virtual) audio streams associated to an audio device (see AudioStream)
- Subscribing to audio hardware, audio device, and audio stream notifications (see Notification Extensions)
- Xcode 12+
- Swift 4.0+
- macOS 10.12+
To install the Swift Package, please follow the steps below:
- Add
https://github.com/rnine/SimplyCoreAudio.git
as a Swift Package Manager dependency to your project. - When asked to Choose Package Options, use the default settings provided by Xcode.
- When asked to Add Package, add
SimplyCoreAudio
to your desired target(s).
-
Import
SimplyCoreAudio
import SimplyCoreAudio
-
Instantiate
SimplyCoreAudio
let simplyCA = SimplyCoreAudio()
-
Interact with
SimplyCoreAudio
// Get the default output device let device = simplyCA.defaultOutputDevice // Get preferred output channels if let stereoPair = device.preferredChannelsForStereo(scope: .output) { let leftChannel = stereoPair.left let rightChannel = stereoPair.right // Use channels... } // Get device samplerate if let sampleRate = device.nominalSampleRate { // Use samplerate... } // Get device virtual main volume if let outVolume = device.virtualMainVolume(scope: .output) { // Use output volume... }
-
Subscribe to hardware-related notifications
// e.g., subscribing to `deviceListChanged` notification. var observer = NotificationCenter.default.addObserver(forName: .deviceListChanged, object: nil, queue: .main) { (notification) in // Get added devices. guard let addedDevices = notification.userInfo?["addedDevices"] as? [AudioDevice] else { return } // Get removed devices. guard let removedDevices = notification.userInfo?["removedDevices"] as? [AudioDevice] else { return } } // Once done observing, remove observer and nil it. NotificationCenter.default.removeObserver(observer) observer = nil
-
Subscribe to notifications from a specific audio device
// Get the default output device let device = simplyCA.defaultOutputDevice // e.g., subscribing to `deviceNominalSampleRateDidChange` notification. var observer = NotificationCenter.default.addObserver(forName: .deviceNominalSampleRateDidChange, object: device, queue: .main) { (notification) in // Handle notification. } // Once done observing, remove observer and nil it. NotificationCenter.default.removeObserver(observer) observer = nil
-
Subscribe to notifications from a specific audio stream
// Get the default output device let device = simplyCA.defaultOutputDevice // Get the first output stream guard let streams = device.streams(scope: .output) else { return } guard let stream0 = streams.first else { return } // e.g., subscribing to `streamPhysicalFormatDidChange` notification. var observer = NotificationCenter.default.addObserver(forName: .streamPhysicalFormatDidChange, object: stream0, queue: .main) { (notification) in // Handle notification. } // Once done observing, remove observer and nil it. NotificationCenter.default.removeObserver(observer) observer = nil
Name | Purpose | User Info |
---|---|---|
defaultInputDeviceChanged |
Called whenever the default input device changes. | N/A |
defaultOutputDeviceChanged |
Called whenever the default output device changes. | N/A |
defaultSystemOutputDeviceChanged |
Called whenever the default system output device changes. | N/A |
deviceListChanged |
Called whenever the list of hardware devices and device subdevices changes. | addedDevices: [AudioDevice] , removedDevices: [AudioDevice] |
Name | Purpose | User Info |
---|---|---|
deviceNominalSampleRateDidChange |
Called whenever the audio device's sample rate changes. | N/A |
deviceAvailableNominalSampleRatesDidChange |
Called whenever the audio device's list of nominal sample rates changes. | N/A |
deviceClockSourceDidChange |
Called whenever the audio device's clock source changes. | N/A |
deviceNameDidChange |
Called whenever the audio device's name changes. | |
deviceOwnedObjectsDidChange |
Called whenever the list of owned audio devices on this audio device changes. | N/A |
deviceVolumeDidChange |
Called whenever the audio device's volume for a given channel and scope changes. | channel: UInt32 , scope: Scope |
deviceMuteDidChange |
Called whenever the audio device's mute state for a given channel and scope changes. | channel: UInt32 , scope: Scope |
deviceIsAliveDidChange |
Called whenever the audio device's list of nominal sample rates changes. | N/A |
deviceIsRunningDidChange |
Called whenever the audio device's is running property changes. | N/A |
deviceIsRunningSomewhereDidChange |
Called whenever the audio device's is running somewhere property changes. | N/A |
deviceIsJackConnectedDidChange |
Called whenever the audio device's is jack connected property changes. | N/A |
devicePreferredChannelsForStereoDidChange |
Called whenever the audio device's preferred channels for stereo property changes. | N/A |
deviceHogModeDidChange |
Called whenever the audio device's hog mode property changes. | N/A |
Name | Purpose | User Info |
---|---|---|
streamIsActiveDidChange |
Called whenever the audio stream isActive flag changes state. |
N/A |
streamPhysicalFormatDidChange |
Called whenever the audio stream physical format changes. | N/A |
Do you want to contribute to the project? Please fork, patch, and then submit a pull request!
Please make sure to install NullAudio.driver
before attempting to run tests:
-
Unzip
NullAudio.driver.zip
and install driver into the system HAL Plug-Ins foldersudo unzip Tests/Extras/NullAudio.driver.zip -d /Library/Audio/Plug-Ins/HAL
-
Reload
coreaudiod
sudo launchctl kill KILL system/com.apple.audio.coreaudiod
- SimplyCoreAudioDemo — a basic SwiftUI-based demo showcasing device enumeration and notifications.
SimplyCoreAudio
was written by Ruben Nine (@rnine) in 2013-2014 (open-sourced in March 2014) and is licensed under the MIT license. See LICENSE.md.