9

ギターのようにコードを弾くためのプラットフォームを作りたいです。たとえば、E コードを演奏するには [0, 2, 2, 1, 0, 0] (Low-E 弦から High-E 弦まで) を演奏します。

(スレッドを使用して) すべての異なる弦を同時に演奏することにより、python で和音を演奏しようとしています。

問題は、次の弦の演奏を開始するたびに、最後の弦の演奏が停止し、新しい弦に​​置き換わるように見えることです。コードを弾いた後に聞こえるのは、最も高い弦 (最後の弦) だけです。

スレッドを正しく使用していませんか? それとも現在の機能の問題でしょうか?それとも、これらの種類のものを処理できないのは winsound.Beep() 関数でしょうか?

これは私のコードです:

from winsound import Beep
import threading
import time


def play(freq, dur):
    Beep(round(freq), round(dur))


def get_freq(string, fret):
    a3_freq = 220
    half_tone = 2 ** (1 / 12)

    higher_from_a3_by = 5 * (string - 2) + fret
    if string > 4:
        higher_from_a3_by += 1
    return a3_freq * half_tone ** higher_from_a3_by


def strum(string, fret, time):
    freq = get_freq(string, fret)
    t = threading.Thread(target=play, args=(freq, time))
    t.start()
    return t


def chord(frets, dur):
    threads = []
    for i in range(6):
        if frets[i] != -1:
            threads.append(strum(i + 1, frets[i], dur))
    for t in threads:
        t.join()


chord((-1, 0, 2, 2, 2, 0), 1000) # plays the A chord for one second, for example.

私がチェックしたことから、 play() および get_freq() 関数には問題はありません。

では、何が問題で、どうすれば修正できますか?

編集:

C# で試してみましたが、うまくいきませんでした。これは C# でスレッドを開始する正しい方法ですか?

foreach (Thread t in threads)
    t.Start();
foreach (Thread t in threads)
    t.Join();
4

3 に答える 3

1

Gevent を使用すると、これがはるかに簡単になります。技術的にはまだシングル スレッドですが、コンテキストの切り替えは非常に高速であるため、同時のように見えます。マルチスレッドの双方向マルチプロセス通信に GIPC を使用することもできます。

しかし、あなたの問題ははるかに簡単だと思います。あなたの問題は風音モジュールです。ビープ音は非同期ではありません。それがあなたの限界です。使用する必要があります

winsound.SND_ASYNC

これにより、複数のイベントを送信して同時に再生できます。

于 2018-04-11T19:07:07.343 に答える
0

これにはスレッドを使用しないことを本当にお勧めします。ポリフォニーの問題を解決するために必要ではなく、非常に複雑です。別の解決策は、現在演奏中の弦のサンプルにアクセスし、新しく演奏した弦を単純に合計することです。ただし、winsound を使用しているため、これはおそらく不可能です。したがって、Pythonを使用してサウンドを再生および/または生成する他の方法を検討することをお勧めします。クイック検索でこれが表示されます

于 2018-04-05T20:45:47.713 に答える