packages feed

ForSyDe-3.0: examples/Equalizer_Shallow/AudioAnalyzer.lhs

\subsection{Overview}

The \process{Audio Analyzer} analyzes the current bass level and raises a flag when the bass level exceeds a limit. 

\begin{figure}
\centering
\scalebox{0.8}{\mbox{\input{Figures/AudioAnalyzer.pstex_t}}}
\caption{The \textit{Audio Analyzer} subsystem}
\label{fig:AudioAnalyzerSubsystem}
\end{figure}

As illutsrated in Figure \ref{fig:AudioAnalyzerSubsystem} the \process{Audio Analyzer} is divided into four blocks. The input signal is first grouped into samples of size $N$ in the process \process{Group Samples} and then processed with a \process{DFT} in order to get the frequency spectrum of the signal. Then the power spectrum is calculated in \process{Spectrum}. In \process{CheckBass} the lowest frequencies are compared with a threshold value. If they exceed this value, the output \process{Distortion Flag} will have the value \constant{Fail}.

Since \process{Group Samples} needs $N$ cycles for the grouping, it produces $N-1$ absent values $\perp$ for each grouped sample. Thus the following processes \process{DFT}, \process{Spectrum} and \process{Check Bass} are all $\Psi$-extended in order to be able to process the absent value $\Abst$.
\begin{code}
module AudioAnalyzer (audioAnalyzer) where

import ForSyDe.Shallow
import Complex
import EqualizerTypes

input = 0.1 :- 0.2 :- input

limit :: Double
limit = 1.0

nLow :: Int
nLow = 3

audioAnalyzer :: Int -> Signal Double -> Signal (AbstExt AnalyzerMsg)
audioAnalyzer pts =  mapSY (psi checkBass) -- Check Bass 
		   . mapSY (psi spectrum)  -- Spectrum
		   . mapSY (psi (dft pts)) -- DFT
		   . groupSY pts	   -- Group Samples 
		   . mapSY toComplex

spectrum :: (RealFloat a) => Vector (Complex a) -> Vector a
spectrum =  mapV log10 . selectLow nLow . mapV power . selectHalf . dropV 1
  where
    log10 x        = log x / log 10
    selectLow n xs = takeV n xs
    selectHalf xs  = takeV half xs
	       where half = floor (fromIntegral (lengthV xs) / 2)  
    power x = (magnitude x) ^ 2

checkBass :: Vector Double -> AnalyzerMsg
checkBass = checkLimit limit . sumV
  where
    checkLimit limit x | x > limit  = Fail
	               | otherwise  = Pass
    sumV vs = foldlV (+) 0.0 vs


toComplex x = x :+ 0
\end{code}