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