0

I am using Apple's Accelerate framework with swift. I am working with DSPSplitComplex numbers to work with complex vectors.

I would like to create a filter bank (An array of filters). To do this, I iterate through a loop, and add the result to my array using the following code:

func makeSine(freq:Float, N:Int) -> DSPSplitComplex {
    var sreal:[Float] = Array(repeating: 0, count: N)
    var simag:[Float] = Array(repeating: 0, count: N)
    var compSine = DSPSplitComplex(realp: UnsafeMutablePointer(mutating:sreal), imagp: UnsafeMutablePointer(mutating:simag))
    for i in 0..<t.count{
        var x = 2 * Float.pi * freq * t[i]
        sreal[i] = cos(x)
        simag[i] = sin(x)
    }
    return compSine
}

the function above makes a complex sine wave. I call the function with:

var s = makeSine(freq:400.0, N:2048)

My issue is using DSPSplitComplex I am creating pointers to the arrays initialised in the function. I cannot inspect the variable s directly in the debug area in Xcode, however I achieve this using the following code:

 var inspect:[Float]=[]

        for i in 0..<t.count {
            inspect.append(s.realp[I])
}

t.count being the length of the filter. Comparing the values of this array with the values printed out whilst inside the makeSine function, they are both very different. Because this is just a pointer, I believe it is not passing the actual values and these arrays are being deallocated.

My problem is that I am looking at iterating through the makeSine (and other functions) a few hundred times, resulting in hundreds of realp and imagp arrays. How do I handle these programatically?

samp17
  • 547
  • 1
  • 4
  • 16
  • 1
    You have a big memory problem here. The function passes pointers to the element storage of local arrays to the caller. Actually those pointers are valid *only* during the call to `UnsafeMutablePointer(mutating:sreal)`. – Martin R Mar 29 '19 at 18:59
  • That confirms what I was thinking. So the real focus is how to overcome this. I do not know in advance how many times I will need to iterate through each function. Does that mean I would be better creating an array of floats for real numbers and an array of floats for imaginary numbers? Whenever I need to use DSPSplitComplex I would create it from the corresponding rows in each? – samp17 Mar 29 '19 at 20:00

1 Answers1

0

Okay, I actually found a way around this earlier than I thought and posting to help others.

At the top of my class I initialise the separate arrays for the real and imaginary parts:

var realSines:[[Float]]=[]
var imagSines:[[Float]]=[]

then the rewritten makeSine function is:

func makeSine(freq:Float, N:Int, iteration:Int) -> DSPSplitComplex {
    var sreal:[Float] = Array(repeating: 0, count: N)
    var simag:[Float] = Array(repeating: 0, count: N)
    var compSine = DSPSplitComplex(realp: UnsafeMutablePointer(mutating:sreal), imagp: UnsafeMutablePointer(mutating:simag))
    for i in 0..<t.count{
        var x = 2 * Float.pi * freq * t[i]
        sreal[i] = cos(x)
        simag[i] = sin(x)
    }
    realSines.append(sreal)
    imagSines.append(simag)
}

then whenever I want to use a DSPSplitComplex I declare it with:

 var tempSineReal = realSines[iteration]
 var tempSineImag = imagSines[iteration]
 var tempSine = DSPSplitComplex(realp: UnsafeMutablePointer(mutating:tempSineReal), imagp: UnsafeMutablePointer(mutating: tempSineImag))
samp17
  • 547
  • 1
  • 4
  • 16