私はスレッドとマルチスレッドのページとチュートリアルを終日見てきましたが、必要なものを実装する方法はまだ分かりません。オーディオストリームを読み込むクラスと、Tkinterで誰もが好きなパッケージを視覚化するクラスがあります。Pythonのマルチプロセスで対処方法がわからない
import numpy as np
from Tkinter import *
from cmath import exp,pi
import audioop,time,colorsys,pyaudio
import multiprocessing
class Recorder():
def __init__(self):
self.p=pyaudio.PyAudio()
self.stream=self.p.open(format=pyaudio.paInt16,channels=1,rate=RATE,input=True,frames_per_buffer=CHUNK)
self.buff = None
self.rms = None
self.m = None
self.running = True
return
def run(self,q=None):
while self.running:
self.buff = np.fromstring(self.stream.read(CHUNK),dtype=np.int16)
self.buff = np.fft.fft(self.buff)/CHUNK
self.rms = audioop.rms(self.buff,2)
self.buff = map(lambda y:(y.real**2+y.imag**2)**(0.5)/(1.516122797*self.rms),self.buff)[:len(self.buff)/2]
self.m = float(max(self.buff))
def get(self,q):
q.put((self.buff,self.rms,self.m))
def end(self):
self.runing = False
self.stream.stop_stream()
self.stream.close()
self.p.terminate()
class Drawer():
def __init__(self):
self.m = 0
self.text = ''
def draw(self,q):
data,rms,m = q.get()
if rms == 0: return False
if m == 0: return False
nData = list()
i = 1
while i*2 < len(data):
nData.append(sum(data[i:i*2])/(i*2-1))
i *= 2
data = nData
maxi = float(max(data))
if maxi > self.m:
self.m = maxi
elif maxi <= 0.5*self.m:
self.m *= 0.75
bWidth = WIDTH/len(data)
for x,y in enumerate(data):
canvas.delete("bar"+str(x))
if GHEIGHT == tBarHeight:
hexcode = "#%02x%02x%02x" % hsv2rgb(1-((y/self.m)*0.75),1,1)
canvas.create_rectangle(x*(WIDTH/len(data)),HEIGHT,x*(WIDTH/len(data))+bWidth,HEIGHT-((y/self.m)*GHEIGHT),tag="bar"+str(x),fill=hexcode)
else:
drawBar(x,x*(WIDTH/len(data)),y,bWidth, self.m)
canvas.delete('display')
canvas.create_text(WIDTH/2, 20, text=self.text, tag = 'display')
return True
def hsv2rgb(h,s,v):
return tuple(int(i * 255) for i in colorsys.hsv_to_rgb(h,s,v))
def update():
global times
t1 = time.time()
## recorder.run()
if not drawer.draw(q):
drawer.m = 0
times.append(time.time()-t1)
drawer.text = ("%.03f"%(sum(times)/len(times)))[2:]
window.after(1,update)
def drawBar(sid, x, y, w, m):
yVal = int(y/m*nBars)
yN = HEIGHT
h = GHEIGHT/nBars
for bar in xrange(yVal):
Hue = 1-(float(bar)/nBars)-0.3*1.1
if Hue < 0: Hue = 0
gradColor = '#%02x%02x%02x' % hsv2rgb(Hue,1,1)
canvas.create_rectangle(x , HEIGHT-(h*bar), x + w, yN - h, fill = gradColor ,outline = "#FFFFFF", tag="bar"+str(sid))
yN -= h
def click(event):
global GHEIGHT
if event.x <= WIDTH/2:
GHEIGHT = window.winfo_screenheight()
else:
GHEIGHT = tBarHeight
global times
times = list()
CHUNK = 2048
RATE = 44100
WIDTH, HEIGHT = 1920, 1080
divs = CHUNK
mSec = 5
tBarHeight = 30
nBars = 20
window = Tk()
global GHEIGHT
GHEIGHT = window.winfo_screenheight()
window.attributes("-fullscreen",True)
canvas = Canvas(window, width=WIDTH, height=HEIGHT, bg="#FFFFFF")
canvas.bind(sequence = "<Button-1>",func = click)
canvas.pack()
#########
recorder = Recorder()
q = multiprocessing.Queue()
p = multiprocessing.Process(target=recorder.run, args=(q,))
p.start()
p.join()
drawer = Drawer()
#########
window.after(0,update)
window.mainloop()
recorder.end()
私はそれが最善のコードではないと知って、それのいくつかの部分は、その進化の名残ですが、今の私は、レコーダーが永遠にその実行機能を実行する必要があり、その上に()描画を呼び出すことができるようにしたいです。問題は、run()を永久に実行してデータをキューに入れる方法がわからないことです。私はすでにput()行に1つのpickleエラーを受け取り、続いてtracebackのエッセイを受け取りました。バック
File "C:\Users\My Name\Documents\Programming\visualizer.py", line 108, in <module>
p.start()
http://stackoverflow.com/questions/7894791/use-numpy-array-in-shared-memory-for-multiprocessingおよびhttp://stackoverflow.com/questions/15414027/multiprocessing-pool-makesも参照してください。 -numpy-matrix-multiplication-slower – torek
printステートメントをレコーダークラスに追加しました。run()とget()の両方が呼び出されません。私もすべてをPythonのネイティブリストに変換しようとしましたが、タプルに入れるためにフロートしてフロートしますが、それでも決してキューに入れられなくても、オーディオストリームについて不平を言います。スレッディングに関しては、ビジュアライザーが時間の1/3程度を費やしているので、動力が必要です。つまり、run()で計算をしているので、必要になる前にそれらを実行してください。 – Neywiny
私はすべてのpyaudioをrun()のループの直前に移動し、get()は適切なタイミングで呼び出されますが、何らかの理由でrun()が実行されていないため、get ()の値 – Neywiny