Page 1 of 2

Recover duration mp3 file

Posted: Thu Mar 09, 2023 1:41 pm
by jak64
Hello all,
I am writing a program in Purebasic which displays, in a ListIconGadget, the list of mp3 files that I have in my folders.
I want to display the duration of each song to the right of the title.
Looking on the forum, I found codes but, in these codes, we open each file to find the duration.
With several hundred mp3 files, the execution time is very, very long.
Isn't there another way to recover the duration of the mp3 without having to open the file?

For example, in the Windows explorer, by right-clicking on the file, then properties, then detail tab, the duration of the mp3 is displayed, without having to open the file.

How to recover this duration without opening the file?

Thank you.

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 2:18 pm
by RASHAD
You can use MCI it still working even with Windows 11
Removed :)

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 2:27 pm
by NicTheQuick
How do you want to extract the audio length of a MP3 without opening the file? There is no way around. Even the file explorer opens them up and extracts the length from each file individually.

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 2:30 pm
by NicTheQuick
RASHAD wrote: Thu Mar 09, 2023 2:18 pm You can use MCI it still working even with Windows 11

Code: Select all

Filename$ = OpenFileRequester("","","ALL|*.*;*.mid|Wave|*.wav|mp3|*.mp3|OGG|*.OGG|MID|*.MID",0)
If Filename$
  mciSendString_("OPEN "+Chr(34)+Filename$+Chr(34)+" Type MPEGVideo ALIAS "+Str(0),0,0,0)
  Length$ = Space(#MAX_PATH)
  mciSendString_("Status 0 length",@Length$,#MAX_PATH,0)
  Duration.q = ValD(length$)
  ;Debug Duration
  ;ms = Duration % 1000
  S = Int(Duration / 1000) : While S > 59:S-60:Wend 
  M = Int(Duration / 1000 / 60) : While M > 59:M-60:Wend 
  H = Int(Duration / 1000 / 60 / 60) : While H > 59:H-60:Wend
  Duration$ =RSet(StrU(H,#PB_Quad),2,"0")+":"+RSet(StrU(M,#PB_Quad),2,"0")+":"+RSet(StrU(S,#PB_Quad),2,"0");+":"+RSet(StrU(ms,#PB_Quad),3,"0")
  Debug Duration$
  mciSendString_("close all ",0,0,0)  
 EndIf
Please remove these ridiculous While loops and replace them with a proper mod operator. Also are you sure you get the length as a float value? Isn't it just an integer? I don't think ValD() is the correct function to use in that context. But I also can not test it because I do not own Windows.

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 2:57 pm
by Marc56us
Opening the file does not necessarily mean loading the entire file.
To read the information (TAGs i.e. duration), we just read the beginning (some bytes).
When you know the MP3 file structure of the header, it is very fast.
Then with PB we mainly use Open, FileSeek(), Read..., Close.
That's all.
:wink:

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 3:09 pm
by Allen
Hi,

I try the code on my MP3 and seems the time is not accurate , code show 5:10, actual is 4:21. (Win 10 x64)

By the way, to convert duration (s) to time format, I suggest

Code: Select all

Debug FormatDate("%hh:%ii:%ss",261)
Thanks

Allen

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 3:41 pm
by NicTheQuick
I remember from the past that many implementations had problems with variable bitrate and then displayed wrong times.

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 3:45 pm
by RASHAD
Professor NicTheQuick
How about remove the post and wait for your correct answer for jack64 ,If you can :wink:

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 3:57 pm
by jak64
Hello RASHAD
I tested this code but it is very very long if there are several hundred mp3s

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 4:16 pm
by RASHAD
Hi jack64
Don't format the duration ms and don't use Debug of course
- Save the Duration times
- Format the Duration later by clicking any item
This is the best I can get
Please report if any improvement achieved

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 4:36 pm
by falsam
Tested with PB 6.0 - Another solution with FMODEX.
Download the include and the 32 and 64 bits dll hosted on the GitHub collaborative platform.

:arrow: GitHub https://github.com/pbcodex/FMODEX-MIN-UNICODE

:arrow: LienDirect https://github.com/pbcodex/FMODEX-MIN-U ... master.zip

The code allows to read the duration of an mp3, ogg or flac file.
It returns the time in milliseconds which will be converted to the format wk day hr min sec with the procedure MsToTime(NbMs) included in this code. (translation DeepL.com)

Code: Select all

EnableExplicit

IncludeFile "fmodex-min.pbi"

Global File.s, FmodSystem.i, Channel.i, Sound.i, lenght.i

Declare.s MsToTime(NbMs)

;Declare FMOD System
FMOD_System_Create(@fmodsystem)

;Init FMOD System
FMOD_System_Init(FmodSystem, 32, #FMOD_INIT_NORMAL, 0)

; Sélectionner un son
File = OpenFileRequester("Selectionner un fichier mp3","","Musique|*.mp3;*.wav;*.ogg;*.flac",0)
If File <> ""
  
  ; Création du stream de lecture 
  FMOD_System_CreateStream(FmodSystem, Ascii(File), #FMOD_SOFTWARE, 0, @sound)
  
  ; Lecture de la lecture du son. Retourne la durée en milliseconde
  FMOD_Sound_GetLength(sound, @lenght, #FMOD_TIMEUNIT_MS)
  
  Debug MsToTime(lenght)
EndIf

Procedure.s MsToTime(NbMs)
  Protected weeks, days, hours, minutes, seconds
  Protected divisor, remainder
  Protected duration$ = ""
  Protected NbSeconds = NbMs/1000
  
  divisor = 7 * 24 * 60 * 60 ; seconds in a week
  weeks = NbSeconds / divisor
  remainder = NbSeconds % divisor
  divisor / 7 ; seconds in a day
  days = remainder / divisor
  remainder % divisor
  divisor / 24 ; seconds in an hour
  hours = remainder / divisor
  remainder % divisor
  divisor / 60 ; seconds in a minute
  minutes = remainder / divisor
  seconds = remainder % divisor
  
  If weeks > 0
    duration$ + Str(weeks) + " wk, "
  EndIf
  
  If days > 0
    duration$ + Str(days) + " d, "
  EndIf
  
  If hours > 0
    duration$ + Str(hours) + " hr, "
  EndIf
  
  If minutes > 0
    duration$ + Str(minutes) + " min, "
  EndIf
  
  If seconds > 0
    duration$ + Str(seconds) + " sec"
  EndIf
  
  If Right(duration$, 2) = ", "
    duration$ = Mid(duration$, 0, Len(duration$) - 2)
  EndIf
  
  ProcedureReturn duration$
EndProcedure

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 4:36 pm
by jak64
Hello RASHAD
I tested the code as you said but it takes 2 minutes and 30 seconds for 5000 mp3 files!

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 5:09 pm
by RASHAD
Hi jack64
Can you post a simple snippet to show how you repeat opening mp3 files
Maybe we can help to decrease the time significantly

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 5:16 pm
by jak64
Hello RASHAD

I use a procedure that I found on the forum and that I adapted to my program.
I put it below
As I am French, the comments are in French

Code: Select all

Procedure ScanDirectory(source.s,  rek = 0) ; Source, indice
  Protected s_name.s
  Protected s_type.w
  Protected s_fullname.s
  Protected Debut.w
  Protected Fin.w
  
  If Right(source, 1) <> "\"
    source + "\"   ; Ajoute les "\" 
  EndIf

  If ExamineDirectory(rek, source, "*")
    While NextDirectoryEntry(rek) 
      s_name = DirectoryEntryName(rek) ; Nom du répertoire ou du fichier
      s_type = DirectoryEntryType(rek) ; Type (Répertoire ou fichier)
      Select s_type          
        Case #PB_DirectoryEntry_File 
          s_fullname.s = source + s_name
          If Right(UCase(s_fullname),4)=".MP3"
            ; Ajouter cette entrée dans la liste des musiques
            AddElement(ListeMesMusiques())
            With ListeMesMusiques()
              \CheminEtTitreComplet = s_fullname
              \CheminEtTitreCompletEpure = EpurerCaracteres(s_fullname)
              \TitreComplet = s_name
              ; Rechercher le genre de musique
              If FindString(source,"\chansons\",1,#PB_String_NoCase) > 0
                \Genre="Chanson"
              ElseIf FindString(source,"\instrumental\",1,#PB_String_NoCase) > 0
                Debut = FindString(source,"\instrumental\",1,#PB_String_NoCase)
                Debut = Debut + 14
                Fin = FindString(source,"\",Debut+1,#PB_String_NoCase)
                If Fin >0
                  \Genre=Mid (source,Debut,(Fin - Debut))
                Else
                  \Genre = "Inconnu"
                EndIf 
              ElseIf FindString(source,"\musique classique\",1,#PB_String_NoCase) > 0
                \Genre = "Musique classique"
              Else
                \Genre= "Inconnu"
              EndIf
              ChercherDureeMp3(\CheminEtTitreComplet)
              ;\Duree=""
            EndWith
          EndIf 
        Case #PB_DirectoryEntry_Directory 
          If s_name <> "." And s_name <> ".." 
            ScanDirectory(source + s_name, rek + 1) 
          EndIf      
      EndSelect 
    Wend 
    FinishDirectory(rek) ; Libère la mémoire
  EndIf
EndProcedure

Re: Recover duration mp3 file

Posted: Thu Mar 09, 2023 5:20 pm
by RASHAD
OK mate :)
Give the forum members some time I am sure you will get better solutions