Python 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

我无法将非交错立体声数据传递到PyAudio

更新(重新编写问题) PyAudio文档中给出的示例演示了如何通过回调传递交错数据。交错立体声数据缓冲区的形状为
(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文档中给出的示例演示了如何通过回调传递交错数据”。您能链接示例吗我会觉得它很有用的,谢谢