Code archives/Audio/OGG Info
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| 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: http://www.blitzbasic.com/logs/createlogpost.php?user=2370&log=1719 ) 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. | |||||
;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_DataType\OGG_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_DataType\OGG_Album$
Case OGG_INF_ARTIST%:Return OGG_DataType\OGG_Artist$
Case OGG_INF_ALBUM_ARTIST%:Return OGG_DataType\OGG_Album_Artist$
;Case OGG_INF_DURATION%:Return Str(OGG_DataType\OGG_DurationMilliseconds)
Case OGG_INF_GENRE%:Return OGG_DataType\OGG_Genre$
Case OGG_INF_TITLE%:Return OGG_DataType\OGG_Title$
; Case OGG_INF_TRACK%:Return Str(OGG_DataType\OGG_Track_No%)
; Case OGG_INF_YEAR%:Return OGG_DataType\OGG_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: OggInfo\OGG_Artist$=sTagData$
Case 1: OggInfo\OGG_Album$=sTagData$
Case 2: OggInfo\OGG_Genre$=sTagData$
Case 3: OggInfo\OGG_Title$=sTagData$
Case 4: OggInfo\OGG_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 (OggInfo\OGG_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
OggInfo\OGG_Filepath$=OGG_Filename$
OggInfo\OGG_FileSize%=FileSize(OGG_Filename$)
ReadOGGTags(OGG_FileHandle)
SeekFile(OGG_FileHandle,False)
Local sHexCheck$=""
Local nIterByteInt%,bResult%
Local bValid%=False
OggInfo\Ogg_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$)
OggInfo\Ogg_PageCount%=OggInfo\Ogg_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)<((OggInfo\OGG_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
OGGInfo\OGG_Container_Version%=ReadByte(OGGFile)*ReadByte(OGGFile)
OGG\OGG_Parent.OGG_Info=OGGInfo
OGG\OGG_Header%=ReadByte(OGGFile)*ReadByte(OGGFile)
OGG\OGG_Granule1%=ReadInt(OGGFile)
OGG\OGG_Granule2%=ReadInt(OGGFile)
OGG\OGG_Bitstream%=ReadInt(OGGFile)
OGG\OGG_Page%=ReadInt(OGGFile)
OGG\OGG_Checksum%=ReadInt(OGGFile)
Local Segments%=ReadByte(OGGFile)*ReadByte(OGGFile)
Local NullByte%=False
While (Not(NullByte%))
NullByte%=ReadByte(OGGFile)
Wend
OGG\OGG_Start%=FilePos(OGGFile)
Local sHexCheck$=""
Local nIterbyteInt%
Local bValid=False
While (bValid=Eof(OGGFile))
If ((FilePos(OGGFile)>((OGG\OGG_Parent\OGG_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)<((OGG\OGG_Parent\OGG_FileSize%)-4))) Then SeekFile(OGGFile,FilePos(OGGFile)-4)
OGG\Ogg_Length%=((FilePos(OGGFile))-OGG\OGG_Start)
Return OGG\Ogg_Length%+OGG\OGG_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
| ||
| To add: For usage, call GetOGGSpecificInfo$(OGG_FileName$,OGGInfoType%,AutoClean%=True) OGG_Filename$ should be the full path to a valid OGG format file OGGInfoType is an integer representing one of the following types of information: 1 : Title 3 : Artist 4 : Album 5 : Album Artist 6 : Genre For 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. |
Code Archives Forum