zeroCrossingRate :: VU.Vector Int -> Int -> VU.Vector Double
zeroCrossingRate signal win_sz = 
    VU.map m $ VU.fromList [0..(numSamples - 1)]
    
  where m :: Int -> Double
        -- sum(|s[k]| * w[n-k])/N
        m n = (fromIntegral $ sumRes n) / 
                    (2 * (fromIntegral win_sz_samples)) 
        
        sumRes n = VU.foldl'(+) 0 $ -- Sum results
                      -- |sgn(s[k] - sgn(s[k-1])| * w[n-k]
                     VU.map (\k -> (abs (signum (signal VU.! k) - 
                                        (signum (signal VU.! (k - 1))))) * 
                                        (rectWindow win_sz_samples (n - k)))
                            -- k values
                            $ VU.fromList 
                                    [(max (n - win_sz_samples + 1) 1) .. 
                                     (min n (numSamples - 1))] 

        -- Number of samples in the Window of win_sz milliseconds 
        win_sz_samples = (numSamples `div` samplingTime) * win_sz
        -- Total number of samples supplied to the convolution function
        numSamples = VU.length signal  


-- Write Samples to CSV file
zeroCrossingRate :: VU.Vector Int -> Int -> VU.Vector Double
zeroCrossingRate signal win_sz = 
    VU.map m $ VU.fromList [0..(numSamples - 1)]
    
  where m :: Int -> Double
        -- sum(|s[k]| * w[n-k])/N
        m n = (fromIntegral $ sumRes n) / 
                    (2 * (fromIntegral win_sz_samples)) 
        
        sumRes n = VU.foldl'(+) 0 $ -- Sum results
                      -- |sgn(s[k] - sgn(s[k-1])| * w[n-k]
                     VU.map (\k -> (abs (signum (signal VU.! k) - 
                                        (signum (signal VU.! (k - 1))))) * 
                                        (rectWindow win_sz_samples (n - k)))
                            -- k values
                            $ VU.fromList 
                                    [(max (n - win_sz_samples + 1) 1) .. 
                                     (min n (numSamples - 1))] 

        -- Number of samples in the Window of win_sz milliseconds 
        win_sz_samples = (numSamples `div` samplingTime) * win_sz
        -- Total number of samples supplied to the convolution function
        numSamples = VU.length signal  


-- Write Samples to CSV file
zeroCrossingRate signal win_sz = 
    VU.map m $ VU.fromList [0..(numSamples - 1)]
    
  where m :: Int -> Double
        -- sum(|s[k]| * w[n-k])/N
        m n = (fromIntegral $ sumRes n) / 
                    (2 * (fromIntegral win_sz_samples)) 
        
        sumRes n = VU.foldl'(+) 0 $ -- Sum results
                      -- |sgn(s[k] - sgn(s[k-1])| * w[n-k]
                     VU.map (\k -> (abs (signum (signal VU.! k) - 
                                        (signum (signal VU.! (k - 1))))) * 
                                        (rectWindow win_sz_samples (n - k)))
                            -- k values
                            $ VU.fromList 
                                    [(max (n - win_sz_samples + 1) 1) .. 
                                     (min n (numSamples - 1))] 

        -- Number of samples in the Window of win_sz milliseconds 
        win_sz_samples = (numSamples `div` samplingTime) * win_sz
        -- Total number of samples supplied to the convolution function
        numSamples = VU.length signal  


-- Write Samples to CSV file