hommage-0.0.5: Haskell Offline Music Manipulation And Generation EDSLSource codeContentsIndex
Sound.Hommage.DFTFilter
Contents
User-Level Filter Functions
CoeffArr
CoeffMap
IO Wrapper
Interface to C-code
Description
This module imports the C-functions for a Fast Fourier Transform and encapsulates them in list-mapping functions. (At first it was a DFT algoritm which I changed, but I didn'd change all the names of the functions, so it is called dft...) The functionality of this module is used for filtering audio data, i. e. for building audio filters.
Synopsis
dftanalyse :: [Double] -> [Complex Double]
dftsynthese :: [Complex Double] -> [Double]
dftfilter :: [Double] -> [Double] -> [Double]
dftfilterBy :: IO (CoeffMap ()) -> [Double] -> [Double]
dftfilterBy' :: s -> IO (s -> CoeffMap s) -> [Double] -> [Double]
type CoeffArr = StorableArray Int Double
readCoeffArr :: CoeffArr -> Int -> IO (Complex Double)
writeCoeffArr :: CoeffArr -> Int -> Complex Double -> IO ()
storeCoeff :: IOArray Int (Complex Double) -> CoeffArr -> IO ()
unstoreCoeff :: CoeffArr -> IOArray Int (Complex Double) -> IO ()
type CoeffMap a = CoeffArr -> CoeffArr -> IO a
mkCoeffMap :: [Double] -> IO (CoeffMap ())
coeffmap :: StorableArray Int Double -> CoeffMap ()
mkAnalyse :: IO (Maybe Double -> IO (Maybe (Complex Double)))
mkSynthese :: IO (Maybe (Complex Double) -> IO (Maybe Double))
mkFilterBuffered :: IO (CoeffMap ()) -> IO (Maybe Double -> IO (Maybe Double))
analyseDFT :: StorableArray Int Double -> StorableArray Int Double -> IO ()
syntheseDFT :: StorableArray Int Double -> StorableArray Int Double -> IO ()
kurveDFT :: StorableArray Int Double -> IO ()
Documentation

Filtering is done with an FFT algorithm written in C (in the file dft.c). This module imports the c-functions for fft (analyseDFT) and inverse fft (syntheseDFT), which operate on Arrays with 1024 Double values. The array-operations are embedded in a mechanism that does buffering, overlapping and windowing and works like a black box that maps one input value to one output value in the IO monad (mkAnalyse, mkSynthese, mkFilterBuffered). Around these IO's some list mapping functions are wrapped (dftanalyse, dftsynthese, dftfilter, dftfilterBy) for convenient use in a Haskell programm.

Mapping the Fourier coefficients during the filter process means filtering the data. The result depends on the way the coefficients are mapped resp. modified while mapping. The function to do this has the type of CoeffMap.

Description of the filtering process:

Filtering is done by mapping the coefficients with CoeffMap. For this the wave data is split into parts of 1024 values, where every part overlaps with the preceeding and succeeding part by 512 values. Via the fourier-transform (analyse) every part is mapped to its frequency spectrum, i. e. its fourier coefficients.

The CoeffMap action is applied to every frequency spectrum (see CoeffArr) in sequence. It reads the coefficients from the first CoeffArr where the input is stored and writes it (or some data derived from it) to the second one. This is the point where the 'real' filtering happens. Via the inverse fourier-transform (synthese) the resulting coefficients are mapped to their real signal values. These signal values are multiplied with a half cosinus curve for fading in and out (windowing). Then they are mixed in the way their source data was split: Every part overlaps for 512 values with the last and the next one.

User-Level Filter Functions
dftanalyse :: [Double] -> [Complex Double]Source
(Fast) Fourier Transformation.
dftsynthese :: [Complex Double] -> [Double]Source
Inverse (Fast) Fourier Transformation
dftfilter :: [Double] -> [Double] -> [Double]Source
(Fast) Fourier Transformation and Inverse with an additional argument with sublists of factors to weight the coefficients. See mkCoeffMap for a decription of that argument.
dftfilterBy :: IO (CoeffMap ()) -> [Double] -> [Double]Source
(Fast) Fourier Transformation and Inverse with a buffer-mapping action for filtering.
dftfilterBy' :: s -> IO (s -> CoeffMap s) -> [Double] -> [Double]Source
(Fast) Fourier Transformation and Inverse with a buffer-mapping action for filtering.
CoeffArr
type CoeffArr = StorableArray Int DoubleSource

Represents a frequency spectrum. Range is from 0 to 1023 (N=1024). Index 0 is constant value, index 1 is Nyquest frequency (real part of the N/2 frequency). Index 2 and 3 are the complex value for the basefrequency, index 4 and 5 are the complex value for the double basefrequency, 6 and 7 for 3 * basefrequency and so on:

 arr [0] = real part of zero frequency (imaginary part is allways 0)
 arr [1] = real part of Nyquest frequency (N/2) (imaginary part is allways 0)
 arr [2] = real part of base frequency
 arr [3] = imag part of base frequency
 arr [4] = real part of base frequency * 2
 arr [5] = imag part of base frequency * 2
 arr [6] = real part of base frequency * 3
 arr [7] = imag part of base frequency * 3
 ...
 arr [N-4] = real part of base frequency * (N/2 - 2)
 arr [N-3] = imag part of base frequency * (N/2 - 2)
 arr [N-2] = real part of base frequency * (N/2 - 1)
 arr [N-1] = imag part of base frequency * (N/2 - 1)

Pseudocode:

 c (0)   = (arr [0] :+ 0)
 c (512) = (arr [1] :+ 0)

and for all i=[1..511]:

 c (i) = (arr [i*2] :+ arr [i*2+1])
readCoeffArr :: CoeffArr -> Int -> IO (Complex Double)Source
Reads a Complex value of a CoeffArr (with Nyquest as imaginary part of coeff 0).
writeCoeffArr :: CoeffArr -> Int -> Complex Double -> IO ()Source
Writes a Complex value of a CoeffArr (with Nyquest as imaginary part of coeff 0).
storeCoeff :: IOArray Int (Complex Double) -> CoeffArr -> IO ()Source
unstoreCoeff :: CoeffArr -> IOArray Int (Complex Double) -> IO ()Source
CoeffMap
type CoeffMap a = CoeffArr -> CoeffArr -> IO aSource
An action that maps the fourier coefficients from the first array to the second. Modifying the data while mapping means filtering. See CoeffArr for a description of the arrays.
mkCoeffMap :: [Double] -> IO (CoeffMap ())Source
Constructs a Coeffmap. The sublists contain the 512 real values with which the basefrequency and the 511 complex fourier coefficients are multiplied (the Nyquist frequency will be zero). The first value is the factor for the constant coefficient, the second for the base frequency, the next one for the double base freq and so on. If the sublists have more than 512 elements, these elements are thrown away. If it is shorter, the array will be filled up with zeros.
coeffmap :: StorableArray Int Double -> CoeffMap ()Source
coeffmap takes an Array with 512 values and uses them for a weigted map of the fourier coefficients. The Nyquist frequency is muliplied with 0.0.
IO Wrapper
mkAnalyse :: IO (Maybe Double -> IO (Maybe (Complex Double)))Source
Constructs an action that maps wave-data to coefficient-data. Has a delay of 512, i. e. the first 512 elements are zero and the result has (these) 512 elemets more than the input.
mkSynthese :: IO (Maybe (Complex Double) -> IO (Maybe Double))Source
Constructs an action that maps coefficient-data to wave-data. Has a delay of 512, i. e. the first 512 elements are zero and the result has (these) 512 elemets more than the input.
mkFilterBuffered :: IO (CoeffMap ()) -> IO (Maybe Double -> IO (Maybe Double))Source
Constructs an action that maps wave-data to wave-data via a Fast Foutrier Transform and inverse, filtered by the given CoeffMap. Has a delay of 1024.
Interface to C-code
analyseDFT :: StorableArray Int Double -> StorableArray Int Double -> IO ()Source
Maps an array with 1024 real values to its frequency spectrum with 512 complex values. The spectrum is stored in the second array with 1024 Doubles which are the real and imaginary parts of the complex values. See CoeffArr for a detailed frequency spectrum desription.
syntheseDFT :: StorableArray Int Double -> StorableArray Int Double -> IO ()Source
Maps a frequency spectrum to its signal value. Both arrays have a length of 1024; the first one contains the 512 complex values of the spectrum. The real signal value will be stored in the second array. See CoeffArr for a detailed frequency spectrum desription.
kurveDFT :: StorableArray Int Double -> IO ()Source
Fades a signal which is stored in an array of length 1024 in and out. The signal is multiplied with a cosinus curve with range 0..pi.
Produced by Haddock version 2.4.2