git.haldean.org symrep / b985cc6
fix sine implementation Will Haldean Brown 6 years ago
2 changed file(s) with 31 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
00 import array
11 import math
22 import struct
3 import symrep
3 import symrep.base
44
55 def sine(freq):
6 return symrep.Node(
7 "sin", lambda t: math.sin(t * freq(t) / (2 * math.pi)), [freq])
6 return symrep.base.Node(
7 "sin", lambda t: math.sin(t * freq(t) * 2. * math.pi), [freq])
8
9 def square(freq):
10 pass
11
12 def _to_short(val, max_amplitude=1.0):
13 short_max = (2 ** 15) - 1
14 val = int(val / max_amplitude * short_max)
15 if val > short_max:
16 return short_max
17 elif val < -short_max:
18 return -short_max
19 return val
820
921 def to_wav(root, sample_rate, length, stream):
10 num_samples = int(math.ceil(length * sample_rate))
11 print 'generating', num_samples, 'samples'
12 bits_per_sample = 32
13
14 def sample_t():
15 i = t = 0
16 while i < num_samples:
17 yield t
18 i += 1
19 t += 1 / sample_rate
20
21 data = array.array("f", (root(t) for t in sample_t()))
22 print 'data is', len(data), 'samples'
23 import pprint; pprint.pprint(data[:20])
22 bits_per_sample = 16
23 data = array.array("h", map(
24 lambda x: _to_short(x[1]),
25 symrep.base.sample(root, 0., length, 1. / sample_rate)))
2426
2527 # begin file header
2628 stream.write("RIFF")
4446
4547 # begin data header
4648 stream.write("data")
47 stream.write(struct.pack("<I", len(data)))
49 stream.write(struct.pack("<I", 4 * len(data)))
4850 data.tofile(stream)
4951
5052 if __name__ == "__main__":
53 n = symrep.base.product(
54 sine(symrep.base.const(440)),
55 sine(symrep.base.const(0.2)),
56 )
5157 with open("test.wav", "w") as f:
52 to_wav(sine(symrep.const(440)), 41000, 10, f)
58 to_wav(n, 44100, 5, f)
2020 def __call__(self, t):
2121 return self.func(t)
2222
23 def sample(root, min_t, max_t, delta_t):
24 t = min_t
25 while t < max_t:
26 yield t, root(t)
27 t += delta_t
28
2329 def collect_nodes(root):
2430 return set([root]).union(
2531 reduce(set.union, map(collect_nodes, root.deps), set()))