2016-05-12 8 views
0

私はvDSP_convを使用して自己相関を実行しています。ほとんどの場合、うまくいきますが、たいていは出力配列にNaNを埋め込んでいます。vDSP_convは時々NANを返します

コード:

func corr_test() { 
    var pass = 0 

    var x = [Float]() 
    for i in 0..<2000 { 
    x.append(Float(i)) 
    } 

    while true { 
    print("pass \(pass)") 

    let corr = autocorr(x) 
    if corr[1].isNaN { 
     print("!!!") 
    } 
    pass += 1 
    } 
} 

func autocorr(a: [Float]) -> [Float] { 
    let resultLen = a.count * 2 + 1 
    let padding = [Float].init(count: a.count, repeatedValue: 0.0) 
    let a_pad = padding + a + padding 
    var result = [Float].init(count: resultLen, repeatedValue: 0.0) 

    vDSP_conv(a_pad, 1, a_pad, 1, &result, 1, UInt(resultLen), UInt(a_pad.count)) 

    return result 
} 

出力:

pass ... 
pass 169 
pass 170 
pass 171 
(lldb) p corr 
([Float]) $R0 = 4001 values { 
    [0] = 2.66466637E+9 
    [1] = NaN 
    [2] = NaN 
    [3] = NaN 
    [4] = NaN 
... 

私はここで何が起こっているかわかりません。私は0パディングを正確に処理していると思います。なぜなら、もし私がいなければ、99%の正確な結果を得ているとは思わないからです。

アイデア?グラシアス。

+0

文書Aは、ベクトルAが「少なくともN + P-1でなければならない」と言います。 Nは出力ベクトルの長さであり、Pはフィルタベクトルの長さであるため、配列をパディングする方法はおそらく間違っていますが、正しい方法が何であるかはまだ分かりません。 –

答えて

0

キーがhttps://developer.apple.com/library/mac/samplecode/vDSPExamples/Listings/DemonstrateConvolution_c.htmlからこのコメントだった:

// “The signal length is padded a bit. This length is not actually passed to the vDSP_conv routine; it is the number of elements 
// that the signal array must contain. The SignalLength defined below is used to allocate space, and it is the filter length 
// rounded up to a multiple of four elements and added to the result length. The extra elements give the vDSP_conv routine 
// leeway to perform vector-load instructions, which load multiple elements even if they are not all used. If the caller did not 
// guarantee that memory beyond the values used in the signal array were accessible, a memory access violation might result.” 

「ビットを埋め込まれます。」そう特定されててくれてありがとう。とにかくここに最終的な作業成果があります:

func autocorr(a: [Float]) -> [Float] { 
let filterLen = a.count 
let resultLen = filterLen * 2 - 1 
let signalLen = ((filterLen + 3) & 0xFFFFFFFC) + resultLen 

let padding1 = [Float].init(count: a.count - 1, repeatedValue: 0.0) 
let padding2 = [Float].init(count: (signalLen - padding1.count - a.count), repeatedValue: 0.0) 
let signal = padding1 + a + padding2 

var result = [Float].init(count: resultLen, repeatedValue: 0.0) 

vDSP_conv(signal, 1, a, 1, &result, 1, UInt(resultLen), UInt(filterLen)) 

// Remove the first n-1 values which are just mirrored from the end so that [0] always has the autocorrelation. 
result.removeFirst(filterLen - 1) 

return result 
} 

ここでの結果は正規化されていません。

関連する問題