该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
本类写文件部分没有测试,读取部分通过测试,也可以用于上一篇的图片解码的文件操作,经测试,解码速度还会加快。
#pragma once
//写没有测试
#include
class FileMap
{
public:
enum fmode {read_only, read_write};
FileMap();
~FileMap();
void open(const char *file_name, fmode mode, DWORD len = 0);
size_t getSize(unsigned long *high=0);
unsigned char * getView() const;
bool flushView(size_t length);
void close();
// 或许要禁用复制和赋值
private:
HANDLE _file;
HANDLE _filemap;
LPVOID _pbuf;
};
然后,我们再来看使用文件内存文件映射后,readFrame的代码变化:
bool MpegLayer3::readFrame()
{
if(_check_frame(mpeg_data) && _is_sync_frame())
{
int frame_size = getFrameLength() - 4;
mpeg_data +=4;//跳过帧头四字节
if(frm.crc)//跳过CRC 2字节
{
mpeg_data += 2;
frame_size -= 2;
}
byte *p = _mp3dec.set_decode_buf(frame_size);
memcpy(p, mpeg_data, frame_size);//读取main_data数据到待解码区
mpeg_data += frame_size; //更新到下一帧位置
return true;
}
if(_sync_frame()) return true;
return false;
}
代码是不是很精简了?同步帧的代码也由于文件映射的使用,从42行,减少到26行,一些相关的函数也由于文件映射而用不上了,速度也快了很多。当然,第二份代码我只用了半天改写主要部分,可以播放,没有信息显示,感兴趣的可以根据第一份代码继续完成信息显示,做为自己的编码练习吧。
再谈一下同步帧的设计思路,这部分和源代码不同,源代码使用的是三帧检测法,写得很复杂,超过100多行,感兴趣的可以去读原代码,我采用的自己弄的双帧检测法,经过测试,也能很好的定位有错误帧的mp3,当然你也可以自行设计,基本过程就是定位数据流中的0xff,由于头部ID3V2标签中可能有jpeg图片数据,而jpeg头部数据也是0xff开头,也以一般要计算ID3V2标签长度,跳过这部分数据再进行定位首帧,可以加快定位,然后记录首帧的关键部分,再检测下一帧的关键数据是否和首帧相同,如果不是首帧,则检测当前帧是否是同步帧,下一帧的位置是当前帧位置+帧长(包括CRC的2个字节)。
四、最后谈一下Vbr可变帧mp3播放时长的计算公式: