Чтение MP3 Frameheader - присвоение битовых значений переменным
Я изучаю Visual Basic.NET и пытаюсь перевести некоторый исходный код Java в проект vb.net. Проект читает данные в формате mp3, а затем аккуратно разбивает файл в соответствии с данными заголовка кадра и т. Д.
Мой вопрос касается чтения заголовка фрейма mp3 файлов. Я понимаю, что сведения о кадре содержатся в первых 4 (32-битных) байтах кадра, а определенные биты представляют определенные значения, как подробно описано здесь: http://www.mp3-tech.org/programmer/frame_header.html
Используя FileStream, я смог прочитать эти данные и отобразить их в двоичном виде в текстовом поле.
Я ищу помощь в чтении битов и присвоении их переменным в моем классе. Я не уверен, что будет правильной процедурой для этого, так как некоторые значения имеют длину 1, 2 или 4 бита, например, биты 19-20 = MpegType, биты 12-15 = BitrateIndex, бит 9 = заполнение и т. Д.
Я смотрел на подобные проекты, доступные на codeproject.com, но я не понимаю, как они достигли вышеуказанного.
Буду признателен за любую оказанную помощь.
РЕДАКТИРОВАТЬ:
Вот основной подпункт, пока я не включил код объявления переменных и свойств и т. Д.
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
Когда это выполняется, вывод в поле расширенного текста выглядит следующим образом:
11111111
11111010
10110011
01001100
Я хочу прочитать эти биты и назначить соответствующие значения для переменных, например
Считайте первые 12 битов для значения синхронизации. Считайте бит 13 для значения mpegID. Считайте биты 14 и 15 для значения layerID и т. Д.
Надеюсь, что это понятнее.
Java-код выглядит следующим образом:
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;
}
}
2 ответа
Вот подробное объяснение кадров и формула того, как данные хранятся в заголовке первых 4 байтов кадра. Я не уверен, чего вы пытаетесь достичь, но, на всякий случай, вы идете. Нет смысла изобретать велосипед.
.Net имеет класс BitArray, который вы бы использовали для хранения своих битов.
Я сталкивался с подобным проектом, который использует функцию для преобразования битов в строку. Я объединил этот код с другим примером, который я нашел, который изменил двоичную строку на целое число. Заинтересованы услышать об альтернативных методах?
Public Function BinaryToInteger(ByVal objBitArray As BitArray, ByVal intStart As Integer, ByVal intEnd As Integer) As Integer
Dim BinaryString As String
Dim BinaryNum As Integer
Dim BitCount As Short
BinaryString = ""
For i As Integer = intStart To intEnd
BinaryString &= IIf(objBitArray.Item(i), "1", "0")
Next
For BitCount = 1 To Len(BinaryString)
BinaryNum = BinaryNum + (CDbl(Mid(BinaryString, Len(BinaryString) - BitCount + 1, 1)) * (2 ^ (BitCount - 1)))
Next BitCount
BinaryToInteger = BinaryNum
End Function