0

I'm writing a program that is continuously taking input from a microphone using pyaudio and every 5 seconds does some calculations after which it updates some matplotlib plot in a tkinter widget. I got so far:

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

I tried to do it with threads and it works fine except for the plotting. It seems matplotlib and tkinter don't work with threads and multiprocessing would be the way to go. So I tried this:

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

Where I get the following error:

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

Any Ideas?

severila
  • 29
  • 3
  • +1 for two good examples, as for the solution, i'm not sure, maybe 'chunksize' instead of 'CHUNK_SIZE' – W1ll1amvl Sep 06 '14 at 19:17
  • 1
    This question is _way_ too complicated for the actual problem. It is best to post the _minimum_ amount of code needed to demonstrate your problem. – tacaswell Sep 06 '14 at 22:09
  • @W1ll1amvl These are actually pretty bad examples (due to excessive un-related to the problem code) – tacaswell Sep 06 '14 at 22:10
  • 1
    @tcaswell i spose you could say that, I was just glad that for once a newbie had made a proper effort to ask a good question, I know that I for one didn't ask a good question the first time ;) – W1ll1amvl Sep 07 '14 at 00:48

1 Answers1

1

The problem is that array in your code is a module, which is not callable (as the error message says).

Either change your import to

from array import array

or change your code to

array.array(...)
tacaswell
  • 84,579
  • 22
  • 210
  • 199