<!--
{
  "documentType" : "article",
  "framework" : "Accelerate",
  "identifier" : "/documentation/Accelerate/performing-fourier-transforms-on-interleaved-complex-data",
  "metadataVersion" : "0.1.0",
  "role" : "article",
  "title" : "Performing Fourier transforms on interleaved-complex data"
}
-->

# Performing Fourier transforms on interleaved-complex data

Optimize discrete Fourier transform (DFT) performance with the vDSP interleaved DFT routines.

## Discussion

In many cases, your code performs Fourier transforms on data that originates as interleaved-complex values. An interleaved-complex representation stores the real and imaginary parts of complex values together as collections of [`DSPComplex`](/documentation/Accelerate/DSPComplex) or [`DSPDoubleComplex`](/documentation/Accelerate/DSPDoubleComplex) structures. Many Fourier-related routines in [`vDSP`](/documentation/Accelerate/vDSP) accept complex values in a split-complex representation that stores real and imaginary parts as separate collections.

For example, the following shows a collection of four complex values in a single interleaved collection:

```swift
let interleaved = [DSPComplex(real: real₀, imag: imag₀),
                   DSPComplex(real: real₁, imag: imag₁),
                   DSPComplex(real: real₂, imag: imag₂),
                   DSPComplex(real: real₃, imag: imag₃)]
```

The following shows the same four complex values as two collections in a split representation:

```swift
let reals = [real₀, real₁, real₂, real₃]
let imaginaries = [imag₀, imag₁, imag₂, imag₃]
```

vDSP routines accept split-complex values either as [`DSPSplitComplex`](/documentation/Accelerate/DSPSplitComplex) structures or as two separate collections.

### Convert interleaved values to split-complex format

Given an array `signal` that contains 32 interleaved-complex values, the following code performs a Fourier transform on the values. Use [`vDSP_ctoz`](/documentation/Accelerate/vDSP_ctoz) to populate the split collections `splitSignalReal` and `splitSignalImag` with the interleaved values from `signal`:

```swift
let complexValuesCount = 32

let signal: [DSPComplex] = [ ... ] // `signal.count` equals `complexValuesCount`.

var splitSignalReal = [Float](repeating: 0,
                              count: complexValuesCount)
var splitSignalImag = [Float](repeating: 0,
                              count: complexValuesCount)

signal.withUnsafeBufferPointer { signalPtr in
    splitSignalReal.withUnsafeMutableBufferPointer { signalRealPtr in
        splitSignalImag.withUnsafeMutableBufferPointer { signalImagPtr in
            var splitComplex = DSPSplitComplex(realp: signalRealPtr.baseAddress!,
                                               imagp: signalImagPtr.baseAddress!)
            
            vDSP_ctoz(signalPtr.baseAddress!, 2,
                      &splitComplex, 1,
                      vDSP_Length(complexValuesCount))
        }
    }
}
```

### Perform a Fourier transform on split data

Use the vDSP function [`vDSP_DFT_zop_CreateSetup`](/documentation/Accelerate/vDSP_DFT_zop_CreateSetup) to create a setup object for complex-to-complex DFTs. The execute function, [`vDSP_DFT_Execute`](/documentation/Accelerate/vDSP_DFT_Execute), automatically switches to a fast Fourier transform (FFT) when the specified count supports the FFT algorithm.

```swift
var splitOutputReal = [Float](repeating: 0,
                              count: complexValuesCount)
var splitOutputImag = [Float](repeating: 0,
                              count: complexValuesCount)

if let splitComplexSetup = vDSP_DFT_zop_CreateSetup(nil,
                                                    vDSP_Length(complexValuesCount),
                                                    .FORWARD) {
    
    vDSP_DFT_Execute(splitComplexSetup,
                     splitSignalReal, splitSignalImag,
                     &splitOutputReal, &splitOutputImag)
    
    vDSP_DFT_DestroySetup(splitComplexSetup)
}


let splitComplexDominantFrequency = vDSP.indexOfMaximum(splitOutputReal)

print("Split-complex dominant frequency",
      splitComplexDominantFrequency.0,
      splitComplexDominantFrequency.1)
```

On return,`splitOutputReal` and `splitOutputImag` contain the split format frequency-domain representation of the values in `signal`. Use [`indexOfMaximum(_:)`](/documentation/Accelerate/vDSP/indexOfMaximum(_:)-5qdtm) to find the dominant frequency.

### Convert split-complex values to interleaved format

Use [`vDSP_ztoc`](/documentation/Accelerate/vDSP_ztoc) to convert the split result to the interleaved format.

```swift
var dftOutputInterleaved = [DSPComplex](repeating: DSPComplex(),
                                        count: complexValuesCount)

splitOutputReal.withUnsafeMutableBufferPointer { dftOutputRealPtr in
    splitOutputImag.withUnsafeMutableBufferPointer { dftOutputImagPtr in
        var splitComplex = DSPSplitComplex(realp: dftOutputRealPtr.baseAddress!,
                                           imagp: dftOutputImagPtr.baseAddress!)
        
        vDSP_ztoc(&splitComplex, 1,
                  &dftOutputInterleaved, 2,
                  vDSP_Length(complexValuesCount))
    }
}
```

On return, `dftOutputInterleaved` contains the DFT result in the interleaved format.

### Perform a Fourier transform directly on interleaved data

vDSP provides routines for DFTs directly on interleaved data. Use these functions instead of using [`vDSP_ctoz`](/documentation/Accelerate/vDSP_ctoz) and [`vDSP_ztoc`](/documentation/Accelerate/vDSP_ztoc) to convert between interleaved and split formats.

The following code performs the transform from the <doc://com.apple.documentation/documentation/Accelerate/performing-fourier-transforms-on-interleaved-complex-data> section directly on the interleaved data:

```swift
var interleavedOutput = [DSPComplex](repeating: DSPComplex(real: 0, imag: 0),
                                     count: complexValuesCount)

if let interleavedSetup = vDSP_DFT_Interleaved_CreateSetup(nil,
                                                           vDSP_Length(complexValuesCount),
                                                           .FORWARD,
                                                           .interleaved_ComplextoComplex) {
    vDSP_DFT_Interleaved_Execute(interleavedSetup,
                                 signal,
                                 &interleavedOutput)
    
    vDSP_DFT_Interleaved_DestroySetup(interleavedSetup)
}

let interleavedDominantFrequency = interleavedOutput.enumerated().max {
    a, b in a.element.real < b.element.real
}

print("Interleaved dominant frequency",
      interleavedDominantFrequency?.offset ?? -1,
      interleavedDominantFrequency?.element.real ?? 0)
```

On return, `interleavedOutput` contains the FFT result in the interleaved format.

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)