BETTY
asked on
Read info from MP3 file
Hi from Barcelona, Spain!
As "Music" section is still under study by EE responsibles, as VB is the language in which I'm developing my program, I've decided this is the correct place to put this question.
The matter is: is there any simple way to read the song time of playing from a MP3 file? Simple means open the file, perhaps look for a given tag ID, read it and it's done. I pray for not having to use C; anyway, VB can open and read from files, too.
If C programming is needed, I would use from VB via a DLL call. I have a freeware 32 bit C compiler, and I think it's not difficult to create a DLL. After, using my VB manual, I can implement the call (I suppose, as I never have done so). The problem then would be the code itself, as I'm a completely newbie to C.
By now my main problem is I don't know if there is any tag or stamp in the file structure to store the playing time, or if WinAmp makes a calculation from several parameters.
I wouldn't want urls as answers, because I've already visited some of them (www.id3.org, etc) and I haven't found nothing; furthermore, all is C-related. The only way to accept an url as answer is to find there the solution to my question (or nearly), not MP3 technical (very technical) stuff.
As "Music" section is still under study by EE responsibles, as VB is the language in which I'm developing my program, I've decided this is the correct place to put this question.
The matter is: is there any simple way to read the song time of playing from a MP3 file? Simple means open the file, perhaps look for a given tag ID, read it and it's done. I pray for not having to use C; anyway, VB can open and read from files, too.
If C programming is needed, I would use from VB via a DLL call. I have a freeware 32 bit C compiler, and I think it's not difficult to create a DLL. After, using my VB manual, I can implement the call (I suppose, as I never have done so). The problem then would be the code itself, as I'm a completely newbie to C.
By now my main problem is I don't know if there is any tag or stamp in the file structure to store the playing time, or if WinAmp makes a calculation from several parameters.
I wouldn't want urls as answers, because I've already visited some of them (www.id3.org, etc) and I haven't found nothing; furthermore, all is C-related. The only way to accept an url as answer is to find there the solution to my question (or nearly), not MP3 technical (very technical) stuff.
An MP3 audio file is separated in smaller parts called frames. Each frame is independent. It has its own header and audio informations. There is no file header. Therefore, you can cut any part of a MP3 file and play it correctly.
The BitRate for each frame can be found in the Frame Header. The Frame Header is 4 bytes long and is located at the beginning of each frame. The Data inside of it is BIT aligned, not byte aligned, as such the 4 bytes represent 32 bits of information. Low Order bits 12-15 of the Frame header, specify the BitRate Code, that then can be looked up in a table, to ascertain what the BitRate value is. Generally speaking, most MP3s are homogenous, which means that if you get the BitRate for the first Frame Header, then the BitRate will be the same for the rest of them. In this case, you can then use the following formula to derive a very close approximation of song length in seconds:
LengthInSeconds = (8 * fileSize) / (Bitrate * 1000)
Keep in mind there are Variable BitRate MP3s out there. In those cases, to get a playing time, you have to calculate it frame by frame. (If you notice the slight delay in loading MP3s with Winamp, this is because it is preprocessing the file to calculate play time).
The MP3 Frame Header, contains 13 Bitcoded fields. As they are all tabular in nature and EE comment entry does not support this (posting tables is a mess), I suggest you go to the Web and obtain a properly formatted Frame Header layout. Here is a good link to get you started:
http://home.swipnet.se/grd/mp3info/
Although it is written in C++, the CMP3INFO class offered there is chock full of information. Additionally, you will find other hyperlinks to peruse on this subject.
The BitRate for each frame can be found in the Frame Header. The Frame Header is 4 bytes long and is located at the beginning of each frame. The Data inside of it is BIT aligned, not byte aligned, as such the 4 bytes represent 32 bits of information. Low Order bits 12-15 of the Frame header, specify the BitRate Code, that then can be looked up in a table, to ascertain what the BitRate value is. Generally speaking, most MP3s are homogenous, which means that if you get the BitRate for the first Frame Header, then the BitRate will be the same for the rest of them. In this case, you can then use the following formula to derive a very close approximation of song length in seconds:
LengthInSeconds = (8 * fileSize) / (Bitrate * 1000)
Keep in mind there are Variable BitRate MP3s out there. In those cases, to get a playing time, you have to calculate it frame by frame. (If you notice the slight delay in loading MP3s with Winamp, this is because it is preprocessing the file to calculate play time).
The MP3 Frame Header, contains 13 Bitcoded fields. As they are all tabular in nature and EE comment entry does not support this (posting tables is a mess), I suggest you go to the Web and obtain a properly formatted Frame Header layout. Here is a good link to get you started:
http://home.swipnet.se/grd/mp3info/
Although it is written in C++, the CMP3INFO class offered there is chock full of information. Additionally, you will find other hyperlinks to peruse on this subject.
Calculates the duration in seconds of a .mp3 file. Also displays the associated layer, bitrate, sample rate of the file
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=1&txtCodeId=4185
This code shows you how to read the ID3-Tag from MP3-Files
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=1&txtCodeId=6326
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=1&txtCodeId=4185
This code shows you how to read the ID3-Tag from MP3-Files
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=1&txtCodeId=6326
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Hi Betty,
Im working on similar lines and i have developed a VB (BAS) module that will open up the mp3 file and tell you the exact playback length!
Yes, you're quite right VB can handle opening and reading the mp3 tag all by itself without VC having to cut in!
I'll email it to you.
All the best!
-headrush
http://kashalkar.tripod.com
Im working on similar lines and i have developed a VB (BAS) module that will open up the mp3 file and tell you the exact playback length!
Yes, you're quite right VB can handle opening and reading the mp3 tag all by itself without VC having to cut in!
I'll email it to you.
All the best!
-headrush
http://kashalkar.tripod.com
ASKER
Rheingold: When I put this question I already had visited the site, and I found code in C++ following some links from there. Thanks.
wsh2: If mp3 files were "uniform" in bitrate, your formula would be genial: simple and fast. Unfortunately, as you say, some (or not so some) files are not bitrate-regular. And I'm so newbie in C++ I would have to spend (not waste if I learn something) lots of time navigating the code. Thanks for the link.
AzraSound and sharmon: I'm going to check your links, and to evaluate which one is better. Specially it's perfect to have a code directly from his author, as if a doubt appears, I expect to ask to perfect person. I'll tell you which one I choose and why.
headrush22m: I'm going to check your link too. But although it's fantastic to get the code directly in my e-mail, think people sometimes research the PAQ for an info through the title, and they will not be very happy if they spend their points in (correctly) answers that are not present. If you put an answer, think in it: if it's not suitable to put it here (length problems), you sould try to give an alternate solution to those who "pay" points after me for the info.
wsh2: If mp3 files were "uniform" in bitrate, your formula would be genial: simple and fast. Unfortunately, as you say, some (or not so some) files are not bitrate-regular. And I'm so newbie in C++ I would have to spend (not waste if I learn something) lots of time navigating the code. Thanks for the link.
AzraSound and sharmon: I'm going to check your links, and to evaluate which one is better. Specially it's perfect to have a code directly from his author, as if a doubt appears, I expect to ask to perfect person. I'll tell you which one I choose and why.
headrush22m: I'm going to check your link too. But although it's fantastic to get the code directly in my e-mail, think people sometimes research the PAQ for an info through the title, and they will not be very happy if they spend their points in (correctly) answers that are not present. If you put an answer, think in it: if it's not suitable to put it here (length problems), you sould try to give an alternate solution to those who "pay" points after me for the info.
A snippet...
' These may not all be used.. I've just cut it from a program and all they really do is store it for global access.
Public HeaderData As String * 4
Public Artist As String, Song As String, Album As String, Notes As String, Year As String
Public Version As Single, Layer As Byte, Bitrate As Integer, SampleRate As Long, FrameLength As Integer, Stereo As Byte
Public Matrix, StereoMode
' Reads various MP3 details from the first packet...
Public Sub ReadHeader(Filename As String)
Dim Byte1 As Byte, Byte2 As Byte, Byte3 As Byte, Byte4 As Byte, BitRateArray, SampleRateArray
Dim hFrameSync As Integer, hVersion As Byte, hLayer As Byte, hProtect As Byte, hBitRate As Byte, hSampleRate As Byte
Dim hPadding As Byte, hPrivate As Byte, hChannel As Byte, hModeExt As Byte, hCopyright As Byte, hOriginal As Byte, hEmphasis As Byte
Open Filename For Binary Access Read As #3
Get #3, , HeaderData
Close #3
Byte1 = Asc(Mid$(HeaderData, 1, 1))
Byte2 = Asc(Mid$(HeaderData, 2, 1))
Byte3 = Asc(Mid$(HeaderData, 3, 1))
Byte4 = Asc(Mid$(HeaderData, 4, 1))
hFrameSync = Byte1 * &H8 + (Byte2 And &HE0) / &H20
hVersion = (Byte2 And &H18) / &H8 ' 0=v2.5, 2=v2, 3=v1
Version = 4 - hVersion
If hVersion = 0 Then Version = 2.5
hLayer = (Byte2 And &H6) / &H2 ' 1=l3, 2=l2, 3=l1
Layer = 4 - hLayer
hProtect = Byte2 And &H1 ' 0=CRC, 1=No
hBitRate = (Byte3 And &HF0) / &H10 ' ---
Select Case Int(Version) * 10 + Layer
Case 11
BitRateArray = Array(0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 999)
Case 12
BitRateArray = Array(0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 999)
Case 13
BitRateArray = Array(0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 999)
Case 21
BitRateArray = Array(0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 999)
Case 22, 23
BitRateArray = Array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 999)
End Select
Bitrate = BitRateArray(hBitRate)
hSampleRate = (Byte3 And &HC) / &H4 ' ---
Select Case Version
Case 1
SampleRateArray = Array(44100, 48000, 32000)
Case 2
SampleRateArray = Array(22050, 24000, 16000)
Case 2.5
SampleRateArray = Array(11025, 12000, 8000)
End Select
SampleRate = SampleRateArray(hSampleRat e)
hPadding = (Byte3 And &H2) / &H2 ' 0=No, 1=Yes
hPrivate = Byte3 And &H1 ' ???
hChannel = (Byte4 And &HC0) / &H40 ' 0=Stereo, 1=JSt, 2=Dual, 3=Mono
Stereo = hChannel
hModeExt = (Byte4 And &H30) / &H10 ' (JSt only) ---
hCopyright = (Byte4 And &H8) / &H8 ' 0=No, 1=Yes
hOriginal = (Byte4 And &H4) / &H4 ' 0=Copy, 1=Original
hEmphasis = Byte4 And &H3 ' 0=None, 1=50/15ms, 3=CCIT J.17
If Layer = 1 Then FrameLength = Fix((12000 * Bitrate / SampleRate + hPadding) * 4) Else FrameLength = Fix(144000 * Bitrate / SampleRate + hPadding)
End Sub
' Inits a couple of arrays
Public Sub InitMP3s()
Matrix = Array("Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip -Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&b", "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro -Techno", "Ambient", "Trip -Hop", "Vocal", "Jazz Funk", "Fusion", "Trance", "Classical", _
"Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno -Industrial", "Electronic", "Pop -Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", _
"Jungle", "Native American", "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo -Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock", _
"Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A Capela", "Euro-House", "Dance Hall")
StereoMode = Array("Stereo", "Joint Stereo", "Dual Channel", "Mono")
End Sub
' These may not all be used.. I've just cut it from a program and all they really do is store it for global access.
Public HeaderData As String * 4
Public Artist As String, Song As String, Album As String, Notes As String, Year As String
Public Version As Single, Layer As Byte, Bitrate As Integer, SampleRate As Long, FrameLength As Integer, Stereo As Byte
Public Matrix, StereoMode
' Reads various MP3 details from the first packet...
Public Sub ReadHeader(Filename As String)
Dim Byte1 As Byte, Byte2 As Byte, Byte3 As Byte, Byte4 As Byte, BitRateArray, SampleRateArray
Dim hFrameSync As Integer, hVersion As Byte, hLayer As Byte, hProtect As Byte, hBitRate As Byte, hSampleRate As Byte
Dim hPadding As Byte, hPrivate As Byte, hChannel As Byte, hModeExt As Byte, hCopyright As Byte, hOriginal As Byte, hEmphasis As Byte
Open Filename For Binary Access Read As #3
Get #3, , HeaderData
Close #3
Byte1 = Asc(Mid$(HeaderData, 1, 1))
Byte2 = Asc(Mid$(HeaderData, 2, 1))
Byte3 = Asc(Mid$(HeaderData, 3, 1))
Byte4 = Asc(Mid$(HeaderData, 4, 1))
hFrameSync = Byte1 * &H8 + (Byte2 And &HE0) / &H20
hVersion = (Byte2 And &H18) / &H8 ' 0=v2.5, 2=v2, 3=v1
Version = 4 - hVersion
If hVersion = 0 Then Version = 2.5
hLayer = (Byte2 And &H6) / &H2 ' 1=l3, 2=l2, 3=l1
Layer = 4 - hLayer
hProtect = Byte2 And &H1 ' 0=CRC, 1=No
hBitRate = (Byte3 And &HF0) / &H10 ' ---
Select Case Int(Version) * 10 + Layer
Case 11
BitRateArray = Array(0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 999)
Case 12
BitRateArray = Array(0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 999)
Case 13
BitRateArray = Array(0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 999)
Case 21
BitRateArray = Array(0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 999)
Case 22, 23
BitRateArray = Array(0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 999)
End Select
Bitrate = BitRateArray(hBitRate)
hSampleRate = (Byte3 And &HC) / &H4 ' ---
Select Case Version
Case 1
SampleRateArray = Array(44100, 48000, 32000)
Case 2
SampleRateArray = Array(22050, 24000, 16000)
Case 2.5
SampleRateArray = Array(11025, 12000, 8000)
End Select
SampleRate = SampleRateArray(hSampleRat
hPadding = (Byte3 And &H2) / &H2 ' 0=No, 1=Yes
hPrivate = Byte3 And &H1 ' ???
hChannel = (Byte4 And &HC0) / &H40 ' 0=Stereo, 1=JSt, 2=Dual, 3=Mono
Stereo = hChannel
hModeExt = (Byte4 And &H30) / &H10 ' (JSt only) ---
hCopyright = (Byte4 And &H8) / &H8 ' 0=No, 1=Yes
hOriginal = (Byte4 And &H4) / &H4 ' 0=Copy, 1=Original
hEmphasis = Byte4 And &H3 ' 0=None, 1=50/15ms, 3=CCIT J.17
If Layer = 1 Then FrameLength = Fix((12000 * Bitrate / SampleRate + hPadding) * 4) Else FrameLength = Fix(144000 * Bitrate / SampleRate + hPadding)
End Sub
' Inits a couple of arrays
Public Sub InitMP3s()
Matrix = Array("Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge", "Hip -Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&b", "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks", "Soundtrack", "Euro -Techno", "Ambient", "Trip -Hop", "Vocal", "Jazz Funk", "Fusion", "Trance", "Classical", _
"Instrumental", "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno -Industrial", "Electronic", "Pop -Folk", "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", _
"Jungle", "Native American", "Cabaret", "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo -Fi", "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock", "Progressive Rock", "Psychedelic Rock", _
"Symphonic Rock", "Slow Rock", "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba", "Folklore", "Ballad", "Power Ballad", "Rythmic Soul", "Freestyle", "Duet", "Punk Rock", "Drum Solo", "A Capela", "Euro-House", "Dance Hall")
StereoMode = Array("Stereo", "Joint Stereo", "Dual Channel", "Mono")
End Sub
ASKER
headrush22m: Your site only leads to your e-mail, so I'm not capable to check anything. This is the cause for me to reject your answer. Anyway, I'm among people here in EE that think no one would have to answer anymore, as the new layout in EE allows to accept a comment as answer. This is due to the fact that some experts don't check locked questions, and this leads to a loss of range of answers.
Note: yor SoundGarden software layout looks great!
Note: yor SoundGarden software layout looks great!
Thanks Betty! yeah i agree with you on the EE front!
ASKER
Cloud 1: This code is similar to the others, perhaps a little more easy as it does not involve lots of Kb or classes. Thanks.
And the winner is... sharmon!!!! Yes, thus AzraSound's ones are near, I think yours is the most complete. Below are the changes needed to work under VB5, VB6 works as is in the link.
prjID3Class.vbp:
Delete the line:
Retained=0
cIDV3.cls:
Between BEGIN y END, in General:Declarations, it's not accepted:
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
In Function GenreText
Change:
Dim aGenre() As Variant
with:
Dim aGenre
And the winner is... sharmon!!!! Yes, thus AzraSound's ones are near, I think yours is the most complete. Below are the changes needed to work under VB5, VB6 works as is in the link.
prjID3Class.vbp:
Delete the line:
Retained=0
cIDV3.cls:
Between BEGIN y END, in General:Declarations, it's not accepted:
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
In Function GenreText
Change:
Dim aGenre() As Variant
with:
Dim aGenre
Well thanks! I wrote it a while back, while it's mostly complete, I haven't really looked through it in a while, I am sure there are things that need tidied up but I am glad you got it all working. Overall it's pretty complete and does most everything. Now you got me wanting to go back and work on it more:) Take care, thanks.
Shannon Harmon
Shannon Harmon
you should try www.wotsit.org
This site contains descriptions of all possible file formats including MP3 - I downloaded information about it a while ago.
Regards