forked from auracaster/pyalsaaudio
playwav uses PCM_FORMAT_U8 for 8bit data.
Added isine as an example for interactive generation of sound. git-svn-id: svn://svn.code.sf.net/p/pyalsaaudio/code/trunk@33 ec2f30ec-7544-0410-870e-f70ca00c83f0
This commit is contained in:
1
CHANGES
1
CHANGES
@@ -3,6 +3,7 @@ Version 0.5:
|
||||
This included a mixertest with more features
|
||||
- fixed/applied patch 2594366: alsapcm_setup does not do any error checking
|
||||
|
||||
|
||||
Version 0.4:
|
||||
- API changes: mixers() and Mixer() now take a card index instead of a
|
||||
card name as optional parameter.
|
||||
|
||||
79
isine.py
Normal file
79
isine.py
Normal file
@@ -0,0 +1,79 @@
|
||||
''' Use this example from an interactive python session, for example:
|
||||
|
||||
>>> from isine import change
|
||||
>>> change(880)
|
||||
'''
|
||||
|
||||
from threading import Thread
|
||||
from Queue import Queue, Empty
|
||||
from math import pi, sin
|
||||
import struct
|
||||
import alsaaudio
|
||||
|
||||
sampling_rate = 44100
|
||||
format = alsaaudio.PCM_FORMAT_S16_LE
|
||||
framesize = 2 # bytes per frame for the values above
|
||||
|
||||
def digitize(s):
|
||||
if s > 1.0 or s < -1.0:
|
||||
raise ValueError
|
||||
|
||||
return struct.pack('h', int(s * 32767))
|
||||
|
||||
def generate(frequency):
|
||||
# generate a buffer with a sine wave of frequency
|
||||
size = int(sampling_rate / frequency)
|
||||
buffer = ''
|
||||
for i in range(size):
|
||||
buffer = buffer + digitize(sin(i/(2 * pi)))
|
||||
|
||||
return buffer
|
||||
|
||||
class SinePlayer(Thread):
|
||||
|
||||
def __init__(self, frequency = 440.0):
|
||||
Thread.__init__(self)
|
||||
self.setDaemon(True)
|
||||
self.device = alsaaudio.PCM()
|
||||
self.device.setchannels(1)
|
||||
self.device.setformat(format)
|
||||
self.device.setrate(sampling_rate)
|
||||
self.queue = Queue()
|
||||
self.change(frequency)
|
||||
|
||||
def change(self, frequency):
|
||||
'''This is called outside of the player thread'''
|
||||
# we generate the buffer in the calling thread for less
|
||||
# latency when switching frequencies
|
||||
|
||||
|
||||
# More than 100 writes/s are pushing it - play multiple buffers
|
||||
# for higher frequencies
|
||||
|
||||
factor = int(frequency/100.0)
|
||||
if factor == 0:
|
||||
factor = 1
|
||||
|
||||
buf = generate(frequency) * factor
|
||||
print 'factor: %d, frames: %d' % (factor, len(buf) / framesize)
|
||||
|
||||
self.queue.put( buf)
|
||||
|
||||
def run(self):
|
||||
buffer = None
|
||||
while True:
|
||||
try:
|
||||
buffer = self.queue.get(False)
|
||||
self.device.setperiodsize(len(buffer) / framesize)
|
||||
self.device.write(buffer)
|
||||
except Empty:
|
||||
if buffer:
|
||||
self.device.write(buffer)
|
||||
|
||||
|
||||
isine = SinePlayer()
|
||||
isine.start()
|
||||
|
||||
def change(f):
|
||||
isine.change(f)
|
||||
|
||||
@@ -14,13 +14,18 @@ import alsaaudio
|
||||
|
||||
def play(device, f):
|
||||
|
||||
|
||||
sys.stdout.write('%d channels, %d sampling rate\n' % (f.getnchannels(),
|
||||
f.getframerate()))
|
||||
# Set attributes
|
||||
device.setchannels(f.getnchannels())
|
||||
device.setrate(f.getframerate())
|
||||
|
||||
# We assume signed data, little endian
|
||||
|
||||
# We 8bit is unsigned in wav files
|
||||
if f.getsampwidth() == 1:
|
||||
device.setformat(alsaaudio.PCM_FORMAT_S8)
|
||||
device.setformat(alsaaudio.PCM_FORMAT_U8)
|
||||
# Otherwise we assume signed data, little endian
|
||||
elif f.getsampwidth() == 2:
|
||||
device.setformat(alsaaudio.PCM_FORMAT_S16_LE)
|
||||
elif f.getsampwidth() == 3:
|
||||
|
||||
Reference in New Issue
Block a user