Преобразование многоканального PyAudio в массив NumPy
все примеры я могу найти моно, с CHANNELS = 1
. Как Вы читаете стерео или многоканальный вход с помощью метода обратного вызова в PyAudio и преобразуете его в 2D-массив NumPy или несколько массивов 1D?
для ввода mono, что-то вроде этого работает:
def callback(in_data, frame_count, time_info, status):
global result
global result_waiting
if in_data:
result = np.fromstring(in_data, dtype=np.float32)
result_waiting = True
else:
print('no input')
return None, pyaudio.paContinue
stream = p.open(format=pyaudio.paFloat32,
channels=1,
rate=fs,
output=False,
input=True,
frames_per_buffer=fs,
stream_callback=callback)
но не работает для стереовхода,result
массив в два раза длиннее, поэтому я предполагаю, что каналы чередуются или что-то еще, но я не могу найти документацию для этого.
1 ответов
представляется чередованием образцов, с левой Первый канал. С сигналом на входе левого канала и тишиной на правом канале я получаю:
result = [0.2776, -0.0002, 0.2732, -0.0002, 0.2688, -0.0001, 0.2643, -0.0003, 0.2599, ...
поэтому, чтобы разделить его на стереопоток, переформуйте в 2D-массив:
result = np.fromstring(in_data, dtype=np.float32)
result = np.reshape(result, (frames_per_buffer, 2))
теперь для доступа к левому каналу используйте result[:, 0]
, и для правого канала, используйте result[:, 1]
.
def decode(in_data, channels):
"""
Convert a byte stream into a 2D numpy array with
shape (chunk_size, channels)
Samples are interleaved, so for a stereo stream with left channel
of [L0, L1, L2, ...] and right channel of [R0, R1, R2, ...], the output
is ordered as [L0, R0, L1, R1, ...]
"""
# TODO: handle data type as parameter, convert between pyaudio/numpy types
result = np.fromstring(in_data, dtype=np.float32)
chunk_length = len(result) / channels
assert chunk_length == int(chunk_length)
result = np.reshape(result, (chunk_length, channels))
return result
def encode(signal):
"""
Convert a 2D numpy array into a byte stream for PyAudio
Signal should be a numpy array with shape (chunk_size, channels)
"""
interleaved = signal.flatten()
# TODO: handle data type as parameter, convert between pyaudio/numpy types
out_data = interleaved.astype(np.float32).tostring()
return out_data