[bb] OGG Info by _PJ_ [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:41

Previous topic - Next topic

BlitzBot

Title : OGG Info
Author : _PJ_
Posted : 1+ years ago

Description : This still needs a lot of work, for example, only a few metatags are currently catered for.
The code itself is scrappy in places (some hideous workarounds for preventing endless loops etc.)

However, it's functional and can be useful in its current state.
Sorry for the unusual format of the code itself, it's taken from part of a larger project (details here: <a href="../logs/createlogpost1b8c.html?user=2370&log=1719" target="_blank">http://www.blitzbasic.com/logs/createlogpost.php?user=2370&log=1719</a>  ) which has a greater scope. Therefore the code here, whilst complete andoperational in its own right, was still based on using and ebing used by external functions to maximise the usefulness.


Code :
Code (blitzbasic) Select
;Const OGG_HEX_CHECK$="OggS"
Const OGG_SIZE_MIN%=512
Const OGG_MAX_TAGS%=5

Global OGG_TAG_LABEL$[OGG_MAX_TAGS]
OGG_TAG_LABEL[0]="ARTIST="
OGG_TAG_LABEL[1]="ALBUM="
OGG_TAG_LABEL[2]="GENRE="
OGG_TAG_LABEL[3]="TITLE="
OGG_TAG_LABEL[4]="ALBUM ARTIST="

Const OGG_INF_UNKNOWN% = 0
Const OGG_INF_TITLE%   = 1
Const OGG_INF_ARTIST% = 3
Const OGG_INF_ALBUM% = 4
Const OGG_INF_ALBUM_ARTIST% = 5
Const OGG_INF_GENRE% = 6
;Const MP3_INF_TRACK% = 7
;Const MP3_INF_YEAR% = 8
;Const OGG_INF_DURATION% = 9

Type OGG_Info
Field OGG_Filepath$
Field OGG_FileSize%
Field OGG_Container_Version%
Field Ogg_PageCount%
Field OGG_Album$
Field OGG_Artist$
Field OGG_Album_Artist$
Field OGG_Genre$
Field OGG_Title$
; Field OGG_DurationMilliseconds%
End Type

Type OGG_PageInfo
Field OGG_Parent.OGG_Info
Field OGG_Header%
Field OGG_Header_Type
Field OGG_Granule1%
Field OGG_Granule2%
Field OGG_Bitstream%
Field OGG_Page%
Field OGG_Checksum%
Field OGG_Start%
Field Ogg_Length%
End Type

Function GetOGGSpecificInfo$(OGG_FileName$,OGGInfoType%,AutoClean%=True)
; Autoclean flag frees up stored MP3 memory automatically

Local sReturn$=GetOGGData$(OGG_FileName$,OGGInfoType%)
If(AutoClean)
ClearAllOggData
End If
Return sReturn$
End Function

Function CheckOGGDataExists%()
Local OGG_DataType.OGG_Info=First OGG_Info
Return (OGG_DataType.OGG_Info<>Null)
End Function

Function GetOGGData$(OGG_FileName$,OGG_Info_Type%)

;Ensure Matching OGG Data Has Been Read

If (Not(CheckOGGDataExists()))
ClearAllOggData
ReadOggData(OGG_FileName$)
End If
If (Not(CheckOGGDataExists()))
ClearAllOggData
Return ""
End If
Local OGG_DataType.OGG_Info=First OGG_Info
If (OGG_DataTypeOGG_Filepath<<OGG_FileName$)
ClearAllOggData
ReadOggData(OGG_FileName$)
End If
If (Not(CheckOGGDataExists()))
ClearAllOggData
Return ""
End If

OGG_DataType.OGG_Info=First OGG_Info

Select (OGG_Info_Type%)
Case OGG_INF_ALBUM%:Return OGG_DataTypeOGG_Album$
Case OGG_INF_ARTIST%:Return OGG_DataTypeOGG_Artist$
Case OGG_INF_ALBUM_ARTIST%:Return OGG_DataTypeOGG_Album_Artist$
;Case OGG_INF_DURATION%:Return Str(OGG_DataTypeOGG_DurationMilliseconds)
Case OGG_INF_GENRE%:Return OGG_DataTypeOGG_Genre$
Case OGG_INF_TITLE%:Return OGG_DataTypeOGG_Title$
; Case OGG_INF_TRACK%:Return Str(OGG_DataTypeOGG_Track_No%)
; Case OGG_INF_YEAR%:Return OGG_DataTypeOGG_ReleaseYear$

End Select

Return ""
End Function

Function AddOGGTag(nTagReference%,sTagData$)

If (nTagReference>=OGG_MAX_TAGS%)
DebugLog("OGG tag reference ("+Str(nTagReference%)+") out of bounds")
Return
End If

Local OggInfo.OGG_Info=First OGG_Info
If (OggInfo.OGG_Info=Null)
Return
End If

OggInfo.OGG_Info=First OGG_Info

If (sTagData$="")
"OGG Tag data string is null"
End If

Select (nTagReference%)
Case 0: OggInfoOGG_Artist$=sTagData$
Case 1: OggInfoOGG_Album$=sTagData$
Case 2: OggInfoOGG_Genre$=sTagData$
Case 3: OggInfoOGG_Title$=sTagData$
Case 4: OggInfoOGG_Album_Artist$=sTagData$
Default:
DebugLog("OGG tag reference ("+Str(nTagReference%)+") out of bounds")
Return
End Select

DebugLog(OGG_TAG_LABEL[nTagReference]+sTagData+" added")
End Function

Function CheckOggTag(nTagReference%,OGGFileStream%)
Local OggInfo.OGG_Info=First OGG_Info
If (OggInfo.OGG_Info=Null)
Return
End If

If (Not(OGGFileStream))
Return False
End If

Local sData$
Local sByte$=" "
Local nIterBytes%
SeekFile(OGGFileStream,False)
For nIterBytes%=0 To OGG_SIZE_MIN
sData$=sData$+Chr(ReadByte(OGGFileStream))
If (Instr(sData$,OGG_TAG_LABEL[nTagReference%]))
sData$=""
While (sByte$<<Chr(False) And (Not(Eof(OGGFileStream))))
sByte$=Chr(ReadByte(OGGFileStream))
sData$=sData+sByte$
Wend
AddOGGTag(nTagReference%,Trim(sData$))
Exit
End If
Next
End Function

Function ReadOGGTags(OGG_Filestream%)
If (Not(OGG_Filestream%))
Return False
End If
Local nCheck%
For nCheck%=0 To (OGG_MAX_TAGS-1)
CheckOggTag(nCheck%,OGG_Filestream%)
Next
End Function

Function ClearAllOggData()
Delete Each OGG_Info
Delete Each OGG_PageInfo
End Function

Function ReadOggData%(OGG_Filename$)
Local OggInfo.OGG_Info=First OGG_Info

;Ensure valid ogg info
If (OggInfo.OGG_Info=Null)
ClearAllOggData
OggInfo.OGG_Info=New OGG_Info
End If
If (OggInfoOGG_Filepath$<>OGG_Filename$)
ClearAllOggData
OggInfo.OGG_Info=New OGG_Info
End If

Local OGG_FileHandle=ReadFile(OGG_Filename$)

If (Not(OGG_FileHandle))
ClearAllOggData
Return False
End If

OggInfoOGG_Filepath$=OGG_Filename$
OggInfoOGG_FileSize%=FileSize(OGG_Filename$)
ReadOGGTags(OGG_FileHandle)
SeekFile(OGG_FileHandle,False)
Local sHexCheck$=""
Local nIterByteInt%,bResult%
Local bValid%=False
OggInfoOgg_PageCount%=False
While (bValid=Eof(OGG_FileHandle))
sHexCheck=""
For nIterByteInt%=0 To 3
sHexCheck$=sHexCheck$+Chr(ReadByte(OGG_FileHandle))
Next
If (sHexCheck$=OGG_HEX_CHECK$)
OggInfoOgg_PageCount%=OggInfoOgg_PageCount+1
DebugLog FilePos(OGG_FileHandle)
bResult%=ReadOGGPageData%(OGG_FileHandle,FilePos(OGG_FileHandle))
If (bResult%) Then SeekFile(OGG_FileHandle,bResult)
End If
If ((FilePos(OGG_FileHandle)<((OggInfoOGG_FileSize%)-4)))  Then SeekFile(OGG_FileHandle,FilePos(OGG_FileHandle)-(4-1))
Wend
Return True
End Function

Function ReadOGGPageData%(OGGFile%,nPos)
If (Not(OGGFile))
Return False
End If
Local OGGInfo.OGG_Info=First OGG_Info
If (OGGInfo.OGG_Info=Null)
ClearAllOggData
Return False
End If
Local OGG.OGG_PageInfo=New OGG_PageInfo
OGGInfoOGG_Container_Version%=ReadByte(OGGFile)*ReadByte(OGGFile)
OGGOGG_Parent.OGG_Info=OGGInfo
OGGOGG_Header%=ReadByte(OGGFile)*ReadByte(OGGFile)
OGGOGG_Granule1%=ReadInt(OGGFile)
OGGOGG_Granule2%=ReadInt(OGGFile)
OGGOGG_Bitstream%=ReadInt(OGGFile)
OGGOGG_Page%=ReadInt(OGGFile)
OGGOGG_Checksum%=ReadInt(OGGFile)
Local Segments%=ReadByte(OGGFile)*ReadByte(OGGFile)
Local NullByte%=False
While (Not(NullByte%))
NullByte%=ReadByte(OGGFile)
Wend
OGGOGG_Start%=FilePos(OGGFile)

Local sHexCheck$=""
Local nIterbyteInt%
Local bValid=False
While (bValid=Eof(OGGFile))
If ((FilePos(OGGFile)>((OGGOGG_ParentOGG_FileSize%)-4))) Then Exit
sHexCheck$=""
While(Chr(ReadByte(OGGFile)))<>(Left(OGG_HEX_CHECK,1)) And (Not(Eof(OGGFile)))
Wend
If (Not(Eof(OGGFile)))
sHexCheck$=Left(OGG_HEX_CHECK,1)
For nIterbyteInt%=0 To 2
sHexCheck$=sHexCheck$+Chr(ReadByte(OGGFile))
Next
If (sHexCheck$=OGG_HEX_CHECK$) Then Exit
SeekFile(OGGFile,FilePos(OGGFile)-(4-1))
EndIf
Wend
If ((FilePos(OGGFile)<((OGGOGG_ParentOGG_FileSize%)-4)))  Then SeekFile(OGGFile,FilePos(OGGFile)-4)
OGGOgg_Length%=((FilePos(OGGFile))-OGGOGG_Start)
Return OGGOgg_Length%+OGGOGG_Start
End Function

Function CheckIsValidOGG%(OGG_Filename$)
Return ((FileType(OGG_Filename$))And (Lower(Right(OGG_Filename$,4))=".ogg") And (FileSize(OGG_Filename$)>OGG_SIZE_MIN))
End Function


Comments :


_PJ_(Posted 1+ years ago)

 To add:For usage, call
GetOGGSpecificInfo$(OGG_FileName$,OGGInfoType%,AutoClean%=True)
OGG_Filename$ should be the full path to a valid OGG format fileOGGInfoType is an integer representing one of the following types of information:1   :   Title3   :   Artist4   :   Album5   :   Album Artist6   :   GenreFor more detailed information, you will need to check the fields of the First Instance of "OGG_Info" Type.Each 'OGGPage' is stored in OGG_PageInfo  type instances. [/i]