导读:
小琢磨了一下mp3的格式,因为很想计算出其文件播放时长
根据RFC文档上的说法,只要知道文件的长度,播放的比特率(bitRate),采样率(Simpling Frequency Rate)以及 填充位数(Padding bits),以及“恒定每26ms能播放一数据帧” 的约定,就可以计算出播放时长
okay,要做的就是,了解mp3帧格式,获取比特率,采样率 以及 填充位数
在mp3文件的末尾,恒存在一个长度为128字节的ID3 Tag Version 1的标签,用以描述文件。如果愿意,还可以添加一个ID3 Tag Version 2到文件头,长度不固定,不过在其头部,会有10字节的描述头,里头标识出这个TAG结构的总长(含10字节),然后,接下来夹着的一直到TAG V1的部分,就是全部的数据帧。
假定这些帧是采取CBR格式,即固定帧长存储,则每一帧的帧头描述都是一样的,基于此,便可计算出所需要的数据
做一个类,来干这件事情:
using System;
using System.IO;
using System.Text;
namespace IndieCommon
{
public abstract class Mp3Tag
{
// 每秒固定可以播放的帧数
const double playFramesPerSec = 38.461538461538461538461538461538
/**////
/// 获取MP3帧头包含的信息
///
/// 帧头四字节数据
/// 帧信息结构
static Mp3Frame getFrameInfo(byte[] FrameHeader)#region static Mp3Frame getFrameInfo(byte[] FrameHeader)
{
// 比特率检索字典
int{
{ 0,0,0,0,0,0},
,
{64,48,{64,48,40,64,48,16},
,
{128,64,
{160,80,
{192,96,
{224,,
{256,,
{288,,
{320,,
{352,,
{384,,
{448,,
{0,0,0,
// 采样率检索字典
int{
{44100,22050,11025},
,
{32000,
/**////
/// 由帧头获取Mp3时长信息
///
/// Mp3结构
/// 帧头
/// ID3 Tag2长度
static void getTimeInfo(ref MP3 paramMP3,byte[] FrameHeader,int ID3V2_frame_size)#region getTimeInfo(ref MP3 paramMP3, {
// 文件长度
Mp3Frame frameInfo frameInfo.CalcFrameSize();
//
frameCount =)frameCount / playFramesPerSec;
paramMP3.seconds
#endregion
/**////
/// 读取MP3信息
///
/// Mp3描述结构
static void readMP3Tag(ref MP3 paramMP3)#region static void readMP3Tag(ref MP3 paramMP3)
public {
// 文件对象
FileStream oFileStream;
oFileStream = 是否有ID3 Tag V2
byte[] header = new byte[10];
, SeekOrigin.Begin);
oFileStream.Read(header, 0, 10);
// ASCIIEncoding();
string id3Tag = instEncoding.GetString(header);
//"ID3")
{
// ID3Tag V2帧长度
int
| (int)(header[7] & 0x7F) * 0x400
| (int)(header[9] & 0x7F);
// 定位到某一帧头
];
oFileStream.Seek(ID3V2_frame_size + 10
);
oFileStream.Close();
// 获取时长
// 直读Frame
// 读取ID3 Tag V1
/**////
/// 更新tag信息
///
///
static void updateMP3Tag(ref MP3 paramMP3)#region static void updateMP3Tag(ref MP3 paramMP3)
public{
// Trim any whitespace
paramMP3.id3Title paramMP3.id3Artist.Trim();
paramMP3.id3Album = paramMP3.id3Album.Trim();
paramMP3.id3Year paramMP3.id3Comment.Trim();
// Ensure all properties are correct size)
paramMP3.id3Title = paramMP3.id3Title.Substring()
paramMP3.id3Artist = paramMP3.id3Artist.Substring()
paramMP3.id3Album = paramMP3.id3Album.Substring()
paramMP3.id3Year = paramMP3.id3Year.Substring(0)
paramMP3.id3Comment = paramMP3.id3Comment.Substring(
byte[] tagByteArray = new byte[128];
}
/**////
/// Mp3结构
///
struct MP3#region struct MP3
public struct MP3
{
public string filePath;
public string fileFileName;
public string fileComplete;
public bool
id3Title;
public string id3Artist;
public string id3Album;
public string id3Year;
public string
id3TrackNumber;
public byte id3Genre;
public long FileLength;
public int hours;
public int minutes;
seconds;
// Required struct constructor
public MP3(string path, string name)
{
this.filePath = path;
this.fileFileName = name;
this.fileComplete = name;
this.hasID3Tag = false
this.id3Title = null
this.id3Artist this.id3Album = null
this.id3Year = null
this.id3Comment = null
0
this.FileLength = 0
this.id3Genre = 0
this.hours = 0
/**////
/// MP3文件帧结构
///
struct Mp3Frame#region struct Mp3Frame
internal struct Mp3Frame
{
public int version; // MPEG版本(2+,2,1,0表示保留)
layer; // 层级(1,2,3,0表示保留)
public int 是否受CRC校验保护(1为保护,0为未保护)
public int frameSize; // 帧长度 bitrate; // 速率,bps
public int simplingRate; // paddingBits; // 填充位数
public int channel; //
/**////
/// 计算帧长度
///
public int CalcFrameSize()
{
// 计算帧长度的公式
this.frameSize = ((this.version == 1 ? 144 : 72
}
很显然,这事儿还没干完,先留着,以后再干~~~
本文转自
http://www.cnblogs.com/moye/archive/2007/08/08/848114.html