jeroldhaas
4/9/2013 - 7:38 PM

DSP functions for Xamarin.iOS bound to the Accelerate framework. See it in action by buying my Spectrogram app for iOS: https://itunes.apple

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];
		}
	}
}