Search code examples
iosswiftaccelerate-frameworkvdsp

Deinterlace a vector using vDSP


Let's say I have a vector:

let input: [Float] = [1, 2, 3, 4, 5, 6, 7, 8, ...]

What I'd like to do is deinterlace this vector by selecting every other value to produce 2 new vectors as output, as follows:

[1, 3, 5, 7, ...]
[2, 4, 6, 8, ...]

What's the best way to do this in vDSP?


Solution

  • The tool you want here is vDSP.convert(interleavedComplexVector:toSplitComplexVector:). Don't let the "complex vector" confuse you. It doesn't matter if these are "complex" or not. An "interleaved complex vector" is just "a series of even and odd values." And a "split complex vector" is just "a struct containing a list of evens and a list of odds." These are sometimes interpreted as real and imaginary components, but that interpretation has nothing to do with how convert works (and often has nothing to do with how these values are used in practice).

    So assuming a [Float] like:

    let input: [Float] = [1, 2, 3, 4, 5, 6, 7, 8]
    

    And two output lists ("vectors") like:

    var evens: [Float] = Array(repeating: 0, count: input.count / 2)
    var odds = evens
    

    You can split them up this way:

    evens.withUnsafeMutableBufferPointer { evenPtr in
        odds.withUnsafeMutableBufferPointer { oddPtr in
    
            var split = DSPSplitComplex(realp: evenPtr.baseAddress!,
                                        imagp: oddPtr.baseAddress!)
    
            input.withUnsafeBytes {
                vDSP.convert(interleavedComplexVector: Array($0.bindMemory(to: DSPComplex.self)),
                             toSplitComplexVector: &split)
            }
        }
    }
    
    // At this point, evens and odds are filled in.
    

    This is intentionally modeled closely on Apple's example code for setting up an FFT.

    If you happen to need more values split up this way (particularly 4 values), take a look at vImageConvert_ARGBFFFFtoPlanarF and related functions. Just like "complex" really just means "two floats," "ARGBFFFF" just means "4 floats." Numbers are just numbers and sometimes the function you need happens to be named based on another use case.