Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | 1x | /** * MPEG parser helper */ const MpegAudio = { BitratesMap: [ 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160], SamplingRateMap: [44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000], SamplesCoefficients: [ // MPEG 2.5 [ 0, // Reserved 72, // Layer3 144, // Layer2 12 // Layer1 ], // Reserved [ 0, // Reserved 0, // Layer3 0, // Layer2 0 // Layer1 ], // MPEG 2 [ 0, // Reserved 72, // Layer3 144, // Layer2 12 // Layer1 ], // MPEG 1 [ 0, // Reserved 144, // Layer3 144, // Layer2 12 // Layer1 ] ], BytesInSlot: [ 0, // Reserved 1, // Layer3 1, // Layer2 4 // Layer1 ], appendFrame: function (track, data, offset, pts, frameIndex) { // Using http://www.datavoyage.com/mpgscript/mpeghdr.htm as a reference if (offset + 24 > data.length) return undefined; let header = this.parseHeader(data, offset); if (header && offset + header.frameLength <= data.length) { let frameDuration = header.samplesPerFrame * 90000 / header.sampleRate; let stamp = pts + frameIndex * frameDuration; let sample = { unit: data.subarray(offset, offset + header.frameLength), pts: stamp, dts: stamp }; track.config = []; track.channelCount = header.channelCount; track.samplerate = header.sampleRate; track.samples.push(sample); track.len += header.frameLength; return { sample, length: header.frameLength }; } return undefined; }, parseHeader: function (data, offset) { let headerB = (data[offset + 1] >> 3) & 3; let headerC = (data[offset + 1] >> 1) & 3; let headerE = (data[offset + 2] >> 4) & 15; let headerF = (data[offset + 2] >> 2) & 3; let headerG = (data[offset + 2] >> 1) & 1; if (headerB !== 1 && headerE !== 0 && headerE !== 15 && headerF !== 3) { let columnInBitrates = headerB === 3 ? (3 - headerC) : (headerC === 3 ? 3 : 4); let bitRate = MpegAudio.BitratesMap[columnInBitrates * 14 + headerE - 1] * 1000; let columnInSampleRates = headerB === 3 ? 0 : headerB === 2 ? 1 : 2; let sampleRate = MpegAudio.SamplingRateMap[columnInSampleRates * 3 + headerF]; let channelCount = data[offset + 3] >> 6 === 3 ? 1 : 2; // If bits of channel mode are `11` then it is a single channel (Mono) let sampleCoefficient = MpegAudio.SamplesCoefficients[headerB][headerC]; let bytesInSlot = MpegAudio.BytesInSlot[headerC]; let samplesPerFrame = sampleCoefficient * 8 * bytesInSlot; let frameLength = parseInt(sampleCoefficient * bitRate / sampleRate + headerG, 10) * bytesInSlot; return { sampleRate, channelCount, frameLength, samplesPerFrame }; } return undefined; }, isHeaderPattern: function (data, offset) { return data[offset] === 0xff && (data[offset + 1] & 0xe0) === 0xe0 && (data[offset + 1] & 0x06) !== 0x00; }, isHeader: function (data, offset) { // Look for MPEG header | 1111 1111 | 111X XYZX | where X can be either 0 or 1 and Y or Z should be 1 // Layer bits (position 14 and 15) in header should be always different from 0 (Layer I or Layer II or Layer III) // More info http://www.mp3-tech.org/programmer/frame_header.html if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) return true; return false; }, probe: function (data, offset) { // same as isHeader but we also check that MPEG frame follows last MPEG frame // or end of data is reached if (offset + 1 < data.length && this.isHeaderPattern(data, offset)) { // MPEG header Length let headerLength = 4; // MPEG frame Length let header = this.parseHeader(data, offset); let frameLength = headerLength; if (header && header.frameLength) frameLength = header.frameLength; let newOffset = offset + frameLength; if (newOffset === data.length || (newOffset + 1 < data.length && this.isHeaderPattern(data, newOffset))) return true; } return false; } }; export default MpegAudio; |