0

ジャック接続のFirewireデバイス(FA-66)からのオーディオを録音するプログラムがあります。インターフェイスはpygtkで作成され、録音はpy-jack(http://sourceforge.net/projects/py-jack/)で作成されます。オーディオの結果を表示するにはGUIを同時に使用する必要があるため、録音は別のスレッドで行われます。

問題は、レコーディングスレッドを開始すると、GUIの応答が非常に遅くなることです。メインスレッドの先頭にgtk.gdk関数start_threads()があります。正しく理解していれば、記録はGUIに影響を与えないため、threads_enter()とthreads_leave()は必要ありません。私が間違っている場合は訂正してください。

関数jack.process()は、3つのマイクからの音声を録音します。たとえば、time.sleep(2)に置き換えると、すべて問題なく動作します。

この場合、スレッドを作成するための最良の方法は何ですか?jack.processがGUIをフリーズするのはなぜですか?すべてのCPU時間か何かがかかりますか?以下の私のコードのサンプル:

soundrecorder.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

スレッドの仕組みを誤解しています。

この場合、スレッドは役に立ちません。

「次に、1 つのサンプルが記録されると、それが分析され、結果が GUI に表示されます。同時に、次のサンプルがすでに記録されています。」

間違っています。スレッドは、同時に 2 つのことを行いません。Python には、2 つのスレッドが同時に Python コードを実行したり、Python オブジェクトに触れたりするのを防ぐグローバル ロックがあります。それに加えて、2 つの CPU またはコアがなければ、2 つのことが同時に起こることはありません。スレッド化メカニズムは、一度に一定数の命令を実行するそれらの間を切り替えるだけです。

スレッドは、処理、メモリ、およびコードの複雑性のオーバーヘッドも追加しますが、メリットはありません。スレッドを使用する Python コードは、シングルスレッドの場合よりも実行速度が遅くなりパフォーマンスも低下します。このルールにはいくつかの例外があり、あなたのケースは例外ではありません。

レコーディング ループをコールバックとして書き直して、GTK ループと統合することをお勧めします (スレッドを使用するよりも優れたパフォーマンスが得られます)。

そのためには、gobject.idle_add優先度の高い a を使用します。

2 つのプロセッサ/コアを使用して、2 つのことを実際に「同時に」実行したい場合は、別のプロセスを起動する必要があります。プロセスを起動してデータを収集し、プロセス間通信メカニズムを介してデータを分析およびプロットしている他のプロセスに送信します。multiprocessingモジュールがそれを支援します。

于 2009-06-03T15:20:15.980 に答える