mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-09 14:44:05 +09:00
mp3 test
This commit is contained in:
283
assets/disk0/tvdos/include/js-mp3/frameheader.js
Normal file
283
assets/disk0/tvdos/include/js-mp3/frameheader.js
Normal file
@@ -0,0 +1,283 @@
|
||||
var consts = require('A:/tvdos/include/js-mp3/consts.js');
|
||||
|
||||
var Frameheader = {
|
||||
createNew: function (value) {
|
||||
// A mepg1FrameHeader is MPEG1 Layer 1-3 frame header
|
||||
var fh = {
|
||||
value: value
|
||||
};
|
||||
|
||||
/**
|
||||
* ID returns this header's ID stored in position 20,19
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
fh.id = function () {
|
||||
return ((fh.value & 0x00180000) >>> 19) >>> 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Layer returns the mpeg layer of this frame stored in position 18,17
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
fh.layer = function () {
|
||||
return ((fh.value & 0x00060000) >>> 17) >>> 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* ProtectionBit returns the protection bit stored in position 16
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
fh.protectionBit = function () {
|
||||
return ((fh.value & 0x00010000) >>> 16) >>> 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* BirateIndex returns the bitrate index stored in position 15,12
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
fh.bitrateIndex = function () {
|
||||
return ((fh.value & 0x0000f000) >>> 12) >>> 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* SamplingFrequency returns the SamplingFrequency in Hz stored in position 11,10
|
||||
*
|
||||
* @returns {*}
|
||||
* @constructor
|
||||
*/
|
||||
fh.samplingFrequency = function () {
|
||||
return consts.newSamplingFrequencyInstance(((fh.value & 0x00000c00) >>> 10) >>> 0)
|
||||
};
|
||||
|
||||
/**
|
||||
* PaddingBit returns the padding bit stored in position 9
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
fh.paddingBit = function () {
|
||||
return ((fh.value & 0x00000200) >>> 9) >>> 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* PrivateBit returns the private bit stored in position 8 - this bit may be used to store
|
||||
* arbitrary data to be used by an application
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
fh.privateBit = function () {
|
||||
return ((fh.value & 0x00000100) >>> 8) >>> 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Mode returns the channel mode, stored in position 7,6
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
fh.mode = function () {
|
||||
return ((fh.value & 0x000000c0) >>> 6) >>> 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* modeExtension returns the mode_extension - for use with Joint Stereo - stored in
|
||||
* position 4,5
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
fh.modeExtension = function () {
|
||||
return ((fh.value & 0x00000030) >>> 4) >>> 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* UseMSStereo returns a boolean value indicating whether the frame uses middle/side stereo.
|
||||
*
|
||||
* @returns {*}
|
||||
*/
|
||||
fh.useMSStereo = function () {
|
||||
if (fh.mode() !== consts.ModeJointStereo) {
|
||||
return false;
|
||||
}
|
||||
return (fh.modeExtension() & 0x2) !== 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* UseIntensityStereo returns a boolean value indicating whether the frame uses intensity
|
||||
* stereo.
|
||||
*
|
||||
* @returns {*}
|
||||
*/
|
||||
fh.useIntensityStereo = function () {
|
||||
if (fh.mode() !== consts.ModeJointStereo) {
|
||||
return false;
|
||||
}
|
||||
return (fh.modeExtension() & 0x1) !== 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copyright returns whether or not this recording is copywritten - stored in position 3
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
fh.copyright = function () {
|
||||
return ((fh.value & 0x00000008) >>> 3) >>> 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* OriginalOrCopy returns whether or not this is an Original recording or a copy of one -
|
||||
* stored in position 2
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
fh.originalOrCopy = function () {
|
||||
return ((fh.value & 0x00000004) >>> 2) >>> 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Emphasis returns emphasis - the emphasis indication is here to tell the decoder that the
|
||||
* file must be de-emphasized - stored in position 0,1
|
||||
*
|
||||
* @returns {number}
|
||||
*/
|
||||
fh.emphasis = function () {
|
||||
return (fh.value & 0x00000003) >>> 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* IsValid returns a boolean value indicating whether the header is valid or not.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
fh.isValid = function () {
|
||||
const sync = 0xffe00000;
|
||||
if ((fh.value & sync) >>> 0 !== sync) {
|
||||
return false;
|
||||
}
|
||||
if (fh.id() === consts.VersionReserved) {
|
||||
return false;
|
||||
}
|
||||
if (fh.bitrateIndex() === 15) {
|
||||
return false;
|
||||
}
|
||||
if (fh.samplingFrequency().value === consts.SamplingFrequencyReserved) {
|
||||
return false;
|
||||
}
|
||||
if (fh.layer() === consts.LayerReserved) {
|
||||
return false;
|
||||
}
|
||||
if (fh.emphasis() === 2) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
fh.frameSize = function () {
|
||||
var value = (144 * Frameheader.bitrate(fh.layer(), fh.bitrateIndex()))
|
||||
/ fh.samplingFrequency().Int()
|
||||
+ fh.paddingBit();
|
||||
return Math.floor(value);
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
fh.numberOfChannels = function () {
|
||||
if (fh.mode() === consts.ModeSingleChannel) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
};
|
||||
|
||||
return fh;
|
||||
},
|
||||
|
||||
bitrate: function (layer, index) {
|
||||
switch (layer) {
|
||||
case consts.Layer1:
|
||||
return [0, 32000, 64000, 96000, 128000, 160000, 192000, 224000,
|
||||
256000, 288000, 320000, 352000, 384000, 416000, 448000][index];
|
||||
case consts.Layer2:
|
||||
return [0, 32000, 48000, 56000, 64000, 80000, 96000, 112000,
|
||||
128000, 160000, 192000, 224000, 256000, 320000, 384000][index];
|
||||
case consts.Layer3:
|
||||
return [0, 32000, 40000, 48000, 56000, 64000, 80000, 96000,
|
||||
112000, 128000, 160000, 192000, 224000, 256000, 320000][index];
|
||||
}
|
||||
throw new Error('not reached');
|
||||
},
|
||||
|
||||
read: function (source, position) {
|
||||
var pos = position;
|
||||
|
||||
var result = source.readFull(4);
|
||||
if (result.err) {
|
||||
return {
|
||||
err: result.err
|
||||
}
|
||||
}
|
||||
var buf = result.buf;
|
||||
if (buf.byteLength < 4) {
|
||||
return {
|
||||
h: 0,
|
||||
position: 0,
|
||||
err: "UnexpectedEOF readHeader (1)"
|
||||
}
|
||||
}
|
||||
|
||||
var b1 = buf[0] >>> 0;
|
||||
var b2 = buf[1] >>> 0;
|
||||
var b3 = buf[2] >>> 0;
|
||||
var b4 = buf[3] >>> 0;
|
||||
|
||||
var fh = Frameheader.createNew((((b1 << 24) >>> 0) | ((b2 << 16) >>> 0) | ((b3 << 8) >>> 0) | ((b4 << 0) >>> 0)) >>> 0);
|
||||
while (!fh.isValid()) {
|
||||
// stopPosition++;
|
||||
|
||||
result = source.readFull(1);
|
||||
if (result.err) {
|
||||
return {
|
||||
err: result.err
|
||||
}
|
||||
}
|
||||
buf = result.buf;
|
||||
|
||||
if (buf.byteLength < 1) {
|
||||
return {
|
||||
h: 0,
|
||||
position: 0,
|
||||
err: "UnexpectedEOF readHeader (2)"
|
||||
}
|
||||
}
|
||||
|
||||
b1 = b2;
|
||||
b2 = b3;
|
||||
b3 = b4;
|
||||
b4 = buf[0] >>> 0;
|
||||
|
||||
fh = Frameheader.createNew((((b1 << 24) >>> 0) | ((b2 << 16) >>> 0) | ((b3 << 8) >>> 0) | ((b4 << 0) >>> 0)) >>> 0);
|
||||
pos++;
|
||||
}
|
||||
|
||||
// If we get here we've found the sync word, and can decode the header
|
||||
// which is in the low 20 bits of the 32-bit sync+header word.
|
||||
if (fh.bitrateIndex() === 0) {
|
||||
return {
|
||||
h: 0,
|
||||
position: 0,
|
||||
err: "mp3: free bitrate format is not supported. Header word is " + fh.value + " at position " + position
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
h: fh,
|
||||
position: pos
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports = Frameheader;
|
||||
Reference in New Issue
Block a user