ios Declare for vDSP

Hi!
Does anybody know the declare syntax for the following (iOS Accelerate framework)

vDSP_create_fftsetup
vDSP_fft_zrip
vDSP_ctoz
vDSP_ztoc

I’ve tried the following without success for vDSP_create_fftsetup :

Declare Function vDSP_create_fftsetup Lib “Accelerate” Selector “vDSP_create_fftsetup:vDSP_Length __vDSP_Log2n:FFTRadix __vDSP_Radix:” (Log2n As Integer, Radix As Integer) As Ptr
Dim iniFTT As Ptr = vDSP_create_fftsetup(10, 0)

I’m not fully sure, but from what I see whith a fast glimpse the accelerate is a framework with global methods, so you need to address them without Selector, just by their name, or as an external method.
Also I’m not sure if the accelerate framework is loaded by default. Have you tested for it?

This does work:

Declare Function vDSP_create_fftsetup Lib "Accelerate" (Log2n As Integer, Radix As Integer) As Ptr Dim iniFTT As Ptr = vDSP_create_fftsetup(10, 0)

The framework is loaded because Xojo sees the lib name there and loads it for you.

Thank you for your fast suggestions … I’ll check it out and post the results …

Works as expected!
Now I’m struggling in order to pass a pointer of (an array of a structure) to a declare function (vDSP_ctoz) : I’m studing the MemoryBlock info … is that the only way to pass a pointer of a structure to a declare function?

Depends on what structure you are using. For something like NSRect, you can simply define it and send it as this structure to the method. For a ptr to a custom structure, like a mix of objects, usually a C array is expected which can easily be set up with a Memoryblock containing a NIL ptr at the end. If you write what method you are researching, I can answer more specifically.

Hi Ulrich, thak you for your help!

I’ve tried to reproduce in Xojo the following structure of a declare function

/* A DSPComplex is a pair of float or double values that together represent a complex value.
*/
typedef struct DSPComplex {
float real;
float imag;
} DSPComplex;

  1. first creating a reference structure in Xojo named COMPLEX (first element: real single, second element: imag single)

  2. creating a test array of the structure with the following code
    Dim source() as COMPLEX
    ReDim source(8)

  3. populating the array with some test data
    source(0).imagp=0
    source(0).realp=76
    source(1).imagp=0
    source(1).realp=23
    source(2).imagp=0
    source(3).realp=2
    source(3).imagp=0
    source(3).realp=56
    source(4).imagp=0
    source(4).realp=8
    source(5).imagp=0
    source(5).realp=75
    source(6).imagp=0
    source(6).realp=2
    source(7).imagp=0
    source(7).realp=44

  4. now I’m trying to create a pointer named ptr2source to this structure (using MemoryBlock: I guess copyng all the structure data in a memoryblock and creating the pointer to the memoryblock) to pass it to tvDSP_ctoz

'declare
Declare Sub vDSP_ctoz Lib “Accelerate” (C As Ptr, IC As Integer, Z As Ptr, IZ As Integer, N As Integer)
'call
vDSP_ctoz(ptr2source, 2, ptr2output, 1, 8)

I guess this will not work, no matter what you try. I have found in Apple’s docs:

[quote]Legacy Macros
On i386 architectures, the functions listed in Legacy APIs are actual symbols, and the recommended replacements for those functions are actually macros that translate the preferred names to the legacy names listed in Legacy APIs.

On the x86-64 architecture in Mac OS X, these macros are not defined. In iOS, these macros are not defined.[/quote]

and vDSP_ctoz seems to be one of them.
(and, btw, my math knowledge is not that good that I wouldn’t be confused about the data types being used)

Oh, I’m sorry, I read the wrong line. c_toz ist cancelled, vDSP_ctoz should be working. But again, I am still trying to understand the docs. Maybe you can help me.

In general, for a C array, the last element should be a ptr(NIL). There are some exceptions to this rule, nameley when an element counter is passed which seems to be the case.
I think a vDSP_Stride should rather be a Int32 or you will encounter problems on a 64bit system. It is defined as a long per the docs, whereas the vDSP_long should be a Uint32.

I know, that still dowsn’t answer the question about the array – I guess in this case it would be a MutableMemoryblock with singlevalues in order realp and imagp and you pass the data property of it to the method.
But what is a DSPSplitComplex? Looks like instead of real and imaginary parts in pairs, they hold C arrays for the vector parts separately. like you wil have to create a memoryblock holding in Ptrvalue(0) the Data property of the real value memoryblock and in Ptrvalue(4) the data ptr to the imaginary memory block. Probably followed by a Ptrvalue(8) = nil to be a real C array.

A challenge not getting confused here.

Sorry for the cryptic sentence. Again, no edit possible. I meant “I believe you will have to create …”

EDIT: And looking more closely on the DSPSplitcomplex description, I think that I am wrong. It is a structure in itself, being made of two ptrs. And those should be the data values of the complex part arrays.

Thanks Ulrich … sorry for the delay… busy weekend … DSPSplitComplex definition:

/* A DSPSplitComplex or DSPDoubleSplitComplex is a structure containing
two pointers, each to an array of float . These represent arrays
of complex values, with the real components of the values stored in one
array and the imaginary components of the values stored in a separate
array.
*/
typedef struct DSPSplitComplex {
float *realp;
float *imagp;
} DSPSplitComplex;
typedef struct DSPDoubleSplitComplex {
double *realp;
double *imagp;
} DSPDoubleSplitComplex;

The input buffer needs to be transformed for next function named vDSP_fft_zrip so that all of the even-numbered elements go into Real array, and all of the odd-numbered elements go into Imaginary array. vDSP_ctoz provides a convenient function to do this…

All the mentioned functions are used for the FFT … you can grab the main concept from
https://mikeash.com/pyblog/friday-qa-2012-10-26-fourier-transforms-and-ffts.html

I know everything about FFT but almost nothing about objective-C … my main goal is to use vDSP in Xojo for this purpose (FFT) in order to make real time processing on sound sources.

Thanks, Daniel. It’s a bit complicated for me because I would have to experiment with the declare myself and would have to set up the base declares first. Do you have a sample project you could share?

Some wild guessing, but what I believe to know so far:
You were right creating a MutableMemoryblock with alternating single values for real and imaginary and then passing the data property of it to the method. vDSP_Stride_C should be a Int32 and have a value of 2.
For DSPSplitComplex, you need another structure, consisting of two ptrs.
You need to pass one element of DSPSplitComplex as byref to the method because that’s where the split data goes. vDSPStride_Z is a Int32 too and is probably 1, or do I err?
And vDSP_Size should be a UInt32, containing the number of elements to copy.

The ptr values of DSPSplitComplex after the byref method call should contain the C type value arrays – which means you should be able to convert them to a Memoryblock and read their single values.

If you want to make sure you do not confuse SplitComplex and DoubleSplitComplex you could set up another Structure for DoubleSplit but this would again only contain two ptrs. Only in this case you would read the ptrs’ memoryblock.doublevalues.

Again, I know almost nothing about FFT and only a bit about Obj C – but I am certain this problem can be solved.

Uli

Hi Ulrich!

a) Yes, vDSPStride_Z =1
b) DSPSplitComplex as byref: you mean something like vDSP_ctoz(ptr2source, 2, byref output, 1, 8) where output is the other structure?
c) Sample project: yes (FFT.xojo_binary_project) , just tell me how to share it (email? bitbucket? attachment to some blog?)

Maybe a link ?

However you like, Daniel! Just send me a link (and give me a few days, I am right in the peak of a project deadline)

Oh, and yes (point b): you need to send a ptr via byref and then take its value to retrieve the (memoryblock) array of SplitComplex structures it points to. It’s a bit strange these methods don’t deliver a function result but work via byref. Apple has implemented a lot of different approaches in different frameworks, I guess.

Here is the project link

http://www.gaiacons.com/download/FFT.zip

Thanks, Daniel!
For your first question: You get the pointer to a Xojo.Memoryblock by using its data property.

And for an external method call into a framework there is no id to pass. This is in a way like a module method, you call it without an instance.

I am not sure if this works correctly, but at least the call works now. I have taken c_to_z instead of z_to_c because you install an array of Complex, don’t you?
I tried to change a real part too but could not find it in the returned memoryblock then – that’s why I am very unsure if this is really what you want. Please keep me informed on this and don’t hesitate to forward me a refined method or other declares. I did not take care for fft_rzip yet, it’s better if you check the result first.

BTW, it’s important to restrict the Integers to UInt32 or Int32 where Apple says so because otherwise your declares will not work on 64 bit.
https://dl.dropboxusercontent.com/u/21200221/Xojo/FFT.xojo_binary_project.zip

Oh, and for the syntax question: Floats/Singles are 4 byte, but you create a memoryblock of a structure holding two bytes. That’s why with the second implementation (which I have done, your first one should work too, but then 0 to 7 and not with step 2) you need to skip each other address (that’s why the loop is 0 to 14 step 2 now). With the loop like it was before, each realp value would have overwritten the last imagep value, I think. But please check if the sourcemb looks ok in debugger.

Hi Ulrich! I’ve made a couple of corrections and vDSP_ctoz is working as expected (see the notes in the project, data in blockmemory is ok i compliance with the function usage). Now I’m trying to use vDSP_fft_zrip without success (I get no usefull debug messages in xojo or console: maybe there is a problem in a pointer or in the declare)

Here is the link of new test:

http://www.gaiacons.com/download/FFT.zip