У меня в качестве входных звуковых сигналов на разных частотах в течение разных промежутков времени. Я пытаюсь нарезать эти входные данные на фрагменты (одинакового размера независимо от входной частоты) и четко воспроизвести фрагменты на выходе. Когда я использую метод блокировки, например stream.write (), я получаю чистый вывод, но не хватает большой вычислительной мощности для выполнения других задач. Итак, я преобразовал код в неблокирующий подход с помощью функции callback (), как показано ниже.
Я попытался создать шаблон своего кода после этого поста: https://stackoverflow.com/a/22354593/12076263, но этоне работает вообще.
# Generate a 250 Hz tone in chunks amounting to 100 chunks per second,
# using a non-blocking method.
#
# How does one fit a 250 Hz wave into 100 Hz packets?
# Slice up a sine wave into segments of two-and-a-half waves apiece:
#
# | | | |
# _ _ _| _ _ | _ _ _| _ _ |
# / \ / \ / \ / \ / \ / \ / \ / \ / \ / \
# \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
# | | | |
# <----X1----> | <----X2----> | <----X1----> | <----X2----> |
#
# Play back each segment in alternating fashion.
# This simulates continuous audio where zero crossings do not necessarily
# occur at the edge of a chunk.
import numpy as np
import pyaudio
import time
# based on examples from https://people.csail.mit.edu/hubert/pyaudio/docs/
def callback(in_data, frame_count, time_info, status):
waveData = Y.tobytes()
return (waveData, pyaudio.paContinue)
Y = np.zeros((441), dtype = np.int16) # initialize audio array Y
p = pyaudio.PyAudio()
stream = p.open(format = 8, # 8 is code for int16 format
channels = 1,
rate = 44100,
frames_per_buffer = 441,
stream_callback = callback, # !! COMMENT OUT to enable blocking
output = True)
stream.start_stream()
X1 = np.linspace(0, 5 * np.pi, num = 441, endpoint = False)
Y1 = (5000 * np.sin(X1)).astype(np.int16) # Generate two-and-a-half waves
X2 = np.linspace(5 * np.pi, 10 * np.pi, num = 441, endpoint = False)
Y2 = (5000 * np.sin(X2)).astype(np.int16) # The "other" two-and-a-half waves
# Play the two wave segments one after the other
# Result should be a clean 250 Hz tone
while True:
Y = Y1 # First set of waves
time.sleep(0.0015) # This 1.5 millisecond delay
# simulates other stuff happening
# within the While loop.
#stream.write(Y.tobytes()) # !! UNCOMMENT to use blocking method
Y = Y2 # Second set of waves
time.sleep(0.0015) # More miscellaneous delays
#stream.write(Y.tobytes()) # !! UNCOMMENT to use blocking method
Ожидается, что синусоида без искажений (как цифровой звук идет), и получил сильно искаженный звук, как рев гигантского кино монстра. Как правило, сообщений об ошибках нет, но если значения time.sleep увеличены, может произойти опустошение. Также проблема исчезнет, если операторы time.sleep будут удалены полностью, но полное приложение, в котором это будет использоваться, будет иметь нагрузку обработки не менее 1,5 миллисекунды для каждого блока.