Обратный вызов PyAudio вызывается только один раз - PullRequest
0 голосов
/ 20 сентября 2018

Я пытаюсь создать простое приложение, которое загружает wav-файлы (по одному на каждую ноту клавиатуры) и воспроизводит конкретные, когда нажата (или проиграна) миди-нота.До сих пор я создал входной поток midi с использованием mido и поток аудио с использованием pyaudio в двух отдельных потоках.цель состоит в том, чтобы поток midi обновлял воспроизводимые в данный момент ноты, а также обратный вызов потока pyaudio для проверки активных нот и их воспроизведения.Midi-поток работает нормально, но мой аудиопоток, кажется, вызывает обратный вызов только один раз, прямо при запуске сценария (print(notes)).Любая идея, как я могу получить обратный вызов аудиопотока, чтобы постоянно обновлять?

import wave
from io import BytesIO
import os
from mido import MidiFile
import pyaudio
from time import sleep
from threading import Thread
import numpy

# Pipe: active, released
# Rank: many pipes
# Stop: one or more ranks
# Manual: multiple ranks
# Organ: multiple manuals

pipes = []
notes = []
p = pyaudio.PyAudio()


def mapRange(num, inMin, inMax, outMin, outMax):
    return int((num - inMin) * (outMax - outMin) / (inMax - inMin) + outMin)

def callback(in_data, frame_count, time_info, status):
    data = bytes(frame_count)
    print(notes)
    for note in notes:
        pipedata = bytes()
        if len(data) != 0:
            data1 = numpy.fromstring(data, numpy.int16)
            data2 = numpy.fromstring(note['sample'].readframes(frame_count), numpy.int16)
            pipedata = (data1 * 0.5 + data2 * 0.5).astype(numpy.int16)
        else:
            data2 = numpy.fromstring(note['sample'].readframes(frame_count), numpy.int16)
            pipedata = data2.astype(numpy.int16)
        data = pipedata.tostring()
    return (data, pyaudio.paContinue)

stream = p.open(format=pyaudio.paInt24,
                channels=2,
                rate=48000,
                output=True,
                stream_callback=callback,
                start=True)

# start the stream (4)
stream.start_stream()

for root, dirs, files in os.walk("samples"):
    for filename in files:
        file_on_disk = open(os.path.join(root, filename), 'rb')
        pipes.append(
            {"sample": wave.open(BytesIO(file_on_disk.read()), 'rb')})
for msg in MidiFile('test.mid').play():
    if msg.type == "note_on":
        notes.append(pipes[mapRange(msg.note, 36, 96, 0, 56)])
        print("on")
    if msg.type == "note_off":
        #notes[mapRange(msg.note, 36, 96, 0, 56)] = False
        print("off")

# wait for stream to finish (5)
while stream.is_active():
    sleep(0.1)

# stop stream (6)
stream.stop_stream()
stream.close()

# close PyAudio (7)
p.terminate()
...