You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Musubi/Packages/MusubiKit/Sources/AudioMatrix/Resampler.swift

61 lines
2.2 KiB

/// Stereo 4-point Hermite resampler for small rate corrections and 44.1 ↔ 48 kHz.
///
/// `step` is input frames per output frame (1.0 = no change). Allocation-free; safe on the render thread.
public struct Resampler: Sendable {
// History per channel: x[-1], x[0], x[1], x[2]. Output is interpolated between x[0] and x[1].
private var left: (Float, Float, Float, Float) = (0, 0, 0, 0)
private var right: (Float, Float, Float, Float) = (0, 0, 0, 0)
private var fraction: Double = 0
public init() {}
/// Number of input frames `process` will consume for `outputFrames` at `step`.
public func inputFramesNeeded(outputFrames: Int, step: Double) -> Int {
var position = fraction
var consumed = 0
for _ in 0..<outputFrames {
position += step
while position >= 1 {
position -= 1
consumed += 1
}
}
return consumed
}
/// Consumes exactly `inputFramesNeeded(outputFrames:step:)` interleaved stereo frames from `input`
/// and writes `outputFrames` interleaved stereo frames to `output`.
public mutating func process(
input: UnsafePointer<Float>, output: UnsafeMutablePointer<Float>, outputFrames: Int, step: Double
) {
var read = 0
for frame in 0..<outputFrames {
let t = Float(fraction)
output[frame * 2] = Self.hermite(left, t)
output[frame * 2 + 1] = Self.hermite(right, t)
fraction += step
while fraction >= 1 {
fraction -= 1
left = (left.1, left.2, left.3, input[read * 2])
right = (right.1, right.2, right.3, input[read * 2 + 1])
read += 1
}
}
}
public mutating func reset() {
left = (0, 0, 0, 0)
right = (0, 0, 0, 0)
fraction = 0
}
@inline(__always)
private static func hermite(_ x: (Float, Float, Float, Float), _ t: Float) -> Float {
let c0 = x.1
let c1 = 0.5 * (x.2 - x.0)
let c2 = x.0 - 2.5 * x.1 + 2 * x.2 - 0.5 * x.3
let c3 = 0.5 * (x.3 - x.0) + 1.5 * (x.1 - x.2)
return ((c3 * t + c2) * t + c1) * t + c0
}
}

Powered by TurnKey Linux.