mp3player
Version:
A mp3 player,get data by ajax and play by audiocontext or mediasource.it can download and reprocessing while playing
115 lines (112 loc) • 5.13 kB
JavaScript
/**
* MP3音频信息解析模块
* http://wiki.hydrogenaud.io/index.php?title=APEv2_specification
* http://www.docin.com/p-1261649617.html
* https://www.codeproject.com/Articles/8295/MPEG-Audio-Frame-Header
*
* audioInfo需要包括的字段:{
* fileSize: 音频文件大小(byte),
* frameSync: 同步头(16进制字符串),
* duration: 总时长(秒),
* sampleRate: 采样率,
* audioDataOffset: audioData开始偏移量(相对于0字节位置),
* totalSize: audioData总大小(仅当音频码率模式为VBR时返回),
* toc: 音频数据索引表(仅当音频码率模式为VBR时返回)
* }
*/
import requestRange from '../common/range';
import bitStream from '../common/bitstream';
import Util from '../common/util';
import Mp3Header from './header';
import Mp3Id3Tag from './id3tag';
//MP3播放信息解析对象
var MP3Info = {
init: function(url, opt) {
var self = this;
var emptyFun = function() {};
this.url = url;
this.decrypt = this.onloadedmetadata = emptyFun;
this.indexSize = 100; //分区数,默认100
this.audioInfo = {}; //存储mp3相关的信息
if (typeof opt == 'object') {
opt.onbeforedecode && (this.decrypt = opt.onbeforedecode);
opt.onloadedmetadata && (this.onloadedmetadata = opt.onloadedmetadata);
opt.indexSize && (this.indexSize = opt.indexSize);
}
return new Promise(function(resolve, reject) {
self._loadHeaderInfo(resolve, reject);
}).then(function() {
return self._loadFirstFrame();
}).then(function(arrayBuffer) {
var header = new Mp3Header(new bitStream(arrayBuffer));
var result = header.parseHeader(true);
if (result) {
self.audioInfo.toc = header.toc;
self.audioInfo.totalSize = header.totalBytes;
self.audioInfo.sampleRate = header.sampleRate;
self.audioInfo.frameSync = header.frameSync;
self.audioInfo.duration = header.totalDuration;
self.audioInfo.bitRate = header.bitRate;
if (!self.audioInfo.toc) { //cbr模式
return self._getFooterLength();
} else {
self.onloadedmetadata(self.audioInfo.duration);
return self.audioInfo;
}
} else {
return false;
}
});
},
//ajax获取音频头部标签头(32B)
_loadHeaderInfo: function(resolve, reject) {
var self = this;
requestRange(self.url, 0, 32 * 8 + 32 * 8 - 1, {
onsuccess: function(request) { //加载前32个字节(判断是否存在ID3V2|Ape头)
var arrayBuffer = request.response;
var contetnRange = request.getResponseHeader('Content-Range');
var length = 0;
var id3tag = null;
self.decrypt(arrayBuffer); //解密
id3tag = new Mp3Id3Tag(arrayBuffer);
self.audioInfo.audioDataOffset = id3tag.parseId3V2() + id3tag.parseApe();
self.audioInfo.fileSize = parseInt(contetnRange.substr(contetnRange.indexOf('/') + 1));
resolve();
}
});
},
//加载第一个数据帧(用来判断音频码率模式)
_loadFirstFrame: function(resolve, reject) {
var self = this;
return new Promise(function(resolve, reject) {
requestRange(self.url, self.audioInfo.audioDataOffset, self.audioInfo.audioDataOffset + 156 * 8 - 1, {
onsuccess: function(request) {
var arrayBuffer = request.response;
self.decrypt(arrayBuffer); //解密
resolve(arrayBuffer);
}
})
})
},
//获取尾部额外信息长度(可能存在id3v1或者ape信息)
_getFooterLength: function() {
var self = this;
return new Promise(function(resolve, reject) {
requestRange(self.url, self.audioInfo.fileSize - (128 + 32), self.audioInfo.fileSize - 1, {
onsuccess: function(request) {
var arrayBuffer = request.response;
var id3tag = null;
var length = 0;
self.decrypt(arrayBuffer); //解密
id3tag = new Mp3Id3Tag(arrayBuffer);
self.audioInfo.footerLength = id3tag.parseId3V1() + id3tag.parseApe();
self.audioInfo.totalSize = self.audioInfo.fileSize - self.audioInfo.audioDataOffset - self.audioInfo.footerLength;
self.audioInfo.duration = self.audioInfo.totalSize * 8 / self.audioInfo.bitRate;
self.onloadedmetadata(self.audioInfo);
resolve(self.audioInfo);
}
})
})
}
}
export default MP3Info;