Visual Basic Development Bookmark and Share   
 Home > Visual Basic Language > Finding Length of an Real Media Audio File
 

Finding Length of an Real Media Audio File

Hi,

I need to find out the length (i.e. HH:MM:SS) of a rm (Real Media) Audio File from my application which I made in Visual Basic 6.0. I don't need to play it or record it, just find out the length of the file.

Please let me know how this can be possible.

Thanks

Amad

Amad  Friday, December 01, 2006 9:59 AM

The web link given details the structure of a real media file.

To use it you would open the real media file and check the header for its version which will let you know the rest of the header format. Following the header is a series of "chunks" which are detailed. The chunk you want is the one below

File properties header (PROP)

This chunk contains some information about the general properties of a RealMedia file. Only one PROP chunk can be present in a file.

A PROP chunk has the following format

dword Chunk type ('PROP')
dword Chunk size (typically 0x32)
word Chunk version (always 0, for every known file)
dword Maximum bit rate
dword Average bit rate
dword Size of largest data packet
dword Average size of data packet
dword Number of data packets in the file
dword File duration in ms
dword Suggested number of ms to buffer before starting playback
dword Offset of the first INDX chunk form the start of the file
dword Offset of the first DATA chunk form the start of the file
word Number of streams in the file
word Flags (bitfield, see below)

As you can see this chunk gives the file duration in milliseconds as a dword (int16).

Reading files is quite easy in VB, for this kind of file you will need to open the file in binary.

I am assuming it is not an .RA file that only contains a string to an internet link, and you will need to provide the file name.

The PROP chunk follows the header so you can do the following but really you should verify that the chunk after the header is the PROP. This is extremely quick and dirty example so you can refine it to your needs.

Dim myHandle As FileStream
Dim myReader As BinaryReader
DIM Duration As Int16

<VBFixedString(4)> public id As String

myHandle = New FileStream(<FILE NAME>, FileMode.Open)
myReader = New BinaryReader(myHandle)

' Read header, only interested in the id part

id = myReader.ReadChars(4)
myReader.ReadBytes(16)

'if it is a header read off bytes to position of duration

If id = ".RMF" Then
   myReader.ReadBytes(26)
   Duration = myReader.ReadInt16

' you can then divide duration by 60,000 to get minutes...

End If

myReader.Close()
myHandle.Close()
myHandle.Dispose()

Rabtok  Friday, December 01, 2006 1:07 PM

A quick search on Google with the words "real media audio file header" produced:


http://wiki.multimedia.cx/index.php?title=RealMedia

Rabtok  Friday, December 01, 2006 11:39 AM

Thanks but this links does not contain any information on how to read the length of the .rm file from Visual Basic. Please note that I require to find out the length of the audio/video file and not the size of the file.

Also how can I read this file header from Visual Basic. Is it possible to do so ?

Thanks

Amad

Amad  Friday, December 01, 2006 12:15 PM

you can read any file length using the System.IO.FileInfo class, if you are referring to the file size.

http://msdn2.microsoft.com/en-us/library/system.io.fileinfo.aspx

http://msdn2.microsoft.com/en-us/library/system.io.fileinfo.length.aspx

ahmedilyas  Friday, December 01, 2006 12:54 PM

The web link given details the structure of a real media file.

To use it you would open the real media file and check the header for its version which will let you know the rest of the header format. Following the header is a series of "chunks" which are detailed. The chunk you want is the one below

File properties header (PROP)

This chunk contains some information about the general properties of a RealMedia file. Only one PROP chunk can be present in a file.

A PROP chunk has the following format

dword Chunk type ('PROP')
dword Chunk size (typically 0x32)
word Chunk version (always 0, for every known file)
dword Maximum bit rate
dword Average bit rate
dword Size of largest data packet
dword Average size of data packet
dword Number of data packets in the file
dword File duration in ms
dword Suggested number of ms to buffer before starting playback
dword Offset of the first INDX chunk form the start of the file
dword Offset of the first DATA chunk form the start of the file
word Number of streams in the file
word Flags (bitfield, see below)

As you can see this chunk gives the file duration in milliseconds as a dword (int16).

Reading files is quite easy in VB, for this kind of file you will need to open the file in binary.

I am assuming it is not an .RA file that only contains a string to an internet link, and you will need to provide the file name.

The PROP chunk follows the header so you can do the following but really you should verify that the chunk after the header is the PROP. This is extremely quick and dirty example so you can refine it to your needs.

Dim myHandle As FileStream
Dim myReader As BinaryReader
DIM Duration As Int16

<VBFixedString(4)> public id As String

myHandle = New FileStream(<FILE NAME>, FileMode.Open)
myReader = New BinaryReader(myHandle)

' Read header, only interested in the id part

id = myReader.ReadChars(4)
myReader.ReadBytes(16)

'if it is a header read off bytes to position of duration

If id = ".RMF" Then
   myReader.ReadBytes(26)
   Duration = myReader.ReadInt16

' you can then divide duration by 60,000 to get minutes...

End If

myReader.Close()
myHandle.Close()
myHandle.Dispose()

Rabtok  Friday, December 01, 2006 1:07 PM

Rabtok,

This was a good help, but I am still not getting the desired results. Following is the code for my application in VB 6. Please also note that I tried this in VB .Net and in the Immediate window copy and pasted the contents of the file through myreader.ReadChars(100), one by one, and found out that the file was .ra5 and also .rmf. So I think I must get the correct information. Shouldn't I ?

Here is my code. Comments explain the results for some of the actions.

Private Sub rmLength()
Dim file_name As String
Dim file_length As Long
Dim fnum As Integer
Dim bytes() As Byte
Dim txt As String
Dim txt2 As String
Dim i As Integer

file_name = "c:\auProject\AudioFile.rm"

fnum = FreeFile

txt = Space$(4)
Open file_name For Binary As #fnum
Get #fnum, 1, txt
Close fnum

MsgBox txt ' this displays .rmf


' The program starts to read from Byte # 1, till 4 characters, since
' the length of '.rmf' is 4.

' Now you said that after 46 bytes i.e. 4 for .rmf and then 16 more
' and then 26 more, it would contain the file duration information

Open file_name For Binary As #fnum
Get #fnum, 47, i
Close fnum

MsgBox i 'this returns 18969

' 18969/60000 becomes less than a minute. The file duration is just
' around 13 minutes.So this is not correct.

End Sub

Please help I am already having sleepless nights over this.


Thanks

Amad

Amad  Tuesday, December 05, 2006 12:20 PM

As I said it is just an example to help you work it out. I do not have a RM file to play with in any format so I can not tinker till I get it, but that is where most of the fun of programming is in tackling these things.

Also I have to hold my hand up to making a small mistake it is int32 not int16...sigh!, apologise.

You can however see from the header file that the bytes following the header marker give the size of the header block, which might be different for .RA5 format vs .RMF format.

To deal with this you would read the size into an int32 then subtract 8 (4 for the header name".RMF" and 4 for the int32 size) this would give you the remainder of the header size, dummy read it and that would put you at the beginning of the next chunk, read its four byte header and verify it is a PROP, if not read its size, subtract 8 and dummy read to the next chunk...until you get PROP...then read out to the duration.

If Real change the headers format for version 5 they might also change the PROP format, but this is the world of internet and the information on the header formats is out there, just apply the above logic to locate your information based on where you know Duration to be in the chunk, if it is different for .RA5 you know it is a .RA5 format already from the first header so you can get the information on the PROP chunk and read to a different offset if you want to.

Example:

Dim myHandle As FileStream
Dim myReader As BinaryReader
DIM Duration As Int32
DIM HdrSize as Int32

<VBFixedString(4)> public id As String

myHandle = New FileStream(<FILE NAME>, FileMode.Open)
myReader = New BinaryReader(myHandle)

' Read header, only interested in the id part

id = myReader.ReadChars(4)
HdrSize = myReader.ReadInt32 - 8

myReader.ReadBytes(HdrSize)

'if it is a header read off bytes to position of duration

If id = ".RMF" Then

   id = myReader.ReadChars(4)

If id="PROP" Then
   myReader.ReadBytes(26)
   Duration = myReader.ReadInt32
End If 

' you can then divide duration by 60,000 to get minutes...

End If

myReader.Close()
myHandle.Close()
myHandle.Dispose()


This is a bare bones example you would put a loop in to find PROP in case it is not the chunk after the header.

Rabtok  Tuesday, December 05, 2006 1:55 PM

I have found the chunk PROP. It starts from the 19th byte. I found that through the code

For cnt = 1 To 10000
Open file_name For Binary As #fnum
Get #fnum, cnt, str
Close fnum

If str = "PROP" Then
MsgBox cnt
Exit Sub
End If


Next

Please note that through cnt I am reading each byte.

Now comes the MAIN problem. After finding the PROP chunk;

I add 4 bytes for each 'dword' and 2 bytes for each 'word'. Is it right, since I don't know how much length in bytes is occupied by dword and word respectively.

Adding in such a way I come to the conclusion that the File Duration must be on the 49th byte. Now having said that I don't know that the file duration can be retrieved by which data type.

I tried String with 4 spaces it returned blank.
I tried integer it returned 3840
I tried long it returned -926216448

None of them when divided by 60,000 gives 13 minutes which is the length of my file.

Can you please look into this, I tried searching the internet for any new format header in which rm files might be available, but couldn't find any.

Thanks

Amad


Amad  Tuesday, December 05, 2006 6:15 PM

VB6 Questions are off topic in these forums.

ReneeC  Wednesday, December 06, 2006 1:29 AM

You need to be able to read a 32 bit (4 byte) integer in its native format, it is not stored as a string it is stored in binary. I do not know how VB6 does this, I presume there is a help file with VB6 that you can scour for how to read a 32 bit int, I suspect that a long is a 32 bit int but once again I do not know VB6 and its variable types.


Rabtok  Wednesday, December 06, 2006 8:47 AM

I have switched to Vb.NET. I am using the following code and in the remarks I have put in the values which are being returned.

Dim Duration As Int32

Dim myHandle As FileStream
Dim myReader As BinaryReader

myHandle = New FileStream("c:\auProject\AudioFile.rm", FileMode.Open)
myReader = New BinaryReader(myHandle)

id = myReader.ReadChars(4)
HdrSize = myReader.ReadInt32

myReader.ReadBytes(10)
id = myReader.ReadChars(4) 'PROP
Duration = myReader.ReadInt32 'chunk size 838860800
Duration = myReader.ReadInt32 ' chunk version. returns 0
Duration = myReader.ReadInt32 ' maximum bit rate 32830
Duration = myReader.ReadInt32 ' average bit rate 32830
Duration = myReader.ReadInt32 ' size of largest data packet 16385
Duration = myReader.ReadInt32 ' Average size of data packet 16385
Duration = myReader.ReadInt32 ' Number of data packets in the file. 251677209
Duration = myReader.ReadInt32 ' File Duration in ms 51403
Duration = myReader.ReadInt32 ' Suggested number of ms to buffer before starting playback 536920067
Duration = myReader.ReadInt32 ' Offset of the first INDX chunk form the start of the file 62926
Duration = myReader.ReadInt32 ' Offset of the first DATA chunk form the start of the file 33614594
Duration = myReader.ReadInt32 ' Number of streams in the file 1145899264
Duration = myReader.ReadInt32 ' Flags (bitfield, see below 21072

Now as you can see that this the values being returned are not correctly depicting the value which the document says resides in them. I think the issue is that we are not using the correct data type to place the value into. Anymore inputs ?

Amad  Wednesday, December 06, 2006 11:06 AM

I do not have a file to work from so can not fully help, however a dword is 32 bit a word is 16 bit, the version variable in PROP is a word not a dword so you will change the offset of the read after you have read the version and be out by one byte from there forward.


Rabtok  Wednesday, December 06, 2006 1:14 PM

You can use google to search for other answers

Custom Search

More Threads

• How to delete a file from RAM
• Optional Object parameter passing in a function
• For and Next loop.... Problem!
• VB Novice Main Menu help
• Couples Of Questions
• Using Find on CollectionBase/IBindingList
• serialport regex match
• PDA Tabbed Pages
• how to disable Enter Key in TextBox Multiline?
• how to render a table using graphics object in Vb.net 2005