diff options
Diffstat (limited to 'display/snd_linux.py')
-rw-r--r-- | display/snd_linux.py | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/display/snd_linux.py b/display/snd_linux.py new file mode 100644 index 0000000..dae82e0 --- /dev/null +++ b/display/snd_linux.py @@ -0,0 +1,148 @@ +import sys +from cStringIO import StringIO +import puremixer +from music1 import Music + + +class Sound: + # Mono only + has_sound = has_music = 0 # until initialized + + BUFFERTIME = 0.09 + FLOPTIME = 0.07 + + Formats = [ + ('U8', 8, 0, None), + ('S8', 8, 1, None), + ('S16_NE', 16, 1, None), + ('S16_LE', 16, 1, 'little'), + ('S16_BE', 16, 1, 'big'), + ('U16_LE', 16, 0, 'little'), + ('U16_BE', 16, 0, 'big'), + ] + + def __init__(self, freq=44100, fmt='S16_NE'): + self.f = None + self.freq = int(freq) + self.format = fmt.upper() + self.params = p = {} + for name, p['bits'], p['signed'], p['byteorder'] in self.Formats: + if name == self.format: + break + else: + print >> sys.stderr, 'available sound formats:' + for name, bits, signed, byteorder in self.Formats: + print >> sys.stderr, ' %-8s %s' % (name, nicefmttext( + bits, signed, byteorder)) + sys.exit(2) + + import linuxaudiodev + try: + f = linuxaudiodev.open('w') + f.setparameters(self.freq, p['bits'], 1, + getattr(linuxaudiodev, 'AFMT_' + self.format)) + except Exception, e: + print >> sys.stderr, "sound disabled: %s: %s" % ( + e.__class__.__name__, e) + return + self.f = f + self.mixer = mixer = puremixer.PureMixer(**p) + buffertime = self.BUFFERTIME + self.bufsize = int(mixer.bytespersample*mixer.freq*buffertime + + 255.5) & ~ 255 + if self.bufsize > f.bufsize(): + self.bufsize = f.bufsize() + buffertime = self.bufsize / float(freq) + self.buffertime = buffertime + self.mixer_channels = [] + self.mixer_accum = {} + self.has_sound = 1 + self.has_music = 1 + + def close(self): + self.f.close() + self.f = None + + def sound(self, f): + return self.mixer.wavesample(f.fopen()) + + def flop(self): + self.mixer_accum = {} + if self.f is None: + return + for i in range(3): + bufsize = self.bufsize - self.f.obufcount() + if bufsize <= 0: + break + self.f.write(self.mixer.mix(self.mixer_channels, bufsize)) + #cnt = getattr(self, 'CNT', 0) + #import time + #print cnt, time.time() + #self.CNT = cnt+1 + return self.FLOPTIME + + def play(self, sound, lvolume, rvolume): + # volume ignored + if sound not in self.mixer_accum: + self.mixer_channels.append(StringIO(sound)) + self.mixer_accum[sound] = 1 + + def play_musics(self, musics, loop_from): + self.cmusics = musics, loop_from, -1 + if self.mixer_channels[:1] != [self]: + self.mixer_channels.insert(0, self) + + def read(self, size): + "Provide some more data to self.mixer.poll()." + musics, loop_from, c = self.cmusics + if c < 0: + data = '' + else: + data = musics[c].mixed.decode(self.mixer, size) + if not data: + c += 1 + if c >= len(musics): # end + c = loop_from + if c >= len(musics): + return '' + self.cmusics = musics, loop_from, c + try: + mixed = musics[c].mixed + except AttributeError: + mixed = musics[c].mixed = Music(musics[c].freezefilename()) + mixed.openchannel() + data = mixed.decode(self.mixer, size) + if 0 < len(data) < size: + data += self.read(size - len(data)) + return data + + def fadeout(self, millisec): + self.cmusics = [], 0, -1 + + +def imperror(): + try: + import linuxaudiodev + except ImportError: + if sys.platform.startswith('linux'): + return 'linuxaudiodev module not installed' + else: + return 'only available on Linux' + +def nicefmttext(bits, signed, byteorder): + s = '%s %d bits' % (signed and 'signed' or 'unsigned', bits) + if byteorder: + s += ' %s endian' % byteorder + return s + +def htmloptionstext(nameval): + import modes + l = ['<font size=-1>Sampling <%s>' % nameval('select', 'fmt')] + for name, bits, signed, byteorder in Sound.Formats: + l.append('<'+nameval('option', 'fmt', name, default='S16_NE')+'>'+ + nicefmttext(bits, signed, byteorder)) + l+= ['</select> rate ', + '<%s size=5>Hz</font>' % nameval('text', 'freq', default='44100'), + '<br>', + modes.musichtmloptiontext(nameval)] + return '\n'.join(l) |