Skip to content

Instantly share code, notes, and snippets.

@praeclarum
Created April 9, 2013 19:38
Show Gist options
  • Save praeclarum/5348699 to your computer and use it in GitHub Desktop.
Save praeclarum/5348699 to your computer and use it in GitHub Desktop.
DSP functions for Xamarin.iOS bound to the Accelerate framework. See it in action by buying my Spectrogram app for iOS: https://itunes.apple.com/us/app/live-spectrogram/id630831185
using System;
using System.Runtime.InteropServices;
namespace Circuit
{
public static class Dsp
{
class FftSetupD : IDisposable
{
public IntPtr Handle;
public FftSetupD (int nlog2)
{
Handle = vDSP_create_fftsetupD (nlog2, FftRadix.Radix2);
}
~FftSetupD ()
{
DisposeIt ();
}
public void Dispose ()
{
GC.SuppressFinalize (this);
DisposeIt ();
}
void DisposeIt ()
{
vDSP_destroy_fftsetupD (Handle);
Handle = IntPtr.Zero;
}
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_create_fftsetupD")]
unsafe static extern IntPtr vDSP_create_fftsetupD (int log2n, FftRadix radix);
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_destroy_fftsetupD")]
unsafe static extern void vDSP_destroy_fftsetupD (IntPtr setup);
}
class FftSetup : IDisposable
{
public IntPtr Handle;
public FftSetup (int nlog2)
{
Handle = vDSP_create_fftsetup (nlog2, FftRadix.Radix2);
}
~FftSetup ()
{
DisposeIt ();
}
public void Dispose ()
{
GC.SuppressFinalize (this);
DisposeIt ();
}
void DisposeIt ()
{
vDSP_destroy_fftsetup (Handle);
Handle = IntPtr.Zero;
}
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_create_fftsetup")]
unsafe static extern IntPtr vDSP_create_fftsetup (int log2n, FftRadix radix);
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_destroy_fftsetup")]
unsafe static extern void vDSP_destroy_fftsetup (IntPtr setup);
}
enum FftDirection : int
{
Forward = 1,
Inverse = -1,
}
enum FftRadix : int
{
Radix2 = 0,
}
[StructLayout (LayoutKind.Sequential)]
unsafe struct SplitComplexD
{
public double* Realp;
public double* Imagp;
}
[StructLayout (LayoutKind.Sequential)]
unsafe struct SplitComplex
{
public float* Realp;
public float* Imagp;
}
public static IDisposable SetupFftD (int nlog2)
{
return new FftSetupD (nlog2);
}
public static IDisposable SetupFft (int nlog2)
{
return new FftSetup (nlog2);
}
public static void Fft (ComplexDataD data, object setup, bool forward)
{
unsafe {
fixed (double *realp = data.Reals) {
fixed (double *imagp = data.Imags) {
SplitComplexD d;
d.Realp = realp;
d.Imagp = imagp;
vDSP_fft_zipD (((FftSetupD)setup).Handle, ref d, 1, GetNLog2 (data.Length), forward ? FftDirection.Forward : FftDirection.Inverse);
}
}
}
}
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_fft_zipD")]
unsafe static extern void vDSP_fft_zipD (IntPtr setup, ref SplitComplexD ioData, int stride, int log2n, FftDirection direction);
public static void Fft (ComplexData data, object setup, bool forward)
{
unsafe {
fixed (float *realp = data.Reals) {
fixed (float *imagp = data.Imags) {
SplitComplex d;
d.Realp = realp;
d.Imagp = imagp;
vDSP_fft_zip (((FftSetup)setup).Handle, ref d, 1, GetNLog2 (data.Length), forward ? FftDirection.Forward : FftDirection.Inverse);
}
}
}
}
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_fft_zip")]
unsafe static extern void vDSP_fft_zip (IntPtr setup, ref SplitComplex ioData, int stride, int log2n, FftDirection direction);
public static void GetMagnitudesSquared (ComplexDataD data, double[] output)
{
unsafe {
fixed (double *realp = data.Reals) {
fixed (double *imagp = data.Imags) {
SplitComplexD d;
d.Realp = realp;
d.Imagp = imagp;
vDSP_zvmagsD (ref d, 1, output, 1, output.Length);
}
}
}
}
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_zvmagsD")]
unsafe static extern void vDSP_zvmagsD (ref SplitComplexD a, int stride, double[] c, int k, int n);
public static void GetMagnitudesSquared (ComplexData data, float[] output)
{
unsafe {
fixed (float *realp = data.Reals) {
fixed (float *imagp = data.Imags) {
SplitComplex d;
d.Realp = realp;
d.Imagp = imagp;
vDSP_zvmags (ref d, 1, output, 1, output.Length);
}
}
}
}
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_zvmags")]
unsafe static extern void vDSP_zvmags (ref SplitComplex a, int stride, float[] c, int k, int n);
public static void GetDecibelsFromPower (double[] power, double[] reference, double[] output)
{
vDSP_vdbconD (power, 1, reference, output, 1, output.Length, 0);
}
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_vdbconD")]
unsafe static extern void vDSP_vdbconD (double[] a, int i, double[] b, double[] c, int k, int n, uint f);
public static void GetDecibelsFromPower (float[] power, float[] reference, float[] output)
{
vDSP_vdbcon (power, 1, reference, output, 1, output.Length, 0);
}
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_vdbcon")]
unsafe static extern void vDSP_vdbcon (float[] a, int i, float[] b, float[] c, int k, int n, uint f);
public static void Lint (float[] a, float[] b, float[] output)
{
vDSP_vlint (a, b, 1, output, 1, output.Length, a.Length);
}
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_vlint")]
unsafe static extern void vDSP_vlint (float[] a, float[] b, int j, float[] c, int k, int n, int m);
public static void MultiplyAndAdd (float[] a, float b, float c, float[] output)
{
vDSP_vsmsa (a, 1, ref b, ref c, output, 1, output.Length);
}
[System.Runtime.InteropServices.DllImport ("__Internal", EntryPoint = "vDSP_vsmsa")]
unsafe static extern void vDSP_vsmsa (float[] a, int i, ref float b, ref float c, float[] d, int l, int n);
public static void Clip (float[] a, float b, float c, float[] output)
{
vDSP_vclip (a, 1, ref b, ref c, output, 1, output.Length);
}
[System.Runtime.InteropServices.DllImport ("__Internal")]
unsafe static extern void vDSP_vclip (float[] a, int i, ref float b, ref float c, float[] d, int l, int n);
}
public class ComplexDataD
{
public readonly double[] Reals;
public readonly double[] Imags;
public int Length { get { return Reals.Length; } }
public ComplexDataD (int n)
{
Reals = new double[n];
Imags = new double[n];
}
}
public class ComplexData
{
public readonly float[] Reals;
public readonly float[] Imags;
public int Length { get { return Reals.Length; } }
public ComplexData (int n)
{
Reals = new float[n];
Imags = new float[n];
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment