Re: Calculate audio length from OGG file
Posted: Wed Jun 27, 2012 1:28 am
Well I hacked together an ugly procedure to calculate Ogg Vorbis length. It finds the sample rate (from the beginning of the file) and the number of samples (from the end) so the length in (milli)seconds can be calculated.
In case anybody else ever needs this, I'll post it here. It's NOT guaranteed to work with every Vorbis file!!!
I only used the bare minimum of the Vorbis specification that I needed... basically the 'OggS' and 'vorbis' headers.
2019-08-13 - Updated the code slightly to work with PB 5.70 / Unicode mode
In case anybody else ever needs this, I'll post it here. It's NOT guaranteed to work with every Vorbis file!!!
I only used the bare minimum of the Vorbis specification that I needed... basically the 'OggS' and 'vorbis' headers.
2019-08-13 - Updated the code slightly to work with PB 5.70 / Unicode mode
Code: Select all
; Cross-platform procedure for determining length (in milliseconds)
; of an Ogg Vorbis audio file. It can easily be adapted to return
; seconds, or samples, or sample rate, etc.
; Absolutely NOT GUARANTEED to work with every .ogg file,
; but it seems to work with all the ones I'm using...
; 2019-08-13 : Updated to PureBasic 5.70 (Unicode fixed)
Procedure.i GetOggLength(File.s)
Protected BufferSize.i = 8192
Protected FN.i, *Buffer, FilePos.i, *P.LONG
Protected Result.i, Samples.q
Protected SampleRate.d
If (File)
FN = ReadFile(#PB_Any, File)
If (FN)
*Buffer = AllocateMemory(BufferSize)
If (*Buffer)
; Find sample rate (search forward from start)
FilePos = 0
Repeat
FileSeek(FN, FilePos)
If (ReadData(FN, *Buffer, BufferSize))
*P = *Buffer + 1
While (*P < *Buffer + BufferSize - 15)
If (*P\l = $62726F76) ; 'brov'
If ((PeekU(*P + 4) = $7369) And (PeekA(*P - 1) = 1)) ; 'si'
SampleRate = PeekL(*P + 11)
Break 2
EndIf
EndIf
*P + 1
Wend
Else
Break
EndIf
FilePos + BufferSize/2
Until (FilePos >= Lof(FN))
If (SampleRate > 0)
; Find number of samples (search backwards from end)
FilePos = Lof(FN) - BufferSize
If (FilePos < 0)
FilePos = 0
EndIf
Repeat
FileSeek(FN, FilePos)
If (ReadData(FN, *Buffer, BufferSize))
*P = *Buffer + BufferSize - 4
While (*P >= *Buffer)
If (*P\l = $5367674F) ; 'SggO'
Samples = PeekQ(*P + 6)
If (Samples > 0)
; Calculate audio length (milliseconds)
Result = Int(1000.0 * Samples / SampleRate)
Break 2
EndIf
EndIf
*P - 1
Wend
Else
Break
EndIf
If (FilePos > 0)
FilePos - BufferSize/2
Else
FilePos = -1
EndIf
Until (FilePos < 0)
EndIf
FreeMemory(*Buffer)
EndIf
CloseFile(FN)
EndIf
EndIf
ProcedureReturn (Result)
EndProcedure
; Test:
File.s = OpenFileRequester("OGG", "", "Ogg Vorbis|*.ogg", 0, #PB_Requester_MultiSelection)
While (File)
Length.i = GetOggLength(File)/1000
Debug Str(Length/60) + ":" + RSet(Str(Length % 60), 2, "0") + " " + GetFilePart(File)
File = NextSelectedFileName()
Wend