2011-10-19 35 views
6

¿Cómo puedo crear un sonido de 440 Hz que se reproduzca sin problemas para siempre con audio con Pygame? Supongo que esto debería ser lo suficientemente fácil, pero no quiero usar ningún archivo estúpido para realizar la tarea. El objetivo final de esto es tocar una nota mientras se mantiene presionada una tecla, como ya hice en otra pregunta. Cualquier ayuda sería muy apreciada ya que he desperdiciado grandes cantidades de tiempo tratando de encontrar una respuesta a esto.Audio de Pygame simple a una frecuencia

Respuesta

3

¿Qué tipo de sonido tiene 440 Hz? Hay muchos tipos de ondas a "440 Hz": seno, sierra, cuadrado, etc. Puede tener una flauta tocando una A, y eso también puede contar.

Suponiendo que desea una onda sinusoidal, parece que puede generar un objeto Sound con pygame.sndarray.samples. (No he probado esto) Puede crear las muestras con:

samples = [math.sin(2.0 * math.pi * frequency * t/sample_rate) for t in xrange(0, duration_in_samples)] 

Esto es, con suerte, materia de onda sinusoidal básica. frequency es la frecuencia deseada, en Hz. sample_rate es el número de muestras/segundo en el audio generado: 44100 Hz es un valor típico. duration_in_samples es la duración del audio. (5 * 44100 == 5 segundos, si el audio está a una frecuencia de muestreo de 44100 Hz.)

Parece que usted podría tener que convertir a un samplesnumpy.array antes de pasar a pygame.sndarray.samples. Los documentos indican que el audio debe coincidir con el formato devuelto por pygame.mixer.get_init, así que ajuste samples de manera adecuada, pero esa es la idea básica. (mixer.get_init le dirá la variable sample_rate arriba, y si es necesario para dar cuenta de equipo de música, y si es necesario ajustar la amplitud de la onda o desplazarlo.)

Hacer samples un número entero de ondas de largo, y debería repetir.

+0

¿Cómo puedo hacer que el sonido suene para siempre? – Paul

+0

diciéndole que bucle siempre cuando juegas. ¿Has intentado leer los documentos? (pygame.org/docs) Específicamente, desea http://pygame.org/docs/ref/mixer.html#Sound.play – Thanatos

6

Después de obtener demasiados "ValueError: la profundidad de la matriz debe coincidir con el número de canales del mezclador" y otros errores similares, descubrí este ejemplo de trabajo http://www.mail-archive.com/[email protected]/msg16140.html. Genera correctamente una matriz de enteros multidimensional de 16 bits que funciona con un mezclador estéreo. Ejemplo mínimo de trabajo a continuación, principalmente extraído del enlace anterior con los bits de pygame necesarios. Probado en Python 2.7.2 con pygame.ver '1.9.1release'.

Este ejemplo reproducirá un tono de 440 Hz de un altavoz y un tono de 550 Hz del otro altavoz en una configuración estéreo. Después de jugar un poco con la duración, descubrí que aparecerán clics audibles en el bucle de sonido si establece la variable "duración" en un valor que no sea un número entero.

import pygame 
from pygame.locals import * 

import math 
import numpy 

size = (1366, 720) 

bits = 16 
#the number of channels specified here is NOT 
#the channels talked about here http://www.pygame.org/docs/ref/mixer.html#pygame.mixer.get_num_channels 

pygame.mixer.pre_init(44100, -bits, 2) 
pygame.init() 
_display_surf = pygame.display.set_mode(size, pygame.HWSURFACE | pygame.DOUBLEBUF) 


duration = 1.0   # in seconds 
#freqency for the left speaker 
frequency_l = 440 
#frequency for the right speaker 
frequency_r = 550 

#this sounds totally different coming out of a laptop versus coming out of headphones 

sample_rate = 44100 

n_samples = int(round(duration*sample_rate)) 

#setup our numpy array to handle 16 bit ints, which is what we set our mixer to expect with "bits" up above 
buf = numpy.zeros((n_samples, 2), dtype = numpy.int16) 
max_sample = 2**(bits - 1) - 1 

for s in range(n_samples): 
    t = float(s)/sample_rate # time in seconds 

    #grab the x-coordinate of the sine wave at a given time, while constraining the sample to what our mixer is set to with "bits" 
    buf[s][0] = int(round(max_sample*math.sin(2*math.pi*frequency_l*t)))  # left 
    buf[s][1] = int(round(max_sample*0.5*math.sin(2*math.pi*frequency_r*t))) # right 

sound = pygame.sndarray.make_sound(buf) 
#play once, then loop forever 
sound.play(loops = -1) 


#This will keep the sound playing forever, the quit event handling allows the pygame window to close without crashing 
_running = True 
while _running: 

    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      _running = False 
      break 

pygame.quit() 
Cuestiones relacionadas