native first
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import Foundation
|
||||
|
||||
public enum PCM16LE {
|
||||
public static func encode(samples: [Float]) -> Data {
|
||||
var data = Data()
|
||||
data.reserveCapacity(samples.count * MemoryLayout<Int16>.size)
|
||||
|
||||
for sample in samples {
|
||||
let clamped = max(-1.0, min(1.0, sample))
|
||||
let scaled: Int16
|
||||
|
||||
if clamped >= 1.0 {
|
||||
scaled = Int16.max
|
||||
} else if clamped <= -1.0 {
|
||||
scaled = Int16.min
|
||||
} else {
|
||||
scaled = Int16((clamped * Float(Int16.max)).rounded())
|
||||
}
|
||||
|
||||
var littleEndian = scaled.littleEndian
|
||||
withUnsafeBytes(of: &littleEndian) { bytes in
|
||||
data.append(contentsOf: bytes)
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
public static func resampleLinear(samples: [Float], sourceRate: Int, targetRate: Int = 16_000) -> [Float] {
|
||||
guard sourceRate > 0, targetRate > 0, !samples.isEmpty else {
|
||||
return []
|
||||
}
|
||||
|
||||
guard sourceRate != targetRate else {
|
||||
return samples
|
||||
}
|
||||
|
||||
let ratio = Double(sourceRate) / Double(targetRate)
|
||||
let outputCount = max(1, Int(Double(samples.count) / ratio))
|
||||
|
||||
return (0..<outputCount).map { index in
|
||||
let sourcePosition = Double(index) * ratio
|
||||
let lowerIndex = Int(sourcePosition)
|
||||
let upperIndex = min(lowerIndex + 1, samples.count - 1)
|
||||
let fraction = Float(sourcePosition - Double(lowerIndex))
|
||||
let lower = samples[min(lowerIndex, samples.count - 1)]
|
||||
let upper = samples[upperIndex]
|
||||
return lower + ((upper - lower) * fraction)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user