2011-10-19 16 views
6

Pygame ile ses kullanarak sonsuza kadar sorunsuz oynayan 440 Hz'lik bir sesi nasıl oluşturabilirim? Bunun yeterince kolay olması gerektiğini düşünüyorum, ancak görevi yerine getirmek için aptalca bir dosya kullanmak istemiyorum. Bunun nihai amacı, başka bir soruda sorduğum gibi bir anahtar tutulurken bir not oynamaktır. Buna bir cevap bulmaya çalışırken çok fazla zaman harcadığım için herhangi bir yardım büyük ölçüde takdir edilecektir.Frekansta Basit Pygame Ses

cevap

3

Ne tür bir 440 Hz ses? "440 Hz" de birçok dalga türü vardır: sinüs, testere, kare, vb. Bir A çalarak bir flüt çalabilirsiniz ve bu da sayılabilir.

Sinüs dalgası istediğinizi varsayarsak, pygame.sndarray.samples ile bir Sound nesnesini oluşturabilirsiniz.

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

Bu umutla temel sinüs dalgası şeyler şudur: Örnek uygulamaları oluşturabilir (Bu test değil). frequency, Hz cinsinden istenen frekanstır. sample_rate, oluşturulan sesteki örnek/saniye sayısıdır: 44100 Hz, tipik bir değerdir. duration_in_samples, sesin uzunluğu. (5 * 44100 == 5 saniye, ses bir 44.100 Hz örnek hızında ise.)

Eğer pygame.sndarray.samples geçmeden önce bir numpy.array için samples dönüştürmek gerekebilir gibi görünüyor. Dokümanlar, sesin pygame.mixer.get_init tarafından döndürülen formatla eşleşmesi gerektiğini belirtir, bu nedenle samples'u uygun şekilde ayarlayın, ancak temel fikir budur. (mixer.get_init Yukarıdaki bilgilerin sample_rate değişken bilgi verin, stereo hesaba gerekip gerekmediğini ve dalganın genliği ayarlamak veya kaydırmaya gerekiyorsa. Edecektir)

uzun dalgaların bir integral sayısına samples olun ve Dönmeli.

+0

Sesin sonsuza dek nasıl oynatabilirim? – Paul

+0

Çaldığın zaman sonsuza kadar dönmesini söyleyerek. Dokümanları okumaya çalıştın mı? (pygame.org/docs) Özellikle, http://pygame.org/docs/ref/mixer.html#Sound.play – Thanatos

6

Tamamen çok fazla "ValueError: Array derinliği, mikser kanallarının sayısıyla eşleşmelidir" ve diğer benzer hatalardan sonra işleyen bu örneği http://www.mail-archive.com/[email protected]/msg16140.html tespit ettim. Bir stereo mikser ile çalışan çok boyutlu bir 16 bit tam sayı dizisini düzgün bir şekilde üretir. Aşağıdaki minimum çalışma örneği, çoğunlukla önceki linkten atılan gerekli pygame bitleriyle kaldırılmıştır. Python 2.7.2'de pygame.ver '1.9.1release' ile test edilmiştir.

Bu örnek, stereo hoparlörde bir hoparlörden 440 Hz ton ve diğer hoparlörden 550 Hz ton ses çıkaracaktır. Süre boyunca biraz oynamadan sonra, "süre" değişkenini tam sayı dışında bir değere ayarlarsanız ses döngüsünde duyulabilir tıkların çıkacağını keşfettim.

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()