0

我有一个程序可以通过插孔连接从火线设备 (FA-66) 录制音频。界面是用 pygtk 创建的,录音是用 py-jack ( http://sourceforge.net/projects/py-jack/ )。录制是在不同的线程中完成的,因为必须同时使用 GUI 来查看音频的结果。

问题是当我启动录制线程时,GUI 响应变得非常缓慢。我在主线程的开头有 gtk.gdk 函数 start_threads() 。如果我做对了,我不需要threads_enter() 和threads_leave(),因为录制不会影响GUI。如果我错了,请纠正。

函数 jack.process() 记录来自三个麦克风的音频。例如,如果我用 time.sleep(2) 替换它,一切正常。

在这种情况下创建线程的最佳方法是什么?为什么 jack.process 会冻结 GUI?它需要所有的cpu时间还是什么?我的代码示例如下:

录音机.py:

...
def start(self):
    Thread(target=self._start).start()

def _start(self):
    while self.eventhandler.record.isSet():
        data = self._jackRecord(self.sample_length)
        self.datahandler.queue.put(data)

def _jackRecord(self, length):
    capture = Numeric.zeros((self.inputs, int(self.sample_rate * length)), 'f')
    output = Numeric.zeros((self.inputs, self.buffer_size), 'f')
    i = 0
    while i < capture.shape[1] - self.buffer_size:
        try:
            jack.process(output, capture[:,i:i+self.buffer_size])
            i += self.buffer_size
        except:
            pass
    return capture        

eventhandler.py:recordStart() 和 recordStop() 只是在按下开始和停止按钮时调用的回调函数。

...
def recordStart(self, widget, data=None):
    if not self.record.isSet():
        self.record.set()
        self.soundrecorder = SoundRecorder(self, self.datahandler)
        self.soundrecorder.connect()
        self.soundrecorder.start()
def recordStop(self, widget, data=None):
    if self.record.isSet():
       self.record.clear()
       del(self.soundrecorder)
4

1 回答 1

2

你误解了线程是如何工作的。

在这种情况下,线程对您没有帮助。

“然后,当记录一个样本时,将对其进行分析,并将结果显示在 GUI 中。同时,已经在记录下一个样本。”

错了。线程不会同时做两件事。在 python 中,有一个全局锁可以防止两个线程同时运行 python 代码或接触 python 对象。除此之外,如果您没有两个 CPU 或内核,则两件事永远不会同时发生。线程机制只是在它们之间切换,每次执行固定数量的指令。

线程还无益地增加了处理、内存和代码复杂性开销。与单线程相比,使用线程的 Python 代码运行速度更慢,性能也更低。这条规则只有少数例外,您的情况不是其中之一。

您可能希望将录制循环重写为回调并将其与 GTK 循环集成(您将获得比使用线程更好的性能)。

为此,请gobject.idle_add优先使用 a 。

如果您想真正“同时”运行两件事,使用两个处理器/内核,您想启动另一个进程。启动一个进程来收集数据并通过某种进程间通信机制将其传输到另一个正在分析和绘制数据的进程。多处理模块可以帮助您。

于 2009-06-03T15:20:15.980 回答