//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2019 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 // //===----------------------------------------------------------------------===// /// Types that support vectorized window generation. @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public protocol vDSP_FloatingPointGeneratable: BinaryFloatingPoint { } extension Float: vDSP_FloatingPointGeneratable {} extension Double: vDSP_FloatingPointGeneratable {} extension vDSP { /// Fill vector with specified scalar value, single-precision. /// /// - Parameter vector: The vector to fill. /// - Parameter value: The fill value. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func fill(_ vector: inout V, with value: Float) where V: AccelerateMutableBuffer, V.Element == Float { let n = vDSP_Length(vector.count) vector.withUnsafeMutableBufferPointer { v in withUnsafePointer(to: value) { vDSP_vfill($0, v.baseAddress!, 1, n) } } } /// Fill vector with specified scalar value, double-precision. /// /// - Parameter vector: The vector to fill. /// - Parameter value: The fill value. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func fill(_ vector: inout V, with value: Double) where V: AccelerateMutableBuffer, V.Element == Double { let n = vDSP_Length(vector.count) vector.withUnsafeMutableBufferPointer { v in withUnsafePointer(to: value) { vDSP_vfillD($0, v.baseAddress!, 1, n) } } } /// Fill vector with zeros, single-precision. /// /// - Parameter vector: The vector to fill. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func clear(_ vector: inout V) where V: AccelerateMutableBuffer, V.Element == Float { let n = vDSP_Length(vector.count) vector.withUnsafeMutableBufferPointer { v in vDSP_vclr(v.baseAddress!, 1, n) } } /// Fill vector with zeros, double-precision. /// /// - Parameter vector: The vector to fill. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func clear(_ vector: inout V) where V: AccelerateMutableBuffer, V.Element == Double { let n = vDSP_Length(vector.count) vector.withUnsafeMutableBufferPointer { v in vDSP_vclrD(v.baseAddress!, 1, n) } } /// Enum specifying window sequence. @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public enum WindowSequence { /// Creates a normalized Hanning window. case hanningNormalized /// Creates a denormalized Hanning window. case hanningDenormalized /// Creates a Hamming window. case hamming /// Creates a Blackman window. case blackman } /// Creates an array containing the specified window. /// /// - Parameter ofType: Specifies single- or double-precision. /// - Parameter sequence: Specifies the window sequence. /// - Parameter count: The number of elements in the array. /// - Parameter isHalfWindow: When true, creates a window with only the first `(N+1)/2` points. /// - Returns: An array containing the specified window. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func window(ofType: T.Type, usingSequence sequence: WindowSequence, count: Int, isHalfWindow: Bool) -> [T] { precondition(count > 0) if T.self == Float.self { let result = Array(unsafeUninitializedCapacity: count) { buffer, initializedCount in formWindow(usingSequence: sequence, result: &buffer, isHalfWindow: isHalfWindow) initializedCount = count } return result as! [T] } else if T.self == Double.self { let result = Array(unsafeUninitializedCapacity: count) { buffer, initializedCount in formWindow(usingSequence: sequence, result: &buffer, isHalfWindow: isHalfWindow) initializedCount = count } return result as! [T] } else { fatalError("This operation only supports `Float` and `Double` types.") } } /// Fills a supplied array with the specified window, single-precision. /// /// - Parameter sequence: Specifies the window sequence. /// - Parameter result: Output values. /// - Parameter isHalfWindow: When true, creates a window with only the first `(N+1)/2` points. @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func formWindow(usingSequence sequence: WindowSequence, result: inout V, isHalfWindow: Bool) where V: AccelerateMutableBuffer, V.Element == Float { let n = vDSP_Length(result.count) result.withUnsafeMutableBufferPointer { v in switch sequence { case .hanningNormalized: vDSP_hann_window(v.baseAddress!, n, Int32(vDSP_HANN_NORM) | Int32(isHalfWindow ? vDSP_HALF_WINDOW : 0)) case .hanningDenormalized: vDSP_hann_window(v.baseAddress!, n, Int32(vDSP_HANN_DENORM) | Int32(isHalfWindow ? vDSP_HALF_WINDOW : 0)) case .hamming: vDSP_hamm_window(v.baseAddress!, n, Int32(isHalfWindow ? vDSP_HALF_WINDOW : 0)) case .blackman: vDSP_blkman_window(v.baseAddress!, n, Int32(isHalfWindow ? vDSP_HALF_WINDOW : 0)) } } } /// Fills a supplied array with the specified window, double-precision. /// /// - Parameter sequence: Specifies the window sequence. /// - Parameter result: Output values. /// - Parameter isHalfWindow: When true, creates a window with only the first `(N+1)/2` points. @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func formWindow(usingSequence sequence: WindowSequence, result: inout V, isHalfWindow: Bool) where V: AccelerateMutableBuffer, V.Element == Double { let n = vDSP_Length(result.count) result.withUnsafeMutableBufferPointer { v in switch sequence { case .hanningNormalized: vDSP_hann_windowD(v.baseAddress!, n, Int32(vDSP_HANN_NORM) | Int32(isHalfWindow ? vDSP_HALF_WINDOW : 0)) case .hanningDenormalized: vDSP_hann_windowD(v.baseAddress!, n, Int32(vDSP_HANN_DENORM) | Int32(isHalfWindow ? vDSP_HALF_WINDOW : 0)) case .hamming: vDSP_hamm_windowD(v.baseAddress!, n, Int32(isHalfWindow ? vDSP_HALF_WINDOW : 0)) case .blackman: vDSP_blkman_windowD(v.baseAddress!, n, Int32(isHalfWindow ? vDSP_HALF_WINDOW : 0)) } } } // MARK: Ramps //===----------------------------------------------------------------------===// // withInitialValue and increment //===----------------------------------------------------------------------===// /// Returns an array containing monotonically incrementing or decrementing values, single-precision. /// /// - Parameter initialValue: Specifies the initial value. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements. /// - Parameter count: The number of elements in the array. /// - Returns: An array containing the specified ramp. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func ramp(withInitialValue initialValue: Float, increment: Float, count: Int) -> [Float] { precondition(count > 0) let result = Array(unsafeUninitializedCapacity: count) { buffer, initializedCount in formRamp(withInitialValue: initialValue, increment: increment, result: &buffer) initializedCount = count } return result } /// Fills a supplied array with monotonically incrementing or decrementing values, single-precision. /// /// - Parameter initialValue: Specifies the initial value. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements. /// - Parameter result: Output values. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func formRamp(withInitialValue initialValue: Float, increment: Float, result: inout V) where V: AccelerateMutableBuffer, V.Element == Float { let n = vDSP_Length(result.count) withUnsafePointer(to: initialValue) { a in withUnsafePointer(to: increment) { b in result.withUnsafeMutableBufferPointer { c in vDSP_vramp(a, b, c.baseAddress!, 1, n) } } } } /// Returns an array containing monotonically incrementing or decrementing values, double-precision. /// /// - Parameter initialValue: Specifies the initial value. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements. /// - Parameter count: The number of elements in the array. /// - Returns: An array containing the specified ramp. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func ramp(withInitialValue initialValue: Double, increment: Double, count: Int) -> [Double] { precondition(count > 0) let result = Array(unsafeUninitializedCapacity: count) { buffer, initializedCount in formRamp(withInitialValue: initialValue, increment: increment, result: &buffer) initializedCount = count } return result } /// Fills a supplied array with monotonically incrementing or decrementing values, double-precision. /// /// - Parameter initialValue: Specifies the initial value. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements. /// - Parameter result: Output values. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func formRamp(withInitialValue initialValue: Double, increment: Double, result: inout V) where V: AccelerateMutableBuffer, V.Element == Double { let n = vDSP_Length(result.count) withUnsafePointer(to: initialValue) { a in withUnsafePointer(to: increment) { b in result.withUnsafeMutableBufferPointer { c in vDSP_vrampD(a, b, c.baseAddress!, 1, n) } } } } //===----------------------------------------------------------------------===// // range //===----------------------------------------------------------------------===// /// Returns an array containing monotonically incrementing or decrementing values within a specified range, single-precision. /// /// - Parameter range: Specifies range of the ramp.. /// - Parameter count: The number of elements in the array. /// - Returns: An array containing the specified ramp. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func ramp(in range: ClosedRange, count: Int) -> [Float] { precondition(count > 0) let result = Array(unsafeUninitializedCapacity: count) { buffer, initializedCount in formRamp(in: range, result: &buffer) initializedCount = count } return result } /// Fills a supplied array with monotonically incrementing or decrementing values within a specified range, single-precision. /// /// - Parameter range: Specifies range of the ramp. /// - Parameter result: Output values. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func formRamp(in range: ClosedRange, result: inout V) where V: AccelerateMutableBuffer, V.Element == Float { let n = vDSP_Length(result.count) withUnsafePointer(to: range.lowerBound) { a in withUnsafePointer(to: range.upperBound) { b in result.withUnsafeMutableBufferPointer { c in vDSP_vgen(a, b, c.baseAddress!, 1, n) } } } } /// Returns an array containing monotonically incrementing or decrementing values within a specified range, double-precision. /// /// - Parameter range: Specifies range of the ramp.. /// - Parameter count: The number of elements in the array. /// - Returns: An array containing the specified ramp. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func ramp(in range: ClosedRange, count: Int) -> [Double] { precondition(count > 0) let result = Array(unsafeUninitializedCapacity: count) { buffer, initializedCount in formRamp(in: range, result: &buffer) initializedCount = count } return result } /// Fills a supplied array with monotonically incrementing or decrementing values within a specified range, double-precision. /// /// - Parameter range: Specifies range of the ramp. /// - Parameter result: Output values. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func formRamp(in range: ClosedRange, result: inout V) where V: AccelerateMutableBuffer, V.Element == Double { let n = vDSP_Length(result.count) withUnsafePointer(to: range.lowerBound) { a in withUnsafePointer(to: range.upperBound) { b in result.withUnsafeMutableBufferPointer { c in vDSP_vgenD(a, b, c.baseAddress!, 1, n) } } } } //===----------------------------------------------------------------------===// // initialValue, multiplyingBy, and increment //===----------------------------------------------------------------------===// /// Returns an array containing monotonically incrementing or decrementing values, multiplying by a source vector, single-precision. /// /// - Parameter initialValue: Specifies the initial value. Modified on return to hold the next value (including accumulated errors) so that the ramp function can be continued smoothly. /// - Parameter multiplyingBy: Input values multiplied by the ramp function. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements /// - Parameter count: The number of elements in the array. /// - Returns: An array containing the specified ramp. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func ramp(withInitialValue initialValue: inout Float, multiplyingBy vector: U, increment: Float) -> [Float] where U: AccelerateBuffer, U.Element == Float { let result = Array(unsafeUninitializedCapacity: vector.count) { buffer, initializedCount in formRamp(withInitialValue: &initialValue, multiplyingBy: vector, increment: increment, result: &buffer) initializedCount = vector.count } return result } /// Fills a supplied array with monotonically incrementing or decrementing values, multiplying by a source vector, single-precision. /// /// - Parameter initialValue: Specifies the initial value. Modified on return to hold the next value (including accumulated errors) so that the ramp function can be continued smoothly. /// - Parameter multiplyingBy: Input values multiplied by the ramp function. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements. /// - Parameter result: Output values. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func formRamp(withInitialValue initialValue: inout Float, multiplyingBy vector: U, increment: Float, result: inout V) where U: AccelerateBuffer, V: AccelerateMutableBuffer, U.Element == Float, V.Element == Float { precondition(vector.count == result.count) let n = vDSP_Length(result.count) result.withUnsafeMutableBufferPointer { dest in vector.withUnsafeBufferPointer { src in withUnsafePointer(to: increment) { step in vDSP_vrampmul(src.baseAddress!, 1, &initialValue, step, dest.baseAddress!, 1, n) } } } } /// Returns an array containing monotonically incrementing or decrementing values, multiplying by a source vector, double-precision. /// /// - Parameter initialValue: Specifies the initial value. Modified on return to hold the next value (including accumulated errors) so that the ramp function can be continued smoothly. /// - Parameter multiplyingBy: Input values multiplied by the ramp function. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements /// - Parameter count: The number of elements in the array. /// - Returns: An array containing the specified ramp. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func ramp(withInitialValue initialValue: inout Double, multiplyingBy vector: U, increment: Double) -> [Double] where U: AccelerateBuffer, U.Element == Double { let result = Array(unsafeUninitializedCapacity: vector.count) { buffer, initializedCount in formRamp(withInitialValue: &initialValue, multiplyingBy: vector, increment: increment, result: &buffer) initializedCount = vector.count } return result } /// Fills a supplied array with monotonically incrementing or decrementing values, multiplying by a source vector, double-precision. /// /// - Parameter initialValue: Specifies the initial value. Modified on return to hold the next value (including accumulated errors) so that the ramp function can be continued smoothly. /// - Parameter multiplyingBy: Input values multiplied by the ramp function. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements. /// - Parameter result: Output values. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func formRamp(withInitialValue initialValue: inout Double, multiplyingBy vector: U, increment: Double, result: inout V) where U: AccelerateBuffer, V: AccelerateMutableBuffer, U.Element == Double, V.Element == Double { precondition(vector.count == result.count) let n = vDSP_Length(result.count) result.withUnsafeMutableBufferPointer { dest in vector.withUnsafeBufferPointer { src in withUnsafePointer(to: increment) { step in vDSP_vrampmulD(src.baseAddress!, 1, &initialValue, step, dest.baseAddress!, 1, n) } } } } //===----------------------------------------------------------------------===// // stereo //===----------------------------------------------------------------------===// /// Returns two arraya containing monotonically monotonically incrementing or decrementing values, multiplying by a source vector, stereo, single-precision. /// /// - Parameter initialValue: Specifies the initial value. Modified on return to hold the next value (including accumulated errors) so that the ramp function can be continued smoothly. /// - Parameter multiplierOne: Input values multiplied by the ramp function. /// - Parameter multiplierTwo: Input values multiplied by the ramp function. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements. /// - Returns: A tuple of two arrays containing the specified ramps. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func stereoRamp(withInitialValue initialValue: inout Float, multiplyingBy multiplierOne: U, _ multiplierTwo: U, increment: Float) -> (firstOutput:[Float], secondOutput: [Float]) where U: AccelerateBuffer, U.Element == Float { let n = multiplierOne.count var firstOutput: Array! let secondOutput = Array(unsafeUninitializedCapacity: n) { secondBuffer, secondInitializedCount in firstOutput = Array(unsafeUninitializedCapacity: n) { firstBuffer, firstInitializedCount in formStereoRamp(withInitialValue: &initialValue, multiplyingBy: multiplierOne, multiplierTwo, increment: increment, results: &firstBuffer, &secondBuffer) firstInitializedCount = n } secondInitializedCount = n } return (firstOutput: firstOutput, secondOutput: secondOutput) } /// Fills a supplied array with monotonically incrementing or decrementing values, multiplying by a source vector, stereo, single-precision. /// /// - Parameter initialValue: Specifies the initial value. Modified on return to hold the next value (including accumulated errors) so that the ramp function can be continued smoothly. /// - Parameter multiplierOne: Input values multiplied by the ramp function. /// - Parameter multiplierTwo: Input values multiplied by the ramp function. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements. /// - Parameter resultOne: Output values. /// - Parameter resultTwo: Output values. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func formStereoRamp(withInitialValue initialValue: inout Float, multiplyingBy multiplierOne: U, _ multiplierTwo: U, increment: Float, results resultOne: inout V, _ resultTwo: inout V) where U: AccelerateBuffer, V: AccelerateMutableBuffer, U.Element == Float, V.Element == Float { precondition(multiplierOne.count == multiplierTwo.count) precondition(resultOne.count == resultTwo.count) precondition(multiplierOne.count == resultOne.count) let n = vDSP_Length(resultTwo.count) resultOne.withUnsafeMutableBufferPointer { o0 in resultTwo.withUnsafeMutableBufferPointer { o1 in multiplierOne.withUnsafeBufferPointer { i0 in multiplierTwo.withUnsafeBufferPointer { i1 in withUnsafePointer(to: increment) { step in vDSP_vrampmul2(i0.baseAddress!, i1.baseAddress!, 1, &initialValue, step, o0.baseAddress!, o1.baseAddress!, 1, n) } } } } } } /// Returns two arraya containing monotonically monotonically incrementing or decrementing values, multiplying by a source vector, stereo, double-precision. /// /// - Parameter initialValue: Specifies the initial value. Modified on return to hold the next value (including accumulated errors) so that the ramp function can be continued smoothly. /// - Parameter multiplierOne: Input values multiplied by the ramp function. /// - Parameter multiplierTwo: Input values multiplied by the ramp function. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements. /// - Returns: A tuple of two arrays containing the specified ramps. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func stereoRamp(withInitialValue initialValue: inout Double, multiplyingBy multiplierOne: U, _ multiplierTwo: U, increment: Double) -> (firstOutput:[Double], secondOutput: [Double]) where U: AccelerateBuffer, U.Element == Double { let n = multiplierOne.count var firstOutput: Array! let secondOutput = Array(unsafeUninitializedCapacity: n) { secondBuffer, secondInitializedCount in firstOutput = Array(unsafeUninitializedCapacity: n) { firstBuffer, firstInitializedCount in formStereoRamp(withInitialValue: &initialValue, multiplyingBy: multiplierOne, multiplierTwo, increment: increment, results: &firstBuffer, &secondBuffer) firstInitializedCount = n } secondInitializedCount = n } return (firstOutput: firstOutput, secondOutput: secondOutput) } /// Fills a supplied array with monotonically incrementing or decrementing values, multiplying by a source vector, stereo, double-precision. /// /// - Parameter initialValue: Specifies the initial value. Modified on return to hold the next value (including accumulated errors) so that the ramp function can be continued smoothly. /// - Parameter multiplierOne: Input values multiplied by the ramp function. /// - Parameter multiplierTwo: Input values multiplied by the ramp function. /// - Parameter increment: The increment (or decrement if negative) between consecutive elements. /// - Parameter resultOne: Output values. /// - Parameter resultTwo: Output values. @inlinable @available(iOS 9999, macOS 9999, tvOS 9999, watchOS 9999, *) public static func formStereoRamp(withInitialValue initialValue: inout Double, multiplyingBy multiplierOne: U, _ multiplierTwo: U, increment: Double, results resultOne: inout V, _ resultTwo: inout V) where U: AccelerateBuffer, V: AccelerateMutableBuffer, U.Element == Double, V.Element == Double { precondition(multiplierOne.count == multiplierTwo.count) precondition(resultOne.count == resultTwo.count) precondition(multiplierOne.count == resultOne.count) let n = vDSP_Length(resultTwo.count) resultOne.withUnsafeMutableBufferPointer { o0 in resultTwo.withUnsafeMutableBufferPointer { o1 in multiplierOne.withUnsafeBufferPointer { i0 in multiplierTwo.withUnsafeBufferPointer { i1 in withUnsafePointer(to: increment) { step in vDSP_vrampmul2D(i0.baseAddress!, i1.baseAddress!, 1, &initialValue, step, o0.baseAddress!, o1.baseAddress!, 1, n) } } } } } } }