mirror of
https://github.com/larsimmisch/pyalsaaudio.git
synced 2026-05-30 01:47:01 +00:00
Correct the sine example (finally!) Closes #10
This commit is contained in:
@@ -6,30 +6,50 @@
|
|||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import sys
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from queue import Queue, Empty
|
from multiprocessing import Queue
|
||||||
|
|
||||||
|
if sys.version_info[0] < 3:
|
||||||
|
from Queue import Empty
|
||||||
|
else:
|
||||||
|
from queue import Empty
|
||||||
|
|
||||||
from math import pi, sin
|
from math import pi, sin
|
||||||
import struct
|
import struct
|
||||||
import alsaaudio
|
import alsaaudio
|
||||||
|
|
||||||
sampling_rate = 44100
|
sampling_rate = 48000
|
||||||
|
|
||||||
format = alsaaudio.PCM_FORMAT_S16_LE
|
format = alsaaudio.PCM_FORMAT_S16_LE
|
||||||
framesize = 2 # bytes per frame for the values above
|
framesize = 2 # bytes per frame for the values above
|
||||||
|
channels = 2
|
||||||
|
|
||||||
def digitize(s):
|
def nearest_frequency(frequency):
|
||||||
if s > 1.0 or s < -1.0:
|
# calculate the nearest frequency where the wave form fits into the buffer
|
||||||
raise ValueError
|
# in other words, select f so that sampling_rate/f is an integer
|
||||||
|
return float(sampling_rate)/int(sampling_rate/frequency)
|
||||||
|
|
||||||
return struct.pack('h', int(s * 32767))
|
def generate(frequency, duration = 0.125):
|
||||||
|
# generate a buffer with a sine wave of `frequency`
|
||||||
|
# that is approximately `duration` seconds long
|
||||||
|
|
||||||
def generate(frequency):
|
# the buffersize we approximately want
|
||||||
# generate a buffer with a sine wave of frequency
|
target_size = int(sampling_rate * channels * duration)
|
||||||
size = int(sampling_rate / frequency)
|
|
||||||
buffer = bytes()
|
# the length of a full sine wave at the frequency
|
||||||
for i in range(size):
|
cycle_size = int(sampling_rate / frequency)
|
||||||
buffer = buffer + digitize(sin(i/(2 * pi)))
|
|
||||||
|
# number of full cycles we can fit into target_size
|
||||||
|
factor = int(target_size / cycle_size)
|
||||||
|
|
||||||
|
size = max(int(cycle_size * factor), 1)
|
||||||
|
|
||||||
|
sine = [ int(32767 * sin(2 * pi * frequency * i / sampling_rate)) \
|
||||||
|
for i in range(size)]
|
||||||
|
|
||||||
|
return struct.pack('%dh' % size, *sine)
|
||||||
|
|
||||||
return buffer
|
|
||||||
|
|
||||||
class SinePlayer(Thread):
|
class SinePlayer(Thread):
|
||||||
|
|
||||||
@@ -37,7 +57,7 @@ class SinePlayer(Thread):
|
|||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
self.setDaemon(True)
|
self.setDaemon(True)
|
||||||
self.device = alsaaudio.PCM()
|
self.device = alsaaudio.PCM()
|
||||||
self.device.setchannels(1)
|
self.device.setchannels(channels)
|
||||||
self.device.setformat(format)
|
self.device.setformat(format)
|
||||||
self.device.setrate(sampling_rate)
|
self.device.setrate(sampling_rate)
|
||||||
self.queue = Queue()
|
self.queue = Queue()
|
||||||
@@ -48,18 +68,14 @@ class SinePlayer(Thread):
|
|||||||
# we generate the buffer in the calling thread for less
|
# we generate the buffer in the calling thread for less
|
||||||
# latency when switching frequencies
|
# latency when switching frequencies
|
||||||
|
|
||||||
|
if frequency > sampling_rate / 2:
|
||||||
|
raise ValueError('maximum frequency is %d' % (sampling_rate / 2))
|
||||||
|
|
||||||
# More than 100 writes/s are pushing it - play multiple buffers
|
f = nearest_frequency(frequency)
|
||||||
# for higher frequencies
|
print('nearest frequency: %f' % f)
|
||||||
|
|
||||||
factor = int(frequency/100.0)
|
buf = generate(f)
|
||||||
if factor == 0:
|
self.queue.put(buf)
|
||||||
factor = 1
|
|
||||||
|
|
||||||
buf = generate(frequency) * factor
|
|
||||||
print('factor: %d, frames: %d' % (factor, len(buf) / framesize))
|
|
||||||
|
|
||||||
self.queue.put( buf)
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
buffer = None
|
buffer = None
|
||||||
|
|||||||
Reference in New Issue
Block a user