pyaudio сохраняет несколько.Файл WAV с неблокированием

#callback #wav #nonblocking #pyaudio

#обратный вызов #wav #без блокировки #pyaudio

Вопрос:

Обновления: Теперь я узнал, что мы можем вставить некоторый код в функцию обратного вызова, и в итоге появилось больше вопросов:

  1. Когда будут вызываться и останавливаться функции обратного вызова? когда мы открываем и закрываем поток?

  2. Функция обратного вызова может возвращать потоковые данные (audio_data из кода). Поскольку мы не вызывали функцию, pyaudio, я полагаю, делает это внутренне. Как мне получить данные обратного потока из обратного вызова?

 import pyaudio
import wave
import numpy as np
import npstreams
import time


CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100

audio = pyaudio.PyAudio()

channel_1_frames = []
channel_2_frames = []
fulldata = np.array([])

def callback(in_data, frame_count, time_info, flag):
    global b,a,fulldata #global variables for filter coefficients and array
    
    audio_data = np.fromstring(in_data, dtype=np.int16)
   
    channel_1 = audio_data[0::CHANNELS]
    channel_2 = audio_data[1::CHANNELS]
    data1 = channel_1.tostring()
    data2 = channel_2.tostring()
    channel_1_frames.append(data1)
    channel_2_frames.append(data2)
    wf1 = wave.open('Channel_1.wav', 'wb')
    wf2 = wave.open('Channel_2.wav', 'wb')
    wf1.setnchannels(1)
    wf2.setnchannels(1)
    wf1.setsampwidth(audio.get_sample_size(FORMAT))
    wf2.setsampwidth(audio.get_sample_size(FORMAT))
    wf1.setframerate(RATE)
    wf2.setframerate(RATE)
    wf1.writeframes(b''.join(channel_1_frames))
    wf2.writeframes(b''.join(channel_2_frames))
    wf1.close()
    wf2.close()
    
    return (audio_data, pyaudio.paContinue)


stream = audio.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                #frames_per_buffer=CHUNK,
                stream_callback=callback)

stream.start_stream()

while stream.is_active():
    time.sleep(10)
    stream.stop_stream()
stream.close()

audio.terminate()
  

=============================================

Я пытаюсь записать несколько каналов в несколько.Файл WAV. Я могу сделать это с помощью stream.read() и массива numpy, чтобы разделить на другой массив и сохранить в .Файл WAV

 stream = audio.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)

print("* recording")

channel_1_frames = []
channel_2_frames = []

for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    data = stream.read(CHUNK)
    # convert string to numpy array
    data_array = np.frombuffer(data, dtype='int16')
    # select channel
    channel_1 = data_array[0::CHANNELS]
    channel_2 = data_array[1::CHANNELS]
    # convert numpy array to string 
    data1 = channel_1.tostring()
    data2 = channel_2.tostring()
    channel_1_frames.append(data1)
    channel_2_frames.append(data2)
stream.stop_stream()
stream.close()
audio.terminate()
  

Однако, из документации модуля,https://people.csail.mit.edu/hubert/pyaudio/docs/#class-stream , там сказано, что stream.read() и stream.write () не должны использоваться для неблокирующего.

И я нашел хороший неблокирующий пример pyaudio с Github:https://gist.github.com/sloria/5693955 Который не использовал stream.read().

Я не уверен, смогу ли я прочитать и включить steam numpy array без stream.read(), так что все еще возможно экспортировать поток в другой .WAV? и сделать его неблокирующим?

Спасибо

Ответ №1:

По мере того, как я больше изучаю кодирование, я нашел ответы.

A1: Функция обратного вызова запускается и останавливается вместе с потоком.

 ######open stream with out starting automatically
audio = pyaudio.PyAudio()
stream = audio.open(format=format,
channels=2,
rate=44100,
input=True,
frames_per_buffer=44100,
stream_callback=self.get_callback(),
start=False)

######start,stop stream
stream.start_stream()
stream.close()
audio.terminate()
  

A2: Для сбора данных в режиме реального времени мы можем использовать queue

 self.recorded_frames = queue.Queue()
    def get_callback(self):
        def callback(in_data, frame_count, time_info, status):
            self.recorded_frames.put(np.frombuffer(in_data, dtype=np.int16))
            return in_data, pyaudio.paContinue
        return callback