/// <summary> /// 解析ID3V2标签固定的10个字节长度的头部 /// </summary> /// <returns> /// 成功返回不包含标签头的tag的大小 /// 失败返回-1 /// </returns> /// /// <remarks> /// ID3v2/file identifier "ID3" /// ID3v2 version 04 00 /// ID3v2 flags abcd0000 /// ID3v2 size 4 * 0xxxxxxx /// /// Version or revision will never be $FF. /// An ID3v2 tag can be detected with the following pattern: /// 49 44 33 yy yy xx zz zz zz zz /// Where yy is less than 0xFF, xx is the 'flags' byte and zz is less than 0x80. /// /// 参考: /// http://id3.org/id3v2.4.0-structure /// mplayer, demux_audio.c, id3v2_tag_size /// </remarks> public static int ParseID3V2FixedTagHead(IGMusicStream stream, byte id3v2_tag_major_version) { if (id3v2_tag_major_version == 0xFF) { logger.ErrorFormat("invalide id3v2_tag_major_version:{0}", id3v2_tag_major_version); return(-1); } byte revision; if (!stream.ReadByte(out revision) || revision == 0xFF) { logger.ErrorFormat("invalide revision:{0}", revision); return(-1); } byte flag; if (!stream.ReadByte(out flag)) { logger.ErrorFormat("read flag failed"); return(-1); } /* 计算标标签帧的大小 */ int size = 0; for (int i = 0; i < 4; i++) { byte size_byte; if (!stream.ReadByte(out size_byte)) { logger.ErrorFormat("read size byte failed"); return(-1); } if (size_byte > 0x80) { logger.ErrorFormat("invalide size byte"); return(-1); } size = size << 7 | size_byte; } return(size); }
/// <summary> /// 找到第一帧的帧头部存储的流媒体信息,包含比特率,采样率等等 /// MP3每一帧的帧头信息都是一样的,只要找到第一帧的帧头信息就知道了整个文件的比特率,采样率等流媒体信息 /// 参考: /// http://id3.org/mp3Frame /// https://tools.ietf.org/html/rfc5219#page-3 /// https://www.cnblogs.com/ranson7zop/p/7655474.html /// mplayer, mp3_hdr.c, mp_get_mp3_header /// </summary> public static bool FindFirstFrameHeader(IGMusicStream stream, byte id3v2_tag_major_version) { bool sync_detected = false; uint int32_frame_head = 0; Layers layer = Layers.Reserve; MPEGVersion mpeg_ver = MPEGVersion.Reserve; int sampling_frequency = 0; int bit_rate_kbps = 0; int channels = 0; long frame_size = 0; int spf = 0; // sample per frame, 每一个音频帧中,采样的个数,是一个恒定值 uint padding = 0; // 填充 #region 检测MP3第一帧头部同步信息(sync),如果是同步信息,那么就说明是编码帧的帧头 /* * MP3编码的每一帧的帧头的有个固定的11位的同步信息,从高位开始计算,每一位都是1 * 这里通过“与”运算符判断帧头的前11位是否都是1(与上0xFFE00000(二进制是11111111111000000000000000000000)) * 这11位的数据叫做同步信息(sync) */ byte[] frame_head = new byte[4]; while (true) { byte cur_byte; stream.ReadByte(out cur_byte); AppendByte(frame_head, cur_byte); /* 每次读取一个字节,并且追加到frame_head里 */ int32_frame_head = (uint)(frame_head[0] << 24 | frame_head[1] << 16 | frame_head[2] << 8 | frame_head[3]); if ((int32_frame_head & 0xFFE00000) == 0xFFE00000) { sync_detected = true; break; } } #endregion if (!sync_detected) { logger.ErrorFormat("MP3 frame head , sync info not found"); return(false); } #region Layer /* |-----------------| | 0 0 | Reserved | |-----------------| | 0 1 | Layer III | |-----------------| | 1 0 | Layer II | |-----------------| | 1 1 | Layer I | |-----------------| */ bool bit18 = Utils.GetBit(int32_frame_head, 18); bool bit17 = Utils.GetBit(int32_frame_head, 17); if (!bit18 && !bit17) { logger.ErrorFormat("not layer-1/2/3"); return(false); } else if (!bit18 && bit17) { layer = Layers.LayerIII; } else if (bit18 && !bit17) { layer = Layers.LayerII; } else if (bit18 && bit17) { layer = Layers.LayerI; } #endregion #region mpeg版本 /* |-----------------| | 0 0 | MPEG 2.5 | |-----------------| | 0 1 | Reserve | |-----------------| | 1 0 | MPEG 2 | |-----------------| | 1 1 | MPEG 1 | |-----------------| */ bool bit20 = Utils.GetBit(int32_frame_head, 20); bool bit19 = Utils.GetBit(int32_frame_head, 19); if (!bit20 && bit19) { logger.ErrorFormat("undefinde mpeg version"); return(false); } else if (!bit20 && !bit19) { mpeg_ver = MPEGVersion.Mpeg2_5; } else if (bit20 && !bit19) { mpeg_ver = MPEGVersion.Mpeg2; } else if (bit20 && bit19) { mpeg_ver = MPEGVersion.Mpeg1; } #endregion #region 采样率 /* |--------------------------------| | bits | MPEG1 | MPEG2 | MPEG2.5 | |--------------------------------| | 0 0 | 44100 | 22050 | 11025 | |--------------------------------| | 0 1 | 48000 | 24000 | 12000 | |--------------------------------| | 1 0 | 32000 | 16000 | 8000 | |--------------------------------| */ bool bit11 = Utils.GetBit(int32_frame_head, 11); bool bit10 = Utils.GetBit(int32_frame_head, 10); int[] sample_frequency_array = SamplingFrequencyMap[mpeg_ver]; if (bit11 && bit10) { logger.ErrorFormat("undefinde sample_frequency"); return(false); } else if (!bit11 && !bit10) { sampling_frequency = sample_frequency_array[0]; } else if (!bit11 && bit10) { sampling_frequency = sample_frequency_array[1]; } else if (bit11 && !bit10) { sampling_frequency = sample_frequency_array[2]; } #endregion #region 比特率 /* |------------------------------------------------------------------| | | MPEG1 | MPEG2/2.5(LSF) | | bits |-----------------------------|-----------------------------| | | LayerI | LayerII | LayerIII | LayerI | LayerII & LayerIII | |------------------------------------------------------------------| | 0000 | Free | |------------------------------------------------------------------| | 0001 | 32 | 32 | 32 | 32 | 8 | |------------------------------------------------------------------| | 0010 | 64 | 48 | 40 | 48 | 16 | |------------------------------------------------------------------| | 0011 | 96 | 56 | 48 | 56 | 24 | |------------------------------------------------------------------| | 0100 | 128 | 64 | 56 | 64 | 32 | |------------------------------------------------------------------| | 0101 | 160 | 80 | 64 | 80 | 40 | |------------------------------------------------------------------| | 0110 | 192 | 96 | 80 | 96 | 48 | |------------------------------------------------------------------| | 0111 | 224 | 112 | 96 | 112 | 56 | |------------------------------------------------------------------| | 1000 | 256 | 128 | 112 | 128 | 64 | |------------------------------------------------------------------| | 1001 | 288 | 160 | 128 | 144 | 80 | |------------------------------------------------------------------| | 1010 | 320 | 192 | 160 | 160 | 96 | |------------------------------------------------------------------| | 1011 | 352 | 224 | 192 | 176 | 112 | |------------------------------------------------------------------| | 1100 | 384 | 256 | 224 | 192 | 128 | |------------------------------------------------------------------| | 1101 | 416 | 320 | 256 | 224 | 144 | |------------------------------------------------------------------| | 1110 | 448 | 384 | 320 | 256 | 160 | |------------------------------------------------------------------| | 1111 | Bad | |------------------------------------------------------------------| | */ bool bit15 = Utils.GetBit(int32_frame_head, 15); bool bit14 = Utils.GetBit(int32_frame_head, 14); bool bit13 = Utils.GetBit(int32_frame_head, 13); bool bit12 = Utils.GetBit(int32_frame_head, 12); int[] bit_rate_array = BitRateMap[mpeg_ver][(int)layer]; uint bit_rate_index = (int32_frame_head >> 12) & 0xF; bit_rate_kbps = bit_rate_array[bit_rate_index]; #endregion #region 通道数 bool bit7 = Utils.GetBit(int32_frame_head, 7); bool bit6 = Utils.GetBit(int32_frame_head, 6); channels = (((int32_frame_head >> 6) & 0x3) == 3) ? 1 : 2; #endregion #region 计算填充 padding = (int32_frame_head >> 9) & 0x1; #endregion #region 计算帧大小 spf = SamplingPerFrame[mpeg_ver][(int)layer]; if (layer == Layers.LayerI) { frame_size = spf / 8 * (bit_rate_kbps * 1000) / sampling_frequency + padding * 4; } else if (layer == Layers.LayerII || layer == Layers.LayerIII) { frame_size = spf / 8 * (bit_rate_kbps * 1000) / sampling_frequency + padding; } #endregion return(true); }