Avatar of Wayne Barron
Wayne Barron
Flag for United States of America asked on

vb.net convert long time to mm:ss

Hello All;

I am using the ID3TagLibrary (http://glassocean.net/perrys-id3-tag-library/)  for my mp3 script that I am designing.
I have everything that I need so far, but the Duration of the track spits out the time like so.

4.185426953125
should be
04:27

This is from another file (song)
2.944617578125
should be
03:08

Can someone assist me in a script that will convert this timestamp to the normal time?
Carrzkiss
Visual Basic.NETASP.NET

Avatar of undefined
Last Comment
Wayne Barron

8/22/2022 - Mon
ASKER CERTIFIED SOLUTION
Ryan Chong

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
Wayne Barron

ASKER
Hey Ryan.

>>  Expression expected.
Wayne Barron

ASKER
It is happening on the
@
Symbol
Wayne Barron

ASKER
Had to remove the @
WORKS!!!!!!!!!!!


TimeSpan.FromMinutes(Convert.ToDouble(mp3.MpegInfo.Duration)).ToString("mm\:ss")
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
Wayne Barron

ASKER
Jumped the gun.
It works, but the wrong time.
So, that code that I provided may not be the correct string that I needed to get.

It is about 12 + seconds off, depending on the length of the file.

I sent the author of the code a message, not really sure if he is going to answer back or not.
He has not been active on his blog for quite a few years.
Wayne Barron

ASKER
Just wondering here.
I wonder if his algorithm is off in his code?

This is the script for the reading of the Duration of the file.
I do not know nearly enough of VB to know what is what on this one.

Public Class MpegInfo

    Public LocationIndex As Integer
    Public HeaderSize As Integer
    Public FileSize As Integer

    ' encoded values
    Public VersionEncoded As String
    Public LayerEncoded As String
    Public BitrateEncoded As String
    Public SamplingRateEncoded As String
    Public ChannelModeEncoded As String
    Public ModeExtensionEncoded As String
    Public EmphasisEncoded As String

    ' literal/computed values
    Public Bitrate As Integer
    Public Duration As String
    Public SamplingRate As String
    Public FrameSize As Integer = 1152 ' this is ALWAYS 1152 for MPEG-1 Layer 3 (mp3)
    Public FrameLength As Integer
    Public Layer As String
    Public Version As String
    Public Kbps As Integer
    Public ProtectionBit As Boolean
    Public PaddingBit As Boolean
    Public PrivateBit As Boolean
    Public ChannelMode As String
    Public Copyright As Boolean
    Public Original As Boolean
    Public Emphasis As String
    Public RawResults As String ' temporary - store raw parse results for diagnostic viewing in the Tag Viewer

    Sub New(ByVal argFileInfo As IO.FileInfo, ByVal argStartIndex As Integer)
        Dim mReader As IO.FileStream = argFileInfo.OpenRead
        Dim mFramesync(10) As Byte                  ' 11 bits for the Frame sync (all bits set)
        Dim mMpegAudioVersionID(1) As Byte          ' 2 bits for the MPEG Audio version ID
        Dim mLayerDescription(1) As Byte            ' 2 bits for the Layer description
        Dim mProtectionBit(0) As Byte               ' 1 bit for the Protection bit
        Dim mBitrateIndex(3) As Byte                ' 4 bits for the Bitrate index
        Dim mSamplingRateFrequencyIndex(1) As Byte  ' 2 bits for the Sampling rate frequency index
        Dim mPaddingBit(0) As Byte                  ' 1 bit for the Padding bit
        Dim mPrivateBit(0) As Byte                  ' 1 bit for the Private bit
        Dim mChannelMode(1) As Byte                 ' 2 bits for the Channel Mode
        Dim mModeExtension(1) As Byte               ' 2 bits for the Mode extension
        Dim mCopyright(0) As Byte                   ' 1 bit for the Copyright
        Dim mOriginal(0) As Byte                    ' 1 bit for the Original
        Dim mEmphasis(1) As Byte                    ' 2 bits for the Emphasis
        Me.FileSize = argFileInfo.Length
        ' start at the beginning of the file
        mReader.Position = 0
        ' set up the byte position and buffer size for reading in chunks of data
        Dim mStartIndex As Integer = argStartIndex
        Dim mEndIndex As Integer = argStartIndex + 20000
        Dim mBufferLength As Integer = 10000
        Dim mBufferOffset As Integer = 0
        Dim mSyncByte As Byte = 255
        Dim mTryHeaders As New ArrayList
        ' set the reader position just after the id3v2 tag
        mReader.Position = mStartIndex
        Do Until mReader.Position >= mEndIndex
            ' read in the next chunk
            Dim mBytes(mBufferLength - 1) As Byte
            mReader.Read(mBytes, 0, mBufferLength)
            Console.WriteLine("Reading next chunk of " & mBufferLength & " bytes...")
            Dim mTryIndex As Integer = 0
            Dim mTryIndexOffset As Integer = 0
            Do Until mTryIndexOffset >= mBufferLength
                ' locate the next sync byte for testing
                mTryIndex = Array.IndexOf(mBytes, mSyncByte, mTryIndexOffset + 1)
                If mTryIndex = -1 Then
                    mTryIndexOffset = mBufferLength
                Else
                    ' increment the offset position to the currently found sync byte
                    mTryIndexOffset = mTryIndex
                    Try
                        If mBytes(mTryIndexOffset + 1) >= 224 Then
                            ' in a try block because blockcopy will fail silently
                            Dim mTryHeader(3) As Byte
                            Buffer.BlockCopy(mBytes, mTryIndexOffset, mTryHeader, 0, 4)
                            If IsValidMpegHeaderBytes(mTryHeader) = "VALID" Then
                                ' TODO: create a strongly typed MpegFrame object here and store them in an array
                                '   so we have the entire mpeg structure
                                mTryHeaders.Add(mTryHeader)
                                ParseMpegHeader(mTryHeader)
                                Dim mFrameLength As Integer = Math.Ceiling((144 * (Me.Bitrate / Me.SamplingRate)) + Me.PaddingBit)
                                Dim mResults = "Detected MPEG header frame sync byte at byte index " & mStartIndex + mTryIndexOffset + mBufferOffset & " or array index " & mTryIndexOffset & " with a binary value of " & BytesToBinaryString(mTryHeader) & " or decoded/interpreted values of Bitrate: " & Me.Bitrate & " Sampling rate: " & Me.SamplingRate & " Frame length in bytes: " & mFrameLength & " Frame duration in milliseconds: " & (1152 / Me.SamplingRate) * 1000
                                Me.RawResults &= vbNewLine & mResults
                                'Console.WriteLine(mResults)
                            End If
                        End If
                    Catch ex As Exception
                        Console.WriteLine(ex.Message)
                    End Try
                End If
            Loop
            mBufferOffset += mBufferLength
        Loop
        '' visualize some data for debugging purposes
        'Dim b() As Byte
        'For Each b In mTryHeaders
        '   MsgBox(System.Text.Encoding.Default.GetString(b))
        'Next
        ' close the file stream
        mReader.Close()
        mReader.Dispose()
    End Sub

    Function IsValidMpegHeaderBytes(ByVal b() As Byte) As String
        Dim result As String = "VALID"
        ' convert the four bytes into a binary sequence, since we are reading data on a per-bit basis
        Dim s As String = BytesToBinaryString(b)
        ' validity the binary sequence 
        If s.Substring(11, 2) = "01" Then
            result = "INVALID A"
        End If
        If s.Substring(13, 2) = "00" Then
            result = "INVALID B"
        End If
        If s.Substring(16, 4) = "1111" Then
            result = "INVALID C"
        End If
        If s.Substring(20, 2) = "11" Then
            result = "INVALID D"
        End If
        If s.Substring(30, 2) = "10" Then
            result = "INVALID E"
        End If
        Return result
    End Function

    ' MPEG DURATION ALGORITHM:
    ' 1) convert bytes to kilobytes: 10971126 / 1024 = 10713.990 kilobytes
    ' 2) convert kilobytes to kilobits: 10713.990 * 8 = 85711.921 kilobits
    ' 3) divide kilobits by bitrate to get duration in seconds: / 320 = 267.849 seconds
    Sub ParseMpegHeader(ByVal argBytes() As Byte)
        ' convert the bytes into a binary sequence, since we are reading data on a per-bit basis
        Dim s As String = BytesToBinaryString(argBytes)
        ' get raw header info, some of these are encoded values and some are literal values
        Me.BitrateEncoded = s.Substring(16, 4)
        Me.SamplingRateEncoded = s.Substring(20, 2)
        Me.PaddingBit = s.Substring(22, 1)
        Me.PrivateBit = s.Substring(23, 1)
        Me.ChannelMode = s.Substring(24, 2)
        Me.ModeExtensionEncoded = s.Substring(26, 2)
        Me.Copyright = s.Substring(28, 1)
        Me.Original = s.Substring(29, 1)
        Me.EmphasisEncoded = s.Substring(30, 1)
        ' convert raw info
        ' Version
        Select Case Me.VersionEncoded
            Case "00"
                Me.Version = 2.5 ' MPEG Version 2.5
            Case "01"
                Me.Version = 0 ' (RESERVED - invalid mpeg header frame)
            Case "10"
                Me.Version = 2 ' MPEG Version 2 (ISO/IEC 13818-3)
            Case "11"
                Me.Version = 1 ' MPEG Version 1 (ISO/IEC 11172-3)
        End Select
        ' Layer
        Select Case Me.LayerEncoded
            Case "00"
                Me.Layer = 0 ' (RESERVED - invalid mpeg header frame)
            Case "01"
                Me.Layer = 3
            Case "10"
                Me.Layer = 2
            Case "11"
                Me.Layer = 1
        End Select
        ' Bitrate and Kbps
        Select Case Me.BitrateEncoded
            Case "0000"
                Me.Bitrate = 0 ' (FREE)
            Case "0001"
                Me.Bitrate = 32000
            Case "0010"
                Me.Bitrate = 40000
            Case "0011"
                Me.Bitrate = 48000
            Case "0100"
                Me.Bitrate = 56000
            Case "0101"
                Me.Bitrate = 64000
            Case "0110"
                Me.Bitrate = 80000
            Case "0111"
                Me.Bitrate = 96000
            Case "1000"
                Me.Bitrate = 112000
            Case "1001"
                Me.Bitrate = 128000
            Case "1010"
                Me.Bitrate = 160000
            Case "1011"
                Me.Bitrate = 192000
            Case "1100"
                Me.Bitrate = 224000
            Case "1101"
                Me.Bitrate = 256000
            Case "1110"
                Me.Bitrate = 320000
            Case "1111"
                Me.Bitrate = 0 ' (BAD - invalid mpeg header frame)
        End Select
        Me.Kbps = Me.Bitrate / 1000
        ' Sampling Rate
        Select Case Me.SamplingRateEncoded
            Case "00"
                Me.SamplingRate = 44100
            Case "01"
                Me.SamplingRate = 48000
            Case "10"
                Me.SamplingRate = 32000
            Case "11"
                Me.SamplingRate = 0 ' (RESERVED - invalid mpeg header frame)
        End Select
        ' Channel Mode
        Select Case Me.ChannelModeEncoded
            Case "00"
                Me.ChannelMode = "Stereo"
            Case "01"
                Me.ChannelMode = "Joint stereo (Stereo)"
            Case "10"
                Me.ChannelMode = "Dual channel (Stereo)"
            Case "11"
                Me.ChannelMode = "Single channel (Mono)"
        End Select
        ' Emphasis
        Select Case Me.EmphasisEncoded
            Case "00"
                Me.Emphasis = "none"
            Case "01"
                Me.Emphasis = "50/15 ms"
            Case "10"
                Me.Emphasis = 0 ' (RESERVED - invalid mpeg header frame)
            Case "11"
                Me.Emphasis = "CCIT J.17"
        End Select
        ' attempt to calculate the song duration using a variety of methods
        Me.Duration = ((Me.FileSize / 1024) * 8) / Me.Kbps
        Me.Duration = ((Me.FileSize / Me.Kbps) / 60)
        Me.Duration = Me.FileSize / (Me.Bitrate * 8)
    End Sub

End Class

Open in new window

Ryan Chong

hmmm.... you probably right on that as I got a mp3 length 2:54 but the value came out as "2.7150556640625", if convert it to proper format, it's approximate to 2:43 , which seems wrong.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Ryan Chong

Had to remove the @
Sorry as I was testing it in C#... in VB.NET, there's no such syntax.

I'm trying another library: TagLib-sharp and it seems working well.

http://download.banshee.fm/taglib-sharp/

Dim mp3 As TagLib.File = TagLib.File.Create("D:\yourPath\test.mp3")

Open in new window


then refer to mp3.Tag for properties such as Title, etc.

mp3.Tag.Title

Open in new window


and use mp3.Properties.Duration to get the duration.
mp3.Properties.Duration.ToString("mm\:ss")

Open in new window

Wayne Barron

ASKER
I just downloaded it, and it is all in C#
I do vb.net

Any examples on doing this in VB.net?
Or, do I just convert the files over to vb using
converter.telerik.com/
Wayne Barron

ASKER
I have no idea on what to do with that code.
Could you perhaps provide me an example project using vb.net using this library?
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
Ryan Chong

@Wayne

the code posted in comment: ID: 42062660 was already in vb.net :)
Wayne Barron

ASKER
How do you use the library?
In the one that I am/was using, I had to install the .dll file.
What do I do with this one?

And yes, I noticed the vb on the post.
Just not sure about how to get the ball rolling on it.
Ryan Chong

for TagLib-sharp which you download the library from: http://download.banshee.fm/taglib-sharp/

just copy the dll into the bin folder:

taglib-sharp.dll

and then add the library via References into your project.

SnapShot.png
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Wayne Barron

ASKER
The project that I am working on/towards.
Is a website, that will be hosted in-house.
This .dll, will it have to be registered on the server, in order to use on the site?
Ryan Chong

This .dll, will it have to be registered on the server, in order to use on the site?
well, most of the cases, we no need to registered it on the machine. we can use it directly.
Wayne Barron

ASKER
Very nice.
I am liking it, it works great.

Have you tried the artist? It gives me an error.

mp3.Tag.Artists
Dim strArtist As String = mp3.Tag.Artists
Value of type String() cannot be converted to String

Genres
does the same thing, as a few others as well.
Your help has saved me hundreds of hours of internet surfing.
fblack61
Wayne Barron

ASKER
When you run the site outside of VS, you get this error.
>>>>   Type 'TagLib.File' is not defined.

On this line.
>>>>    Dim mp3 As TagLib.File = TagLib.File.Create

Something needs to go in the

In one of my other projects, I had to call the JSON file like this.
Imports Newtonsoft.Json

So, there has to be something to call on this one as well.
Ryan Chong

based on the property, mp3.Tag.Artists is a String array. So, you need to check its length and grab the array's value accordingly. This is same for mp3.Tag.Genres.

but you may look for:

  • mp3.Tag.FirstArtist
  • mp3.Tag.FirstGenre
Ryan Chong

In one of my other projects, I had to call the JSON file like this.
Imports Newtonsoft.Json
Ok, so you may try do the same for the TagLib-Sharp as well.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Wayne Barron

ASKER
I just found the   mp3.Tag.FirstGenre
So that works.

I added all these, however. They are all greyed out.
Tells me they are not necessary

Imports TagLib
Imports TagLib.IFD
Imports TagLib.IFD.Tags
Imports TagLib.Xmp
And I still get the error.
Type 'TagLib.File' is not defined.
Ryan Chong

And I still get the error.
Type 'TagLib.File' is not defined.
have you copied the relevant dlls into the bin folder of your web server?

if this issue persists, you may try to create another question as it seems not really relevant to the question that you original asked for.
Wayne Barron

ASKER
I was thinking about doing that very thing, Ryan.
I had the same issue with the other Library as well.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Wayne Barron

ASKER