mirror of
https://github.com/larsimmisch/pyalsaaudio.git
synced 2026-04-16 16:15:31 +00:00
82 lines
2.1 KiB
Python
82 lines
2.1 KiB
Python
''' Use this example from an interactive python session, for example:
|
|
|
|
>>> from isine import change
|
|
>>> change(880)
|
|
'''
|
|
|
|
from __future__ import print_function
|
|
|
|
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 = bytes()
|
|
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(int(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)
|
|
|