packages feed

HSoM-1.0.0: HSoM/Examples/FFT.lhs

Filename: fft.hs
Created by: Daniel Winograd-Cort
Created on: unknown
Last Modified by: Daniel Winograd-Cort
Last Modified on: 16-Dec-2015 by Donya Quick

This module requires the array and pure-fft packages.

> {-# LANGUAGE Arrows #-}
> module HSoM.Examples.FFT where
> import FRP.UISF
> import Control.Arrow.Operations
> import Numeric.FFT (fft)
> import Data.Complex
> import Data.Map (Map)
> import qualified Data.Map as Map



Alternative for working with Math.FFT instead of Numeric.FFT
import qualified Math.FFT as FFT
import Data.Array.IArray
import Data.Array.CArray
myFFT n lst = elems $ (FFT.dft) (listArray (0, n-1) lst)


--------------------------------------
-- Fast Fourier Transform
--------------------------------------

Returns n samples of type b from the input stream at a time, 
updating after k samples.  This function is good for chunking 
data and is a critical component to fftA

> quantize :: ArrowCircuit a => Int -> Int -> a b (SEvent [b])
> quantize n k = proc d -> do
>     rec (ds,c) <- delay ([],0) -< (take n (d:ds), c+1)
>     returnA -< if c >= n && c `mod` k == 0 then Just ds else Nothing

Converts the vector result of a dft into a map from frequency to magnitude.
One common use is:
fftA >>> arr (fmap $ presentFFT clockRate)

> presentFFT :: Double -> [Double] -> Map Double Double
> presentFFT clockRate a = Map.fromList $ zipWith (curry mkAssoc) [0..] a where 
>     mkAssoc (i,c) = (freq, c) where
>         samplesPerPeriod = fromIntegral (length a)
>         freq = i * (clockRate / samplesPerPeriod)

Given a quantization frequency (the number of samples between each 
successive FFT calculation) and a fundamental period, this will decompose
the input signal into its constituent frequencies.
NOTE: The fundamental period must be a power of two!

> fftA :: ArrowCircuit a => Int -> Int -> a Double (SEvent [Double])
> fftA qf fp = proc d -> do
>     carray <- quantize fp qf -< d :+ 0
>     returnA -< fmap (map magnitude . take (fp `div` 2) . fft) carray