Login Register
Frontpage Code library Pastebin

GetMP3Length

Author: valtzu
Added: 18.4.2011 23:06
Edited: 18.4.2011 23:06
Category: Ääni & musiikki

Description

Laskee MP3 -kappaleen pituuden sekunteina. Uudelleenkirjoitettu versio, jonka pitäisi tunnistaa lähes kaikenlaiset mp3:set.

Code

Select all
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
Function GetMP3Length(fileName As String)
    If Not FileExists(filename) Then Return False
    s = FileSize(fileName)
    f = OpenToRead(fileName)
    songLength   = 0
    vbr          = False
    tagEndOffset = 0     // Missä kohtaa ID3v2-tagi loppuu
    Repeat
        // Luetaanpa big endian dword
        fourr= ReadByte(f)Shl 24+ReadByte(f)Shl 16+ReadByte(f) Shl 8+ReadByte(f)
        If (fourr Shr 8) = $334449 Then // "ID3"
            SeekFile f, FileOffset(f)+2
            tagSize    = ReadInt(f)
            tagSize    = tagSize Shl 1 Shr 25+tagSize Shl 9 Shr 25 Shl 7+tagSize Shl 17 Shr 25 Shl 14+tagSize Shl 25 Shr 25 Shl 21
            tagEndOffset=FileOffset(f)+tagSize
            SeekFile f, tagEndOffset
        ElseIf fourr Shr 21 = 2047 Then // 0b11111111111
            mpegVer = fourr Shl 11 Shr 30 // 0 = mpeg-2.5, 1=-, 2=mpeg-2, 3=mpeg-1
            layer   = fourr Shl 13 Shr 30 // 0 = -, 1=III, 2=II, 3=I
            crcProt = fourr Shl 15 Shr 31 // 0 = protected, 1=not protected
            brIndex = fourr Shl 16 Shr 28 // should not be 1111
            srIndex = fourr Shl 20 Shr 30 // 0=44100,1=48000,2=32000,3=-
            padding = fourr Shl 22 Shr 31 // 0=not padded
            channel = fourr Shl 24 Shr 30 // 0=stereo, 1=joint stereo, 2=dual mono, 3=mono
            If crcProt = 0 Then crc = ReadShort(f)
            If brIndex < 15 Then
                If mpegVer = 2 Or mpegVer = 0 Then
                    Select layer
                        Case 2,1: bitRates$="000008016024032040048056064080096112128144160"
                        Case 0,3: bitRates$="000032048056064080096112128144160176192224256"
                    End Select
                    bitRate    = Int(Mid(bitRates,brIndex*3+1,3))*1000
                    If mpegVer = 2 Then
                        sampleRate = Int(Mid("1600220524000000",srIndex*4+1,4))*10
                    Else
                        sampleRate = Int(Mid("11025120000800000000",srIndex*5+1,5))
                    EndIf
                    samplesPerFrame = Mid("038411520576",Int(Min(2,3-layer))*4+1,4)
                Else
                    Select layer
                        Case 3  : bitRates$="000032064096128160192224256288320352384416448"
                        Case 2  : bitRates$="000032048056064080096112128160192224256320384"
                        Case 1,0: bitRates$="000032040048056064080096112128160192224256320"
                    End Select
                    bitRate    = Int(Mid(bitRates$,brIndex*3+1,3))*1000
                    sampleRate = Int(Mid("441480320000",srIndex*3+1,3))*100
                    samplesPerFrame = Mid("038411521152",Int(Min(2,3-layer))*4+1,4)
                EndIf
                If layer = 3 Then
                    frameLen = RoundDown(12.0*bitRate/sampleRate+padding)*4
                Else
                    frameLen = RoundDown((144.0*bitRate/sampleRate)+padding)
                EndIf
                nextOffset = FileOffset(f)+frameLen
                // ainoastaan mpeg-1 ja mpeg-2 voi olla vbr:ää
                If mpegVer = 3 Or mpegVer = 2 Then
                    If mpegVer = 3 Then
                        xingOff = 21 + 15*(channel<>3)
                    Else
                        xingOff = 13 + 8*(channel<>3)
                    EndIf
                    SeekFile f, FileOffset(f)+xingOff-4
                    If ReadInt(f) = $58696E67 Then // "Xing"
                        vbr = True
                        If ReadInt(f) Shr 24 Mod 2 Then
                            vbrFrameC = ReadInt(f)
                            vbrFrameC = vbrFrameC Shr 24+vbrFrameC Shl 24+vbrFrameC Shl 8 Shr 24 Shl 8+vbrFrameC Shl 16 Shr 24 Shl 16
                            songLength = vbrFrameC*samplesPerFrame/sampleRate
                            Exit
                        EndIf
                    Else
                        vbr = False
                        Exit
                    EndIf
                EndIf
                If nextOffset>=s Then Exit
                SeekFile f, nextOffset // hypätään seuraavan framen alkuun
            Else
                // eipä löytynyt haluamaaamme, joten palataan takaisin päin
                SeekFile f, FileOffset(f)-3
            EndIf
        Else
            // mennäänpä taaksepäin, koska ei löytynyt, mitä etsittiin
            SeekFile f, FileOffset(f)-3
        EndIf
    Until FileOffset(f)>s-5 Or songLength
    CloseFile f
    // Jos tiedosto ei ollut vbr-muodossa,niin lasketaan pituus suoraan bitratesta 
    If (Not vbr) And bitRate Then songLength = (s-tagEndOffset)*8/bitRate
    Return songLength
End Function

mp3file$ = "Media\SK_Battle2.mp3"
songLength = GetMP3Length(mp3file)

If songLength Then // Onnistuiko?
    Print "The song "+mp3file+" is "+songLength+" seconds long."
Else
    Print "Error occured :("
EndIf
WaitKey

Comments

No comments. You can be first!

Leave a comment

You must be logged in to comment.