Python多处理,不懂h

2024-04-20 11:20:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我整天都在看线程和多线程的页面和教程,我仍然不知道如何实现我所需要的。我有一个类可以读取音频流,还有一个类可以用Tkinter可视化,Tkinter是每个人最喜欢的软件包。你知道吗

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

我知道它不是最好的代码,它的某些部分是它进化的残余,但现在我想让recorder永远运行它的run函数,并对其调用draw()。问题是我不知道如何让run()永远运行并将数据放入队列。我已经在put()行收到了一个pickle错误,后面是一篇回溯文章。你知道吗

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

可以追溯到

File "C:\Users\My Name\Documents\Programming\visualizer.py", line 108, in <module>
    p.start()

Tags: importselfdatalenifdefbarwindow
1条回答
网友
1楼 · 发布于 2024-04-20 11:20:01

问题很可能是audiooppyaudio正在返回一个_portaudio.Stream对象,该对象是不可复制的。由于多个进程不能共享内存,它们必须使用某种序列化方法来回传递消息,而multiprocessing使用pickle模块。如果不能pickle对象,就不能在进程之间传递它。你知道吗

除非您需要使用多个CPU核的性能优势,否则您可以使用threading模块而不是multiprocessing。你知道吗

相关问题 更多 >