Implement m4a
This commit is contained in:
@@ -25,3 +25,75 @@ exports.getInt24 = function getInt24 (b, offset, big_endian) {
|
||||
if (int < 0) int += 16777216;
|
||||
return int;
|
||||
};
|
||||
|
||||
var decodeString = exports.decodeString = function decodeString(b, charset, start, end) {
|
||||
switch (charset) {
|
||||
case 'ascii':
|
||||
return {
|
||||
text: b.toString(charset, start, end),
|
||||
length: end - start
|
||||
};
|
||||
case 'utf16':
|
||||
var bytes = getBytes(b, start, end);
|
||||
return {
|
||||
text: readUTF16String(bytes),
|
||||
length: bytes.length
|
||||
};
|
||||
case 'utf8':
|
||||
var text = b.toString(charset, start, end);
|
||||
return {
|
||||
text: text,
|
||||
length: Buffer.byteLength(text)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
var getBytes = function getBytes (b, start, end) {
|
||||
var i = start,
|
||||
a = [];
|
||||
|
||||
while (i <= end) {
|
||||
a.push(b[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
return a;
|
||||
};
|
||||
|
||||
var readUTF16String = function readUTF16String (bytes) {
|
||||
var ix = 0,
|
||||
offset1 = 1,
|
||||
offset2 = 0,
|
||||
maxBytes = Math.min(maxBytes || bytes.length, bytes.length);
|
||||
|
||||
if (bytes[0] === 0xFE && bytes[1] === 0xFF) {
|
||||
bigEndian = true;
|
||||
ix = 2;
|
||||
offset1 = 0;
|
||||
offset2 = 1;
|
||||
} else if (bytes[0] === 0xFF && bytes[1] === 0xFE) {
|
||||
bigEndian = false;
|
||||
ix = 2;
|
||||
}
|
||||
|
||||
var arr = [];
|
||||
for (var j = 0; ix < maxBytes; j++) {
|
||||
var byte1 = bytes[ix + offset1],
|
||||
byte2 = bytes[ix + offset2],
|
||||
word1 = (byte1 << 8) + byte2;
|
||||
ix += 2;
|
||||
|
||||
if (word1 === 0x0000) {
|
||||
break;
|
||||
} else if (byte1 < 0xD8 || byte1 >= 0xE0) {
|
||||
arr[j] = String.fromCharCode(word1);
|
||||
} else {
|
||||
var byte3 = bytes[ix+offset1],
|
||||
byte4 = bytes[ix+offset2],
|
||||
word2 = (byte3 << 8) + byte4;
|
||||
ix += 2;
|
||||
arr[j] = String.fromCharCode(word1, word2);
|
||||
}
|
||||
}
|
||||
return arr.join('');
|
||||
};
|
||||
|
||||
+5
-76
@@ -1,7 +1,8 @@
|
||||
var Buffer = require('buffer').Buffer,
|
||||
strtok = require('strtok'),
|
||||
common = require('./common'),
|
||||
findZero = common.findZero;
|
||||
var Buffer = require('buffer').Buffer,
|
||||
strtok = require('strtok'),
|
||||
common = require('./common'),
|
||||
findZero = common.findZero,
|
||||
decodeString = common.decodeString;
|
||||
|
||||
exports.readData = function readData (b, type, offset, length, flags, major) {
|
||||
major || (major = 3);
|
||||
@@ -120,28 +121,6 @@ var getTextEncoding = function getTextEncoding (byte) {
|
||||
return 'utf8';
|
||||
};
|
||||
|
||||
var decodeString = function decodeString(b, charset, start, end) {
|
||||
switch (charset) {
|
||||
case 'ascii':
|
||||
return {
|
||||
text: b.toString(charset, start, end),
|
||||
length: end - start
|
||||
};
|
||||
case 'utf16':
|
||||
var bytes = getBytes(b, start, end);
|
||||
return {
|
||||
text: readUTF16String(bytes),
|
||||
length: bytes.length
|
||||
};
|
||||
case 'utf8':
|
||||
var text = b.toString(charset, start, end);
|
||||
return {
|
||||
text: text,
|
||||
length: Buffer.byteLength(text)
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
var PICTURE_TYPE = exports.PICTURE_TYPE = [
|
||||
"32x32 pixels 'file icon' (PNG only)",
|
||||
"Other file icon",
|
||||
@@ -164,53 +143,3 @@ var PICTURE_TYPE = exports.PICTURE_TYPE = [
|
||||
"Band/artist logotype",
|
||||
"Publisher/Studio logotype"
|
||||
];
|
||||
|
||||
var getBytes = function getBytes (b, start, end) {
|
||||
var i = start,
|
||||
a = [];
|
||||
|
||||
while (i <= end) {
|
||||
a.push(b[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
return a;
|
||||
};
|
||||
|
||||
var readUTF16String = function readUTF16String (bytes) {
|
||||
var ix = 0,
|
||||
offset1 = 1,
|
||||
offset2 = 0,
|
||||
maxBytes = Math.min(maxBytes || bytes.length, bytes.length);
|
||||
|
||||
if (bytes[0] === 0xFE && bytes[1] === 0xFF) {
|
||||
bigEndian = true;
|
||||
ix = 2;
|
||||
offset1 = 0;
|
||||
offset2 = 1;
|
||||
} else if (bytes[0] === 0xFF && bytes[1] === 0xFE) {
|
||||
bigEndian = false;
|
||||
ix = 2;
|
||||
}
|
||||
|
||||
var arr = [];
|
||||
for (var j = 0; ix < maxBytes; j++) {
|
||||
var byte1 = bytes[ix + offset1],
|
||||
byte2 = bytes[ix + offset2],
|
||||
word1 = (byte1 << 8) + byte2;
|
||||
ix += 2;
|
||||
|
||||
if (word1 === 0x0000) {
|
||||
break;
|
||||
} else if (byte1 < 0xD8 || byte1 >= 0xE0) {
|
||||
arr[j] = String.fromCharCode(word1);
|
||||
} else {
|
||||
var byte3 = bytes[ix+offset1],
|
||||
byte4 = bytes[ix+offset2],
|
||||
word2 = (byte3 << 8) + byte4;
|
||||
ix += 2;
|
||||
arr[j] = String.fromCharCode(word1, word2);
|
||||
}
|
||||
}
|
||||
return arr.join('');
|
||||
};
|
||||
|
||||
+98
-1
@@ -1,4 +1,101 @@
|
||||
var strtok = require('strtok'),
|
||||
common = require('./common'),
|
||||
getInt24 = common.getInt24;
|
||||
|
||||
exports.readTags = function readTags () {
|
||||
var buffer = this.buffer;
|
||||
var tag = {};
|
||||
readAtom(this.buffer, tag, 0, this.buffer.length);
|
||||
return tag;
|
||||
};
|
||||
|
||||
var readAtom = function readAtom (b, tag, offset, length, indent) {
|
||||
var seek = offset,
|
||||
atom_size,
|
||||
atom_name;
|
||||
|
||||
indent = indent === undefined ? '' : indent + ' ';
|
||||
|
||||
while (seek < offset + length) {
|
||||
atom_offset = seek;
|
||||
|
||||
atom_size = strtok.UINT32_BE.get(b, seek);
|
||||
if (atom_size === 0) return;
|
||||
|
||||
if (b[seek + 4] === 169) {
|
||||
atom_name = b.toString('ascii', seek + 5, seek + 5 + 3);
|
||||
} else {
|
||||
atom_name = b.toString('ascii', seek + 4, seek + 4 + 4);
|
||||
}
|
||||
|
||||
if (~CONTAINER_ATOMS.indexOf(atom_name)) {
|
||||
if (atom_name === 'meta') seek += 4;
|
||||
return readAtom(b, tag, seek + 8, atom_size - 8, indent);
|
||||
}
|
||||
|
||||
if (ATOMS[atom_name]) {
|
||||
var klass = getInt24(b, seek + 16 + 1, true),
|
||||
atom = ATOMS[atom_name],
|
||||
type = TYPES[klass];
|
||||
|
||||
if (atom_name === 'trkn') {
|
||||
tag[atom[0]] = b[seek + 16 + 11];
|
||||
tag['count'] = b[seek + 16 + 13];
|
||||
} else {
|
||||
var data_start = seek + 16 + 4 + 4,
|
||||
data_end = atom_size - 16 - 4 - 4;
|
||||
|
||||
switch (type) {
|
||||
case 'text':
|
||||
tag[atom[0]] = b.toString('utf8', data_start, data_start + data_end);
|
||||
break;
|
||||
case 'uint8':
|
||||
tag[atom[0]] = strtok.UINT16_BE.get(b, data_start);
|
||||
break;
|
||||
case 'jpeg':
|
||||
case 'png':
|
||||
tag[atom[0]] = {
|
||||
format: 'image/' + type,
|
||||
data: b.slice(data_start, data_start + data_end)
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
seek += atom_size;
|
||||
}
|
||||
};
|
||||
|
||||
var TYPES = exports.TYPES = {
|
||||
'0' : 'uint8',
|
||||
'1' : 'text',
|
||||
'13' : 'jpeg',
|
||||
'14' : 'png',
|
||||
'21' : 'uint8'
|
||||
};
|
||||
|
||||
var CONTAINER_ATOMS = exports.CONTAINER_ATOMS = [
|
||||
'moov',
|
||||
'udta',
|
||||
'meta',
|
||||
'ilst'
|
||||
];
|
||||
|
||||
var ATOMS = exports.ATOMS = {
|
||||
'alb': ['album'],
|
||||
'art': ['artist'],
|
||||
'ART': ['artist'],
|
||||
'aART': ['artist'],
|
||||
'day': ['year'],
|
||||
'nam': ['title'],
|
||||
'gen': ['genre'],
|
||||
'trkn': ['track'],
|
||||
'wrt': ['composer'],
|
||||
'too': ['encoder'],
|
||||
'cprt': ['copyright'],
|
||||
'covr': ['picture'],
|
||||
'grp': ['grouping'],
|
||||
'keyw': ['keyword'],
|
||||
'lyr': ['lyrics'],
|
||||
'gen': ['genre']
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user