-   Programming (
-   -   python alsa: How to play smoothly? (

eantoranz 11-19-2009 03:03 PM

python alsa: How to play smoothly?

I'm working on a personal research project. What I need to do is to be able to play waves at will.

I tried this morning to use alsa to have the output straight into the speakers but I just can't get to play waves smoothly without sound breakage.

I tried with different PCM modes but none worked. I also tried with PCM_NORMAL using a separate thread to not block my wave calculations, but that didn't work either.

So, to keep it simple, take a look at this two versions of the same file:

With threads:

You will need the from the project too.

The way to call it is very simple:

./ 440

That should play a simple A4 sine wave on both channels.

Thanks for any help you could provide.

ntubski 11-21-2009 02:13 PM

I got only silence from your program. :confused:

Just looking at the code it seems that you call math.sin a whole lot which is unnecessary: just calculate one period and then repeat it.

The following works for me without any breakage, though I use 8-bit samples because I didn't feel like bit-bashing.

#!/usr/bin/env python

import alsaaudio, sys

from numpy import arange        # like range, but supports floating point
from math import pi, sin

channels = 2
sample_size = 1                    # bytes per sample
frame_size = channels * sample_size # bytes per frame
frame_rate = 44100                  # frames per second
byte_rate = frame_rate * frame_size # bytes per second
# 1 second worth of data per pcm.write() call
# decrease if shorter notes are needed
period_size = frame_rate

pcm = alsaaudio.PCM(alsaaudio.PCM_PLAYBACK)
def quantize(f):                # map (-1..1) -> [0..256)
    return int((f+1)*127)      # depends on PCM format

def sine_wave(freq):
    wave = [chr(quantize(sin(x))) * channels for x
            in arange(0, 2*pi, 2*pi / (frame_rate / freq))]
    wave_data = "".join(wave)
    (nwaves, extra_bytes) = divmod(period_size * frame_size, len(wave_data))
    pcm.write((wave_data * nwaves) + wave_data[:extra_bytes])

for i in range(10):

All times are GMT -5. The time now is 01:11 PM.