我在Windows10的Python3.7下使用audiomath,我想在实时应用程序的不同时间临时创建Player实例,以播放已经加载到内存中的Sound实例。它看起来有时可以非常快地构建(不到一毫秒),但有时需要几百毫秒(这可能会扰乱我的应用程序的时间)。我认为这反映了初始化PortAudio和/或打开流的开销,但我不清楚什么时候会发生这种情况。有没有一种方法可以提前初始化一切和/或优化一切,使Player构造始终快速进行?
发布于 2019-08-27 10:53:54
的确,初始化库和流需要时间。如果您没有跟踪您有多少个Player实例,那么这种开销(至少是流打开部分)可能会在意想不到的时候发生。默认情况下,当您创建第一个Player时,会隐式地自动创建/打开/启动一个流,当不再有Player实例在使用它时,它会自动停止/关闭/删除。因此,当您的最后一个Player实例被垃圾收集时,流将关闭:然后,如果您随后创建另一个实例,您将再次获得流初始化成本。也许这解释了你的观察,它“有时”慢,有时不慢?下面是IPython的%timeit工具的结果,说明了它是如何工作的(audiomath 1.5.1,Python 3.7.3,Windows10):
import audiomath as am
s = am.TestSound('12')
timeit -n1 -r1 am.Player(s)
# 722 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
# First-ever Player: it took 722 ms to initialize the PortAudio
# library and opening a stream
timeit -n1 -r1 am.Player(s)
# 281 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
# The previous player was garbage-collected, so we're working off a
# blank slate, but the library is already initialized, so 281 is
# just the stream-opening overhead.
timeit -n1 -r1 am.Player(s)
# 283 ms ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
# Same again.
p = am.Player(s) # now, let's keep a reference to an active Player
timeit -n1 -r1 am.Player(s)
# 52.3 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
# With p still alive, creating another Player is really fast (although
# on some implementations such as macOS, even this can spend some tens
# of milliseconds just deciding which device should be used)最干净的方法是显式创建一个Stream实例,使其在整个会话期间保持活动状态,并显式地告诉新的Player实例通过它们的stream=构造函数参数使用它:
import audiomath as am
s = am.TestSound('12')
f = am.Stream()
timeit -n1 -r1 am.Player(s, stream=f)
# 50.3 µs ± 0 ns per loop (mean ± std. dev. of 1 run, 1 loop each)
# All Players, even the first, are initialized lightning-fast与Player一样,Stream类由audiomath.PortAudioInterface后端导出,并在加载后端(默认情况下)时在顶级名称空间中可用。它没有很好的文档,但值得了解的输入参数(用于指定要使用的API和设备)与audiomath.PortAudioInterface.FindDevices的输入参数相同
https://stackoverflow.com/questions/57666930
复制相似问题