blob: 559cd5024b1845508273c932492cd320db033339 [file] [log] [blame]
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
@_exported import CoreAudio // Clang module
extension UnsafeBufferPointer {
/// Initialize an `UnsafeBufferPointer<Element>` from an `AudioBuffer`.
/// Binds the buffer's memory type to `Element`.
public init(_ audioBuffer: AudioBuffer) {
let count = Int(audioBuffer.mDataByteSize) / MemoryLayout<Element>.stride
let elementPtr = audioBuffer.mData?.bindMemory(
to: Element.self, capacity: count)
self.init(start: elementPtr, count: count)
}
}
extension UnsafeMutableBufferPointer {
/// Initialize an `UnsafeMutableBufferPointer<Element>` from an
/// `AudioBuffer`.
public init(_ audioBuffer: AudioBuffer) {
let count = Int(audioBuffer.mDataByteSize) / MemoryLayout<Element>.stride
let elementPtr = audioBuffer.mData?.bindMemory(
to: Element.self, capacity: count)
self.init(start: elementPtr, count: count)
}
}
extension AudioBuffer {
/// Initialize an `AudioBuffer` from an
/// `UnsafeMutableBufferPointer<Element>`.
public init<Element>(
_ typedBuffer: UnsafeMutableBufferPointer<Element>,
numberOfChannels: Int
) {
let byteSize = typedBuffer.count * MemoryLayout<Element>.stride
self.init(mNumberChannels: UInt32(numberOfChannels),
mDataByteSize: UInt32(byteSize),
mData: UnsafeMutableRawPointer(typedBuffer.baseAddress))
}
}
extension AudioBufferList {
/// - Returns: the size in bytes of an `AudioBufferList` that can hold up to
/// `maximumBuffers` `AudioBuffer`s.
public static func sizeInBytes(maximumBuffers: Int) -> Int {
precondition(maximumBuffers >= 1,
"AudioBufferList should contain at least one AudioBuffer")
return MemoryLayout<AudioBufferList>.size +
(maximumBuffers - 1) * MemoryLayout<AudioBuffer>.stride
}
/// Allocate an `AudioBufferList` with a capacity for the specified number of
/// `AudioBuffer`s.
///
/// The `count` property of the new `AudioBufferList` is initialized to
/// `maximumBuffers`.
///
/// The memory should be freed with `free()`.
public static func allocate(maximumBuffers: Int)
-> UnsafeMutableAudioBufferListPointer {
let byteSize = sizeInBytes(maximumBuffers: maximumBuffers)
let ablMemory = calloc(byteSize, 1)
precondition(ablMemory != nil,
"failed to allocate memory for an AudioBufferList")
let listPtr = ablMemory!.bindMemory(to: AudioBufferList.self, capacity: 1)
(ablMemory! + MemoryLayout<AudioBufferList>.stride).bindMemory(
to: AudioBuffer.self, capacity: maximumBuffers)
let abl = UnsafeMutableAudioBufferListPointer(listPtr)
abl.count = maximumBuffers
return abl
}
}
/// A wrapper for a pointer to an `AudioBufferList`.
///
/// Like `UnsafeMutablePointer`, this type provides no automated memory
/// management and the user must therefore take care to allocate and free
/// memory appropriately.
public struct UnsafeMutableAudioBufferListPointer {
/// Construct from an `AudioBufferList` pointer.
public init(_ p: UnsafeMutablePointer<AudioBufferList>) {
unsafeMutablePointer = p
}
/// Construct from an `AudioBufferList` pointer.
public init?(_ p: UnsafeMutablePointer<AudioBufferList>?) {
guard let unwrapped = p else { return nil }
self.init(unwrapped)
}
/// The number of `AudioBuffer`s in the `AudioBufferList`
/// (`mNumberBuffers`).
public var count: Int {
get {
return Int(unsafeMutablePointer.pointee.mNumberBuffers)
}
nonmutating set(newValue) {
unsafeMutablePointer.pointee.mNumberBuffers = UInt32(newValue)
}
}
/// The pointer to the first `AudioBuffer` in this `AudioBufferList`.
internal var _audioBuffersPointer: UnsafeMutablePointer<AudioBuffer> {
// AudioBufferList has one AudioBuffer in a "flexible array member".
// Position the pointer after that, and skip one AudioBuffer back. This
// brings us to the start of AudioBuffer array.
let rawPtr = UnsafeMutableRawPointer(unsafeMutablePointer + 1)
return rawPtr.assumingMemoryBound(to: AudioBuffer.self) - 1
}
// FIXME: the properties 'unsafePointer' and 'unsafeMutablePointer' should be
// initializers on UnsafePointer and UnsafeMutablePointer, but we don't want
// to allow any UnsafePointer<Element> to be initializable from an
// UnsafeMutableAudioBufferListPointer, only UnsafePointer<AudioBufferList>.
// We need constrained extensions for that. rdar://17821143
/// The pointer to the wrapped `AudioBufferList`.
public var unsafePointer: UnsafePointer<AudioBufferList> {
return UnsafePointer(unsafeMutablePointer)
}
/// The pointer to the wrapped `AudioBufferList`.
public var unsafeMutablePointer: UnsafeMutablePointer<AudioBufferList>
}
extension UnsafeMutableAudioBufferListPointer
: MutableCollection, RandomAccessCollection {
public typealias Element = AudioBuffer
public typealias Index = Int
public typealias Indices = Range<Int>
/// Always zero, which is the index of the first `AudioBuffer`.
public var startIndex: Int {
return 0
}
/// The "past the end" position; always identical to `count`.
public var endIndex: Int {
return count
}
/// Access an indexed `AudioBuffer` (`mBuffers[i]`).
public subscript(index: Index) -> Element {
get {
precondition(index >= 0 && index < self.count,
"subscript index out of range")
return (_audioBuffersPointer + index).pointee
}
nonmutating set(newValue) {
precondition(index >= 0 && index < self.count,
"subscript index out of range")
(_audioBuffersPointer + index).pointee = newValue
}
}
}