-
Notifications
You must be signed in to change notification settings - Fork 0
/
tools.py
99 lines (93 loc) · 2.37 KB
/
tools.py
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
"""
Various tools for easier work.
"""
from functools import wraps
from audiolazy import Stream, sHz
import math
def streamify(gen):
"""
Take a generator and make it return streams.
"""
@wraps(gen)
def _g(*args,**kwargs):
g = gen(*args,**kwargs)
return Stream(g)
return _g
@streamify
def buffer_stream(stream,length,frac):
"""
Assuming only a given length of a given stream is wanted, buffers
a fraction of it, and keeps reading at a lower pace from the original
stream. Rounds frac to the nearst 1/1000, to escape floating-point
errors.
"""
n = int(frac*1000)
stream.limit(length)
to_read_1000 = length*n
int_to_read = to_read_1000 / 1000
rem = to_read_1000 % 1000
buf = stream.take(int_to_read)
op_n = 1000 - n
while True:
rem += op_n
if rem >= 1000:
try:
val = stream.take()
except StopIteration:
for x in buf:
yield x
break
buf.append(val)
rem -= 1000
if len(buf) > 0:
yield buf[0]
else:
try:
stream.take()
except StopIteration:
break
else:
raise AssertionError("Iterator should be empty.")
del buf[0]
@streamify
def nat_buffer_stream(stream,length,ratio):
"""
Assuming only a given length of a given stream is wanted, buffers
a fraction of it required to read from the stream only once every
ratio outputs.
"""
stream.limit(length)
to_read = int(math.ceil(length * float(ratio-1) / ratio))
buf = stream.take(to_read)
for val in stream:
buf.append(val)
for i in xrange(ratio):
yield buf[i]
del buf[:ratio]
for val in buf:
yield val
def sine_amp(freq,h,t):
"""
Returns the amplitude of a sine.
Input:
freq: frequency in Hz.
h: 2*pi / samprate.
t: sample index (not sec).
"""
return math.sin(t*float(freq)*h)
def frange(start,end=None,step=None):
"""
like xrange but floating-point.
"""
if end is None:
end = start
start = 0.0
else:
start = float(start)
if step is None:
step = 1.0
else:
step = float(step)
while start != end:
yield start
start += step