I am learning visual basic .net and I am attempting to translate some java source code to a vb.net project. The project reads mp3 details and then splits the file accurately according to the frameheader details etc.
My question relates to reading the frame header of mp3 files. I understand that the frame details are contained in the first 4 (32-bits) bytes of a frame and certain bits represent certain values as detailed here: http://www.mp3-tech.org/programmer/frame_header.html
Using FileStream I have been able to read this data and display it in binary within a text box.
I am looking for help on reading the bits and assigning them to variables within my class. I am not sure what would be the correct procedure to do this as some values as 1, 2 or 4 bits in length e.g. bits 19-20 = MpegType, bits 12-15 = BitrateIndex, bit 9 = Padding etc.
I have looked at similar projects available on codeproject.com but I do not understand how they have achieved the above.
Any help is much appreciated.
EDIT:
Here is the main sub so far, I have not included the code declaring variables and properties etc.
Public Sub decode()
Dim fs As FileStream
Dim bytes(3) As Byte
fs = New FileStream(mFilename, FileMode.Open, FileAccess.Read)
If fs.CanRead Then
fs.Read(bytes, 0, bytes.Length)
For i As Integer = 0 To bytes.Length - 1
Form1.RichTextBox.Text += Convert.ToString(bytes(i), 2).PadLeft(8, "0"c) & vbCrLf
Next
fs.Close()
fs.Dispose()
Else
MsgBox("File CANNOT be read!!!")
End If
End Sub
When this is run the output in the rich text box is as follows:
11111111
11111010
10110011
01001100
I want to read through these bits and assign the appropriate values to the variables e.g.
Read the first 12 bits for sync value. Read bit 13 for mpegID value. Read bit 14 and 15 for layerID value etc.
Hope that is clearer.
The java code is as follows:
public FrameHeader() {
this.header32 = 0;
valid = false;
}
public FrameHeader(int header32) {
this.header32 = header32;
decode();
}
public void setHeader32(int header32) {
this.header32 = header32;
decode();
}
private void decode() {
mpegID = (header32 >> 19) & 3;
layerID = (header32 >> 17) & 3;
crc16used = (header32 & 0x00010000) == 0;
bitrateIndex = (header32 >> 12) & 0xF;
samplingrateIndex = (header32 >> 10) & 3;
padding = (header32 & 0x00000200) != 0;
privateBitSet = (header32 & 0x00000100) != 0;
mode = (header32 >> 6) & 3;
modeExtension = (header32 >> 4) & 3;
copyrighted = (header32 & 0x00000008) != 0;
original = (header32 & 0x00000004) == 0; // bit set -> copy
emphasis = header32 & 3;
valid = (mpegID != ILLEGAL_MPEG_ID) && (layerID != ILLEGAL_LAYER_ID) && (bitrateIndex != 0)
&& (bitrateIndex != 15) && (samplingrateIndex != ILLEGAL_SR);
if (valid) {
samplingrateHz = SAMPLING_RATES[samplingrateIndex];
if (mpegID == MPEG2_ID)
samplingrateHz >>= 1; // 16,22,48 kHz
if (mpegID == MPEG25_ID)
samplingrateHz >>= 2; // 8,11,24 kHz
channels = (mode == MODE_MONO) ? 1 : 2;
bitrateKBPS = BITRATE_MAP[mpegID][layerID][bitrateIndex];
if (layerID == LAYER1_ID) {
// layer 1: always 384 samples/frame and 4byte-slots
samplesPerFrame = 384;
bytesPerSlot = 4;
}
else {
// layer 2: always 1152 samples/frame
// layer 3: MPEG1: 1152 samples/frame, MPEG2/2.5: 576
// samples/frame
samplesPerFrame = ((mpegID == MPEG1_ID) || (layerID == LAYER2_ID)) ? 1152 : 576;
bytesPerSlot = 1;
}
frameSize = ((bitrateKBPS * 125) * samplesPerFrame) / samplingrateHz;
if (bytesPerSlot > 1)
frameSize -= frameSize % bytesPerSlot;
if (padding)
frameSize += bytesPerSlot;
}
}
Here is a detailed explanation of frames and a formula on how data is held in the header, the first 4 bytes of a frame. I am not sure what you are trying to accomplish but, just in case, here you go. There is no point in reinventing the wheel.
.Net has class called BitArray that you would use to store your bits.