2017-03-03 3 views
0

Wenn ich ein Geräusch alle 0,5 Sekunden mit PyGame spielen:Bad Timing, wenn Audiodateien mit PyGame spielen

import pygame, time 

pygame.mixer.init() 
s = pygame.mixer.Sound("2.wav") 

for i in range(8): 
    pygame.mixer.Channel(i).play(s) 
    time.sleep(0.5) 

es nicht das Timing nicht respektiert überhaupt richtig.

Es ist wie es gibt eine Pause von 0,2 Sekunden als 0,7 Sekunden dann 0,2 Sekunden wieder, es ist sehr unregelmäßig.


Hinweise:

  • Ich weiß, dass time.sleep() nicht die genaueste in der Welt ist, sondern auch mit den genaueren Lösungen from here, ist das Problem noch vorhanden

  • Getestet auf ein RaspberryPi

  • Das Problem ist immer noch da, wenn ich viele verschiedene Dateienspielen, mit mir in einer großen Auswahl. So ist das Problem nicht aus der Tatsache, versucht es die gleiche Datei

+1

"Pause von 0,2 Sekunden als 0,7 Sekunden, dann wieder 0,2 Sekunden, es ist sehr unregelmäßig." das klingt für mich nicht sehr unregelmäßig, es klingt zyklisch. Wie lange hält der Ton? Besonders seit '0.7 == (Schlafzeit + 0.2) ' – roganjosh

+0

@roganjosh warum würde es solch einen Zyklus geben? 's.play()' ist nicht blockierend und sollte den Code fortführen – Basj

+0

@roganjosh Ich änderte den Code, um von den Kanälen Gebrauch zu machen, also sollte jeder gespielte Ton nicht einen anderen stören. Problem immer noch vorhanden ... – Basj

Antwort

1

Hier zu replay ist der Grund:

enter image description here

Selbst wenn wir den Audio-Puffer auf ein Minimum zu verringern unterstützt durch die Soundkarte (1024 oder 512 Samples anstelle von pygames Standard 4096), die Unterschiede bleiben bestehen, was zu einem "Metronom Beat" führt.

Ich werde mit einer Arbeitslösung aktualisieren, sobald ich eine finden. (Ich habe ein paar Ideen in dieser Richtung).

1

Wie Sie in Ihrer eigenen Antwort geschrieben haben, ist der Grund für die Timing-Probleme sehr wahrscheinlich, dass der Audio-Callback entkoppelt vom Rest der Anwendung ausgeführt wird.

Das Audio-Backend verfügt normalerweise über eine Art Uhr, auf die sowohl innerhalb der Callback-Funktion als auch außerhalb davon zugegriffen werden kann. Ich sehe zwei mögliche Lösungen:

  1. eine Bibliothek verwenden, die Ihnen die Callback-Funktion implementieren, können Sie sich, die Startzeiten des Sounds innerhalb der Callback-Funktion berechnen, diese Zeiten mit der aktuellen Zeit des „Audio vergleichen Uhr "und schreiben Sie Ihren Sound an den Ausgang an der entsprechenden Stelle im Ausgabepuffer.

  2. Verwenden Sie eine Bibliothek, mit der Sie die genaue Zeit (in Bezug auf die "Audio Clock") angeben können, wann Sie mit dem Abspielen Ihrer Sounds beginnen sollen. Diese Bibliothek würde die Schritte des vorherigen Punktes für Sie übernehmen.

Für die erste Option, könnten Sie die sounddevice Modul verwenden. Die Callback-Funktion (die Sie implementieren müssen) erhält ein Argument mit dem Namen time, das ein Attribut time.outputBufferDacTime hat, das ein Fließkommawert ist, der die Zeit (in Sekunden) angibt, wann das erste Sample des Ausgabepuffers abgespielt wird .

Volle Enthüllung: Ich bin der Autor des sounddevice Moduls, also ist meine Empfehlung ziemlich voreingenommen.

Ganz kürzlich habe ich angefangen, an dem Modul rtmixer zu arbeiten, das für die zweite Option verwendet werden kann. Bitte beachten Sie, dass dies in einem sehr frühen Entwicklungsstadium ist, also verwenden Sie es mit Vorsicht. Mit diesem Modul müssen Sie keine Callback-Funktion schreiben. Sie können die Funktion rtmixer.Mixer.play_buffer() verwenden, um einen Audiopuffer zu einer bestimmten Zeit (in Sekunden) abzuspielen. Als Referenz können Sie die aktuelle Zeit von rtmixer.Mixer.time abrufen.

+0

Sehr gute Antwort! Vielen Dank! Ich ging fast auf die gleiche Idee: einen Zeitstempel aus dem Loop-Thread "play sound events" senden, den der Audio-Callback im "mixing thread" mit der entsprechenden Position verwendet. Ich werde definitiv 'Sounddevice' verwenden, das ich bereits für mein Projekt http://www.samplerbox.org verwende! Danke – Basj

+0

Cooles Zeug, ich bin beeindruckt! – Matthias

+0

Re @Matthias, macht 'rtmixer' das eigentliche Mischen/Summieren in C oder Cython (nicht cpython aber cython), um es zu beschleunigen? So habe ich das Sampling für SamplerBox gemacht ([siehe hier] (https://github.com/josepernest/SamplerBox/blob/master/samplerbox_audio.pyx)) und ich habe mich gefragt, ob du auch bemerkt hast, dass du den Mix-Mathe-Part machst Eine kompilierte Sprache hat auch die Performance für dich massiv verbessert. – Basj

Verwandte Themen