Python PyAudio能否处理非交错缓冲区?
我无法将非交错立体声数据传递到PyAudio 更新(重新编写问题) PyAudio文档中给出的示例演示了如何通过回调传递交错数据。交错立体声数据缓冲区的形状为Python PyAudio能否处理非交错缓冲区?,python,numpy,pyaudio,Python,Numpy,Pyaudio,我无法将非交错立体声数据传递到PyAudio 更新(重新编写问题) PyAudio文档中给出的示例演示了如何通过回调传递交错数据。交错立体声数据缓冲区的形状为(n帧,2),如下所示: array([[f0l, f0r], [f1l, f1r], [f2l, f2r], ...], dtype=float32) array([[f0l, f1l, f2l, ...], [f0r, f1r, f2r, ...]], dtype=float32
(n帧,2)
,如下所示:
array([[f0l, f0r],
[f1l, f1r],
[f2l, f2r],
...], dtype=float32)
array([[f0l, f1l, f2l, ...],
[f0r, f1r, f2r, ...]], dtype=float32)
PA_NONINTERLEAVED = 0x80000000
stream = p.open(format=pyaudio.paFloat32 | PA_NONINTERLEAVED,
channels=DEFAULT_CHANNEL_COUNT,
rate=SRATE,
output=True,
stream_callback=callback)
部分出于说教的原因,我希望在回调中使用非交错数据。阅读文档时,我认为非交错立体声数据缓冲区的形状为(2,n帧)
,如下所示:
array([[f0l, f0r],
[f1l, f1r],
[f2l, f2r],
...], dtype=float32)
array([[f0l, f1l, f2l, ...],
[f0r, f1r, f2r, ...]], dtype=float32)
PA_NONINTERLEAVED = 0x80000000
stream = p.open(format=pyaudio.paFloat32 | PA_NONINTERLEAVED,
channels=DEFAULT_CHANNEL_COUNT,
rate=SRATE,
output=True,
stream_callback=callback)
和AFAICT,在非交织模式下设置流的调用应在format参数的非交织位中或,如下所示:
array([[f0l, f0r],
[f1l, f1r],
[f2l, f2r],
...], dtype=float32)
array([[f0l, f1l, f2l, ...],
[f0r, f1r, f2r, ...]], dtype=float32)
PA_NONINTERLEAVED = 0x80000000
stream = p.open(format=pyaudio.paFloat32 | PA_NONINTERLEAVED,
channels=DEFAULT_CHANNEL_COUNT,
rate=SRATE,
output=True,
stream_callback=callback)
但当我试着运行它的时候,它会出现故障,或者用数字噪音炸我的耳朵,或者什么都不播放——所有这些都是某个地方内存崩溃的标志
是否有人成功地将非交错数据传递到PyAudio
原始问题(和完整的代码示例)
以下代码应将440Hz正弦波写入左通道,将442Hz正弦波写入右通道
相反,它是错误的
我已经成功地使用交错numpy数据运行了一个类似的测试,但我希望可以将通道数据分开。有人指出我做错了什么吗
# python sketches/s05.py
"""
PyAudio / NumPy example: synthesize and play stereo sine waves
using non-interleaved buffers
"""
import pyaudio
import numpy as np
import time
p = pyaudio.PyAudio()
SRATE = 44100
DEFAULT_CHANNEL_COUNT = 2
DEFAULT_FRAME_COUNT = 1024
# from http://portaudio.com/docs/v19-doxydocs/portaudio_8h.html
PA_NONINTERLEAVED = 0x80000000
class Sinner:
def __init__(self, freq, channel):
self._dtheta = freq * 2.0 * np.pi / SRATE
self._theta = 0.0
self._channel = channel
def render(self, buffer, frame_count):
thetas = np.arange(frame_count) * self._dtheta + self._theta
np.sin(thetas, buffer[self._channel])
self._theta += frame_count * self._dtheta
sin_l = Sinner(440.0, 0)
sin_r = Sinner(442.0, 1)
out_data = np.zeros((DEFAULT_CHANNEL_COUNT, DEFAULT_FRAME_COUNT),
dtype=np.float32)
def callback(in_data, frame_count, time_info, status):
global sin_l, sin_r, out_data
if (out_data.shape[1] != frame_count):
# resize numpy array if needed
out_data = np.zeros((DEFAULT_CHANNEL_COUNT, frame_count),
dtype=np.float32)
sin_l.render(out_data, frame_count)
sin_r.render(out_data, frame_count)
print(out_data[0])
print(out_data[1])
return (out_data * 0.4, pyaudio.paContinue)
stream = p.open(format=pyaudio.paFloat32 | PA_NONINTERLEAVED,
channels=DEFAULT_CHANNEL_COUNT,
rate=SRATE,
output=True,
stream_callback=callback)
stream.start_stream()
while stream.is_active(): time.sleep(0.1)
stream.stop_stream()
stream.close()
p.terminate()
我非常怀疑非交错数据在教学上的优越性,听听你的另一部分理由会很有趣
如果传递二维数组,是否知道matplotlib会打印列
另外,看起来您忽略了数组的顺序设置。只有在假设order='C'
的情况下,你在问题中所说的才有意义。通过运行数组,然后将缓冲区传递给PyAudio(但不使用PA_NONINTERLEAVED
标志!),您应该能够获得所需的行为。
请注意,在许多情况下,这会产生不必要的数据副本
给出示例代码后,您似乎误解了PortAudio的“非交错”模式的工作原理。在这种模式下,PortAudio假设输入和输出数据是指向一组其他数组的指针的C数组,每个数组保存一个通道的数据。为了能够使用它,您需要获取指向NumPy数组每一行的指针。我不知道这在纯Python中是否可行
最后,一些广告:你应该考虑使用模块而不是PyOdio。它仍然使用交错数据,通道存储在列中,但它直接支持NumPy阵列,并且应该比PyAudio更易于安装和使用。否,至少在版本0.2.11中仍然如此。当录制某些内容时,此回调代码只允许在一个通道上投影,在示例中为第一个通道。诀窍是使用NumPy并将数据排列成一个数组(立方体),其尺寸为帧x通道x数据(SAMPLE\u WIDTH
),然后投影到第一个通道(0):
#16位采样宽度
样本宽度=2
定义音频回调(输入数据、帧计数、时间信息、状态标志):
通道=int(len(in_数据)/(采样宽度*帧计数))
buffer=np.frombuffer(在数据中,dtype=uint8)
first_channel=buffer.reforme(帧计数、通道、采样宽度)[:,0,:]tobytes()
音频\u示例。附加(第一个\u通道)
#不记录时,将处理后的数据作为第一个元组部分返回此处
返回None,pyaudio.paccontinue
FWIW,我已经有了使用交错数据的工作代码,我计划继续使用它。因此,正如我所说,整个非交错练习实际上是说教式的。但是a=np.zeros((2,5),dtype=float32)
实际上不是产生了两个数组,五个元素长,这样一个[0]将是非交织模式下的左通道吗?(虽然我在安装和使用PyAudio时没有遇到任何问题,但sounddevice似乎解决了问题,所以我将深入研究。)是的,a[0]
将是一个包含左声道的NumPy数组,但是当您将属于a
的缓冲区传递给PortAudio时,它希望会有指针,但它只会找到音频数据(很可能会产生您描述的错误).PyAudio必须明确地处理对PA_NONINTERLEAVED
的支持,我想不是。我曾考虑在模块中实现这一点,但到目前为止,似乎没有人需要这一点…“PyAudio文档中给出的示例演示了如何通过回调传递交错数据”。您能链接示例吗我会觉得它很有用的,谢谢