2016-12-26 14 views
0

私はスレッドとマルチスレッドのページとチュートリアルを終日見てきましたが、必要なものを実装する方法はまだ分かりません。オーディオストリームを読み込むクラスと、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() 

答えて

1

に問題をトレース

PicklingError: Can't pickle <type '_portaudio.Stream'>: it's not found as _portaudio.Stream 

audioopまたはpyaudioどちらかがunpickleableある_portaudio.Streamオブジェクトを返している可能性があります。複数のプロセスはメモリを共有できないため、multiprocessingpickleモジュールを使用するシリアライズ方法を使用してメッセージを前後に渡す必要があります。オブジェクトをピクルできない場合は、プロセス間でオブジェクトを渡すことはできません。

複数のCPUコアを使用することによるパフォーマンスのメリットが必要な場合を除き、multiprocessingの代わりにthreadingモジュールを使用して離れることができます。

+0

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

+0

printステートメントをレコーダークラスに追加しました。run()とget()の両方が呼び出されません。私もすべてをPythonのネイティブリストに変換しようとしましたが、タプルに入れるためにフロートしてフロートしますが、それでも決してキューに入れられなくても、オーディオストリームについて不平を言います。スレッディングに関しては、ビジュアライザーが時間の1/3程度を費やしているので、動力が必要です。つまり、run()で計算をしているので、必要になる前にそれらを実行してください。 – Neywiny

+0

私はすべてのpyaudioをrun()のループの直前に移動し、get()は適切なタイミングで呼び出されますが、何らかの理由でrun()が実行されていないため、get ()の値 – Neywiny

関連する問題