Autospectrum computation with vDSP_zaspec doesn't work

80 Views Asked by At

I try to compute the autospectrum of a recorded signal, I use the function vDSP_zaspec. Normally the output array is real.

class  func autoSpectrum (input: [Float])->[Float] {
        
        var real = [Float](input)
        var imaginary = [Float](repeating: 0.0, count : input.count)
        var Output:[Float] = [Float](repeating:0 , count: input.count)
        let length = vDSP_Length(real.count/2)
   
        real.withUnsafeMutableBufferPointer {realBP in
                   imaginary.withUnsafeMutableBufferPointer {imaginaryBP in
                      
                       var splitComplex = DSPSplitComplex(realp: realBP.baseAddress!, imagp: imaginaryBP.baseAddress!)
                       vDSP_zaspec(&splitComplex, &Output, vDSP_Length(input.count))
                    
                   }
               }
    let value = vDSP.rootMeanSquare(Output)
   Output = vDSP.divide(Output, value)

        return Output
    }

I did a test with a 500 Hz sin wave and this is what the Output array looks like :

enter image description here

The chart is far from the expected result...The result looks like the absolute value of the recorded audio file...

If someone could help me, it will be great !

1

There are 1 best solutions below

3
Flex Monkey On

vDSP_zaspec returns the sum of each real part squared and the corresponding imaginary part squared. The Apple documentation describes it as "Compute the element-wise sum of the squares of the real and imaginary parts of a complex vector".

The following pieces of code calculate the same results:

var real: [Float] = [-2, 7, -3]
var imaginary: [Float] = [4, -1, -4]

var vDSPresult: [Float] = [0, 0, 0]
var scalarResult: [Float] = [0, 0, 0]

real.withUnsafeMutableBufferPointer {realBP in
    imaginary.withUnsafeMutableBufferPointer {imaginaryBP in
        var splitComplex = DSPSplitComplex(realp: realBP.baseAddress!,
                                           imagp: imaginaryBP.baseAddress!)
        vDSP_zaspec(&splitComplex,
                    &vDSPresult,
                    vDSP_Length(vDSPresult.count))
        
    }
}

print(vDSPresult)

for i in 0 ..< scalarResult.count {
    scalarResult[i] = pow(real[i], 2) + pow(imaginary[i], 2)
}

print(scalarResult)