6e524e850f05fa1660126dbd161f2ace1bb62b4d
[naja.git] / tools / gen_sound.py
1 # Generate imperfect sine waves
2 #
3 # Design notes. Produces ~= (user requested) s of raw audio
4 # We're aiming for an 8-bit'ish effect, so we're going with
5 # 8125 Hz, 8 bit sampling, but faking it out to
6 # CDDA output (44100 Hz, 16 bit signed) for easier conversion to ogg
7 # by multiply the value by 256 (after roundin) and repeating it 4 times.
8
9 import sys
10 import math
11 import struct
12
13 OUTPUT_RATE = 8125
14 DEFAULT_VOL = 95
15
16
17 def gen_sine(freq, secs, volume):
18     filename = 'beep%s.pcm' % freq
19     # We generate freq cycles and sample that OUTPUT_RATE times
20     per_cycle = OUTPUT_RATE / freq
21     data = []
22     for x in range(per_cycle):
23         rad = float(x) / per_cycle * 2 * math.pi
24         y = 256 * int(volume * math.sin(rad))
25         data.extend([struct.pack('<i', y)] * 4)
26     output = open(filename, 'w')
27     # This is correct because OUTPUT_RATE = CDDA rate / 4 and we repeat
28     # the samples 4 times, so this works out to CDDA rate
29     for x in range(int(freq * secs)):
30         output.write(''.join(data))
31     output.close()
32     print 'Wrote output to %s' % filename
33
34
35 def usage():
36     print 'Unexpected input'
37     print 'Usage gen_sound <freq> [<length>] [<volume>]'
38     print ' where <freq> is the frequency in Hz (int)'
39     print ' [<length>] is the time in seconds (float) - default 0.25'
40     print (' and [<volume>] is the volume (integer between 0 and 127)'
41            ' - default %s' % DEFAULT_VOL)
42
43
44 if __name__ == "__main__":
45     try:
46         freq = int(sys.argv[1])
47         if len(sys.argv) > 2:
48             secs = float(sys.argv[2])
49         else:
50             secs = 0.25
51         if len(sys.argv) > 3:
52             volume = int(sys.argv[3])
53         else:
54             volume = DEFAULT_VOL
55     except Exception, exc:
56         usage()
57         print 'Error was', exc
58         sys.exit(1)
59
60     if volume > 128 or volume < 0:
61         usage()
62         print 'Invalid volume: %s' % volume
63         sys.exit(1)
64
65     if freq > 2000 or freq < 100:
66         usage()
67         print 'Invalid freq: %s' % volume
68         sys.exit(1)
69
70     gen_sine(freq, secs, volume)