2016-12-18 10 views
0

Я хочу сыграть заметку о удерживании клавиши с помощью python. В настоящее время я реализую и изменяю код here. Тем не менее, проблема, с которой я сталкиваюсь, заключается в том, что функция keydown вызывается многократно, когда ключ удерживается, в результате вырезание и выключение звука каждый раз, когда вызывается функция keydown.Воспроизведение заметки на удерживании клавиши с помощью PyAudio и TK

Я ищу способ поддерживать способность играть на аккордах, но удаляю это внутри и без вырезания, не вызывая keydown на одной и той же клавише до тех пор, пока на клавиатуре не будет вызвана клавиша. Конкретная часть кода, над которым я работал, показана ниже.

Заранее спасибо.

p = pyaudio.PyAudio() 
chord = Chord() 
gen = NoteGen() 

def callback(in_data, frame_count, time_info, status): 
    wave = chord(frame_count) 
    data = wave.astype(numpy.float32).tostring() 
    return (data, pyaudio.paContinue) 

stream = p.open(
    format=pyaudio.paFloat32, 
    channels=1, 
    rate=44100, 
    output=True, 
    stream_callback=callback 
) 

stream.start_stream() 


def keydown(event): 
    k = gen(event.char) 
    print("add note: " + event.char) 
    chord.add_note(k) 
    print [(n.name, n.frequency) for n in chord.notes] 


def keyup(event): 
    k = gen(event.char) 
    print("remove note: " + event.char) 
    chord.remove_note(k) 
    print [n.name for n in chord.notes] 


root = Tk() 
frame = Frame(root, width=100, height=100) 
frame.bind_all("<KeyPress>", keydown) 
frame.bind_all("<KeyRelease>", keyup) 
frame.pack() 
root.mainloop() 

stream.stop_stream() 
stream.close() 
p.terminate() 

ответ

1

есть словарь, который будет содержать код ключа в качестве ключа и состояния (логического, например) этого ключа в качестве значения.

Итак, когда вызывается клавиша, проверьте, находится ли код ключа в dict, если он не просто добавляет его со значением 1. И начните воспроизведение заметки. Если он присутствует, проверьте состояние этого ключа, и если он нажат, проигнорируйте событие. Осталось пойти на ноту. На клавиатуре установите состояние клавиши на 0.

А также не используйте обратный вызов для воспроизведения звука, прерывая такое воспроизведение, это вызовет кошмары.

Лучше напишите потоку записку внутри потока.

Запишите данные в куски и проверьте флаг остановки.

При вызове Ключевание установить флаг и сделать:

stream.stop_stream(); stream.start_stream() 

Чтобы точно отрезать звук.

Положите часть записи в блок try-except, чтобы при принуждении потока останавливаться снаружи потока, ничего плохого не происходит.

Если вы хотите улучшить использование pyaudio для таких вещей, что позволит вам воспроизводить сразу несколько звуков, выполните поиск PyPI для модуля SWmixer. Вам также понадобится numpy. Затем вы используете SWMixer для загрузки каждого звука в свой собственный объект и запуска и остановки, как вы хотите. Его использование очень похоже на модуль pygame.mixer.

BTW, если вы попытаетесь использовать несколько потоков PyAudio параллельно, я не уверен, как это будет работать.

Я имею в виду, что вы можете использовать один выход и один входной поток параллельно без особых проблем, но более чем 2 выходных потока могут вызвать некоторые проблемы. Вот почему я упомянул SWMixer. Я никогда не пробовал использовать более одного, поэтому я мог ошибаться.

Но я попытался использовать несколько экземпляров самого PyAudio. Он работает, уменьшая объем ранее названных. Так что я тоже с потоками. Таким образом, вы услышите последнюю ноту громче, чем раньше, или вы можете получить забавные шумы.

0

Вы можете использовать некоторую глобальную переменную, чтобы проверить, было ли уже запущено событие keydown.

key_pressed = False 

def keydown(event): 
    if key_pressed: 
     return 

    key_pressed = True 
    k = gen(event.char) 
    print("add note: " + event.char) 
    chord.add_note(k) 
    print [(n.name, n.frequency) for n in chord.notes] 


def keyup(event): 
    key_pressed = False 
    k = gen(event.char) 
    print("remove note: " + event.char) 
    chord.remove_note(k) 
    print [n.name for n in chord.notes] 
+0

Как вы могли видеть, переменная называется хордой. Таким образом, конечной целью было бы одновременное воспроизведение нескольких заметок. Если я не ошибаюсь. Поэтому одна переменная не будет делать. – Dalen

+0

@ Дален, это пример.Можно сделать массив переменных или словарь с разными ключами и проверить его. Как я вижу, в настоящее время на любой клавише воспроизводится только одна нота (44100 Гц). – akarilimano

+0

yep, Да, именно так! – Dalen