### Get and Set Default Audio Devices (Swift) Source: https://context7.com/rnine/simplycoreaudio/llms.txt Shows how to query the current default input, output, and system output devices using SimplyCoreAudio. It also demonstrates how to change these default devices programmatically and verify the changes. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() // Get current default devices if let defaultInput = simplyCA.defaultInputDevice { print("Default input: \(defaultInput.name)") print("Input UID: \(defaultInput.uid ?? "Unknown")") } if let defaultOutput = simplyCA.defaultOutputDevice { print("Default output: \(defaultOutput.name)") print("Output UID: \(defaultOutput.uid ?? "Unknown")") } if let systemOutput = simplyCA.defaultSystemOutputDevice { print("System output: \(systemOutput.name)") } // Change default devices if let device = simplyCA.allOutputDevices.first { // Set as default output device device.isDefaultOutputDevice = true // Set as default input device (if it supports input) if device.channels(scope: .input) > 0 { device.isDefaultInputDevice = true } // Set as system output device device.isDefaultSystemOutputDevice = true } // Check if a device is currently the default if let device = simplyCA.defaultOutputDevice { print("Is default output: \(device.isDefaultOutputDevice)") // true print("Is default input: \(device.isDefaultInputDevice)") // depends on device } ``` -------------------------------- ### Manage Stereo Channels with SimplyCoreAudio Source: https://context7.com/rnine/simplycoreaudio/llms.txt Demonstrates how to get and set preferred stereo channels, retrieve channel names, check jack connection status, and get layout channels for an audio device. It utilizes the SimplyCoreAudio library for macOS audio device interaction. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultOutputDevice { // Get preferred stereo channels if let stereoPair = device.preferredChannelsForStereo(scope: .output) { print("Left channel: \(stereoPair.left)") print("Right channel: \(stereoPair.right)") } // Set preferred stereo channels let newPair: StereoPair = (left: 1, right: 2) let success = device.setPreferredChannelsForStereo(channels: newPair, scope: .output) print("Set stereo channels: \(success ? \"succeeded\" : \"failed\")") // Get channel names let channelCount = device.channels(scope: .output) for channel in 1...channelCount { if let channelName = device.name(channel: channel, scope: .output) { print("Channel \(channel): \(channelName)") } } // Check jack connection status if let jackConnected = device.isJackConnected(scope: .output) { print("Output jack connected: \(jackConnected)") } // Get layout channels (from preferred channel layout) if let layoutChannels = device.layoutChannels(scope: .output) { print("Layout channels: \(layoutChannels)") } } ``` -------------------------------- ### Manage Audio Data Sources with SimplyCoreAudio Source: https://context7.com/rnine/simplycoreaudio/llms.txt This Swift code snippet shows how to retrieve and manage data sources for audio input devices. It covers getting the current data source, listing all available sources by their IDs, and obtaining the human-readable names for each source ID. This functionality is useful for selecting specific microphones or line inputs. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultInputDevice { // Get current data source if let currentSources = device.dataSource(scope: .input) { print("Current data source IDs: \(currentSources)") } // Get all available data sources if let allSources = device.dataSources(scope: .input) { print("Available data sources: \(allSources)") // Get names for each source for sourceID in allSources { if let name = device.dataSourceName(dataSourceID: sourceID, scope: .input) { print("Source \(sourceID): \(name)") // Example: "Internal Microphone", "Line In" } } } } ``` -------------------------------- ### Instantiate SimplyCoreAudio and Enumerate Devices (Swift) Source: https://context7.com/rnine/simplycoreaudio/llms.txt Demonstrates how to create an instance of SimplyCoreAudio and access all available audio devices, including input, output, I/O, physical, and aggregate devices. It also shows how to retrieve raw device IDs. ```swift import SimplyCoreAudio // Create the main SimplyCoreAudio instance let simplyCA = SimplyCoreAudio() // Access all available audio devices let allDevices = simplyCA.allDevices print("Total devices: \(allDevices.count)") // Get specific device types let inputDevices = simplyCA.allInputDevices let outputDevices = simplyCA.allOutputDevices let ioDevices = simplyCA.allIODevices // Devices with both input and output // Get non-aggregate (physical) devices only let physicalDevices = simplyCA.allNonAggregateDevices // Get aggregate devices only let aggregateDevices = simplyCA.allAggregateDevices // Get raw device IDs if needed let deviceIDs: [AudioObjectID] = simplyCA.allDeviceIDs ``` -------------------------------- ### Initialize SimplyCoreAudio and Query Devices Source: https://github.com/rnine/simplycoreaudio/blob/develop/README.md Demonstrates how to instantiate the SimplyCoreAudio manager and perform common operations such as retrieving default devices, filtering device lists, and modifying device settings like default input/output status. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() let device = simplyCA.defaultOutputDevice let allOutputDevices = simplyCA.allOutputDevices let filteredDevices = simplyCA.allDevices.filter { $0.channels(scope: .output) > 0 } device.isDefaultOutputDevice = true if let sampleRate = device.nominalSampleRate { print(sampleRate) } ``` -------------------------------- ### SimplyCoreAudio Initialization Source: https://context7.com/rnine/simplycoreaudio/llms.txt The main entry point for the framework, used to enumerate all available audio devices and manage hardware-related notifications. ```APIDOC ## SimplyCoreAudio Initialization ### Description Initializes the SimplyCoreAudio instance to access system audio hardware and enumerate devices. ### Method Initializer ### Endpoint SimplyCoreAudio() ### Parameters None ### Response - **allDevices** (Array) - List of all connected audio devices. - **allInputDevices** (Array) - List of devices with input capabilities. - **allOutputDevices** (Array) - List of devices with output capabilities. ### Response Example { "allDevices": ["Built-in Microphone", "External Headphones"], "allInputDevices": ["Built-in Microphone"], "allOutputDevices": ["External Headphones"] } ``` -------------------------------- ### Running Tests Source: https://github.com/rnine/simplycoreaudio/blob/develop/README.md Instructions on how to set up and run tests for the project. ```APIDOC ## Running Tests ### Prerequisites Before running tests, ensure that `NullAudio.driver` is installed. ### Installation of `NullAudio.driver` 1. Download and build the `NullAudio.driver` from its source. 2. Install the driver into the system's HAL Plug-Ins folder: ```shell /Library/Audio/Plug-Ins/HAL ``` 3. Reload the `coreaudiod` service: ```shell sudo launchctl kill KILL system/com.apple.audio.coreaudiod ``` After completing these steps, you can proceed with running the tests. ``` -------------------------------- ### Swift: Manage Audio Device Sample Rates Source: https://context7.com/rnine/simplycoreaudio/llms.txt Illustrates how to work with audio device sample rates using SimplyCoreAudio in Swift. This includes retrieving the nominal and actual sample rates, listing all supported rates, and changing the device's nominal sample rate. Proper sample rate management is essential for audio quality and compatibility. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultOutputDevice { // Get current sample rates if let nominalRate = device.nominalSampleRate { print("Nominal sample rate: \(nominalRate) Hz") } if let actualRate = device.actualSampleRate { print("Actual sample rate: \(actualRate) Hz") } // Get all supported sample rates if let supportedRates = device.nominalSampleRates { print("Supported sample rates: \(supportedRates)") // Example output: [44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0] } // Change sample rate let success = device.setNominalSampleRate(48000.0) if success { print("Sample rate changed to 48kHz") } else { print("Failed to change sample rate") } } ``` -------------------------------- ### Manage Audio Device Latency and Buffer Size with SimplyCoreAudio Source: https://context7.com/rnine/simplycoreaudio/llms.txt This snippet demonstrates how to retrieve various latency metrics (total, presentation, device, safety offset) and buffer size information for audio devices. It also shows how to set the buffer frame size, with a note on the trade-off between lower latency and CPU usage. Dependencies include the SimplyCoreAudio library. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultOutputDevice { // Get total latency in frames let totalLatency = device.latency(scope: .output) print("Total output latency: \(totalLatency) frames") // Get latency in seconds if let latencySeconds = device.presentationLatency(scope: .output) { print("Presentation latency: \(latencySeconds * 1000) ms") } // Individual latency components if let deviceLatency = device.deviceLatency(scope: .output) { print("Device latency: \(deviceLatency) frames") } if let safetyOffset = device.safetyOffset(scope: .output) { print("Safety offset: \(safetyOffset) frames") } if let bufferSize = device.bufferFrameSize(scope: .output) { print("Buffer size: \(bufferSize) frames") } // Get available buffer sizes if let availableSizes = device.bufferFrameSizeRange(scope: .output) { print("Available buffer sizes: \(availableSizes)") // Example: [32, 64, 128, 256, 512, 1024, 2048, 4096] } // Set buffer size (lower = less latency, more CPU) let success = device.setBufferFrameSize(256, scope: .output) if success { print("Buffer size set to 256 frames") } } ``` -------------------------------- ### Contribution Guidelines Source: https://github.com/rnine/simplycoreaudio/blob/develop/README.md Information on how to contribute to the SimplyCoreAudio project. ```APIDOC ## Further Development & Patches ### Contributing To contribute to the SimplyCoreAudio project, please follow these steps: 1. Fork the repository. 2. Implement your desired changes or features. 3. Submit a pull request for review. ``` -------------------------------- ### Create and Manage Aggregate Devices with SimplyCoreAudio Source: https://context7.com/rnine/simplycoreaudio/llms.txt Shows how to create an aggregate audio device by combining existing input and output devices. It covers checking aggregate device properties, accessing subdevices, and removing the aggregate device when no longer needed. This functionality is useful for expanding channel counts or consolidating audio interfaces. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() // Get existing devices to combine let inputDevice = simplyCA.allInputDevices.first let outputDevice = simplyCA.allOutputDevices.first // Create an aggregate device if let mainDevice = outputDevice, let secondDevice = inputDevice { if let aggregateDevice = simplyCA.createAggregateDevice( mainDevice: mainDevice, secondDevice: secondDevice, named: "My Aggregate Device", uid: "com.myapp.aggregate.device" ) { print("Created aggregate device: \(aggregateDevice.name)") print("Aggregate UID: \(aggregateDevice.uid ?? \"Unknown\")") // Check aggregate device properties print("Is aggregate: \(aggregateDevice.isAggregateDevice)") // Get subdevices if let subdevices = aggregateDevice.ownedAggregateDevices { print("Subdevices: \(subdevices.map { $0.name })") } // Get input subdevices if let inputSubdevices = aggregateDevice.ownedAggregateInputDevices { print("Input subdevices: \(inputSubdevices.map { $0.name })") } // Get output subdevices if let outputSubdevices = aggregateDevice.ownedAggregateOutputDevices { print("Output subdevices: \(outputSubdevices.map { $0.name })") } // Destroy aggregate device when done let status = simplyCA.removeAggregateDevice(id: aggregateDevice.id) if status == noErr { print("Aggregate device removed") } } } // List all existing aggregate devices for device in simplyCA.allAggregateDevices { print("Aggregate: \(device.name)") if let transport = device.transportType { print(" Transport: \(transport.rawValue)") // \"Aggregate\" } } ``` -------------------------------- ### Manage Audio Device Clock Sources Source: https://context7.com/rnine/simplycoreaudio/llms.txt Demonstrates how to retrieve current clock source information, list all available sources, and update the active clock source ID for an audio device. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultOutputDevice { if let clockSourceID = device.clockSourceID { print("Clock source ID: \(clockSourceID)") } if let clockSourceName = device.clockSourceName { print("Clock source name: \(clockSourceName)") } if let clockSourceIDs = device.clockSourceIDs { print("Available clock source IDs: \(clockSourceIDs)") } if let clockSourceNames = device.clockSourceNames { print("Available clock sources: \(clockSourceNames)") } if let sourceID = device.clockSourceIDs?.first { if let name = device.clockSourceName(clockSourceID: sourceID) { print("Clock source \(sourceID): \(name)") } } if let newSourceID = device.clockSourceIDs?.last { let success = device.setClockSourceID(newSourceID) print("Clock source change: \(success ? "succeeded" : "failed")") } } ``` -------------------------------- ### Implement SimplyCoreAudio Notification Monitoring Source: https://context7.com/rnine/simplycoreaudio/llms.txt Demonstrates how to register and manage observers for hardware-related notifications using NotificationCenter. This pattern ensures the application stays in sync with audio device changes like list updates or default device switches. ```swift class AudioManager { let simplyCA = SimplyCoreAudio() private var observers: [NSObjectProtocol] = [] func startMonitoring() { let notificationNames: [Notification.Name] = [ .deviceListChanged, .defaultInputDeviceChanged, .defaultOutputDeviceChanged, .defaultSystemOutputDeviceChanged ] for name in notificationNames { observers.append( NotificationCenter.default.addObserver( forName: name, object: nil, queue: .main ) { [weak self] notification in self?.handleNotification(notification) } ) } } func stopMonitoring() { observers.forEach { NotificationCenter.default.removeObserver($0) } observers.removeAll() } private func handleNotification(_ notification: Notification) { switch notification.name { case .deviceListChanged: print("Device list changed") case .defaultInputDeviceChanged: print("Default input changed") case .defaultOutputDeviceChanged: print("Default output changed") default: break } } } ``` -------------------------------- ### Query Audio Device Properties (Swift) Source: https://context7.com/rnine/simplycoreaudio/llms.txt Explains how to retrieve detailed properties of an individual `AudioDevice` object, including its name, ID, UID, manufacturer, transport type, state (alive, running), I/O capabilities, and related devices. It also shows how to look up devices by ID or UID. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() // Look up device by ID or UID if let device = AudioDevice.lookup(by: someDeviceID) { // Basic device information print("Name: \(device.name)") print("ID: \(device.id)") print("UID: \(device.uid ?? "Unknown")") print("Model UID: \(device.modelUID ?? "Unknown")") print("Manufacturer: \(device.manufacturer ?? "Unknown")") // Transport type (USB, Built-In, Bluetooth, etc.) if let transport = device.transportType { print("Transport: \(transport.rawValue)") // e.g., "USB", "Built-In", "Bluetooth" } // Device state print("Is alive: \(device.isAlive)") print("Is running: \(device.isRunning)") print("Is running somewhere: \(device.isRunningSomewhere)") print("Is hidden: \(device.isHidden)") // I/O capabilities print("Is input only: \(device.isInputOnlyDevice)") print("Is output only: \(device.isOutputOnlyDevice)") print("Input channels: \(device.channels(scope: .input))") print("Output channels: \(device.channels(scope: .output))") // Related devices and owned objects if let relatedDevices = device.relatedDevices { print("Related devices: \(relatedDevices.map { $0.name })") } if let controlList = device.controlList { print("Control objects: \(controlList.count)") } } // Look up device by UID string if let device = AudioDevice.lookup(by: "AppleHDAEngineOutput:1B,0,1,1:0") { print("Found device: \(device.name)") } ``` -------------------------------- ### Managing Latency and Buffer Size Source: https://context7.com/rnine/simplycoreaudio/llms.txt This section demonstrates how to retrieve and manage audio device latency and buffer sizes using SimplyCoreAudio. ```APIDOC ## Managing Latency and Buffer Size SimplyCoreAudio provides comprehensive latency information and buffer size management for audio devices. ### Description This endpoint allows you to get and set audio device latency and buffer size information. ### Method N/A (This is a code example for library usage) ### Endpoint N/A ### Parameters N/A ### Request Example ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultOutputDevice { // Get total latency in frames let totalLatency = device.latency(scope: .output) print("Total output latency: \(totalLatency) frames") // Get latency in seconds if let latencySeconds = device.presentationLatency(scope: .output) { print("Presentation latency: \(latencySeconds * 1000) ms") } // Individual latency components if let deviceLatency = device.deviceLatency(scope: .output) { print("Device latency: \(deviceLatency) frames") } if let safetyOffset = device.safetyOffset(scope: .output) { print("Safety offset: \(safetyOffset) frames") } if let bufferSize = device.bufferFrameSize(scope: .output) { print("Buffer size: \(bufferSize) frames") } // Get available buffer sizes if let availableSizes = device.bufferFrameSizeRange(scope: .output) { print("Available buffer sizes: \(availableSizes)") // Example: [32, 64, 128, 256, 512, 1024, 2048, 4096] } // Set buffer size (lower = less latency, more CPU) let success = device.setBufferFrameSize(256, scope: .output) if success { print("Buffer size set to 256 frames") } } ``` ### Response N/A (This is a code example for library usage) #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Inspect and Query Audio Streams Source: https://context7.com/rnine/simplycoreaudio/llms.txt Shows how to iterate through input and output streams of a device, inspect physical and virtual audio formats, and look up specific streams by ID. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultOutputDevice { if let outputStreams = device.streams(scope: .output) { for stream in outputStreams { print("Stream ID: \(stream.id)") print("Active: \(stream.active)") print("Scope: \(stream.scope?.rawValue ?? "Unknown")") print("Starting channel: \(stream.startingChannel ?? 0)") print("Terminal type: \(stream.terminalType)") print("Latency: \(stream.latency ?? 0) frames") if let physicalFormat = stream.physicalFormat { print("Physical format:") print(" Sample rate: \(physicalFormat.mSampleRate)") print(" Channels: \(physicalFormat.mChannelsPerFrame)") print(" Bits per channel: \(physicalFormat.mBitsPerChannel)") } if let virtualFormat = stream.virtualFormat { print("Virtual format:") print(" Sample rate: \(virtualFormat.mSampleRate)") print(" Channels: \(virtualFormat.mChannelsPerFrame)") } if let formats = stream.availablePhysicalFormats { print("Available physical formats: \(formats.count)") } if let formats = stream.availableVirtualFormats { print("Available virtual formats: \(formats.count)") } if let matchingFormats = stream.availablePhysicalFormatsMatchingCurrentNominalSampleRate() { print("Formats at current sample rate: \(matchingFormats.count)") } if let mixableFormats = stream.availableVirtualFormatsMatchingCurrentNominalSampleRate(false) { print("Mixable formats at current rate: \(mixableFormats.count)") } } } if let inputStreams = device.streams(scope: .input) { print("Input streams: \(inputStreams.count)") } } if let stream = AudioStream.lookup(by: someStreamID) { print("Found stream: \(stream.description)") } ``` -------------------------------- ### Data Sources Source: https://context7.com/rnine/simplycoreaudio/llms.txt This section explains how to access and manage data sources (inputs/outputs) for audio devices. ```APIDOC ## Data Sources Data sources represent different physical inputs or outputs on a device (e.g., internal microphone vs. line input). ### Description This endpoint allows you to retrieve information about available data sources on an audio device and set the current data source. ### Method N/A (This is a code example for library usage) ### Endpoint N/A ### Parameters N/A ### Request Example ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultInputDevice { // Get current data source if let currentSources = device.dataSource(scope: .input) { print("Current data source IDs: \(currentSources)") } // Get all available data sources if let allSources = device.dataSources(scope: .input) { print("Available data sources: \(allSources)") // Get names for each source for sourceID in allSources { if let name = device.dataSourceName(dataSourceID: sourceID, scope: .input) { print("Source \(sourceID): \(name)") // Example: "Internal Microphone", "Line In" } } } } ``` ### Response N/A (This is a code example for library usage) #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Default Device Management Source: https://context7.com/rnine/simplycoreaudio/llms.txt Methods for querying and setting the system's default input, output, and system output devices. ```APIDOC ## Default Device Management ### Description Allows getting and setting the system default audio devices via the SimplyCoreAudio instance or individual AudioDevice properties. ### Method GET/SET ### Endpoint SimplyCoreAudio.defaultInputDevice / AudioDevice.isDefaultOutputDevice ### Parameters - **isDefaultOutputDevice** (Bool) - Set to true to make the device the system default output. ### Response Example { "defaultInput": "Built-in Microphone", "isDefaultOutput": true } ``` -------------------------------- ### Subscribe to Audio Device Notifications in Swift Source: https://context7.com/rnine/simplycoreaudio/llms.txt Demonstrates how to register observers for various device-specific events like sample rate, volume, mute, clock source, and hog mode changes. It uses the NotificationCenter to listen for specific events on a target AudioDevice instance. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() var observers: [NSObjectProtocol] = [] if let device = simplyCA.defaultOutputDevice { observers.append(NotificationCenter.default.addObserver(forName: .deviceNominalSampleRateDidChange, object: device, queue: .main) { notification in if let audioDevice = notification.object as? AudioDevice { print("Sample rate changed: \(audioDevice.nominalSampleRate ?? 0) Hz") } }) observers.append(NotificationCenter.default.addObserver(forName: .deviceVolumeDidChange, object: device, queue: .main) { notification in if let channel = notification.userInfo?["channel"] as? UInt32, let scope = notification.userInfo?["scope"] as? Scope, let audioDevice = notification.object as? AudioDevice { let volume = audioDevice.volume(channel: channel, scope: scope) print("Volume changed - channel: \(channel), scope: \(scope), volume: \(volume ?? 0)") } }) observers.append(NotificationCenter.default.addObserver(forName: .deviceMuteDidChange, object: device, queue: .main) { notification in if let channel = notification.userInfo?["channel"] as? UInt32, let scope = notification.userInfo?["scope"] as? Scope, let audioDevice = notification.object as? AudioDevice { let muted = audioDevice.isMuted(channel: channel, scope: scope) print("Mute changed - channel: \(channel), muted: \(muted ?? false)") } }) observers.append(NotificationCenter.default.addObserver(forName: .deviceClockSourceDidChange, object: device, queue: .main) { notification in if let audioDevice = notification.object as? AudioDevice { print("Clock source: \(audioDevice.clockSourceName ?? "Unknown")") } }) observers.append(NotificationCenter.default.addObserver(forName: .deviceIsAliveDidChange, object: device, queue: .main) { notification in if let audioDevice = notification.object as? AudioDevice { print("Device alive: \(audioDevice.isAlive)") } }) observers.append(NotificationCenter.default.addObserver(forName: .deviceHogModeDidChange, object: device, queue: .main) { notification in if let audioDevice = notification.object as? AudioDevice { print("Hog mode PID: \(audioDevice.hogModePID ?? -1)") } }) } ``` -------------------------------- ### Subscribe to SimplyCoreAudio Notifications in Swift Source: https://context7.com/rnine/simplycoreaudio/llms.txt This Swift code demonstrates how to subscribe to various hardware audio notifications provided by SimplyCoreAudio using NotificationCenter. It covers device list changes, default output/input device changes, and system output device changes. It also includes a cleanup function to remove observers. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() var observers: [NSObjectProtocol] = [] // Device list changes (devices added/removed) observers.append( NotificationCenter.default.addObserver( forName: .deviceListChanged, object: nil, queue: .main ) { notification in if let addedDevices = notification.userInfo?["addedDevices"] as? [AudioDevice] { for device in addedDevices { print("Device added: \(device.name)") } } if let removedDevices = notification.userInfo?["removedDevices"] as? [AudioDevice] { for device in removedDevices { print("Device removed: \(device.name)") } } } ) // Default device changes observers.append( NotificationCenter.default.addObserver( forName: .defaultOutputDeviceChanged, object: nil, queue: .main ) { _ in if let device = simplyCA.defaultOutputDevice { print("New default output: \(device.name)") } } ) observers.append( NotificationCenter.default.addObserver( forName: .defaultInputDeviceChanged, object: nil, queue: .main ) { _ in if let device = simplyCA.defaultInputDevice { print("New default input: \(device.name)") } } ) observers.append( NotificationCenter.default.addObserver( forName: .defaultSystemOutputDeviceChanged, object: nil, queue: .main ) { _ in print("System output device changed") } ) // Clean up observers when done func cleanup() { for observer in observers { NotificationCenter.default.removeObserver(observer) } observers.removeAll() } ``` -------------------------------- ### Subscribe to Device and Stream Notifications Source: https://github.com/rnine/simplycoreaudio/blob/develop/README.md Explains how to monitor specific audio devices or streams for property changes like sample rate or physical format updates. This requires targeting a specific object instance when adding the observer. ```swift let device = simplyCA.defaultOutputDevice var observer = NotificationCenter.default.addObserver(forName: .deviceNominalSampleRateDidChange, object: device, queue: .main) { (notification) in // Handle change } NotificationCenter.default.removeObserver(observer) observer = nil ``` -------------------------------- ### Subscribe to Hardware Notifications Source: https://github.com/rnine/simplycoreaudio/blob/develop/README.md Shows how to observe system-wide hardware changes, such as device list updates, using NotificationCenter. The observer retrieves added or removed devices from the notification's user info dictionary. ```swift var observer = NotificationCenter.default.addObserver(forName: .deviceListChanged, object: nil, queue: .main) { (notification) in guard let addedDevices = notification.userInfo?["addedDevices"] as? [AudioDevice] else { return } guard let removedDevices = notification.userInfo?["removedDevices"] as? [AudioDevice] else { return } } NotificationCenter.default.removeObserver(observer) observer = nil ``` -------------------------------- ### AudioDevice Property Querying Source: https://context7.com/rnine/simplycoreaudio/llms.txt Accessing detailed metadata and state information for specific audio devices. ```APIDOC ## AudioDevice Property Querying ### Description Retrieves detailed information about an audio device including manufacturer, transport type, and current state. ### Method GET ### Endpoint AudioDevice.lookup(by: String) ### Parameters - **id/uid** (String) - The unique identifier for the audio device. ### Response - **name** (String) - Device name. - **transportType** (String) - Hardware transport (e.g., USB, Bluetooth). - **isAlive** (Bool) - Device connection status. ### Response Example { "name": "External USB DAC", "transportType": "USB", "isAlive": true } ``` -------------------------------- ### Swift: Control Audio Device Volume and Mute Source: https://context7.com/rnine/simplycoreaudio/llms.txt Demonstrates how to manage audio device volume and mute states using SimplyCoreAudio in Swift. It covers setting virtual main volume, balance, channel-specific volume, and mute status. This functionality is crucial for applications requiring precise audio output control. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultOutputDevice { // Virtual main volume (0.0 to 1.0 scalar) if device.canSetVirtualMainVolume(scope: .output) { // Get current volume if let volume = device.virtualMainVolume(scope: .output) { print("Current volume: \(volume * 100) traditional_percent") } // Get volume in decibels if let volumeDb = device.virtualMainVolumeInDecibels(scope: .output) { print("Volume in dB: \(volumeDb) dBFS") } // Set volume to 50 traditional_percent device.setVirtualMainVolume(0.5, scope: .output) } // Virtual main balance (0.0 = left, 0.5 = center, 1.0 = right) if device.canSetVirtualMainBalance(scope: .output) { if let balance = device.virtualMainBalance(scope: .output) { print("Balance: \(balance)") } device.setVirtualMainBalance(0.5, scope: .output) // Center } // Channel-level volume control let channel: UInt32 = 1 if device.canSetVolume(channel: channel, scope: .output) { // Get channel volume if let channelVolume = device.volume(channel: channel, scope: .output) { print("Channel \(channel) volume: \(channelVolume)") } // Get volume in decibels if let volumeDb = device.volumeInDecibels(channel: channel, scope: .output) { print("Channel \(channel) volume: \(volumeDb) dBFS") } // Set channel volume device.setVolume(0.75, channel: channel, scope: .output) } // Mute controls if device.canMuteMainChannel(scope: .output) { // Check mute state if let isMuted = device.isMainChannelMuted(scope: .output) { print("Main channel muted: \(isMuted)") } } // Mute specific channel if device.canMute(channel: 1, scope: .output) { device.setMute(true, channel: 1, scope: .output) if let muted = device.isMuted(channel: 1, scope: .output) { print("Channel 1 muted: \(muted)") } } // Get comprehensive volume info for a channel if let volumeInfo = device.volumeInfo(channel: 1, scope: .output) { print("Has volume: \(volumeInfo.hasVolume)") print("Volume: \(volumeInfo.volume ?? 0)") print("Can set volume: \(volumeInfo.canSetVolume)") print("Can mute: \(volumeInfo.canMute)") print("Is muted: \(volumeInfo.isMuted)") print("Can play thru: \(volumeInfo.canPlayThru)") print("Is play thru set: \(volumeInfo.isPlayThruSet)") } } ``` -------------------------------- ### Manage Hog Mode with SimplyCoreAudio Source: https://context7.com/rnine/simplycoreaudio/llms.txt Explains how to manage hog mode, which grants exclusive access to an audio device, preventing other applications from using it. The code demonstrates checking the current hog mode status, requesting exclusive access, verifying ownership, and releasing hog mode when finished. This is crucial for applications requiring uninterrupted audio device control. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultOutputDevice { // Check current hog mode status if let hogPID = device.hogModePID { if hogPID == -1 { print("Device is available to all processes") } else { print("Device is hogged by process: \(hogPID)") } } // Request exclusive access (hog mode) let hogSuccess = device.setHogMode() if hogSuccess { print("Successfully acquired hog mode") // Verify we own it let currentPID = ProcessInfo.processInfo.processIdentifier if device.hogModePID == pid_t(currentPID) { print("We own hog mode") } // Release hog mode when done let releaseSuccess = device.unsetHogMode() if releaseSuccess { print("Released hog mode") } } else { print("Failed to acquire hog mode (device may be in use)") } } ``` -------------------------------- ### Volume Conversion Utilities Source: https://context7.com/rnine/simplycoreaudio/llms.txt This section covers utilities for converting audio volume between scalar (0.0-1.0) and decibel (dBFS) formats. ```APIDOC ## Volume Conversion Utilities SimplyCoreAudio provides utilities to convert between scalar (0.0-1.0) and decibel volume representations. ### Description This endpoint provides functions to convert audio volume values between scalar and decibel formats for a specific channel and scope. ### Method N/A (This is a code example for library usage) ### Endpoint N/A ### Parameters N/A ### Request Example ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultOutputDevice { let channel: UInt32 = 1 // Convert scalar to decibels let scalarVolume: Float32 = 0.5 if let dbVolume = device.scalarToDecibels(volume: scalarVolume, channel: channel, scope: .output) { print("\(scalarVolume) scalar = \(dbVolume) dBFS") } // Convert decibels to scalar let dbValue: Float32 = -12.0 if let scalar = device.decibelsToScalar(volume: dbValue, channel: channel, scope: .output) { print("\(dbValue) dBFS = \(scalar) scalar") } } ``` ### Response N/A (This is a code example for library usage) #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Subscribe to Audio Stream Notifications in Swift Source: https://context7.com/rnine/simplycoreaudio/llms.txt Shows how to monitor changes to individual audio streams, such as active state and physical format updates. This is useful for tracking changes in stream configuration on a specific output device. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() var observers: [NSObjectProtocol] = [] if let device = simplyCA.defaultOutputDevice, let streams = device.streams(scope: .output), let stream = streams.first { observers.append(NotificationCenter.default.addObserver(forName: .streamIsActiveDidChange, object: stream, queue: .main) { notification in if let audioStream = notification.object as? AudioStream { print("Stream \(audioStream.id) active: \(audioStream.active)") } }) observers.append(NotificationCenter.default.addObserver(forName: .streamPhysicalFormatDidChange, object: stream, queue: .main) { notification in if let audioStream = notification.object as? AudioStream, let format = audioStream.physicalFormat { print("Stream format changed:") print(" Sample rate: \(format.mSampleRate)") print(" Channels: \(format.mChannelsPerFrame)") print(" Bits: \(format.mBitsPerChannel)") } }) } ``` -------------------------------- ### Managing Audio Device Clock Sources Source: https://context7.com/rnine/simplycoreaudio/llms.txt Methods to retrieve current clock source information and update the active clock source for an audio device. ```APIDOC ## GET /device/clockSource ### Description Retrieves the current clock source ID and name for the default output device. ### Method GET ### Parameters None ### Response #### Success Response (200) - **clockSourceID** (UInt32) - The unique identifier of the current clock source. - **clockSourceName** (String) - The human-readable name of the clock source. ## POST /device/clockSource ### Description Updates the active clock source for the device. ### Method POST ### Parameters #### Request Body - **clockSourceID** (UInt32) - Required - The ID of the clock source to set. ### Response #### Success Response (200) - **success** (Boolean) - Indicates if the operation was successful. ``` -------------------------------- ### Convert Volume Between Scalar and Decibels with SimplyCoreAudio Source: https://context7.com/rnine/simplycoreaudio/llms.txt This Swift code provides utilities for converting audio volume levels between a scalar representation (0.0 to 1.0) and decibels (dBFS). It demonstrates how to use the `scalarToDecibels` and `decibelsToScalar` methods, specifying the channel and scope for the conversion. This is essential for accurate audio level manipulation. ```swift import SimplyCoreAudio let simplyCA = SimplyCoreAudio() if let device = simplyCA.defaultOutputDevice { let channel: UInt32 = 1 // Convert scalar to decibels let scalarVolume: Float32 = 0.5 if let dbVolume = device.scalarToDecibels(volume: scalarVolume, channel: channel, scope: .output) { print("\(scalarVolume) scalar = \(dbVolume) dBFS") } // Convert decibels to scalar let dbValue: Float32 = -12.0 if let scalar = device.decibelsToScalar(volume: dbValue, channel: channel, scope: .output) { print("\(dbValue) dBFS = \(scalar) scalar") } } ``` -------------------------------- ### Working with Audio Streams Source: https://context7.com/rnine/simplycoreaudio/llms.txt Methods to inspect stream properties, including physical/virtual formats, latency, and channel configurations. ```APIDOC ## GET /device/streams ### Description Retrieves a list of input or output streams for a specific audio device. ### Method GET ### Parameters #### Query Parameters - **scope** (String) - Required - The scope of the stream (e.g., 'input' or 'output'). ### Response #### Success Response (200) - **streams** (Array) - A list of stream objects containing ID, active status, latency, and format details. ## GET /stream/{id} ### Description Look up a specific audio stream by its unique identifier. ### Method GET ### Parameters #### Path Parameters - **id** (UInt32) - Required - The unique ID of the stream. ### Response #### Success Response (200) - **stream** (Object) - Detailed properties of the requested audio stream. ``` -------------------------------- ### Audio Device Notifications Source: https://github.com/rnine/simplycoreaudio/blob/develop/README.md Callbacks triggered by changes in audio device properties. ```APIDOC ## Audio Device Notifications ### Description These callbacks are invoked when specific properties of an audio device change. ### Notifications - `deviceNominalSampleRateDidChange`: Called when the audio device's sample rate changes. - `deviceAvailableNominalSampleRatesDidChange`: Called when the list of available nominal sample rates for the audio device changes. - `deviceClockSourceDidChange`: Called when the audio device's clock source changes. - `deviceNameDidChange`: Called when the audio device's name changes. - `deviceOwnedObjectsDidChange`: Called when the list of audio objects owned by this audio device changes. - `deviceVolumeDidChange`: Called when the volume for a specific channel and scope of the audio device changes. User Info: `channel: UInt32`, `scope: Scope`. - `deviceMuteDidChange`: Called when the mute state for a specific channel and scope of the audio device changes. User Info: `channel: UInt32`, `scope: Scope`. - `deviceIsAliveDidChange`: Called when the audio device's alive status changes. - `deviceIsRunningDidChange`: Called when the audio device's running status changes. - `deviceIsRunningSomewhereDidChange`: Called when the audio device's running somewhere status changes. - `deviceIsJackConnectedDidChange`: Called when the audio device's jack connected status changes. - `devicePreferredChannelsForStereoDidChange`: Called when the audio device's preferred channels for stereo change. - `deviceHogModeDidChange`: Called when the audio device's hog mode changes. ``` -------------------------------- ### Audio Stream Notifications Source: https://github.com/rnine/simplycoreaudio/blob/develop/README.md Callbacks triggered by changes in audio stream properties. ```APIDOC ## Audio Stream Notifications ### Description These callbacks are invoked when specific properties of an audio stream change. ### Notifications - `streamIsActiveDidChange`: Called when the `isActive` flag of the audio stream changes. - `streamPhysicalFormatDidChange`: Called when the physical format of the audio stream changes. ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.