-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathWindows.hs
125 lines (110 loc) · 4.7 KB
/
Windows.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
{-# LANGUAGE ConstraintKinds #-}
module Windows(
hann
, noWindow
, hamming
, tukey
, cosine
, lanczos
, triangular
, cossq
, frameWithWinAndOverlap
, flattenWithOverlapS
) where
import Prelude hiding(splitAt,(++),concat,zipWith,concatMap,null,head,take)
import Common
import Signal
import Internal
import Data.List.Stream
import qualified Data.Vector.Unboxed as U
import Data.Vector.Unboxed((!),Unbox(..))
frameWithWinAndOverlap :: (Unbox a, Num t)
=> Int -- ^ Window size
-> Int -- ^ Overlap in samples
-> (Int -> Int -> a -> a) -- ^ Window function
-> Sampled t a -- ^ Input signal
-> Sampled t (U.Vector a) -- Result and new sampling period
frameWithWinAndOverlap winSize o winF signal =
let r' = (period signal) * fromIntegral (winSize - o)
frame z =
let (ws,r1) = splitAtVectorS (winSize - o) z
(os,r2) = splitAtVectorS o r1
h = toVectorBS $ imapBS (winF winSize) (appendBS ws os)
in
consS h (frame r1)
in
Sampled r' (frame (getSignal signal))
flattenWithOverlapS :: (Unbox a,Num a, Fractional t)
=> Int -- ^ Window size
-> Int -- ^ Overlap
-> Sampled t (U.Vector a) -- ^ Signal
-> Sampled t a -- ^ Result and new sampling period
flattenWithOverlapS winSize o s | null (getSamples . getSignal $ s) = error "A signal can't be empty : in flattenWithOverlapS"
| o == 0 = Sampled r' (concatMapS U.toList . getSignal $ s)
| otherwise =
let h = headS (getSignal s)
n = U.length h
index = U.fromList [0..o-1]
_flatten [] = []
_flatten (a:b:l) = U.toList (U.slice o (n-o) v) : _flatten (b:l)
where
combine b i x | i >= o = x + (b!(i-o))
| otherwise = x
v = U.imap (combine b) a
news = appendListS (take o . U.toList $ h)
(concatS . onSamples _flatten . getSignal $ s)
in
Sampled r' news
where
r' = (period s) / fromIntegral (winSize - o)
cossq m i x = let sq z = z * z
in
x* sq(sin(pi*fromIntegral i / fromIntegral (m-1)))
hann :: (Num a, HasDoubleRepresentation a)
=> Int
-> Int
-> a
-> a
hann m n x = x * (fromDouble $ 0.5 * (1 - cos (2 * pi * fromIntegral n / fromIntegral (m - 1))))
noWindow :: Int -> Int -> a -> a
noWindow _ _ x = x
hamming :: (Num a, HasDoubleRepresentation a)
=> Double -- ^ Alpha
-> Int
-> Int
-> a
-> a
hamming alpha m n x = x * (fromDouble $ alpha - (1 - alpha) * cos(2*pi*fromIntegral n / fromIntegral (m-1)))
tukey :: (Num a, HasDoubleRepresentation a)
=> Double -- ^ Alpha
-> Int
-> Int
-> a
-> a
tukey alpha m n x | n <= floor (alpha * fromIntegral (m-1) / 2.0) =
x * (fromDouble $ 0.5 * (1 + cos(pi * (2*fromIntegral n/alpha/ fromIntegral (m-1) - 1))))
| (floor $ alpha * fromIntegral (m-1) / 2.0) <= n
&& n <= floor (fromIntegral (m-1)*(1 - alpha / 2.0)) = x
| otherwise = x * (fromDouble $ 0.5 *
(1 + cos(pi * (2*fromIntegral n/alpha/ fromIntegral (m-1) - 2 / alpha + 1))))
cosine :: (Num a, HasDoubleRepresentation a)
=> Int
-> Int
-> a
-> a
cosine m n x = x * (fromDouble $ sin (pi * fromIntegral n / fromIntegral (m-1)))
lanczos :: (Num a, HasDoubleRepresentation a)
=> Int
-> Int
-> a
-> a
lanczos m n x = x * (fromDouble $ sinc (2*fromIntegral n / fromIntegral (m-1) - 1))
where
sinc x | x == 0 = 1
| otherwise = sin(pi*x) / (pi*x)
triangular :: (Num a, HasDoubleRepresentation a)
=> Int
-> Int
-> a
-> a
triangular m n x = x * (fromDouble $ 2.0 / fromIntegral (m+1) * (fromIntegral (m+1)/2.0 - abs (fromIntegral n - fromIntegral(m-1)/2.0)))