[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] noob questions about creating and playing sounds



On Mon, Jul 20, 2009 at 11:52 AM, Paulo Silva<nitrofurano@xxxxxxxxx> wrote:
> just a question: afaik, since Pygame uses SDL, Pygame only can play
> sounds were loaded, and the only way to 'create' (one of the questions
> of this mailinglist post) sounds is writing binary data into a .raw
> file, and calling SoX for converting it as .ogg, .wav, etc.?

Paulo, I am not sure if I understand you correctly. The posted code
actually 'creates' the sound, (a numpy array with a sine curve),
converts it into a mixer.Sound object, and plays that back. This path
without .ogg or .wav files is exactly what I am looking for.

It just fails partially, because it creates a horrible rattle noise.
And I am unable to discover where the noise comes from. (The data
curve is smooth, and no clipping occurs. I also tried using longer
arrays with many cycles of my curve.)

What I am not sure if it can be done (or how), is to create the sound
in real-time, and play that back. As an example, make the sound's
frequency and amplitude depend on the mouse pointer's position. But
maybe this is a limitation of the SDL?

Thanks!
#! /usr/bin/env python

import numpy
import pygame

# Create the sound wave in the required bit-rate.
def sine_array(freq, amplitude, sample_rate):
    wavelength = sample_rate / freq
    omega = 2 * numpy.pi / wavelength
    xvalues = numpy.arange(wavelength) * omega
    return numpy.int16(amplitude * numpy.sin(xvalues))

# Two different methods for playing the sound.
def play_maxtime(sound, duration):
    sound.play(loops=-1, maxtime=duration)
    pygame.time.delay(duration)

def play_loops(sound, duration):
    sound.play(loops=-1)
    pygame.time.delay(duration)
    sound.stop()

# Initialize PyGame & PyGame sound system.
sample_rate, bit_rate, channels = 22050, -16, 1
pygame.mixer.pre_init(sample_rate, bit_rate, channels)
pygame.init()
sample_rate, bit_rate, channels = pygame.mixer.get_init()
assert bit_rate == -16   # sine_array only implements 16 bit signed
pygame.sndarray.use_arraytype('numpy')

# Create a sound array, and convert it to a Sound object.
sound_array = sine_array(440, 20000, sample_rate)
sound = pygame.sndarray.make_sound(sound_array)

# Play the sound using two different methods.
duration = 2000
play_maxtime(sound, duration)
pygame.time.delay(duration)
play_loops(sound, duration)