1
0
mirror of synced 2026-05-22 22:53:20 +00:00

Implement m4a

This commit is contained in:
Tim-Smart
2010-09-01 01:40:55 +12:00
parent 8189121269
commit b4e6a268f6
3 changed files with 175 additions and 77 deletions
+72
View File
@@ -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
View File
@@ -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
View File
@@ -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']
};