【问题标题】:Swift Linear Interpolation and UpSampling快速线性插值和上采样
【发布时间】:2019-04-12 05:53:23
【问题描述】:

我有一个不均匀采样的指标流。我想将这些指标线性插值和上采样到特定的采样频率。我曾尝试使用 Accelerate Framework 和 SIMD 框架,但我不确定该怎么做。

问题本身如下:

let original_times:[Double] = [0.0, 2.0, 3.0, 6.0, 10.0]
let original_values: [Double] = [50.0, 20.0, 30.0, 40.0, 10.0]
let new_times:[Double] = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]

所以我正在寻找一种通过某种线性插值方法找到 new_values 的方法。

【问题讨论】:

    标签: arrays swift interpolation accelerate-framework linear-interpolation


    【解决方案1】:

    插值是一个广泛的领域(参见。维基百科:https://en.wikipedia.org/wiki/Interpolation

    最简单的方法是这样的线性插值。

    class LinearInterpolation {
    
        private var n : Int
        private var x : [Double]
        private var y : [Double]
        init (x: [Double], y: [Double]) {
            assert(x.count == y.count)
            self.n = x.count-1
            self.x = x
            self.y = y
        }
        
        func Interpolate(t: Double) -> Double {
            if t <= x[0] { return y[0] }
            for i in 1...n {
                if t <= x[i] {
                    let ans = (t-x[i-1]) * (y[i] - y[i-1]) / (x[i]-x[i-1]) + y[i-1]
                    return ans
                }
            }
            return y[n]
        }
    }
    

    用法:

        let original_times:[Double] = [0.0, 2.0, 3.0, 6.0, 10.0]
        let original_values: [Double] = [50.0, 20.0, 30.0, 40.0, 10.0]
        let new_times:[Double] = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
        let ipol = LinearInterpolation(x: original_times, y: original_values)
        for t in new_times {
            let y = ipol.Interpolate(t: t)
            print("t: \(t) y: \(y)")
        }
    

    在包含音频数据之类的用例中,您应该看看傅立叶分析。

    【讨论】:

      【解决方案2】:

      vDSP_vgenpD 将为您完成这项工作。将原始时间和值传递给它,它将用插值填充一个数组。例如:

      import Accelerate
      
      let original_times:[Double] =    [0.0,  2.0,  3.0,  6.0, 10.0]
      let original_values: [Double] = [50.0, 20.0, 30.0, 40.0, 10.0]
      
      var new_values = [Double](repeating: 0,
                                count: 11)
      
      let stride = vDSP_Stride(1)
      
      vDSP_vgenpD(original_values, stride,
                  original_times, stride,
                  &new_values, stride,
                  vDSP_Length(new_values.count),
                  vDSP_Length(original_values.count))
      

      您可以通过以下方式获取时间/值元组数组:

      let result = new_values.enumerated().map{ return $0 }
      

      看起来像:

      【讨论】:

      • 如果我想将 40hz 上采样到 50hz,如何做类似的方法。
      猜你喜欢
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-09
      • 2015-09-03
      • 2014-10-04
      • 2018-11-16
      相关资源
      最近更新 更多