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 |
|
| 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 |