Page 1 of 1

Posted: Sun Jan 05, 2003 1:35 pm
by BackupUser
Restored from previous forum. Originally posted by ses.

Hi all!

I have trouble to translate the VisualBasic-Source into
Purebasic-Code. I never used VB.
Can someone help me, to get this code in PB?

Code: Select all

Private Sub cmdOpen_Click()
  Dim MP3FileName$, Mp3FileNumber, Mp3FileContent$
  Dim ID3Position As Long, ID3Length$, lngID3Length As Long
  Dim ID3Version$, ID3V2Tag$
  
  On Error Resume Next
    
    'Öffnen-Dialog
    lstID3V2Info.Clear
    File.DefaultExt = ".MP3"
    File.DialogTitle = "MP3 öffnen"
    File.Filter = "MP3-Dateien|*.MP3"
    File.ShowOpen
    
    If Dir$(File.filename)  "" Then
      lblStatus.Caption = "MP3 öffnen..."
      
      MP3FileName$ = File.filename
      Mp3FileNumber = FreeFile
      'MP3 einlesen...
      Open MP3FileName$ For Binary As Mp3FileNumber
        lblStatus.Caption = "Bitte warten, lese MP3 ein..."
        Mp3FileContent$ = String$(LOF(Mp3FileNumber), "!")
      Get Mp3FileNumber, , Mp3FileContent$
      Close Mp3FileNumber
      
      'ID3V2-Tag suchen
      lblStatus.Caption = "Bitte warten, suche ID3V2-Tag"
      ID3Position = InStr(Mp3FileContent$, "ID3")
      If ID3Position = 0 Then
        lblStatus.Caption = "Kein ID3V2-Tag vorhanden"
        Exit Sub
      End If
      
      'Tag gefunden, weiter gehts!
      lblStatus.Caption = "ID3V2-Tag gefunden!"
      ID3Version$ = Mid$(Mp3FileContent$, ID3Position + 3, 2)
      
      'Versionkontrolle
      If Asc(Left$(ID3Version$, 1))  2 And _
        Asc(Left$(ID3Version$, 1))  3 And _
        Asc(Left$(ID3Version$, 1))  4 Then
          lblStatus.Caption = "Falsche Version! (" + _
                              Trim$(Str$(Asc(Left$(ID3Version$, _
                              1)))) + ")"
          Exit Sub
      End If
      
      'Version anzeigen
      lstID3V2Info.AddItem "ID3V2-Version:" + _
                      Str$(Asc(Left$(ID3Version$, 1))) + "." + _
                      Trim$(Str$(Asc(Right$(ID3Version$, 1))))
                      
      'Länge bestimmen
      ID3Length$ = Mid$(Mp3FileContent$, ID3Position + 6, 4)
      lngID3Length = 256 * 8 * 8 * Asc(Left$(ID3Length$, 1)) + _
                     256 * 8 * Asc(Mid$(ID3Length$, 2, 1)) + _
                     256 * Asc(Mid$(ID3Length$, 3, 1)) + _
                     Asc(Mid$(ID3Length$, 4, 1))
      lstID3V2Info.AddItem "Länge des ID3V2-Tags:" + _
                           Str$(lngID3Length) + " Byte"
                           
      ID3V2Tag$ = Mid$(Mp3FileContent$, ID3Position, _
                       lngID3Length + 10)
                       
      Mp3FileContent$ = ""
      
      'Nach Extended Header suchen...
      If Asc(Mid$(ID3V2Tag$, 6, 1)) Or 4 = True Then
        lstID3V2Info.AddItem "Extended Header gefunden"
        ID3V2Tag$ = Mid$(ID3V2Tag$, 10)
      End If
      ID3V2Tag$ = Mid$(ID3V2Tag$, 11)
      
      'Nun Frame für Frame abarbeiten...
      Dim FrameName$
      Dim FrameLen$, lngFrameLen
      Dim FrameFlags$, Frame$
      
      Do
        'ID3V2.3
        If Asc(Left$(ID3Version$, 1)) = 3 Or _
           Asc(Left$(ID3Version$, 1)) = 4 Then
          
          'Frame-Header auslesen
          FrameName$ = Left$(ID3V2Tag$, 4)
          
          'Wenn es sich um den Footer handelt, dann sind wir
          'fertig!
          If Left$(FrameName$, 3) = "3DI" Then Exit Do
          FrameLen$ = Mid$(ID3V2Tag$, 5, 4)
          lngFrameLen = 256 * 8 * 8 * Asc(Left$(FrameLen$, 1)) _
                        + 256 * 8 * Asc(Mid$(FrameLen$, 2, 1)) _
                        + 256 * Asc(Mid$(FrameLen$, 3, 1)) + _
                        Asc(Mid$(FrameLen$, 4, 1))
          
          FrameFlags$ = Mid$(ID3V2Tag$, 9, 2)
          ID3V2Tag$ = Mid$(ID3V2Tag$, 11)
          
          'Frame-Content bestimmen
          Select Case FrameName$
            Case "PCNT": Frame$ = "Play Counter:"
            Case "TRCK": Frame$ = "Track:"
            Case "TENC": Frame$ = "Encoded von:"
            Case "WXXX": Frame$ = "Link:"
            Case "TCOP": Frame$ = "Copyright (c):"
            Case "TOPE": Frame$ = "Ursprünglicher Künstler:"
            Case "TCOM": Frame$ = "Composer:"
            Case "TCON": Frame$ = "Genre:"
            Case "COMM": Frame$ = "Kommentar:"
            Case "TYER": Frame$ = "Jahr:"
            Case "TALB": Frame$ = "Album:"
            Case "TPE1": Frame$ = "Künstler:"
            Case "TIT2": Frame$ = "Titel:"
            Case "TLAN": Frame$ = "Sprache:"
            Case "TLEN": Frame$ = "Länge:"
            Case "TMED": Frame$ = "Medientyp:"
            Case "TPUB": Frame$ = "Publisher:"
            Case "TSSE": Frame$ = "Decoding-Software:"
            Case Else:   Frame$ = "Unbekanntes Frame(" + _
                                   FrameName$ + "):"
          End Select
          
          If Left$(ID3V2Tag$, 1) = Chr$(0) Then
            lstID3V2Info.AddItem Frame$ + " " + _
                                 Mid$(ID3V2Tag$, 2, _
                                 lngFrameLen - 1)
          Else
            lstID3V2Info.AddItem Frame$ + " " + _
                                 Left$(ID3V2Tag$, _
                                 lngFrameLen)
          End If
          
          ID3V2Tag$ = Mid$(ID3V2Tag$, lngFrameLen + 1)
        
        'ID3V2.2
        ElseIf Asc(Left$(ID3Version$, 1)) = 2 Then
          
          'Frame-Header auslesen
          FrameName$ = Left$(ID3V2Tag$, 3)
          
          'Wenn es sich um den Footer handelt, dann sind wir
          'fertig!
          If FrameName$ = "3DI" Then Exit Do
          FrameLen$ = Mid$(ID3V2Tag$, 4, 3)
          lngFrameLen = 256 * 8 * Asc(Left$(FrameLen$, 1)) + _
                        256 * Asc(Mid$(FrameLen$, 2, 1)) + _
                        Asc(Mid$(FrameLen$, 3, 1))
                        
          ID3V2Tag$ = Mid$(ID3V2Tag$, 7)
          
          'Frame-Content bestimmen
          Select Case FrameName$
            Case "TRK": Frame$ = "Track:"
            Case "TEN": Frame$ = "Encoded von:"
            Case "TCR": Frame$ = "Copyright (c):"
            Case "TOA": Frame$ = "Ursprünglicher Künstler:"
            Case "TCM": Frame$ = "Composer:"
            Case "TCO": Frame$ = "Genre:"
            Case "COM": Frame$ = "Kommentar:"
            Case "TYE": Frame$ = "Jahr:"
            Case "TAL": Frame$ = "Album:"
            Case "TP1": Frame$ = "Künstler:"
            Case "TT2": Frame$ = "Titel:"
            Case "TLA": Frame$ = "Sprache:"
            Case "TMT": Frame$ = "Medientyp:"
            Case "TSS": Frame$ = "Decoding-Software:"
            Case Else:  Frame$ = "Unbekanntes Frame(" + _
                                 FrameName$ + "):"
          End Select
          
          If Left$(ID3V2Tag$, 1) = Chr$(0) Then
            lstID3V2Info.AddItem Frame$ + " " + _
                                 Mid$(ID3V2Tag$, _
                                 2, lngFrameLen - 1)
          Else
            lstID3V2Info.AddItem Frame$ + " " + _
                                 Left$(ID3V2Tag$, _
                                 lngFrameLen)
          End If
          
          ID3V2Tag$ = Mid$(ID3V2Tag$, lngFrameLen + 1)
          
        End If
      Loop Until Len(ID3V2Tag$) = 0
      lblStatus.Caption = "Bereit!"
    End If
End Sub
Thanks for your help
ses

Posted: Sun Jan 05, 2003 2:31 pm
by BackupUser
Restored from previous forum. Originally posted by redacid.

Is it important to use the V2 Tags? If it's enough you can use V1-Tags which are much easier to use. I can send you my example-code how *I* did it.

regards,
Redacid
---
Viva Los Tioz!
registered user of PB3.40 on WinXP

Posted: Sun Jan 05, 2003 2:47 pm
by BackupUser
Restored from previous forum. Originally posted by ses.

Yes it is important to get the v2-Tag
ID3v1-Tag is esay to get. I wrote an example same days ago.
but I need ID3v2 Tag

Posted: Sun Jan 05, 2003 9:37 pm
by BackupUser
Restored from previous forum. Originally posted by redacid.

If you find a solution please share it :)

regards,
Redacid
---
Viva Los Tioz!
registered user of PB3.40 on WinXP

Posted: Sun Jan 05, 2003 10:08 pm
by BackupUser
Restored from previous forum. Originally posted by ricardo.
Originally posted by redacid

Is it important to use the V2 Tags? If it's enough you can use V1-Tags which are much easier to use. I can send you my example-code how *I* did it.
Why dont you post it here? I will like to see it.
And i think that this database (teh forum) is the best archive to hold good codes.
Every good code should be here for easy search.


Best Regards

Ricardo

Dont cry for me Argentina...

Posted: Sun Jan 05, 2003 11:50 pm
by BackupUser
Restored from previous forum. Originally posted by redacid.

I didn't say that it's good... It works - nothing more. I don't know if it can be done in a much better way.

Code: Select all

    If ReadFile(0,mp3file$)
        Filelength=Lof()
        If AllocateMemory(0,filelength)
           MemPointer=UseMemory(0)
           ReadData(MemPointer, filelength)

           header$    = PeekS(MemPointer+filelength-128, 3)

           If header$ = "TAG" 
              songtitle$ = PeekS(MemPointer+filelength-125,30)
              artist$    = PeekS(MemPointer+filelength- 95,30)
              album$     = PeekS(MemPointer+filelength- 65,30)
              year$      = PeekS(MemPointer+filelength- 35, 4)
              comment$   = PeekS(MemPointer+filelength- 31,30)
              genre      = PeekB(MemPointer+filelength-  1)
           Else
               MessageRequester("Test","No ID3-V1-Tags available",0)
           EndIf 
      EndIf
Comment: the Tags have a fixed length (for example Songtitle is 30 chars). This code is based on some Visual Basic examples I found somewhere. Feel free to improve it - as I could profit from any improvements, too. ^

regards,
Redacid
---
Viva Los Tioz!
registered user of PB3.40 on WinXP

Posted: Sun Jan 05, 2003 11:52 pm
by BackupUser
Restored from previous forum. Originally posted by redacid.

oh, I think the code is pretty much self-describing. But if you need some more help feel free to ask.

regards,
Redacid
---
Viva Los Tioz!
registered user of PB3.40 on WinXP

Posted: Mon Jan 06, 2003 3:37 am
by BackupUser
Restored from previous forum. Originally posted by Franco.

I don't know if I can be any help, but some time ago I wrote code to identify the MP3 information.
It seems to work well for ID3 version 1.
ID3 version 2 code is partially in there (reads only the version number).
I didn't know how to implement/use 'syncsafe integers', so I stopped to code :cry:

Anyway here is what I had so far:

Code: Select all

; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; ID3 INFORMATION FORMAT

; Overall tag Structure:
;
; +-----------------------------+
; |      Header (10 bytes)      |
; +-----------------------------+

; ID3v2/file identifier      "ID3"
; ID3v2 version              $04 00
; ID3v2 flags                %abcd0000
; ID3v2 size             4 * %0xxxxxxx

; +-----------------------------+
; |       Extended Header       |
; | (variable length, OPTIONAL) |
; +-----------------------------+
; |   Frames (variable length)  |
; +-----------------------------+
; |           Padding           |
; | (variable length, OPTIONAL) |
; +-----------------------------+
; | Footer (10 bytes, OPTIONAL) |
; +-----------------------------+

Structure ID3
  FileID.b[3]     ; 3 bytes
  IDMajor.b[1]    ; 1 byte
  IDMinor.b[1]    ; 1 byte - Revision
  FlagA.b[1]      ; 1 byte - Unsynchronisation
  FlagB.b[1]      ; 1 byte - Extended header 
  FlagC.b[1]      ; 1 byte - Experimental indicator
  FlagD.b[1]      ; 1 byte - Footer present 
  Size.l          ; 32 bit synchsafe integers

;   In some parts of the tag it is inconvenient to use the
;   unsychronisation scheme because the size of unsynchronised data is
;   not known in advance, which is particularly problematic with size
;   descriptors. The solution in ID3v2 is to use synchsafe integers, in
;   which there can never be any false synchs. Synchsafe integers are
;   integers that keep its highest bit (bit 7) zeroed, making seven bits
;   out of eight available. Thus a 32 bit synchsafe integer can store 28
;   bits of information.
;   
;   Example:
;   
;     255 (%11111111) encoded as a 16 bit synchsafe integer is 383
;     (%00000001 01111111). 
EndStructure

Structure ID3Info
  Header.ID3
  ExHeader.b[30] ; variable lenght OPTIONAL
  Frames.b[30]   ; variable lenght
  Padding.b[30]  ; variable lenght OPTIONAL
  Footer.b[10]   ; OPTIONAL
EndStructure

; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; --------------------------
; TAG INFORMATION FORMAT
; --------------------------
; Data     Length in bytes
; --------------------------
; Tag      3
; Title    30
; Artist   30
; Album    30
; Year     4
; Comment  30
; Genre    1

; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Structure TagInfo
  Tag.b[3]       ; 3
  Songname.b[30] ; 30
  Artist.b[30]   ; 30
  Album.b[30]    ; 30
  Year.b[4]      ; 4
  Comment.b[30]  ; 30
  Genre.b[1]     ; 1
EndStructure

Structure Header
  Tag.b[3]       ; 3
EndStructure

Mp3TAG.TagInfo
Mp3ID3.ID3Info
Mp3Search.Header

;start
FileName$ = OpenFileRequester("Select a MP3 file", "", "*.mp3", 0) 
OpenFile(1,FileName$)
ReadData(@Mp3Search,3)
FileSeek(0) ; go back to the beginning for further file operation
SearchIdentifier$ = PeekS(@Mp3Search\Tag[0],3)


If SearchIdentifier$ = "TAG"
  Mp3HeaderPosition$ = "Start"
  Mp3Format$ = "TAG"
  MessageRequester("Found @ file start",SearchIdentifier$,0) 
ElseIf SearchIdentifier$ = "ID3"
  Mp3HeaderPosition$ = "Start"
  Mp3Format$ = "ID3"
  MessageRequester("Found @ file start",SearchIdentifier$,0) 
Else
  FileSize.l = FileSize(FileName$)
  SearchHeader.l = FileSize.l - 128
  FileSeek(SearchHeader)
  ReadData(@Mp3Search,3)
  FileSeek(SearchHeader) ; go back for further file operation
  SearchIdentifier$ = PeekS(@Mp3Search\Tag[0],3)
  If SearchIdentifier$ = "TAG"
    Mp3HeaderPosition$ = "End"
    Mp3Format$ = "TAG"
    MessageRequester("Found @ file end",SearchIdentifier$,0) 
  Else
    SearchHeader.l = FileSize.l - 10 ; footer is 10byte long
    FileSeek(SearchHeader)
    ReadData(@Mp3Search,3)
    FileSeek(SearchHeader) ; go back for further file operation

    If SearchIdentifier$ = "3DI" ; footer has mirrored ID
      Mp3HeaderPosition$ = "End"
      Mp3Format$ = "ID3"
      MessageRequester("Found @ file end",SearchIdentifier$,0)
    Else 
      MessageRequester("Message","No TAG information found",0)
    EndIf
  EndIf
EndIf

If Mp3Format$ = "TAG"
  ReadData(@Mp3TAG,127) 
  CloseFile(1)

  Tag$ = PeekS(@Mp3TAG\Tag[0],3)
  Songname$ = PeekS(@Mp3TAG\Songname[0],30)
  Artist$ = PeekS(@Mp3TAG\Artist[0],30)
  Album$ = PeekS(@Mp3TAG\Album[0],30)
  Year$ = PeekS(@Mp3TAG\Year[0],4)
  Comment$ = PeekS(@Mp3TAG\Comment[0],30)
  
  ;display retrieved information
;  Text$="TAG: "+Tag$+Chr(13)
;  Text$=Text$+"Songname: "+Songname$+Chr(13)
  Text$="Songname: "+Songname$+Chr(13)
  Text$=Text$+"Artist: "+Artist$+Chr(13)
  Text$=Text$+"Album: "+Album$+Chr(13)
  Text$=Text$+"Year: "+Year$+Chr(13)
  Text$=Text$+"Comment: "+Comment$+Chr(13)
  
  MessageRequester("Information",Text$,0) 
  
ElseIf SearchIdentifier$ = "ID3"
  ReadData(@Mp3ID3,10) 
  CloseFile(1)

  ID$ = PeekS(@Mp3ID3\Header\FileID[0],3) ;PeekS works only with NULL terminated strings properly
  VersionMajor$ = Str(PeekB(@Mp3ID3\Header\IDMajor[0]))
  VersionMinor$ = Str(PeekB(@Mp3ID3\Header\IDMinor[0]))
  MessageRequester("ID",ID$,0) 
  MessageRequester("Version",VersionMajor$+"."+VersionMinor$,0) 
EndIf

Have a nice day...

Franco

Posted: Mon Jan 06, 2003 12:12 pm
by BackupUser
Restored from previous forum. Originally posted by Insomniac.

Hi redacid,

in your example did not seem necessary to read the whole file into memory as you were only interested in the last 128 bytes.

You will find you will run into problems if you read large files into memory. You can find examples in the forum for reading files in 'chunks'.

I re-arranged your code to 'fileseek' to the end of the file. Hope the numbers are right, I only did it quickly but it worked on the few files I tested.

CR.s = Chr(13)

mp3file$ = OpenFileRequester("","","*.mp3",0)

If ReadFile(0,mp3file$)
Filelength=Lof()
If AllocateMemory(0,128)
MemPointer=UseMemory(0)
FileSeek(filelength - 128)
ReadData(MemPointer, 128)

header$ = PeekS(MemPointer, 3)

If header$ = "TAG"
songtitle$ = PeekS(MemPointer + 3, 30)
artist$ = PeekS(MemPointer + 33, 30)
album$ = PeekS(MemPointer + 63, 30)
year$ = PeekS(MemPointer + 93, 4)
comment$ = PeekS(MemPointer + 97, 30)
genre = PeekB(MemPointer + 127)

MessageRequester("",songtitle$+CR+artist$+CR+album$+CR+year$+CR+comment$+CR+Str(genre),0)
Else
MessageRequester("","No ID3-V1-Tags available",0)
EndIf
EndIf

EndIf

Regards

Insomniac

Posted: Mon Jan 06, 2003 6:18 pm
by BackupUser
Restored from previous forum. Originally posted by redacid.

Thanks. That's what I thought, too. With most MP3-files it will be ok, but if you (for example) get a whole storybook (Lord of the rings) as mp3 with 50MB or more it could cause trouble. So thanks for your improvement as I didn't know that FileSeek even existed... :)

regards,
Redacid
---
Viva Los Tioz!
registered user of PB3.40 on WinXP