【问题标题】:Reading MP3 Frameheader - assigning bit values to variables读取 MP3 帧头 - 将位值分配给变量
【发布时间】:2012-01-24 20:04:49
【问题描述】:

我正在学习visual basic .net,我正在尝试将一些java 源代码转换为vb.net 项目。项目读取mp3详细信息,然后根据frameheader详细信息等准确分割文件。

我的问题与阅读 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 位。 读取 mpegID 值的第 13 位。 读取第 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;
    }
}

【问题讨论】:

  • 贴出你的 Java 和 VB 源代码,我相信会有人为你出谋划策。
  • 添加了我当前的代码和更多信息。

标签: vb.net mp3 filestream bitarray bitconverter


【解决方案1】:

Here is 帧的详细解释以及数据如何保存在帧头中的公式,帧的前 4 个字节。 我不确定您要完成什么,但以防万一,here you go。重新发明轮子是没有意义的。

.Net 有一个名为 BitArray 的类,您可以使用它来存储您的位。

【讨论】:

  • 我能够读取前 4 个字节,但我不知道如何将这些字节中的位转换为适当的变量。
  • 我遇到了一个类似的项目,它使用函数将位转换为字符串。显然我可以使用这种方法,因为我很好奇是否有使用 BitArray 的替代方法。
【解决方案2】:

我遇到了一个类似的项目,它使用函数将位转换为字符串。我将此代码与我发现将二进制字符串更改为整数的另一个示例相结合。有兴趣了解替代方法吗?

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

【讨论】:

  • 该函数使用位数组并从 int start 读取意图并返回一个字符串。您可以将其读入另一个位数组并返回该位数组。
  • 我不明白您为什么将位数组读入另一个位数组?我已经更改了上面的函数,首先它从开始和结束参数中读取位,转换为字符串,然后转换为整数。
  • 为什么不先解析字符串然后转换成 int 呢?
  • 这不是我已经在做的吗?您将如何正确解析字符串?我更新了我的帖子以显示我当前的功能。
  • 看起来您拥有的解决方案正在为您工作。我只是说你从一串 0 和 1 开始,你可以从一开始就解析它。但无论对你有用,我很高兴你找到了解决方案。
猜你喜欢
  • 2017-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-11
  • 2015-01-23
  • 2021-02-22
相关资源
最近更新 更多