pyAudiere problem

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

Hi Jungs,

Ich habe ein problem mit pyaudiere (OS ist Win XP). Ich habe folgendes Test skript geschrieben:

Code: Alles auswählen

#!usr/bin/python

import audiere

print dir(audiere)

# Open default audio device
d = audiere.open_device()

i = 0
while i < 2:
    # Stream a mp3 file:
    f = d.open_file('eine\\mp3\\datei', 1)
    f.play()
    
    i += 1
    
print 'test'
Das print 'test' am ende ist nur da um zu sehen, ob der Code gelesen wird, falls kein sound output da ist.

so aber nun zum problem: When ich IDLE benutze klappt das alles wunderbar. Jedoch wenn ich das skript von eclipse oder via cmd laufen lasse passiert gar nichts... warum weiss ich nicht. falls mir irgendjemand weiterhelfen koennte, waere das klasse.


Als erklaerung, ich brauche eine library in python die 3 oder mehrere mp3 dateien gleichzeitig abspielen kann und mit der man auch waehrend des abspielens eine mp3 file wechseln kann.

Falls ihr dazu alternativen seht, waere ich auch fuer diese dankbar. im uebrigen habe ich PyGame versucht. geht leider nicht (nur ein stream channel), pymedia konnte ich nicht installieren (kein support mehr glaube ich), genausowenig gstreamer. bin mit meinem latein aktuell ein bisschen am ende ;( ich danke fuer jede hilfe
Zuletzt geändert von Anonymous am Mittwoch 19. Mai 2010, 07:08, insgesamt 1-mal geändert.
Grund: Syntax-Highlighting aktiviert.
BlackJack

@Nebelhom: Welche Version verwendest Du denn? Ich kann da weder in der kurzen Doku für die Python-Anbindung, noch im Quelltext von 1.9.4 oder im SVN-Trunk eine `play()`-Methode entdecken!?
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

Hi BlackJack

sorry ich benutze pyAudiere-0.2-py2.6. Ich haette das im betreff ausfuehrlicher angeben sollen. Hier ist der link zur website:

http://pyaudiere.org/

ich habe die Win binary (von der website) benutzt, um es zu installieren. soweit ich weiss, brauch man dafuer nicht mit audiere (hier der link dazu) selbst rum zu spielen. Ich hatte das auf ubuntu versucht und bin nicht wirklich weit gekommen, deshalb habe ich auf die (generell) einfachen windows installationen gesetzt ;) (bitte keinen glaubenskrieg. ich mag ubuntu sehr, aber sobald irgendetwas nicht in den repositories ist, kann man als laie schonmal ins schwitzen kommen)

die play()-method habe ich aus den "examples" der website. das uebliche anfangen in dem man beispiele aendert.

danke das du dir das anschaust.
BlackJack

@Nebelhom: Ich hab's jetzt nicht installiert, aber Sound wird doch asynchron abgespielt, oder? Ich hätte da mal 'ne Vermutung was am Programmende dann passiert. Du musst dem Sound wahrscheinlich einfach ein bisschen Zeit geben, damit man ihn auch hören kann. :-)
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

hmmm,

ich werde das heute abend mal ausprobieren, aber ich denke ehrlich gesagt nicht, dass es daran liegt, weil eclipse pydev mir ja anzeigt, dass das skript fertig ist und wenn das der fall ist, dann haette die musik file ja anfangen muessen, waehrend ich an dem skript rumgewurschtelt habe...

aber jeder vorschlag ist willkommen und ich werde das heute abend mal abchecken. wie lang denkst du sollte ich da warten?

by the by, ich hatte letztens mal ein aehnliches problem mit pygame. da hat IDLE (also wohl Tkinter) die datei einfach so gespielt (a la channel = pygame.mixer.Sound(datei.wav); dann channel.play()), waehrend ich in allen anderen skripten einen endless loop, um das channel.play() einbauen musste, damit die datei abgespielt wurde. IDLE macht da etwas fuer mcih automatisch, aber ich weiss nicht was... (while loop kanns nicht sein, weil den hab ich ja schon ;) )

Danke schon mal fuer den vorschlag :D
BlackJack

@Nebelhom: Was meinst Du mit "an dem Skript rumgewurschtelt"? So wie es da steht wird in einer Schleife mehrfach das Abspielen asynchron gestartet, dann wird etwas mit ``print`` ausgegeben, und danach ist das Programm beendet. Und damit dürfte auch die Soundausgabe enden. Die Schleife zweimal durchlaufen und eine ``print``-Anweisung ausführen ist höchstwahrscheinlich schnell genug, dass man von dem Sound gar nicht erst etwas zu hören bekommt.

Bei `pygame` dürfte es genau das gleiche Problem gewesen sein.

Idle ist selbst in Python geschrieben und die Skripte werden da nicht extern ausgeführt, sondern innerhalb eines laufenden Interpretierers, der am Ende nicht beendet wird, darum kann man sich nicht darauf verlassen, dass sich Programme ohne Idle genau so verhalten. Das ist übrigens grundsätzlich eine Sache, die man bei IDEs auch in einigen anderen Programmiersprachen beachten sollte, dass die Ablaufumgebung von der IDE beeinflusst werden kann, was zum Beispiel Pfade, Umgebungsvariablen, oder eben auch Intepretierer bei Sprachen wie Python angeht.

Man sollte Programme immer auch mal ohne IDE testen und das Verhalten was man da sieht als das "normale" betrachten.
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

sorry, ich muss dich falsch verstanden haben. ich dachte, nachdem das skript durchgelaufen ist, muss ich noch ein wenig warten und dann ist es gut. das der interpreter nicht offen ist, ist mir nicht in den sinn gekommen ;)

ja was interne ablaeufe angeht, bin ich ein greenhorn. Auf jeden fall habe ich mal wieder etwas gelernt :)

ok was schlaegst du vor? sollte ich am besten einen " while True:" loop einbauen, um zu sehen, ob die datei abgespielt wird?

Ich hoffe, ich versteh dich richtig mit "dem interpreter etwas mehr zeit geben"

Meinst du, dass in IDLE der interpreter fortwaehrend im hintergrund laufend ist, waehrend in der cmd eingabeaufforderung und in pydev, der interpreter nur fuer die zeit, um das skript laufen zu lassen, angeschmissen wird... ist das so richtig?

daraus wuerde ich schluss folgern, dass ich mit einem endless loop, den interpreter laenger offen habe, damit die datei auch angespielt wird...

sag einfach "ja", falls ich das hier richtig verstanden habe. ich muss sowas erst durch eigene formulierung in meine birne bekommen ;(

ich bedanke mich schonmal fuer die erlaeuterung. Du hast einen hobby pythonisten ein kleines stueck schlauer gemacht ;)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Mit deinen Vermutungen liegst du schon ganz gut. Zum eigentlichen Problem: Schau doch mal auf die PyAudiere-Seite. Dort ist sogar ein Beispiel!

Sebastian
Das Leben ist wie ein Tennisball.
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

hmmm... also ich habe audiere jetzt dazu gebracht, eine audio datei abzuspielen (sowohl .wav, als auch .mp3 und.ogg so wie es audiere versprochen hat).

Vielen Dank euch allen fuer die Hilfe! Hier erst der Code und dann ein kleines Problem "mit dem Code"

Code: Alles auswählen

#!usr/bin/python

import audiere
import time

# Open default audio device
d = audiere.open_device()

f = d.open_file('path/to/audio/file', 1)

f.play()

while f.playing: # f.playing is either 0 or 1 depending on whether
                     # f has finished playing or not
    time.sleep(0.1)

leider klappt das bis jetzt nur mit einem while loop (wie im example auf der homepage). Wenn ich in diesem loop bin, dann ist das skript leider in einer warteschleife bis die datei fertig gespielt hat. das ist zum beispiel bei einem GUI doof, weil dann nix klappt, bis das ganze fertig ist und dann kann ich erst wieder einen knopf druecken.
koenntet ihr mir pointers in die richtige richtung geben. Ich hatte eigentlich gehofft, dass ich einfach nur einen channel fuer jede datei aufmachen muss und dann kann ich die separat behandeln, waehrend die anderen weiterlaufen. mit dem while loop ist das dummerweise unmoeglich...

muss ich dafuer threading benutzen? ich habe mir sagen lassen, dass das sehr schnell, sehr komplex werden kann.

gibt es auch einfachere herangehensweisen?

wie immer, vielen Dank fuer eure Hilfe.
BlackJack

@Nebelhom: Wenn Du das in einer GUI machst, dann hast Du doch das Problem erst gar nicht, welches die ``while``-Schleife hier löst. Ein GUI-Programm läuft solange wie die Hauptschleife des verwendeten GUI-Toolkits läuft, und die tut das für gewöhnlich bis der Benutzer eine Aktion ausführt, die das Programm beenden soll.
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

@BlackJack

Dieselbe Annahme hatte ich auch, aber irgendwie will das nicht so wie ich will. Der folgende Code funktioniert in meiner GUI nicht ohne den "while" loop.

Code: Alles auswählen

    def onPlay(self, event):
        d = audiere.open_device()
        
        f = d.open_file('keks.wav')
        f.play()
        
        while f.playing: # <- Ohne diesen loop, hoere ich keinen sound
            time.sleep(0.1)
uebersehe ich schon wieder irgendetwas offensichtliches? ich benutze wxpython und die function ist teil des hauptframes (when "play button" is pressed). mit "while" funktionierts und alles stoppt bis die datei fertig ist und ohne geht nichts.

Danke fuers feedback :)
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

Ok, ich beende diesen Thread mal, weil ich einen sehr schwerwiegenden bug bei meinem system mit audiere entdeckt habe.

wenn ich die datei in den arbeitsspeicher hochladen will anstatt zu streamen, wird mein PC abgeschossen. Kurzer Blue Screen mit schrift die zu kurz da ist, um gelesen zu werden und dann wird mein PC neu hochgefahren... mal sehen, vielleicht finde ich ja eine Kontaktadresse zu dem Author von audiere, damit ich ihm den bug mitteilen kann. habe aber leider keinen bug report site finden koennen. Aber bei so einem Bug werde ich die library erstmal nicht benutzen

Korrektur: .wav, .mp3 kann hochgeladen werden. .ogg files schiessen den PC ab... damit kann ich dann evtl noch arbeiten ;)... wenn ich das problem noch geloest bekomme ;)

hat jemand von euch dieselbe Erfahrung schonmal gemacht?
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Du kannst auch deaktivieren, dass bei einem Bluescreen automatisch neugestartet wird (Google hilft), vielleicht kannst du ja mit der Meldung etwas anfangen.
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

Echt? Das wusste ich "auch" nicht. na dann werde ich mal das Orakel von Google befragen zu diesem Thema :)
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

Nee, leider hat das auch nichtgeholfen ;(. Nur Ratschlaege was ich machen soll und dann folgende Fehlermeldung:

Code: Alles auswählen

*** STOP: 0x000000BE, (0xC0000005, 0x804F104B, 0xB5BEA954, 0x00000000
Falls das einem von euch hilft, dann lasst mich bitte wissen, wie man das beheben kann.

Leider bin ich auch nicht in der Lage gewesen, die Tondatei mit pyaudiere abzuspielen ohne einen while loop zu benutzen und dadurch mein Programm in wartemodus zu versetzen :( schade eigentlich.

Falls einer von euch Erfahrung mit pyAudiere hat und das Problem elegant umschifft (das elegant ist nicht sooooo wichtig), waere es nett, wenn ihr mir da aushelfen koenntet.

Ich danke euch allen fuer euer feedback. Ich bin wirklich angetan von der Kompetenz in diesem Forum :D (Auch im Hinblick auf andere threads)
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Also mit GTK kann man über den Befehl `main_iteration` die GUI-Events ablaufen lassen. In Kombination mit subprocess hab ich das mit einer while Schleife folgendermaßen gelöst.

Code: Alles auswählen

proc = Popen(...)
while proc.poll() is None:
    gtk.main_iteration()
Damit wird auf den Prozess gewartet und gleichzeitig ist noch die GUI aktiv (bei mir in Form einer Progressbar).

Vielleicht kann man das mit wx ähnlich lösen.
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

ms4py hat geschrieben:Also mit GTK kann man über den Befehl `main_iteration` die GUI-Events ablaufen lassen. In Kombination mit subprocess hab ich das mit einer while Schleife folgendermaßen gelöst.

Code: Alles auswählen

proc = Popen(...)
while proc.poll() is None:
    gtk.main_iteration()
Damit wird auf den Prozess gewartet und gleichzeitig ist noch die GUI aktiv (bei mir in Form einer Progressbar).

Vielleicht kann man das mit wx ähnlich lösen.
Es klappt! Sort of... ;) Es gibt tatsaechlich einen Befehl in wxPython genannt "wx.EnableTopLevelWindows()", der durch einen boolean definiert ist (True fuer an und False fuer aus, is klar). Das sieht dann bei mir im GUI so aus als function:

Code: Alles auswählen

def onPlay(self, event):
       
    d = audiere.open_device()

    f = d.open_file('my/audio/file', -1) # -1 equals 'streaming', 0 is load fully into RAM prior to use
    f.play()
        
    while f.playing:
        wx.EnableTopLevelWindows()
Leider spuckt das noch einen Fehler aus, aber ansonsten klappt's. Der Fehler ist komisch weil in der documentation ist der default value auf True gesetzt und wenn ich True explizit angebe, stuerzt das programm ab...

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Dokumente und Einstellungen\Nebelhom\workspace\DSAMusic\src\DSAMusicGUI.py", line 159, in onPlay
    wx.EnableTopLevelWindows()
  File "C:\Python26\lib\site-packages\wx-2.8-msw-unicode\wx\_misc.py", line 382, in EnableTopLevelWindows
    return _misc_.EnableTopLevelWindows(*args, **kwargs)
TypeError: Required argument 'enable' (pos 1) not found
Ich bedanke mich zweitausend mal fuer diesen hilfreichen tipp!!! <insert smiley fuer fuesse kuess> ;)

Alles andere wird jetzt wohl ein Problem mit wxPython sein und das werde ich in einem separaten thread auffuehren, falls es denn notwendig ist.
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

Kurzes add-on. Ich habe es jetzt ungewollt geschafft mein problem mit dem eingefrorenen GUI zu beheben, indem ich die audio datei abspiel und stop funktion in eine andere klasse verschoben habe. Ich war etwas ueberrascht, dass das ging, weil ich eigentlich nur dabei war herauszufinden, wie ich die audiere library fuer meine zwecke benutzen kann (problem war: wie stoppe ich die datei wenn ich sie erst innerhalb der funktion play definiere, oeffne und abspiele)

unten angehaengt der sample code und mein frage:

War das zu erwarten, dass ich das gui einfrieren loese indem ich die logik in eine andere klasse versetze? (denn ich bin davon wirklich ueberrascht)

Ausserdem, da ich mit OOP noch nicht besonders gut bin. ist es clever, dieses outsourcing der logik auf andere klassen?

Ich war der meinung "Ja", aufgrund der pythonic code reusability predigt, aber bitte belehrt mich, falls ich das falsch verstanden habe.

Code: Alles auswählen

class Audiofile:
    
    # Amazingly, this works without locking up the GUI!!!
    
    def __init__(self, path):
        
        self.path = path
        self.file = audiere.open_device()
        self.song = self.file.open_file(path, -1) # -1 stands for streaming, tested with .mp3, .wav, .ogg
    
    def player(self):    
        self.song.play()
        
    def stopper(self):
        self.song.stop()

# Excerpt from gui functions bound to buttons in wxpython

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):

# constructor stuffs
   
   ...

   wx.EVT_BUTTON (self, ID_PLAY, self.onPlay)       
   wx.EVT_BUTTON (self, ID_STOP, self.onStop)
   
   ...
   self.audio = Audiofile('an/audio/file')

   def onPlay(self, event):
        self.audio.player()
        
    def onStop(self, event):
        self.audio.stopper()
BlackJack

@Nebelhom: Dass das reine verschieben sollte das Problem eigentlich nicht gelöst haben. Bist Du sicher, dass Du nicht noch etwas anderes an der Programmlogik verändert hast?

Wieso nennts Du das Device-Objekt `file`? Das finde ich ein wenig verwirrend.

Der Kommentar bezüglich der -1 und dem Streaming ist falsch. Als zweites Argument wird dort ein Wahrheiswert erwartet und -1 ist zufällig "wahr". Genauso wie -2 oder 42 oder die Zeichenkette "spam". Man sollte dort aber trotzdem `True` übergeben um es dem Leser deutlicher zu machen.

`player()` und `stopper()` sollten wohl eher `play()` und `stop()` heissen.
Nebelhom
User
Beiträge: 155
Registriert: Mittwoch 19. Mai 2010, 01:31

hi blackjack, danke fuers feedback. es kommt also nicht nur mir etwas komisch vor, dass das jetzt so uuuurploetzlich toll funktioniert.

zu deinen kommentaren:

1) soweit ich das verstehe, habe ich nur das button binding, dass ich innerhalb der "myframe" class angegeben habe, in die class audiofile verschoben. Der grosse unterschied, glaube ich, war diesmal, dass ich den "while playing"-loop weglassen konnte und die datei wurde immernoch abgespielt (weil die gui einen endlos-loop gibt). Warum ich den diesmal weglassen konnte ist mir jedoch ein absolutes raetsel.

als vergleich, frueher gab es die audiofile class nicht und dafuer hatte ich die funktion folgendermassen definiert innerhalb von myframe (bitte keine groesseren kommentare zu der funktion, dass hab ich nur so da rein geschrieben, um zu sehen ob es geht und sofort gesehen, dass das gui einfriert):

Code: Alles auswählen

    def onPlay(self, event, path='my/audio/file'):

        d = audiere.open_device() #defined without self
        f = d.open_file(path)
        f.play()
        
        while f.playing: # leaving it out causes the audiofile not to play
            time.sleep(.01)
2) ja namensgebung. es erschien mir gestern, um 2 uhr morgens sehr clever meine "datei" mit self.file zu benennen. ich werde es mal umbenennen in etwas besseres. aber bei namensgebung von variablen bin ich ziemlich schlecht

3) Streaming: Nach nochmaligen nachschauen, frage ich mich wirklich, woher ich das -1 habe.... weil selbst im example code steht nur eine "1" da... notiert. danke fuer die bemerkung. da habe ich einfach geschlafen.

4) player() und stopper(): da die methoden bei audiere play() und stop() jeweils hiessen, dachte ich es hlft gegen die verwirrung, wenn ich meine funktionen anders nenne, falls ein fehler auftritt, damit ich weiss wo der fehler ist. in meinem code selbst oder in der art wie ich versuche die audiere library zu benutzen. Ist das falsch... nein nicht falsch... programmiererisch ungeschlacht? ;)

danke fuer die kommentare. wieder ein paar sachen mehr auf die ich aufmerksam sein muss :) schade, dass du auch nicht weisst, warum sich mein problem geloest hat. ich mag es nicht, wenn sich etwas verbessert, ich aber nicht verstehe, warum (und dann daraus etwas lerne).

thanks again
Antworten