完全同时生成Python线程?

时间:2017-11-16 05:38:44

标签: python multithreading audio

现在我和一些朋友正在制作一个程序,用Python中的方波生成音乐(我们还在开发的早期阶段)。沿途的一个障碍是我们认为PyAudio一次只能播放一个声音,如果你试图互相播放声音,例如做一个和弦,声音只是互相覆盖。我们当前的策略是使用线程来绕过它,它几乎可以工作,但是线程启动的时间略有偏差。以下是生成C大调和弦的代码片段:

import numpy as np
import pyaudio
import math
from scipy import signal
import multiprocessing
from time import time

def noteTest(frequency):
    l = np.linspace(0, 2, 384000, endpoint=False)
    p = pyaudio.PyAudio()
    stream = p.open(format=pyaudio.paInt16, channels=1, rate=192000, output=True)
    wave_data = signal.square(2 * math.pi * frequency * l)
    stream.write(wave_data)

def playNotes():
    if __name__ == "__main__":
        multiprocessing.Process(target = noteTest, args = [523.25113060119]).start()
        print(time())
        multiprocessing.Process(target = noteTest, args = [659.25511382575]).start()
        print(time())
        multiprocessing.Process(target = noteTest, args = [783.99087196355]).start()
        print(time())

playNotes()

当我查看程序的输出时,这是它给出的时间:

1510810518.870557
1510810518.8715587
1510810518.8730626

正如您所看到的,线程相隔千分之一秒。这是令人惊讶的明显,即使只有一个和弦,但我们担心,如果我们试图制作一首真正的歌曲,因为曲目将分开并彼此脱离时间,这将成为一个更大的问题。请注意,我们使用DO测试的所有计算机都有多个物理核心。有没有办法让线程更好地同步,或者我们最好找到替代解决方案?

1 个答案:

答案 0 :(得分:1)

选项是在播放声音之前在每个线程中有延迟。如果您对启动线程所涉及的偏移有一个合理的了解,则可以将该值作为延迟传递。

例如,假设启动线程之间有1ms的延迟:

  • 0ms:启动线程1,延迟1ms
  • 0ms:线程1在新核心上启动,等待
  • 1ms:启动线程2,没有延迟
  • 1ms:线程1在延迟后开始播放
  • 1ms:线程2在新内核上启动,没有延迟,并开始播放

另一种选择是让每个线程开始,但是在开始播放之前等待主进程循环到所有线程的信号。