Audio Duration

Get help with using AutoHotkey and its commands and hotkeys
User avatar
PuzzledGreatly
Posts: 1048
Joined: 29 Sep 2013, 22:18

Audio Duration

27 Oct 2013, 19:30

I've been using the following function to get the duration of wav and audio files:

Code: Select all

GetAudioDuration( mFile ) { ; SKAN [url] www.autohotkey.com/forum/viewtopic.php?p=361791#361791[url]

 VarSetCapacity( DN,16 ), DLLFunc := "winmm.dll\mciSendString" ( A_IsUnicode ? "W" : "A" )
 DllCall( DLLFunc, Str,"open " """" mFile """" " Alias MP3", UInt,0, UInt,0, UInt,0 )
 DllCall( DLLFunc, Str,"status MP3 length", Str,DN, UInt,16, UInt,0 )
 DllCall( DLLFunc, Str,"close MP3", UInt,0, UInt,0, UInt,0 )
 
Return DN
}
However recently I discovered that for some mp3's it is returning shorter duration's than actual (eg the song Midnight Stroll is 2:34 but the function returns 2:11). Does anyone know a more reliable method to get the duration of media files? I want to be able to call an action after a file finishes playing but have it interruptible so I don't want to use wait with SoundPlay. Thanks.
gregster
Posts: 5837
Joined: 30 Sep 2013, 06:48

Re: Audio Duration

27 Oct 2013, 20:53

In the past, I always got good results with the AudioGenie3 DLL. ( http://sourceforge.net/projects/audiogenie/ ) You can do lots of other stuff with it, for example, read embedded covers from mp3s or modify tags.
Quick example for AHK Unicode:

Code: Select all

hAG3 := DllCall( "LoadLibrary", Str,"AudioGenie3.dll" )		
path := "GhostRiders.mp3"				; obvly put here the path to your soundfile 	
MsgBox % DllCall("AudioGenie3\AUDIOAnalyzeFileW", Str, Path)     ; don't leave out! analyzes sound file, returns 1 for mp3, 5 for wav, etc.    
MsgBox % "Artist: "DllCall("AudioGenie3\AUDIOGetArtistW", Str )						; returns artist
msgbox % "Duration: " DllCall("AudioGenie3\AUDIOGetDurationW", Float)   		; returns duration in seconds
DllCall("FreeLibrary", UInt, hAG3)
ExitApp
If you need the ANSI version, I can probably cough that up, too... :geek:

So how do you play the file then? Via WMPlayer.OCX and COM? Or MCI?
If you need some mighty stuff, you may also try the BASS Audio library http://www.un4seen.com/. There should be some examples on the old forum... otherwise I would have to cough out some more. But that might take some time to locate. I renewed my system today and my backups are a mess :D
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Audio Duration

27 Oct 2013, 21:58

I need the ANSI version. Could you please post that, too? :geek:
gregster wrote:In the past, I always got good results with the AudioGenie3 DLL. ( http://sourceforge.net/projects/audiogenie/ ) You can do lots of other stuff with it, for example, read embedded covers from mp3s or modify tags.
Quick example for AHK Unicode:

Code: Select all

hAG3 := DllCall( "LoadLibrary", Str,"AudioGenie3.dll" )		
path := "GhostRiders.mp3"				; obvly put here the path to your soundfile 	
MsgBox % DllCall("AudioGenie3\AUDIOAnalyzeFileW", Str, Path)     ; don't leave out! analyzes sound file, returns 1 for mp3, 5 for wav, etc.    
MsgBox % "Artist: "DllCall("AudioGenie3\AUDIOGetArtistW", Str )						; returns artist
msgbox % "Duration: " DllCall("AudioGenie3\AUDIOGetDurationW", Float)   		; returns duration in seconds
DllCall("FreeLibrary", UInt, hAG3)
ExitApp
If you need the ANSI version, I can probably cough that up, too... :geek:

So how do you play the file then? Via WMPlayer.OCX and COM? Or MCI?
If you need some mighty stuff, you may also try the BASS Audio library http://www.un4seen.com/. There should be some examples on the old forum... otherwise I would have to cough out some more. But that might take some time to locate. I renewed my system today and my backups are a mess :D
gregster
Posts: 5837
Joined: 30 Sep 2013, 06:48

Re: Audio Duration

27 Oct 2013, 22:31

Here you go:

Code: Select all

loadAG3 := DllCall( "LoadLibrary", Str,"AudioGenie3.dll" )							  ; dll should be in the script directory
path := "GhostRiders.mp3"			; obvly put here the path to your soundfile     	
ATOU(PathUni, path)                            ; Path from Ansi to Unicode
MsgBox % DllCall("AudioGenie3\AUDIOAnalyzeFileW", Str, PathUni)     	; don't leave out! reads and analyzes sound file, returns 1 for mp3 , 5 for wav, etc  
MsgBox % "Artist: " UTOA( DllCall("AudioGenie3\AUDIOGetArtistW")  )   			; returns artist (Unicode to Ansi)
msgbox % "Duration: " DllCall("AudioGenie3\AUDIOGetDurationW", Float)   	; returns duration in seconds
DllCall("FreeLibrary", UInt, loadAG3)
ExitApp

; Useful functions by SKAN
ATOU( ByRef Unicode, Ansi )       ; Ansi to Unicode
{     
    VarSetCapacity( Unicode, (Len:=StrLen(Ansi))*2+1, 0 )
    Return DllCall( "MultiByteToWideChar", Int,0,Int,0,Str,Ansi,Int,Len, Str,Unicode, Int,Len )
}

UTOA( pUnicode )                     ; Unicode to Ansi
{                        
  VarSetCapacity( Ansi,(nSz:=DllCall( "lstrlenW", UInt,pUnicode )+1) )
  DllCall( "WideCharToMultiByte", Int,0, Int,0, UInt,pUnicode, Int,nSz
                                , Str,Ansi, Int,nSz+1, Int,0, Int,0 )
  Return Ansi
}
It's a bit longer, but since AudioGenie3 uses Unicode anyway, you have to use the two functions ATOU() and UTOA() as a workaround (made by SKAN, I think) for ANSI, if the DllCalls are using strings (like paths or names). The 'Duration'-DllCall uses floating numbers, that's why it can stay unchanged (related stuff: http://l.autohotkey.net/docs/commands/DllCall.htm#types and http://l.autohotkey.net/docs/Compat.htm#DllCall).
Somewhere, a wrapper for the most used functions might still float around, but I think the links in the old forum are dead. But if you want to use other functions of AG3, you can look up the data types in the Audiogenie documentation (http://sourceforge.net/projects/audioge ... 0.4.0/doc/) and use them similarly.

Disclaimer: Note that I have no clue what I am doing, when DllCalls are concerned... but that should work...
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Audio Duration

27 Oct 2013, 22:49

thanks, that was fast! i already tested the Unicode version and it works great. :ugeek:
gregster
Posts: 5837
Joined: 30 Sep 2013, 06:48

Re: Audio Duration

27 Oct 2013, 23:30

You are welcome, but without SKAN's functions I would have been lost with ANSI.

Btw, there is even another 'Duration' function, which gives the duration of a song in milliseconds:

Code: Select all

msgbox % "Duration: " DllCall("AudioGenie3\AUDIOGetDurationMillisW", Int)
For my applications, either one would be sufficient. But this library is huge...
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Audio Duration

27 Oct 2013, 23:40

what do you think of a similar function (below) i have been using: :ugeek:

Code: Select all

{
o:=comobjcreate("Shell.Application")
;fileselectfile,file,c:\
;file := Clipboard
;msgbox %file%
splitpath,file,file,directory
if errorlevel
	exitapp
od:=o.namespace(directory)
of:=od.parsename(file)
loop,50 ; 50 is an arbitrary number > 21
	if(od.getdetailsof("",a_index)=="Duration"){
		length:=od.getdetailsof(of,a_index)
		break
	}
stringsplit,length,length,:
MP3Len := 3600000*length1+60000*length2+1000*length3
;msgbox,% "Duration of " file " in millisceonds is " 3600000*length1+60000*length2+1000*length3 "."
}
User avatar
PuzzledGreatly
Posts: 1048
Joined: 29 Sep 2013, 22:18

Re: Audio Duration

28 Oct 2013, 00:11

Thanks for the link. I downloaded AudioGeni3.dll and put it in my script directory. I tried the sample code but got three blank message boxes. I'm using Windows 7, 64 bit. What can I do to make it work? Cheers.
User avatar
PuzzledGreatly
Posts: 1048
Joined: 29 Sep 2013, 22:18

Re: Audio Duration

28 Oct 2013, 00:22

Thanks, I tried the o:=comobjcreate("Shell.Application") script. On Windows 7 I needed to change the word "Duration" to "Length" but it did give me a result. I wonder how reliable this method is? I still need to test it with a file that my original method (Skan's function) mistimed.
gregster
Posts: 5837
Joined: 30 Sep 2013, 06:48

Re: Audio Duration

28 Oct 2013, 00:39

@PuzzledGreatly: Hmm, not sure. I tested it succesfully on Win32 Vista, with newest AHK, both ANSI and Unicode.
I have really no clue about 64 bit and its implications. Perhaps some of our veterans can help with this question.

But are you sure that the path to your sound file is right? Perhaps put it for testing in the script dir, too...

And what happens when you look at msgbox % loadAG3 , directly after you loaded the dll with loadAG3 :=DllCall( "LoadLibrary", Str,"AudioGenie3.dll" ) ? Is it 0? Then there is a problem with loading the dll. If it's a handle like 1659633664 or something, the problem is probably later in the code.

Edit:
You might also want to try this variant of the COM method by Trubbleguy: http://www.autohotkey.com/board/topic/9 ... layerocx7/ But don't overwrite your tags...
Last edited by gregster on 28 Oct 2013, 00:48, edited 3 times in total.
gregster
Posts: 5837
Joined: 30 Sep 2013, 06:48

Re: Audio Duration

28 Oct 2013, 00:43

@Guest10:
I am always interested in dealing with audio files, because I have a lot of them ;) I think, I have tried something similar already. In fact, I remember now that I already suggested something like this, some time ago, in the "old" german subforum ( http://www.autohotkey.com/board/topic/9 ... /?p=597935 ) after I had seen it in posts from Trubbleguy and Seidenweber. It wasn't about duration, though, but other tags.

If you only need to read some properties or tags, it's seems to be a very good way. You don't need an extra dll. Did you test it with mp3s that have variable bitrates? That seems to be one of the problems sometimes.

Recently I have seen another script from Trubbleguy using COM, but with WMPlayer.OCX.7 instead ( http://www.autohotkey.com/board/topic/9 ... layerocx7/ ). I tried only reading tags with it. It seemed to work, too. I didn't test writing tags with it, yet.

AudioGenie3, I mostly used to extract the embedded cover art of mp3s, which is quite easy with it. It also supports writing tags of a lot of formats.
I guess the best choice depends on your application case.
User avatar
PuzzledGreatly
Posts: 1048
Joined: 29 Sep 2013, 22:18

Re: Audio Duration

28 Oct 2013, 05:45

Thanks gregster, loadAG3 returns 0 with everything in the same directory. Perhaps the dll doesn't work with 64 bit. Will check out the other link you gave.
gregster
Posts: 5837
Joined: 30 Sep 2013, 06:48

Re: Audio Duration

28 Oct 2013, 07:53

Yeah, I think the dll that is not properly supported by 32 bit, even if it's called "32-64bit" here: http://sourceforge.net/projects/audioge ... /V2.0.4.0/. Then errorlevel is probably -3, too, in your script (http://ahkscript.org/docs/commands/DllCall.htm). But I found some complaints in the internet that there were problems with using that version on 64bit in general, not only with AHK. You might still try to use that dll with the 32bit AHK-exe ( like here: http://www.autohotkey.com/board/topic/7 ... /?p=452133 ), Ansi or Unicode (see above for the use of the two variants). But that's only a rough workaround.

There seems to be a 64bit_only version, though. (See here: http://sourceforge.net/projects/audioge ... 4bit_only/ It's also bigger: 641kb. When you use the download button on the front page, you seem to get only the 32bit version, which is roughly a 100kb smaller.
Since I have no 64bit system, I can't try it. But you might...
User avatar
PuzzledGreatly
Posts: 1048
Joined: 29 Sep 2013, 22:18

Re: Audio Duration

28 Oct 2013, 09:16

Thanks for the suggestion. I used the 64 bit version you linked to and it worked.
RijulAhuja
Posts: 44
Joined: 30 Sep 2013, 07:29

Re: Audio Duration

29 Oct 2013, 12:03

I have personally used the COM method, and it works great. It can retrieve other tags as well, but is not able to change them, I believe.
But the AudioGenie method is better, I migrated to it later, although I don't remember requiring a different DLL for 64 bit. :?:
Verdlin
Posts: 63
Joined: 04 Oct 2013, 08:55
GitHub: Aatoz

Re: Audio Duration

29 Oct 2013, 16:27

Windows also stores audio durations in file Metadata. If that information is reliable, then this would likely be faster, and more convenient, than using any external library out there. Not sure how to retrieve the Metadata, or else I would post an example. Likely requires some sleuthing through MSDN and then DllCalls
gregster
Posts: 5837
Joined: 30 Sep 2013, 06:48

Re: Audio Duration

29 Oct 2013, 16:49

@ Verdlin:
In my understanding, this metadata is used by the two COM methods mentioned above. On the other hand, the DllCalls by Skan, also posted above, seemed to be not reliable (obv. that was the reason for the original post). Of course there might be other possibilities left...
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Audio Duration

29 Oct 2013, 18:49

does COM method use native file Metadata? :ugeek:
gregster
Posts: 5837
Joined: 30 Sep 2013, 06:48

Re: Audio Duration

29 Oct 2013, 19:15

Guest10 wrote:does COM method use native file Metadata? :ugeek:
I might be wrong, but I think, that soundfile metadata often consists of the available tags of an audio file that are queried by windows. On the other hand, file size, creation date and other common file properties probably come directly from windows functions via the Shell32.dll. At least, if you use 'GetDetailsOf' and the Shell-Com-Object.

The other COM method from Trubbleguy uses the WMP infrastructure which probably itself makes use of the shell and the tags. But I haven't investigated that thouroughly, so far.

Or do you mean something else by 'native file metadata'?
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Audio Duration

29 Oct 2013, 19:54

thanks, by 'native file metadata' i meant 'file metadata' -- 'native' was superfluous. :ugeek:
gregster wrote:
Guest10 wrote:does COM method use native file Metadata? :ugeek:
I might be wrong, but I think, that soundfile metadata often consists of the available tags of an audio file that are queried by windows. On the other hand, file size, creation date and other common file properties probably come directly from windows functions via the Shell32.dll. At least, if you use 'GetDetailsOf' and the Shell-Com-Object.

The other COM method from Trubbleguy uses the WMP infrastructure which probably itself makes use of the shell and the tags. But I haven't investigated that thouroughly, so far.

Or do you mean something else by 'native file metadata'?

Return to “Ask For Help”

Who is online

Users browsing this forum: Arsonistic, dmatch, Google [Bot], joedf, mikeyww, Out2lunch, paul1965, Spawnova and 63 guests