Make chess puzzle level (Kasparov to F3) winnable.
[naja.git] / naja / gen_sound.py
1 import math
2 import struct
3
4
5 def gen_sine(freq, secs, volume):
6     """
7     Generate imperfect sine waves
8
9     Design notes. Produces ~= (user requested) s of raw audio
10     We're aiming for an 8-bit'ish effect, so we're going with
11     8125 Hz, 8 bit sampling, but faking it out to
12     CDDA output (44100 Hz, 16 bit signed) for easier conversion to ogg
13     by multiply the value by 256 (after roundin) and repeating it 4 times.
14     """
15     OUTPUT_RATE = 8125
16     # We generate freq cycles and sample that OUTPUT_RATE times
17     per_cycle = OUTPUT_RATE // freq
18     data = []
19     for x in range(per_cycle):
20         rad = float(x) / per_cycle * 2 * math.pi
21         y = 256 * int(volume * math.sin(rad))
22         data.extend([struct.pack('<i', y)] * 4)
23     # This is correct because OUTPUT_RATE = CDDA rate / 4 and we repeat
24     # the samples 4 times, so this works out to CDDA rate
25     for x in range(int(freq * secs)):
26         yield b''.join(data)
27
28
29 class Chunk(object):
30     def __init__(self, type, **kwargs):
31         self.type = type
32         self.volume = 95
33         self.length = 0.25
34         for k, v in kwargs.iteritems():
35             setattr(self, k, v)
36
37     def raw(self):
38         if self.type == 'silence':
39             for i in xrange(int(88200 * self.length)):
40                 yield '\x00'
41
42         if self.type == 'sine':
43             for data in gen_sine(self.freq, self.length, self.volume):
44                 yield data
45
46
47 def scale(start, stop, step, type='sine', **kwargs):
48     for freq in range(start, stop, step):
49         yield Chunk(type, freq=freq, **kwargs)