sox -t raw -e signed-integer -c 2 -r 44100 -b 16 beep100.pcm my_sound.ogg
on those instead.
-silence.ogg
------------
-
-Notes:
- Generated 2 secs of silence - dd if=/dev/zero of=silence.pcm bs=176400 count=2 ; oggenc -r silence.pcm
- Generated by Neil Muller, Aug 2010
- Not copyrightable.
-
-zzzzz.ogg
----------
-
-Notes:
- Generated by: tools/gen_sound.py 25 0.5 50 ; oggenc -o zzzzz.ogg -r beep100.pcm
- Generate by Simon Cross, May 2014
- License: MIT-style permissive license - see LICENSE.txt
-
-error.ogg
----------
-
-Notes:
- Generated by: tools/gen_sound.py 1000 0.25 ; oggenc -o error.ogg -r beep1000.pcm
- Generated by Neil Muller, May 2014
- License: MIT-style permissive license - see LICENSE.txt
-
-startup.ogg
------------
-
-Notes:
- Generated by: tools/gen_sound.py 200 0.25 ; tools/gen_sound.py 400 0.25 ; tools/gen_sound.py 600 0.25 ; tools/gen_sound.py 800 0.25 ;
- cat beep200.pcm beep400.pcm beep600.pcm beep800.pcm > startup.pcm ;
- oggenc -o startup.ogg -r startup.pcm
- Generated by Neil Muller, May 2014
- License: MIT-style permissive license - see LICENSE.txt
-
-
-shutdown.ogg
-------------
-
-Notes:
- Generated by: tools/gen_sound.py 200 0.25 ; tools/gen_sound.py 400 0.25 ; tools/gen_sound.py 600 0.25 ; tools/gen_sound.py 800 0.25 ;
- cat beep800.pcm beep600.pcm beep400.pcm beep200.pcm > shutdown.pcm ;
- oggenc -o shutdown.ogg -r shutdown.pcm
- Generated by Stefano Rivera, May 2014
- License: MIT-style permissive license - see LICENSE.txt
-
-
-zoop.ogg
---------
-
-Notes:
- Generated by:
- for ((j=500; $j < 800; j= $j+20 )); do python ../../tools/gen_sound.py $j 0.01 50; done
- cat beep5??.pcm beep6??.pcm beep7??.pcm > zoop.pcm
- oggenc -o zoop.ogg -r zoop.pcm
- Generated by Neil Muller, May 2014
- License: MIT-style permissive license - see LICENSE.txt
-
-chirp.ogg
----------
-
-Notes:
- Generate by:
- python ../../tools/gen_sound.py 1650 0.05 50 ; python ../../tools/gen_sound.py 1450 0.05 50
- cat beep1450.pcm beep1650.pcm > chirp.pcm
- oggenc -o chirp.ogg -r chirp.pcm
- Generated by Neil Muller, May 2014
- License: MIT-style permissive license - see LICENSE.txt
-
-
-grind.ogg
----------
-
-Notes:
- Generate by:
- ./tools/gen_sound.py 25 0.01 25 ; ./tools/gen_sound.py 120 0.01 25 ; ./tools/gen_sound.py 150 0.01 25 ; ./tools/gen_sound.py 170 0.01 25 ; ./tools/gen_sound.py 200 0.01 25 ; ./tools/gen_sound.py 250 0.01 25 ; ./tools/gen_sound.py 350 0.01 25 ; ./tools/gen_sound.py 300 0.01 25
- cat beep100.pcm beep250.pcm beep100.pcm beep200.pcm beep170.pcm beep300.pcm beep170.pcm beep100.pcm beep300.pcm beep120.pcm beep100.pcm beep300.pcm beep170.pcm beep120.pcm beep200.pcm beep170.pcm beep150.pcm beep300.pcm beep250.pcm beep350.pcm beep350.pcm beep120.pcm beep150.pcm beep300.pcm beep120.pcm beep200.pcm beep150.pcm beep200.pcm beep100.pcm beep120.pcm beep100.pcm beep300.pcm beep350.pcm beep200.pcm beep100.pcm beep300.pcm beep200.pcm beep200.pcm beep120.pcm beep250.pcm beep120.pcm beep100.pcm beep150.pcm beep100.pcm beep350.pcm beep120.pcm beep170.pcm beep170.pcm beep250.pcm beep170.pcm beep250.pcm beep100.pcm beep170.pcm beep350.pcm beep250.pcm beep150.pcm beep250.pcm beep200.pcm beep350.pcm beep120.pcm beep100.pcm beep120.pcm beep350.pcm beep100.pcm beep120.pcm beep200.pcm beep170.pcm beep300.pcm beep350.pcm beep100.pcm beep300.pcm beep120.pcm beep350.pcm beep250.pcm beep350.pcm beep150.pcm beep100.pcm > grind.pcm
- oggenc -o grind.ogg -r grind.pcm
-
- # order selected by:
-
- #! /bin/python
- import random
- files = ['beep100.pcm', 'beep150.pcm', 'beep200.pcm', 'beep350.pcm', 'beep120.pcm', 'beep170.pcm', 'beep250.pcm', 'beep300.pcm']
- cmd = 'cat beep100.pcm %s beep100.pcm > grind.pcm'
- rnd = []
- for x in range(75):
- rnd.append(random.choice(files))
- print cmd % ' '.join(rnd)
-
- Generated by Neil Muller, May 2014
- License: MIT-style permissive license - see LICENSE.txt
-
+See __init__.py and tools/gen_sound.py
--- /dev/null
+import random
+
+from naja.gen_sound import Chunk, scale
+
+
+def grind():
+ yield Chunk('sine', freq=100, length=0.01, volume=25)
+ tones = []
+ for freq in (100, 150, 200, 350, 120, 170, 300):
+ tones.append(Chunk('sine', freq=freq, length=0.01, volume=25))
+ for i in range(75):
+ yield random.choice(tones)
+ yield Chunk('sine', freq=100, length=0.01, volume=25)
+
+
+SOUNDS = {
+ 'chirp': scale(1650, 1449, -200, length=0.05, volume=50),
+ 'error': Chunk('sine', freq=1000, length=0.25),
+ 'grind': grind(),
+ 'shutdown': scale(800, 199, -200),
+ 'silence': Chunk('silence', length=2),
+ 'startup': scale(200, 801, 200),
+ 'zoop': scale(500, 800, 20, length=0.01, volume=50),
+ 'zzzzz': Chunk('sine', freq=100, length=0.5, volume=50),
+}
from naja.constants import ACTION_GLYPHS, BITS, CHESS_PIECES
+from naja.sound import sound
from naja.utils import bit_glyphs, move_glyph
GLYPHS = (ACTION_GLYPHS.CHANGE_BOARD,)
def perform_action(self, board, location):
+ sound.play_sound('change.ogg')
board.shift_locations(self.data['direction'])
GLYPHS = (ACTION_GLYPHS.CHANGE_BOARD,)
def perform_action(self, board, location):
+ sound.play_sound('change.ogg')
board.rotate_locations(self.data['rot_direction'])
--- /dev/null
+import math
+import struct
+
+
+def gen_sine(freq, secs, volume):
+ """
+ Generate imperfect sine waves
+
+ Design notes. Produces ~= (user requested) s of raw audio
+ We're aiming for an 8-bit'ish effect, so we're going with
+ 8125 Hz, 8 bit sampling, but faking it out to
+ CDDA output (44100 Hz, 16 bit signed) for easier conversion to ogg
+ by multiply the value by 256 (after roundin) and repeating it 4 times.
+ """
+ OUTPUT_RATE = 8125
+ # We generate freq cycles and sample that OUTPUT_RATE times
+ per_cycle = OUTPUT_RATE // freq
+ data = []
+ for x in range(per_cycle):
+ rad = float(x) / per_cycle * 2 * math.pi
+ y = 256 * int(volume * math.sin(rad))
+ data.extend([struct.pack('<i', y)] * 4)
+ # This is correct because OUTPUT_RATE = CDDA rate / 4 and we repeat
+ # the samples 4 times, so this works out to CDDA rate
+ for x in range(int(freq * secs)):
+ yield b''.join(data)
+
+
+class Chunk(object):
+ def __init__(self, type, **kwargs):
+ self.type = type
+ self.volume = 95
+ self.length = 0.25
+ for k, v in kwargs.iteritems():
+ setattr(self, k, v)
+
+ def raw(self):
+ if self.type == 'silence':
+ for i in xrange(int(176400 * self.length)):
+ yield '\x00'
+
+ if self.type == 'sine':
+ for data in gen_sine(self.freq, self.length, self.volume):
+ yield data
+
+
+def scale(start, stop, step, type='sine', **kwargs):
+ for freq in range(start, stop, step):
+ yield Chunk(type, freq=freq, **kwargs)
#!/usr/bin/env python
-# Generate imperfect sine waves
-#
-# Design notes. Produces ~= (user requested) s of raw audio
-# We're aiming for an 8-bit'ish effect, so we're going with
-# 8125 Hz, 8 bit sampling, but faking it out to
-# CDDA output (44100 Hz, 16 bit signed) for easier conversion to ogg
-# by multiply the value by 256 (after roundin) and repeating it 4 times.
-
+from subprocess import Popen, PIPE
+import os
import sys
-import math
-import struct
-OUTPUT_RATE = 8125
-DEFAULT_VOL = 95
+
+def gen_raw(description):
+ for chunk in description:
+ for blob in chunk.raw():
+ yield blob
-def gen_sine(freq, secs, volume):
- filename = 'beep%s.pcm' % freq
- # We generate freq cycles and sample that OUTPUT_RATE times
- per_cycle = OUTPUT_RATE // freq
- data = []
- for x in range(per_cycle):
- rad = float(x) / per_cycle * 2 * math.pi
- y = 256 * int(volume * math.sin(rad))
- data.extend([struct.pack('<i', y)] * 4)
- output = open(filename, 'wb')
- # This is correct because OUTPUT_RATE = CDDA rate / 4 and we repeat
- # the samples 4 times, so this works out to CDDA rate
- for x in range(int(freq * secs)):
- output.write(b''.join(data))
- output.close()
- print ('Wrote output to %s' % filename)
+def encode(filename, data):
+ print "Writing %s" % filename
+ p = Popen(('oggenc', '-o', filename, '--raw', '--quiet', '-'),
+ stdin=PIPE, cwd='data/sounds')
+ for blob in data:
+ p.stdin.write(blob)
+ p.stdin.close()
+ assert p.wait() == 0
-def usage():
- print ('Unexpected input')
- print ('Usage gen_sound <freq> [<length>] [<volume>]')
- print (' where <freq> is the frequency in Hz (int)')
- print (' [<length>] is the time in seconds (float) - default 0.25')
- print (' and [<volume>] is the volume (integer between 0 and 127)'
- ' - default %s' % DEFAULT_VOL)
+def write(basename, description):
+ return encode('%s.ogg' % basename, gen_raw(description))
-if __name__ == "__main__":
- try:
- freq = int(sys.argv[1])
- if len(sys.argv) > 2:
- secs = float(sys.argv[2])
- else:
- secs = 0.25
- if len(sys.argv) > 3:
- volume = int(sys.argv[3])
- else:
- volume = DEFAULT_VOL
- except Exception as exc:
- usage()
- print ('Error was: %s' % exc)
- sys.exit(1)
+def main():
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
+ from data.sounds import SOUNDS
+ from naja.gen_sound import Chunk
- if volume > 128 or volume < 0:
- usage()
- print ('Invalid volume: %s' % volume)
- sys.exit(1)
+ sounds = SOUNDS.keys()
+ if len(sys.argv) > 1:
+ sounds = (sys.argv[1:])
+ for sound in sounds:
+ description = SOUNDS[sound]
+ if isinstance(description, Chunk):
+ description = (description,)
+ write(sound, description)
- if freq > 2000 or freq < 100:
- usage()
- print ('Invalid freq: %s' % volume)
- sys.exit(1)
- gen_sine(freq, secs, volume)
+if __name__ == '__main__':
+ main()