Das Problem ist ein wenig kompliziert, so muss ich Ihnen die ganze Geschichte geben:In Python: Warum muss ein in einer Methode zurückgegebenes Numpy-Array in der Instanz gespeichert werden?
I Grundsound mit dem Paket pyaudio erstellen bin versucht. Das Modul pyaudio fragt nach einer Rückruffunktion, die Audiodaten liest. Es sieht im Wesentlichen wie folgt:
def callback():
return sound.readframes()
Ich habe eine Klasse, die Audiodaten zur Verfügung stellt. Er erzeugt ein Signal, indem er ein numpiges Array indiziert, das eine Wellenlänge einer grundlegenden Wellenform enthält. Es sieht im Wesentlichen wie folgt:
class Wave(object):
data = [] # one wavelength of a basic waveform like a sine wave will be stored here
def readframes(self):
indices = # the indices for the next frames
# based on a frequency and the current position
return self.data[indices]
class SineWave(Wave):
data = # points of a sine wave in a numpy array
sound = SineWave()
# pyaudio now reads audio data in a non-blocking callback mode
Nun zum Problem:
Es gab Lärm zwischen jedem Aufruf readframes oder jedem Block von Audiodaten. Der Ton selbst war noch intakt, aber es gab ein zusätzliches Klicken. Durch Erhöhen der Größe des zurückgegebenen Datenblocks wurde auch die Zeit zwischen jedem Klicken erhöht. Ich weiß immer noch nicht genau, was das Rauschen verursacht hat, aber ich habe es behoben, indem ich das zurückgegebene numpy Array in der Instanz gespeichert habe, anstatt es direkt zurückzugeben.
Das verursacht Lärm:
return self.data[indices]
Dies verursacht nicht Lärm:
+ self.result = self.data[indices]
+ return self.result
Es ist nicht eine Veränderung der Daten sein können, die den Lärm verursacht oder sonst würde dies nicht beheben . Warum muss das Ergebnis in der Instanz gespeichert werden?
Update:
Ich muss auch erwähnen, dass der Lärm nicht immer auftritt ich das Skript ausführen. Es tritt zufällig ungefähr 50% der Läufe auf. Entweder erscheint das Geräusch gleich zu Beginn und wird nicht verschwinden oder es erscheint gar nicht. Es sieht aus wie ein Problem mit der Initialisierung des Sound-Geräts, aber wie das mit meinem Fix in Verbindung stehen könnte, ist ein Geheimnis.
Hier ist Code, der das Geräuschproblem reproduziert:
import pyaudio
import time
from numpy import sin, linspace, arange, pi, float32, uint32
SR = 44100 # sampling rate
FPB = 2048 # frames per buffer
class SineWave(object):
"""A sine wave"""
data_size = 2**10
data = sin(linspace(0, 2*pi, data_size, endpoint=False, dtype=float32))
def __init__(self, frequency):
self.pos = 0
self.fq = frequency
self.ppf = self.data_size * self.fq/SR # points per frame
def readframes(self):
size = FPB
pos = self.pos
indices = (arange(pos, size+pos)*self.ppf).astype(uint32) & (self.data_size-1)
self.pos = (self.pos + size) % SR
self.result = self.data[indices]
return self.data[indices]
def callback(in_data, frame_count, time_info, status):
return sound.readframes(), pyaudio.paContinue
p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(4),
channels=1,
rate=SR,
output=True,
stream_callback=callback,
frames_per_buffer=FPB)
sound = SineWave(440)
stream.start_stream()
time.sleep(2)
stream.stop_stream()
stream.close()
p.terminate()
Auf meinem System das Rauschen in etwa 90% der Läufe erscheint.
Ändern
return self.data[indices]
zu
return self.result
behebt es.
Ich fügte ein funktionierendes Codebeispiel hinzu, das das Rauschen erzeugt. Das Problem ist kein Fehler im Code, es muss etwas damit zu tun haben, was im Hintergrund passiert, da das Rauschen nicht jedes Mal auftritt, wenn ich das Skript ausführe. – uzumaki
@uzumaki Ich habe meine Antwort erweitert. – Matthias