关于MP3文件播放时间的计算

导读:
  小琢磨了一下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格式,即固定帧长存储,则每一帧的帧头描述都是一样的,基于此,便可计算出所需要的数据
  做一个类,来干这件事情:
   ContractedBlock.gif
  
   ExpandedBlockStart.gif
  
   None.gif
  
  using System;
   None.gif
  using System.IO;
   None.gif
  using System.Text;
   None.gif
  
   None.gif
  namespace IndieCommon
   ExpandedBlockStart.gif
  
   ContractedBlock.gif
  
   dot.gif
  {
   InBlock.gif
  
  public abstract class Mp3Tag
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {
   InBlock.gif
  
  // 每秒固定可以播放的帧数
   InBlock.gif
  const double playFramesPerSec = 38.461538461538461538461538461538
   InBlock.gif
  
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  /**////
   InBlock.gif
  /// 获取MP3帧头包含的信息
   InBlock.gif
  
  ///
   InBlock.gif
  /// 帧头四字节数据
   ExpandedSubBlockEnd.gif
  /// 帧信息结构
   ContractedSubBlock.gif
  
   ExpandedSubBlockStart.gif
  
  static Mp3Frame getFrameInfo(byte[] FrameHeader)#region static Mp3Frame getFrameInfo(byte[] FrameHeader)
   InBlock.gif
  {
   InBlock.gif
  
  // 比特率检索字典
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  int{
   dot.gif
  { 0,0,0,0,0,0},
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  ,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {64,48,{64,48,40,64,48,16},
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  ,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {128,64,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {160,80,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {192,96,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {224,,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {256,,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {288,,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {320,,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {352,,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {384,,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {448,,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {0,0,0,
   InBlock.gif
  // 采样率检索字典
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  int{
   dot.gif
  {44100,22050,11025},
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  ,
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {32000,
   InBlock.gif
  
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  /**////
   InBlock.gif
  /// 由帧头获取Mp3时长信息
   InBlock.gif
  
  ///
   InBlock.gif
  /// Mp3结构
   InBlock.gif
  /// 帧头
   ExpandedSubBlockEnd.gif
  /// ID3 Tag2长度
   ContractedSubBlock.gif
  
   ExpandedSubBlockStart.gif
  
  static void getTimeInfo(ref MP3 paramMP3,byte[] FrameHeader,int ID3V2_frame_size)#region getTimeInfo(ref MP3 paramMP3, {
   InBlock.gif
  
  // 文件长度
   InBlock.gif
  
   InBlock.gif
  Mp3Frame frameInfo frameInfo.CalcFrameSize();
   InBlock.gif
  
  //
   InBlock.gif
  frameCount =)frameCount / playFramesPerSec;
   InBlock.gif
  
   InBlock.gif
  paramMP3.seconds
   ExpandedSubBlockEnd.gif
  #endregion
   InBlock.gif
  
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  /**////
   InBlock.gif
  /// 读取MP3信息
   InBlock.gif
  
  ///
   ExpandedSubBlockEnd.gif
  /// Mp3描述结构
   ContractedSubBlock.gif
  
   ExpandedSubBlockStart.gif
  
  static void readMP3Tag(ref MP3 paramMP3)#region static void readMP3Tag(ref MP3 paramMP3)
   InBlock.gif
  public {
   InBlock.gif
  
  // 文件对象
   InBlock.gif
  FileStream oFileStream;
   InBlock.gif
  
  oFileStream = 是否有ID3 Tag V2
   InBlock.gif
  byte[] header = new byte[10];
   InBlock.gif
  , SeekOrigin.Begin);
   InBlock.gif
  
  oFileStream.Read(header, 0, 10);
   InBlock.gif
  
  
   InBlock.gif
  
  // ASCIIEncoding();
   InBlock.gif
  
  string id3Tag = instEncoding.GetString(header);
   InBlock.gif
  
  //"ID3")
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {
   InBlock.gif
  
  // ID3Tag V2帧长度
   InBlock.gif
  int
   InBlock.gif
  | (int)(header[7] & 0x7F) * 0x400
   InBlock.gif
  | (int)(header[9] & 0x7F);
   InBlock.gif
  
  // 定位到某一帧头
   InBlock.gif
  ];
   InBlock.gif
  
  oFileStream.Seek(ID3V2_frame_size + 10
   InBlock.gif
  );
   InBlock.gif
  
  oFileStream.Close();
   InBlock.gif
  
  // 获取时长
   InBlock.gif
  
   InBlock.gif
  // 直读Frame
   InBlock.gif
  
  // 读取ID3 Tag V1
   InBlock.gif
  
   InBlock.gif
  
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  /**////
   InBlock.gif
  /// 更新tag信息
   InBlock.gif
  
  ///
   ExpandedSubBlockEnd.gif
  ///
   ContractedSubBlock.gif
  
   ExpandedSubBlockStart.gif
  
  static void updateMP3Tag(ref MP3 paramMP3)#region static void updateMP3Tag(ref MP3 paramMP3)
   InBlock.gif
  public{
   InBlock.gif
  
  // Trim any whitespace
   InBlock.gif
  paramMP3.id3Title paramMP3.id3Artist.Trim();
   InBlock.gif
  
  paramMP3.id3Album = paramMP3.id3Album.Trim();
   InBlock.gif
  
  paramMP3.id3Year paramMP3.id3Comment.Trim();
   InBlock.gif
  
   InBlock.gif
  
  // Ensure all properties are correct size)
   InBlock.gif
  
  paramMP3.id3Title = paramMP3.id3Title.Substring()
   InBlock.gif
  
  paramMP3.id3Artist = paramMP3.id3Artist.Substring()
   InBlock.gif
  
  paramMP3.id3Album = paramMP3.id3Album.Substring()
   InBlock.gif
  
  paramMP3.id3Year = paramMP3.id3Year.Substring(0)
   InBlock.gif
  
  paramMP3.id3Comment = paramMP3.id3Comment.Substring(
   InBlock.gif
  byte[] tagByteArray = new byte[128];
   InBlock.gif
  
  
   ExpandedSubBlockEnd.gif
  }
   InBlock.gif
  
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  /**////
   InBlock.gif
  /// Mp3结构
   ExpandedSubBlockEnd.gif
  
  ///
   ContractedSubBlock.gif
  
   ExpandedSubBlockStart.gif
  
  struct MP3#region struct MP3
   InBlock.gif
  public struct MP3
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {
   InBlock.gif
  
  public string filePath;
   InBlock.gif
  
  public string fileFileName;
   InBlock.gif
  
  public string fileComplete;
   InBlock.gif
  
  public bool
   InBlock.gif
  id3Title;
   InBlock.gif
  
  public string id3Artist;
   InBlock.gif
  
  public string id3Album;
   InBlock.gif
  
  public string id3Year;
   InBlock.gif
  
  public string
   InBlock.gif
  id3TrackNumber;
   InBlock.gif
  
  public byte id3Genre;
   InBlock.gif
  
  public long FileLength;
   InBlock.gif
  
  public int hours;
   InBlock.gif
  
  public int minutes;
   InBlock.gif
  seconds;
   InBlock.gif
  
   InBlock.gif
  
  // Required struct constructor
   InBlock.gif
  public MP3(string path, string name)
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  {
   InBlock.gif
  
  this.filePath = path;
   InBlock.gif
  
  this.fileFileName = name;
   InBlock.gif
  
  this.fileComplete = name;
   InBlock.gif
  
  this.hasID3Tag = false
   InBlock.gif
  this.id3Title = null
   InBlock.gif
  this.id3Artist this.id3Album = null
   InBlock.gif
  this.id3Year = null
   InBlock.gif
  this.id3Comment = null
   InBlock.gif
  0
   InBlock.gif
  this.FileLength = 0
   InBlock.gif
  this.id3Genre = 0
   InBlock.gif
  this.hours = 0
   InBlock.gif
  
   InBlock.gif
  
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  /**////
   InBlock.gif
  /// MP3文件帧结构
   ExpandedSubBlockEnd.gif
  
  ///
   ContractedSubBlock.gif
  
   ExpandedSubBlockStart.gif
  
  struct Mp3Frame#region struct Mp3Frame
   InBlock.gif
  internal struct Mp3Frame
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {
   InBlock.gif
  
  public int version; // MPEG版本(2+,2,1,0表示保留)
   InBlock.gif
  layer; // 层级(1,2,3,0表示保留)
   InBlock.gif
  public int 是否受CRC校验保护(1为保护,0为未保护)
   InBlock.gif
  public int frameSize; // 帧长度 bitrate; // 速率,bps
   InBlock.gif
  public int simplingRate; // paddingBits; // 填充位数
   InBlock.gif
  public int channel; //
   InBlock.gif
  
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  /**////
   InBlock.gif
  /// 计算帧长度
   ExpandedSubBlockEnd.gif
  
  ///
   InBlock.gif
  
  public int CalcFrameSize()
   ExpandedSubBlockStart.gif
  
   ContractedSubBlock.gif
  
  
   dot.gif
  {
   InBlock.gif
  
  // 计算帧长度的公式
   InBlock.gif
  this.frameSize = ((this.version == 1 ? 144 : 72
   ExpandedBlockEnd.gif
  }
   None.gif
  
  很显然,这事儿还没干完,先留着,以后再干~~~

本文转自
http://www.cnblogs.com/moye/archive/2007/08/08/848114.html

你可能感兴趣的:(关于MP3文件播放时间的计算)