2016-12-18 3 views
0

Ich möchte eine Notiz über Schlüssel halten mit Python spielen. Ich implementiere und modifiziere derzeit den gefundenen Code here. Das Problem, vor dem ich stehe, ist jedoch, dass die Keydown-Funktion wiederholt aufgerufen wird, wenn die Taste gedrückt wird. Dadurch wird das Audio bei jedem Aufruf der Keydown-Funktion ein- und ausgeschaltet.Note auf Schlüssel halten mit PyAudio und TK spielen

Ich bin auf der Suche nach einer Möglichkeit, die Fähigkeit zu behalten, Akkorde zu spielen, aber entferne diese Ein- und Ausschneidevorgänge, indem ich Keydown nicht auf der gleichen Taste anrufe, bis keyup auf der Taste aufgerufen wurde. Der spezifische Teil des Codes, an dem ich gearbeitet habe, ist unten abgebildet.

Vielen Dank im Voraus.

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() 

Antwort

1

Haben Sie ein Wörterbuch, das einen Schlüsselcode als Schlüssel und einen Zustand (z. B. boolesch) dieses Schlüssels als Wert enthält.

Also, wenn die Taste gedrückt ist, überprüfen Sie, ob der Schlüsselcode im Diktat ist, wenn es nicht nur mit Wert 1 addiert wird. Und beginnen Sie mit der Wiedergabe der Notiz. Wenn es vorhanden ist, überprüfen Sie den Status dieses Schlüssels, und wenn es gedrückt wird, ignorieren Sie das Ereignis. Sonst gehst du die Note spielen. Bei der Tastenkombination den Status des Schlüssels auf 0 setzen.

Und, auch, verwenden Sie nicht Callback, um Audio abzuspielen, unterbricht so gespielte Note wird Sie Alpträume verursachen.

Besser schreiben Sie in einem Stream die Notiz in einem Thread.

Schreiben Sie die Daten in Stücke und prüfen Sie, ob das Flag gestoppt wird.

Wenn Taste nach oben wird das Kennzeichen genannt und zu tun:

stream.stop_stream(); stream.start_stream() 

Um genau den Ton abgeschnitten.

Setzen Sie den schreibenden Teil in den try-except-Block, so dass nichts passiert, wenn Sie den Stream zwingen, von außerhalb des Threads anzuhalten.

Wenn Sie eine bessere Möglichkeit wünschen, pyaudio für solche Dinge zu verwenden, die es Ihnen ermöglichen, mehrere Sounds gleichzeitig zu spielen, suchen Sie PyPI für SWmixer Modul. Sie werden auch brauchen, numpy. Dann verwenden Sie SWMixer, um jeden Sound in ein eigenes Objekt zu laden und ihn wie gewünscht zu starten und zu stoppen. Seine Verwendung ist sehr ähnlich zu pygame.mixer Modul.

BTW, wenn Sie versuchen, mehrere PyAudio Streams parallel zu verwenden, bin ich mir nicht sicher, wie das funktionieren würde.

Ich meine, ich weiß, dass Sie einen Ausgang und einen Eingangsstrom parallel ohne viel Mühe verwenden können, aber mehr als 2 Ausgangsströme können einige verursachen. Deshalb habe ich SWMixer erwähnt. Ich habe nie versucht, mehr als einen zu verwenden, also könnte ich mich irren.

Aber ich habe versucht, mehrere Instanzen von PyAudio selbst zu verwenden. Es funktioniert, indem es die Lautstärke von vorher genannten verringert. Damit ich auch mit Streams komme. Sie werden also die letzte Note lauter hören als vorher, oder Sie könnten komische Geräusche hören.

0

Sie können eine globale Variable verwenden, um zu überprüfen, ob bereits ein Keydown-Ereignis ausgelöst wurde.

+0

Wie Sie sehen konnten, ist Variable namens Akkord. Das ultimative Ziel wäre also, mehrere Noten gleichzeitig spielen zu können. Wenn ich mich nicht irre. Daher würde eine Variable nicht ausreichen. – Dalen

+0

@Dalen, es ist ein Beispiel.Man kann ein Array von Variablen oder ein Wörterbuch mit verschiedenen Schlüsseln erstellen und überprüfen. Wie ich sehe, spielt momentan nur eine Note (44100 Hz) auf einer beliebigen Taste. – akarilimano

+0

Ja, Ja, nur so! – Dalen