Musikdateien richtig abspielen

Spezielle Fragen zu 2D- und 3D-Grafik, Sound und Video
Antworten
basicwurm
Foriker
Beiträge: 37
Registriert: Di 8. Jan 2013, 16:59
Kontaktdaten:

Musikdateien richtig abspielen

Beitrag von basicwurm » Di 2. Aug 2016, 17:04

Hallo Gambistas,
Ich möchte einen Player für Musikdateien schreiben und stoße dabei auf 2 Probleme.

1. Die Dateien eines Ordners sollen der Reihe nach gespielt werden (Klassische Musik...) und sind mit Track 1.wav, Track 2.wav usw. benannt. Liest man sie mit For each aus, wird aber zuerst Track 10 gespielt. Die Filenames in ein Array zu stopfen und es zu sortieren, hilft nix - auch dann wird alfabetisch sortiert.
Als Lösung fand ich, die Filenames in ein ListView zu schreiben und dieses zu sortieren. Dann stehen sie zwar richtig drin, können aber nur mit MoveFirst/MoveNext richtig ausgelesen werden, weil der Index ja gleich bleibt. Weiß jemand eine bessere/einfachere Lösung?

2. Es braucht eine Schleife, um alle files abzuspielen, und die darf erst weitermachen, wenn ein file fertig abgespielt ist. Der folgende Code beginnt nur dann Track 1 zu spielen, wenn die While-Schleife auskommentiert ist - MIT ihr beginnt er mit Track 10, dem letzten. Das bedeutet wohl, dass die Schleife voll durchläuft und erst dann zu spielen beginnt? gbHandbuch zu MoveNext: "Returns TRUE if there is no child item left." Was funktioniert da nicht, das MoveNext oder das Music.Stopped?

Vielen Dank schon mal für eure Antworten!

Verwendete Komponenten: gb.media, gb.sdl2.audio
gambas code
Public Sub PLAY_Click()

Dim FIL As String               ' File zum abspielen
Dim PFA As String               ' Kompletter Pfad
Dim N As String                 ' IndexNr
Dim I As Integer = 1
 
For Each FIL In Dir(ORD)        ' Public Ordner vom DirChooser
  If FIL Ends "wav" Or FIL Ends "mp3" Or FIL Ends "ogg" Then
    N = CStr(I)
    LV.Add(N, FIL)               ' Alle files in ListView schreiben    
    I = I + 1
  Endif
Next

LV.Sorted = True                  ' ListView sortieren
LV.MoveFirst  

While LV.MoveNext() = False       ' lt. Handbuch
  FIL = CString(LV.Item.Text)
  PFA = ORD &/ FIL                 ' Pfad + Filename
  LB.Text = "Playing " & FIL        ' Label anzeigen
  Music.Load(PFA)
  Music.Play
  Wait
  If Music.Stopped = 0 Then LV.MoveNext() ' Etwas davon funktioniert nicht
Wend
End
Zuletzt geändert von tux_ am Di 2. Aug 2016, 17:25, insgesamt 1-mal geändert.
Grund: Bitte fuer Gambas-Code die gambas-Tags anstatt der code-Tags verwenden.

tux_
Moderator
Beiträge: 946
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: Musikdateien richtig abspielen

Beitrag von tux_ » Di 2. Aug 2016, 17:43

1. Die Dateien eines Ordners sollen der Reihe nach gespielt werden (Klassische Musik...) und sind mit Track 1.wav, Track 2.wav usw. benannt. Liest man sie mit For each aus, wird aber zuerst Track 10 gespielt. Die Filenames in ein Array zu stopfen und es zu sortieren, hilft nix - auch dann wird alfabetisch sortiert.
Du moechtest die natuerliche oder Versions-Sortierung der Dateinamen, wie sie auch von "ls -v" erzeugt wird. Dazu gambas code
Dir(sPfad).Sort(gb.Natural)
2. Es braucht eine Schleife, um alle files abzuspielen, und die darf erst weitermachen, wenn ein file fertig abgespielt ist. Der folgende Code beginnt nur dann Track 1 zu spielen, wenn die While-Schleife auskommentiert ist - MIT ihr beginnt er mit Track 10, dem letzten. Das bedeutet wohl, dass die Schleife voll durchläuft und erst dann zu spielen beginnt? gbHandbuch zu MoveNext: "Returns TRUE if there is no child item left." Was funktioniert da nicht, das MoveNext oder das Music.Stopped?
Weder noch. Der Music.Play()-Aufruf wartet nicht, bis das Musikstueck fertig gespielt ist, sondern stoeszt nur den Abspielprozess an und kehrt danach sofort zurueck, sodass dein Programm mit anderen Dingen weiterarbeiten kann, waehrend im Hintergrund die Datei abgespielt wird. (Denk daran, dass dein SDL-Programm ein Computerspiel sein koennte, bei dem Hintergrundmusik laufen soll, aber das Programm hauptsaechlich mit anderen Rechnungen beschaeftigt ist.) Deine Schleife laedt also schnell hintereinander alle Musikdateien und faengt an, sie abzuspielen. Das Abspielen der naechsten Datei beendet natuerlich das der vorherigen, sodass du am Ende der Schleife nur das letzte Stueck hoerst. Leider verfuegt die Music-Klasse ueber keine Events, aber da du sowieso auf das Ende der Musikdatei warten moechtest anstatt etwas nebenher zu machen, kannst du den Status des Players pollen: gambas code
Music.Load(PFA)
Music.Play()
Do
  Wait 1
Loop Until Music.State = Music.Stopped
Uebrigens leistet die Zeile "If Music.Stopped = 0 Then ..." in deinem Quelltext wahrscheinlich nicht, was du dir dachtest. Music.Stopped ist eine Konstante in der Music-Klasse [1], naemlich konstant 0. Ob die Musik gestoppt hat, erfaehrst du wie oben gezeigt, indem du die Eigenschaft Music.State mit den drei Konstanten Music.Playing, Music.Paused und Music.Stopped vergleichst.

Ich schaetze mal, dass gb.media eine bessere Schnittstelle bietet als gb.sdl2.audio, habe aber noch mit keiner von beiden selbst gearbeitet. Jedenfalls haben die Objekte in gb.media auch Ereignisse, mit denen du eleganter auf das Ende der Musikdatei warten kannst.

[1] http://gambaswiki.org/wiki/comp/gb.sdl2 ... ic/stopped
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

gambasso
Foriker
Beiträge: 849
Registriert: Sa 17. Mär 2012, 09:55
Kontaktdaten:

Re: Musikdateien richtig abspielen

Beitrag von gambasso » Di 2. Aug 2016, 17:52

moin,

ist der veröffentliche Text Original oder gibt es da noch irgenwelche Verzwickungen?
Beispiel: gambas code
If FIL Ends "wav" Or FIL Ends "mp3" Or FIL Ends "ogg" Then
was ist 'FIL Ends' ? wie setzt sich das zusammen? Oder ist es nur symbolisch zur Erklärung?
Gruss

basicwurm
Foriker
Beiträge: 37
Registriert: Di 8. Jan 2013, 16:59
Kontaktdaten:

Re: Musikdateien richtig abspielen

Beitrag von basicwurm » Mi 3. Aug 2016, 16:59

@tux
Hurra, es funktioniert alles! Vielen Dank für deine Tipps! Und das Programm ist jetzt viel kürzer.
Ich kann sogar, während es läuft, diese Antwort schreiben. Insgesamt scheint es mir ein gutes Beispiel, was man in gb mit ein paar Zeilen Code erreichen kann. Nebenbei: Die Tonqualität ist trotz meiner billigen Soundkarte ausgezeichnet.
gambas code
Public Sub PLAY_Click()

Dim FIL As String               ' File zum abspielen
Dim PFA As String              ' Kompletter Pfad
Dim ARR As String[]           ' Array für Dir-Inhalt

ARR = Dir(ORD).Sort(gb.Natural) ' Public ORD = Ordner vom DirChooser

For Each FIL In ARR
     
  If FIL Ends "wav" Or FIL Ends "mp3" Or FIL Ends "ogg" Then
    PFA = ORD &/ FIL                ' Pfad + Filename
    LB.Text = "Playing " & FIL  ' Label anzeigen
    Music.Load(PFA)
    Music.Play()
  Endif  
    Do
      Wait 1
    Loop Until Music.State = Music.Stopped
Next

End
@gambasso

Also das "Ends" ist ein ganz normaler Bestandteil der String-Funktionen. Lt. Gambas-Index "Returns TRUE if the String string ends with the Pattern string". Ich brauche es hier, weil in meinen Musik-Ordnern auch .png-files mit Plattencovers und .txt-files mit Liedtexten liegen.

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast