来自pyaudio的Tkinter多处理和音频输入

时间:2014-09-06 16:07:04

标签: python matplotlib tkinter multiprocessing pyaudio

我正在编写一个程序,该程序使用pyaudio连续从麦克风获取输入,并且每5秒进行一些计算,之后它会在tkinter小部件中更新一些matplotlib图。 我到目前为止:

import threading
from array import array
from Queue import Queue, Full
import pyaudio
from matplotlib import pyplot as plt
import numpy as np

CHUNK_SIZE = 1000
MIN_VOLUME = 500
PLOT_CHUNK_SIZE = CHUNK_SIZE * 5
BUF_MAX_SIZE = CHUNK_SIZE * 10
PLOT_MAX_SIZE = PLOT_CHUNK_SIZE * 10

big_chunk = np.array( [])

def main():

    stopped = threading.Event()
    q = Queue(maxsize=int(round(BUF_MAX_SIZE / CHUNK_SIZE)))
    plot_queue = Queue(maxsize=int(round(PLOT_MAX_SIZE / PLOT_CHUNK_SIZE)))

    listen_t = threading.Thread(target=listen, args=(stopped, q))
    listen_t.start()
    record_t = threading.Thread(target=record, args=(stopped, q, plot_queue))
    record_t.start()
    plot_t = threading.Thread(target=plot_chunk, args=(stopped, plot_queue))
    plot_t.start()

    try:
        while True:
            listen_t.join(0.1)
            record_t.join(0.1)
            plot_t.join(0.1)
    except KeyboardInterrupt:
            stopped.set()

    listen_t.join()
    record_t.join()
    plot_t.join()


def record(stopped, q, plot_queue):
    global big_chunk, p, ready
    while True:
        if stopped.wait(timeout=0):
            break
        vol = max(q.get())
        if vol >= MIN_VOLUME:
            big_chunk = np.append(big_chunk, q.get())
            print 'new chunk'
            if len(big_chunk) > PLOT_CHUNK_SIZE-1:
                plot_queue.put(big_chunk)
                big_chunk = np.array( [])
        else:
            print "-",

def plot_chunk(stopped, plot_queue):
    while True:
        if stopped.wait(timeout=0):
            break
        features = plot_queue.get()
        my_features = do_calculations(features)
        plt.imshow(my_features)


def listen(stopped, q):
    stream = pyaudio.PyAudio().open(
        format=pyaudio.paInt16,
        channels=1,
        rate=44100,
        input=True,
        frames_per_buffer=1024,
    )

    while True:
        if stopped.wait(timeout=0):
            break
        try:
            q.put(array('h', stream.read(CHUNK_SIZE)))
        except Full:
            pass  # discard


if __name__ == '__main__':
    main()

我尝试用线程做它,除了绘图之外它工作正常。似乎matplotlib和tkinter不能使用线程和多处理将是最佳选择。所以我尝试了这个:

import Tkinter as Tk
import multiprocessing
from Queue import Empty, Full
import time
import pyaudio
import array

class GuiApp(object):
   def __init__(self,q):
      self.root = Tk.Tk()
      self.root.geometry('300x100')
      self.text_wid = Tk.Text(self.root,height=100,width=100)
      self.text_wid.pack(expand=1,fill=Tk.BOTH)
      self.root.after(100,self.CheckQueuePoll,q)

   def CheckQueuePoll(self,c_queue):
      try:
         str = c_queue.get(0)
         self.text_wid.insert('end',str)
      except Empty:
         pass
      finally:
         self.root.after(100, self.CheckQueuePoll, c_queue)

# Data Generator which will generate Data
def GenerateData(q):
   for i in range(10):
      print "Generating Some Data, Iteration %s" %(i)
      time.sleep(0.1)
      q.put("Some Data from iteration %s \n" %(i))

def listen( q):
    CHUNK_SIZE = 100
    stream = pyaudio.PyAudio().open(
        format=pyaudio.paInt16,
        channels=1,
        rate=44100,
        input=True,
        frames_per_buffer=1024,
    )

    while True:
        try:
            q.put(array('h', stream.read(CHUNK_SIZE)))
        except Full:
            pass  # discard

if __name__ == '__main__':
# Queue which will be used for storing Data

   q = multiprocessing.Queue()
   q2 = multiprocessing.Queue()
   q.cancel_join_thread() # or else thread that puts data will not term
   q2.cancel_join_thread() # or else thread that puts data will not term
   gui = GuiApp(q)
   t1 = multiprocessing.Process(target=GenerateData,args=(q,))
   t2 = multiprocessing.Process(target=listen,args=(q2,))
   t1.start()
   t2.start()
   gui.root.mainloop()

   t1.join()
   t2.join()

我收到以下错误:

q.put(array('h', stream.read(CHUNK_SIZE)))
TypeError: 'module' object is not callable

任何想法?

1 个答案:

答案 0 :(得分:1)

问题是代码中的array是一个模块,不可调用(如错误信息所示)。

将导入更改为

from array import array

将您的代码更改为

array.array(...)