music-metadata 7.12.5 → 8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -31
- package/lib/ParserFactory.d.ts +3 -3
- package/lib/ParserFactory.js +37 -41
- package/lib/aiff/AiffParser.d.ts +2 -2
- package/lib/aiff/AiffParser.js +25 -17
- package/lib/aiff/AiffToken.d.ts +3 -2
- package/lib/aiff/AiffToken.js +13 -12
- package/lib/apev2/APEv2Parser.d.ts +5 -5
- package/lib/apev2/APEv2Parser.js +29 -32
- package/lib/apev2/APEv2TagMapper.d.ts +1 -1
- package/lib/apev2/APEv2TagMapper.js +2 -6
- package/lib/apev2/APEv2Token.d.ts +1 -1
- package/lib/apev2/APEv2Token.js +13 -19
- package/lib/asf/AsfObject.d.ts +5 -4
- package/lib/asf/AsfObject.js +42 -56
- package/lib/asf/AsfParser.d.ts +1 -1
- package/lib/asf/AsfParser.js +15 -19
- package/lib/asf/AsfTagMapper.d.ts +2 -2
- package/lib/asf/AsfTagMapper.js +2 -6
- package/lib/asf/AsfUtil.d.ts +3 -2
- package/lib/asf/AsfUtil.js +4 -7
- package/lib/asf/GUID.d.ts +1 -1
- package/lib/asf/GUID.js +1 -4
- package/lib/browser.js +99 -0
- package/lib/common/BasicParser.d.ts +4 -4
- package/lib/common/BasicParser.js +1 -5
- package/lib/common/CaseInsensitiveTagMap.d.ts +3 -3
- package/lib/common/CaseInsensitiveTagMap.js +2 -6
- package/lib/common/CombinedTagMapper.d.ts +4 -4
- package/lib/common/CombinedTagMapper.js +20 -24
- package/lib/common/FourCC.d.ts +1 -1
- package/lib/common/FourCC.js +3 -6
- package/lib/common/GenericTagMapper.d.ts +4 -4
- package/lib/common/GenericTagMapper.js +2 -6
- package/lib/common/GenericTagTypes.js +5 -10
- package/lib/common/MetadataCollector.d.ts +2 -2
- package/lib/common/MetadataCollector.js +20 -25
- package/lib/common/RandomFileReader.d.ts +2 -2
- package/lib/common/RandomFileReader.js +2 -6
- package/lib/common/RandomUint8ArrayReader.d.ts +1 -1
- package/lib/common/RandomUint8ArrayReader.js +1 -5
- package/lib/common/Util.d.ts +1 -1
- package/lib/common/Util.js +11 -25
- package/lib/core.d.ts +4 -4
- package/lib/core.js +18 -28
- package/lib/dsdiff/DsdiffParser.d.ts +1 -1
- package/lib/dsdiff/DsdiffParser.js +24 -28
- package/lib/dsdiff/DsdiffToken.d.ts +3 -3
- package/lib/dsdiff/DsdiffToken.js +4 -7
- package/lib/dsf/DsfChunk.d.ts +1 -1
- package/lib/dsf/DsfChunk.js +8 -11
- package/lib/dsf/DsfParser.d.ts +1 -1
- package/lib/dsf/DsfParser.js +13 -17
- package/lib/flac/FlacParser.d.ts +5 -5
- package/lib/flac/FlacParser.js +22 -26
- package/lib/id3v1/ID3v1Parser.d.ts +2 -2
- package/lib/id3v1/ID3v1Parser.js +16 -21
- package/lib/id3v1/ID3v1TagMap.d.ts +1 -1
- package/lib/id3v1/ID3v1TagMap.js +2 -6
- package/lib/id3v2/AbstractID3Parser.d.ts +2 -2
- package/lib/id3v2/AbstractID3Parser.js +13 -17
- package/lib/id3v2/FrameParser.d.ts +2 -2
- package/lib/id3v2/FrameParser.js +12 -17
- package/lib/id3v2/ID3v22TagMapper.d.ts +2 -2
- package/lib/id3v2/ID3v22TagMapper.js +4 -8
- package/lib/id3v2/ID3v24TagMapper.d.ts +3 -3
- package/lib/id3v2/ID3v24TagMapper.js +5 -9
- package/lib/id3v2/ID3v2Parser.d.ts +3 -3
- package/lib/id3v2/ID3v2Parser.js +10 -14
- package/lib/id3v2/ID3v2Token.d.ts +2 -2
- package/lib/id3v2/ID3v2Token.js +9 -12
- package/lib/iff/index.d.ts +1 -1
- package/lib/iff/index.js +4 -7
- package/lib/index.d.ts +4 -28
- package/lib/index.js +14 -44
- package/lib/lyrics3/Lyrics3.d.ts +1 -1
- package/lib/lyrics3/Lyrics3.js +3 -7
- package/lib/matroska/MatroskaDtd.d.ts +1 -1
- package/lib/matroska/MatroskaDtd.js +111 -114
- package/lib/matroska/MatroskaParser.d.ts +5 -5
- package/lib/matroska/MatroskaParser.js +20 -24
- package/lib/matroska/MatroskaTagMapper.d.ts +1 -1
- package/lib/matroska/MatroskaTagMapper.js +2 -6
- package/lib/matroska/types.d.ts +1 -1
- package/lib/matroska/types.js +6 -9
- package/lib/mp4/Atom.d.ts +2 -2
- package/lib/mp4/Atom.js +4 -8
- package/lib/mp4/AtomToken.d.ts +2 -2
- package/lib/mp4/AtomToken.js +29 -44
- package/lib/mp4/MP4Parser.d.ts +2 -2
- package/lib/mp4/MP4Parser.js +12 -16
- package/lib/mp4/MP4TagMapper.d.ts +1 -1
- package/lib/mp4/MP4TagMapper.js +4 -8
- package/lib/mpeg/ExtendedLameHeader.d.ts +2 -2
- package/lib/mpeg/ExtendedLameHeader.js +6 -9
- package/lib/mpeg/MpegParser.d.ts +1 -1
- package/lib/mpeg/MpegParser.js +17 -21
- package/lib/mpeg/ReplayGainDataFormat.d.ts +1 -1
- package/lib/mpeg/ReplayGainDataFormat.js +2 -5
- package/lib/mpeg/XingTag.d.ts +3 -3
- package/lib/mpeg/XingTag.js +9 -13
- package/lib/musepack/index.d.ts +1 -1
- package/lib/musepack/index.js +10 -12
- package/lib/musepack/sv7/BitReader.d.ts +1 -1
- package/lib/musepack/sv7/BitReader.js +2 -6
- package/lib/musepack/sv7/MpcSv7Parser.d.ts +1 -1
- package/lib/musepack/sv7/MpcSv7Parser.js +9 -13
- package/lib/musepack/sv7/StreamVersion7.d.ts +1 -1
- package/lib/musepack/sv7/StreamVersion7.js +3 -6
- package/lib/musepack/sv8/MpcSv8Parser.d.ts +1 -1
- package/lib/musepack/sv8/MpcSv8Parser.js +9 -13
- package/lib/musepack/sv8/StreamVersion8.d.ts +1 -1
- package/lib/musepack/sv8/StreamVersion8.js +5 -9
- package/lib/ogg/Ogg.js +1 -2
- package/lib/ogg/OggParser.d.ts +3 -3
- package/lib/ogg/OggParser.js +19 -24
- package/lib/ogg/opus/Opus.d.ts +1 -1
- package/lib/ogg/opus/Opus.js +2 -6
- package/lib/ogg/opus/OpusParser.d.ts +6 -6
- package/lib/ogg/opus/OpusParser.js +4 -8
- package/lib/ogg/speex/Speex.d.ts +1 -1
- package/lib/ogg/speex/Speex.js +3 -6
- package/lib/ogg/speex/SpeexParser.d.ts +6 -6
- package/lib/ogg/speex/SpeexParser.js +5 -9
- package/lib/ogg/theora/Theora.d.ts +1 -1
- package/lib/ogg/theora/Theora.js +2 -5
- package/lib/ogg/theora/TheoraParser.d.ts +5 -5
- package/lib/ogg/theora/TheoraParser.js +5 -9
- package/lib/ogg/vorbis/Vorbis.d.ts +3 -3
- package/lib/ogg/vorbis/Vorbis.js +6 -10
- package/lib/ogg/vorbis/VorbisDecoder.js +2 -6
- package/lib/ogg/vorbis/VorbisParser.d.ts +11 -11
- package/lib/ogg/vorbis/VorbisParser.js +18 -22
- package/lib/ogg/vorbis/VorbisTagMapper.d.ts +2 -2
- package/lib/ogg/vorbis/VorbisTagMapper.js +3 -7
- package/lib/riff/RiffChunk.d.ts +3 -3
- package/lib/riff/RiffChunk.js +3 -7
- package/lib/riff/RiffInfoTagMap.d.ts +2 -2
- package/lib/riff/RiffInfoTagMap.js +4 -8
- package/lib/type.d.ts +6 -5
- package/lib/type.js +1 -5
- package/lib/wav/BwfChunk.d.ts +1 -1
- package/lib/wav/BwfChunk.js +8 -11
- package/lib/wav/WaveChunk.d.ts +3 -3
- package/lib/wav/WaveChunk.js +4 -9
- package/lib/wav/WaveParser.d.ts +2 -2
- package/lib/wav/WaveParser.js +17 -21
- package/lib/wavpack/WavPackParser.d.ts +1 -1
- package/lib/wavpack/WavPackParser.js +17 -21
- package/lib/wavpack/WavPackToken.d.ts +1 -1
- package/lib/wavpack/WavPackToken.js +4 -8
- package/package.json +29 -41
package/lib/core.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import { Readable } from 'stream';
|
|
3
|
-
import * as strtok3 from 'strtok3/
|
|
4
|
-
import { IAudioMetadata, INativeTagDict, IOptions, IPicture, IPrivateOptions, IRandomReader, ITag } from './type';
|
|
5
|
-
export { IFileInfo } from 'strtok3/
|
|
3
|
+
import * as strtok3 from 'strtok3/core';
|
|
4
|
+
import { IAudioMetadata, INativeTagDict, IOptions, IPicture, IPrivateOptions, IRandomReader, ITag } from './type.js';
|
|
5
|
+
export { IFileInfo } from 'strtok3/core';
|
|
6
6
|
/**
|
|
7
7
|
* Parse audio from Node Stream.Readable
|
|
8
8
|
* @param stream - Stream to read the audio track from
|
package/lib/core.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const APEv2Parser_1 = require("./apev2/APEv2Parser");
|
|
8
|
-
const ID3v1Parser_1 = require("./id3v1/ID3v1Parser");
|
|
9
|
-
const Lyrics3_1 = require("./lyrics3/Lyrics3");
|
|
1
|
+
import * as strtok3 from 'strtok3/core';
|
|
2
|
+
import { ParserFactory } from './ParserFactory.js';
|
|
3
|
+
import { RandomUint8ArrayReader } from './common/RandomUint8ArrayReader.js';
|
|
4
|
+
import { APEv2Parser } from './apev2/APEv2Parser.js';
|
|
5
|
+
import { hasID3v1Header } from './id3v1/ID3v1Parser.js';
|
|
6
|
+
import { getLyricsHeaderLength } from './lyrics3/Lyrics3.js';
|
|
10
7
|
/**
|
|
11
8
|
* Parse audio from Node Stream.Readable
|
|
12
9
|
* @param stream - Stream to read the audio track from
|
|
@@ -14,10 +11,9 @@ const Lyrics3_1 = require("./lyrics3/Lyrics3");
|
|
|
14
11
|
* @param fileInfo - File information object or MIME-type string
|
|
15
12
|
* @returns Metadata
|
|
16
13
|
*/
|
|
17
|
-
function parseStream(stream, fileInfo, options = {}) {
|
|
14
|
+
export function parseStream(stream, fileInfo, options = {}) {
|
|
18
15
|
return parseFromTokenizer(strtok3.fromStream(stream, typeof fileInfo === 'string' ? { mimeType: fileInfo } : fileInfo), options);
|
|
19
16
|
}
|
|
20
|
-
exports.parseStream = parseStream;
|
|
21
17
|
/**
|
|
22
18
|
* Parse audio from Node Buffer
|
|
23
19
|
* @param uint8Array - Uint8Array holding audio data
|
|
@@ -26,65 +22,59 @@ exports.parseStream = parseStream;
|
|
|
26
22
|
* @returns Metadata
|
|
27
23
|
* Ref: https://github.com/Borewit/strtok3/blob/e6938c81ff685074d5eb3064a11c0b03ca934c1d/src/index.ts#L15
|
|
28
24
|
*/
|
|
29
|
-
async function parseBuffer(uint8Array, fileInfo, options = {}) {
|
|
30
|
-
const bufferReader = new
|
|
25
|
+
export async function parseBuffer(uint8Array, fileInfo, options = {}) {
|
|
26
|
+
const bufferReader = new RandomUint8ArrayReader(uint8Array);
|
|
31
27
|
await scanAppendingHeaders(bufferReader, options);
|
|
32
28
|
const tokenizer = strtok3.fromBuffer(uint8Array, typeof fileInfo === 'string' ? { mimeType: fileInfo } : fileInfo);
|
|
33
29
|
return parseFromTokenizer(tokenizer, options);
|
|
34
30
|
}
|
|
35
|
-
exports.parseBuffer = parseBuffer;
|
|
36
31
|
/**
|
|
37
32
|
* Parse audio from ITokenizer source
|
|
38
33
|
* @param tokenizer - Audio source implementing the tokenizer interface
|
|
39
34
|
* @param options - Parsing options
|
|
40
35
|
* @returns Metadata
|
|
41
36
|
*/
|
|
42
|
-
function parseFromTokenizer(tokenizer, options) {
|
|
43
|
-
return
|
|
37
|
+
export function parseFromTokenizer(tokenizer, options) {
|
|
38
|
+
return ParserFactory.parseOnContentType(tokenizer, options);
|
|
44
39
|
}
|
|
45
|
-
exports.parseFromTokenizer = parseFromTokenizer;
|
|
46
40
|
/**
|
|
47
41
|
* Create a dictionary ordered by their tag id (key)
|
|
48
42
|
* @param nativeTags list of tags
|
|
49
43
|
* @returns tags indexed by id
|
|
50
44
|
*/
|
|
51
|
-
function orderTags(nativeTags) {
|
|
45
|
+
export function orderTags(nativeTags) {
|
|
52
46
|
const tags = {};
|
|
53
47
|
for (const tag of nativeTags) {
|
|
54
48
|
(tags[tag.id] = (tags[tag.id] || [])).push(tag.value);
|
|
55
49
|
}
|
|
56
50
|
return tags;
|
|
57
51
|
}
|
|
58
|
-
exports.orderTags = orderTags;
|
|
59
52
|
/**
|
|
60
53
|
* Convert rating to 1-5 star rating
|
|
61
54
|
* @param rating: Normalized rating [0..1] (common.rating[n].rating)
|
|
62
55
|
* @returns Number of stars: 1, 2, 3, 4 or 5 stars
|
|
63
56
|
*/
|
|
64
|
-
function ratingToStars(rating) {
|
|
57
|
+
export function ratingToStars(rating) {
|
|
65
58
|
return rating === undefined ? 0 : 1 + Math.round(rating * 4);
|
|
66
59
|
}
|
|
67
|
-
exports.ratingToStars = ratingToStars;
|
|
68
60
|
/**
|
|
69
61
|
* Select most likely cover image.
|
|
70
62
|
* @param pictures Usually metadata.common.picture
|
|
71
63
|
* @return Cover image, if any, otherwise null
|
|
72
64
|
*/
|
|
73
|
-
function selectCover(pictures) {
|
|
65
|
+
export function selectCover(pictures) {
|
|
74
66
|
return pictures ? pictures.reduce((acc, cur) => {
|
|
75
67
|
if (cur.name && cur.name.toLowerCase() in ['front', 'cover', 'cover (front)'])
|
|
76
68
|
return cur;
|
|
77
69
|
return acc;
|
|
78
70
|
}) : null;
|
|
79
71
|
}
|
|
80
|
-
|
|
81
|
-
async function scanAppendingHeaders(randomReader, options = {}) {
|
|
72
|
+
export async function scanAppendingHeaders(randomReader, options = {}) {
|
|
82
73
|
let apeOffset = randomReader.fileSize;
|
|
83
|
-
if (await
|
|
74
|
+
if (await hasID3v1Header(randomReader)) {
|
|
84
75
|
apeOffset -= 128;
|
|
85
|
-
const lyricsLen = await
|
|
76
|
+
const lyricsLen = await getLyricsHeaderLength(randomReader);
|
|
86
77
|
apeOffset -= lyricsLen;
|
|
87
78
|
}
|
|
88
|
-
options.apeHeader = await
|
|
79
|
+
options.apeHeader = await APEv2Parser.findApeFooterOffset(randomReader, apeOffset);
|
|
89
80
|
}
|
|
90
|
-
exports.scanAppendingHeaders = scanAppendingHeaders;
|
|
@@ -1,42 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
const ID3v2Parser_1 = require("../id3v2/ID3v2Parser");
|
|
10
|
-
const DsdiffToken_1 = require("./DsdiffToken");
|
|
11
|
-
const debug = (0, debug_1.default)('music-metadata:parser:aiff');
|
|
1
|
+
import * as Token from 'token-types';
|
|
2
|
+
import initDebug from 'debug';
|
|
3
|
+
import * as strtok3 from 'strtok3/core';
|
|
4
|
+
import { FourCcToken } from '../common/FourCC.js';
|
|
5
|
+
import { BasicParser } from '../common/BasicParser.js';
|
|
6
|
+
import { ID3v2Parser } from '../id3v2/ID3v2Parser.js';
|
|
7
|
+
import { ChunkHeader64 } from './DsdiffToken.js';
|
|
8
|
+
const debug = initDebug('music-metadata:parser:aiff');
|
|
12
9
|
/**
|
|
13
10
|
* DSDIFF - Direct Stream Digital Interchange File Format (Phillips)
|
|
14
11
|
*
|
|
15
12
|
* Ref:
|
|
16
13
|
* - http://www.sonicstudio.com/pdf/dsd/DSDIFF_1.5_Spec.pdf
|
|
17
14
|
*/
|
|
18
|
-
class DsdiffParser extends
|
|
15
|
+
export class DsdiffParser extends BasicParser {
|
|
19
16
|
async parse() {
|
|
20
|
-
const header = await this.tokenizer.readToken(
|
|
17
|
+
const header = await this.tokenizer.readToken(ChunkHeader64);
|
|
21
18
|
if (header.chunkID !== 'FRM8')
|
|
22
19
|
throw new Error('Unexpected chunk-ID');
|
|
23
|
-
const type = (await this.tokenizer.readToken(
|
|
20
|
+
const type = (await this.tokenizer.readToken(FourCcToken)).trim();
|
|
24
21
|
switch (type) {
|
|
25
22
|
case 'DSD':
|
|
26
23
|
this.metadata.setFormat('container', `DSDIFF/${type}`);
|
|
27
24
|
this.metadata.setFormat('lossless', true);
|
|
28
|
-
return this.readFmt8Chunks(header.chunkSize - BigInt(
|
|
25
|
+
return this.readFmt8Chunks(header.chunkSize - BigInt(FourCcToken.len));
|
|
29
26
|
default:
|
|
30
27
|
throw Error(`Unsupported DSDIFF type: ${type}`);
|
|
31
28
|
}
|
|
32
29
|
}
|
|
33
30
|
async readFmt8Chunks(remainingSize) {
|
|
34
|
-
while (remainingSize >=
|
|
35
|
-
const chunkHeader = await this.tokenizer.readToken(
|
|
31
|
+
while (remainingSize >= ChunkHeader64.len) {
|
|
32
|
+
const chunkHeader = await this.tokenizer.readToken(ChunkHeader64);
|
|
36
33
|
// If the data is an odd number of bytes in length, a pad byte must be added at the end
|
|
37
34
|
debug(`Chunk id=${chunkHeader.chunkID}`);
|
|
38
35
|
await this.readData(chunkHeader);
|
|
39
|
-
remainingSize -= (BigInt(
|
|
36
|
+
remainingSize -= (BigInt(ChunkHeader64.len) + chunkHeader.chunkSize);
|
|
40
37
|
}
|
|
41
38
|
}
|
|
42
39
|
async readData(header) {
|
|
@@ -48,15 +45,15 @@ class DsdiffParser extends BasicParser_1.BasicParser {
|
|
|
48
45
|
debug(`DSDIFF version=${version}`);
|
|
49
46
|
break;
|
|
50
47
|
case 'PROP': // 3.2 PROPERTY CHUNK
|
|
51
|
-
const propType = await this.tokenizer.readToken(
|
|
48
|
+
const propType = await this.tokenizer.readToken(FourCcToken);
|
|
52
49
|
if (propType !== 'SND ')
|
|
53
50
|
throw new Error('Unexpected PROP-chunk ID');
|
|
54
|
-
await this.handleSoundPropertyChunks(header.chunkSize - BigInt(
|
|
51
|
+
await this.handleSoundPropertyChunks(header.chunkSize - BigInt(FourCcToken.len));
|
|
55
52
|
break;
|
|
56
53
|
case 'ID3': // Unofficial ID3 tag support
|
|
57
54
|
const id3_data = await this.tokenizer.readToken(new Token.Uint8ArrayType(Number(header.chunkSize)));
|
|
58
55
|
const rst = strtok3.fromBuffer(id3_data);
|
|
59
|
-
await new
|
|
56
|
+
await new ID3v2Parser().parse(this.metadata, rst, this.options);
|
|
60
57
|
break;
|
|
61
58
|
default:
|
|
62
59
|
debug(`Ignore chunk[ID=${header.chunkID}, size=${header.chunkSize}]`);
|
|
@@ -75,7 +72,7 @@ class DsdiffParser extends BasicParser_1.BasicParser {
|
|
|
75
72
|
async handleSoundPropertyChunks(remainingSize) {
|
|
76
73
|
debug(`Parsing sound-property-chunks, remainingSize=${remainingSize}`);
|
|
77
74
|
while (remainingSize > 0) {
|
|
78
|
-
const sndPropHeader = await this.tokenizer.readToken(
|
|
75
|
+
const sndPropHeader = await this.tokenizer.readToken(ChunkHeader64);
|
|
79
76
|
debug(`Sound-property-chunk[ID=${sndPropHeader.chunkID}, size=${sndPropHeader.chunkSize}]`);
|
|
80
77
|
const p0 = this.tokenizer.position;
|
|
81
78
|
switch (sndPropHeader.chunkID.trim()) {
|
|
@@ -89,7 +86,7 @@ class DsdiffParser extends BasicParser_1.BasicParser {
|
|
|
89
86
|
await this.handleChannelChunks(sndPropHeader.chunkSize - BigInt(Token.UINT16_BE.len));
|
|
90
87
|
break;
|
|
91
88
|
case 'CMPR': // 3.2.3 Compression Type Chunk
|
|
92
|
-
const compressionIdCode = (await this.tokenizer.readToken(
|
|
89
|
+
const compressionIdCode = (await this.tokenizer.readToken(FourCcToken)).trim();
|
|
93
90
|
const count = await this.tokenizer.readToken(Token.UINT8);
|
|
94
91
|
const compressionName = await this.tokenizer.readToken(new Token.StringType(count, 'ascii'));
|
|
95
92
|
if (compressionIdCode === 'DSD') {
|
|
@@ -119,7 +116,7 @@ class DsdiffParser extends BasicParser_1.BasicParser {
|
|
|
119
116
|
debug(`After Parsing sound-property-chunk ${sndPropHeader.chunkSize}, remaining ${remaining} bytes`);
|
|
120
117
|
await this.tokenizer.ignore(Number(remaining));
|
|
121
118
|
}
|
|
122
|
-
remainingSize -= BigInt(
|
|
119
|
+
remainingSize -= BigInt(ChunkHeader64.len) + sndPropHeader.chunkSize;
|
|
123
120
|
debug(`Parsing sound-property-chunks, remainingSize=${remainingSize}`);
|
|
124
121
|
}
|
|
125
122
|
if (this.metadata.format.lossless && this.metadata.format.sampleRate && this.metadata.format.numberOfChannels && this.metadata.format.bitsPerSample) {
|
|
@@ -130,14 +127,13 @@ class DsdiffParser extends BasicParser_1.BasicParser {
|
|
|
130
127
|
async handleChannelChunks(remainingSize) {
|
|
131
128
|
debug(`Parsing channel-chunks, remainingSize=${remainingSize}`);
|
|
132
129
|
const channels = [];
|
|
133
|
-
while (remainingSize >=
|
|
134
|
-
const channelId = await this.tokenizer.readToken(
|
|
130
|
+
while (remainingSize >= FourCcToken.len) {
|
|
131
|
+
const channelId = await this.tokenizer.readToken(FourCcToken);
|
|
135
132
|
debug(`Channel[ID=${channelId}]`);
|
|
136
133
|
channels.push(channelId);
|
|
137
|
-
remainingSize -= BigInt(
|
|
134
|
+
remainingSize -= BigInt(FourCcToken.len);
|
|
138
135
|
}
|
|
139
136
|
debug(`Channels: ${channels.join(', ')}`);
|
|
140
137
|
return channels;
|
|
141
138
|
}
|
|
142
139
|
}
|
|
143
|
-
exports.DsdiffParser = DsdiffParser;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IGetToken } from 'strtok3/
|
|
2
|
-
import { IChunkHeader64 } from '../iff';
|
|
3
|
-
export { IChunkHeader64 } from '../iff';
|
|
1
|
+
import { IGetToken } from 'strtok3/core';
|
|
2
|
+
import { IChunkHeader64 } from '../iff/index.js';
|
|
3
|
+
export { IChunkHeader64 } from '../iff/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* DSDIFF chunk header
|
|
6
6
|
* The data-size encoding is deviating from EA-IFF 85
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.ChunkHeader64 = void 0;
|
|
4
|
-
const Token = require("token-types");
|
|
5
|
-
const FourCC_1 = require("../common/FourCC");
|
|
1
|
+
import * as Token from 'token-types';
|
|
2
|
+
import { FourCcToken } from '../common/FourCC.js';
|
|
6
3
|
/**
|
|
7
4
|
* DSDIFF chunk header
|
|
8
5
|
* The data-size encoding is deviating from EA-IFF 85
|
|
9
6
|
* Ref: http://www.sonicstudio.com/pdf/dsd/DSDIFF_1.5_Spec.pdf
|
|
10
7
|
*/
|
|
11
|
-
|
|
8
|
+
export const ChunkHeader64 = {
|
|
12
9
|
len: 12,
|
|
13
10
|
get: (buf, off) => {
|
|
14
11
|
return {
|
|
15
12
|
// Group-ID
|
|
16
|
-
chunkID:
|
|
13
|
+
chunkID: FourCcToken.get(buf, off),
|
|
17
14
|
// Size
|
|
18
15
|
chunkSize: Token.INT64_BE.get(buf, off + 4)
|
|
19
16
|
};
|
package/lib/dsf/DsfChunk.d.ts
CHANGED
package/lib/dsf/DsfChunk.js
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.FormatChunk = exports.ChannelType = exports.DsdChunk = exports.ChunkHeader = void 0;
|
|
4
|
-
const Token = require("token-types");
|
|
5
|
-
const FourCC_1 = require("../common/FourCC");
|
|
1
|
+
import * as Token from 'token-types';
|
|
2
|
+
import { FourCcToken } from '../common/FourCC.js';
|
|
6
3
|
/**
|
|
7
4
|
* Common chunk DSD header: the 'chunk name (Four-CC)' & chunk size
|
|
8
5
|
*/
|
|
9
|
-
|
|
6
|
+
export const ChunkHeader = {
|
|
10
7
|
len: 12,
|
|
11
8
|
get: (buf, off) => {
|
|
12
|
-
return { id:
|
|
9
|
+
return { id: FourCcToken.get(buf, off), size: Token.UINT64_LE.get(buf, off + 4) };
|
|
13
10
|
}
|
|
14
11
|
};
|
|
15
12
|
/**
|
|
16
13
|
* Common chunk DSD header: the 'chunk name (Four-CC)' & chunk size
|
|
17
14
|
*/
|
|
18
|
-
|
|
15
|
+
export const DsdChunk = {
|
|
19
16
|
len: 16,
|
|
20
17
|
get: (buf, off) => {
|
|
21
18
|
return {
|
|
@@ -24,7 +21,7 @@ exports.DsdChunk = {
|
|
|
24
21
|
};
|
|
25
22
|
}
|
|
26
23
|
};
|
|
27
|
-
var ChannelType;
|
|
24
|
+
export var ChannelType;
|
|
28
25
|
(function (ChannelType) {
|
|
29
26
|
ChannelType[ChannelType["mono"] = 1] = "mono";
|
|
30
27
|
ChannelType[ChannelType["stereo"] = 2] = "stereo";
|
|
@@ -33,11 +30,11 @@ var ChannelType;
|
|
|
33
30
|
ChannelType[ChannelType["4 channels"] = 5] = "4 channels";
|
|
34
31
|
ChannelType[ChannelType["5 channels"] = 6] = "5 channels";
|
|
35
32
|
ChannelType[ChannelType["5.1 channels"] = 7] = "5.1 channels";
|
|
36
|
-
})(ChannelType =
|
|
33
|
+
})(ChannelType = ChannelType || (ChannelType = {}));
|
|
37
34
|
/**
|
|
38
35
|
* Common chunk DSD header: the 'chunk name (Four-CC)' & chunk size
|
|
39
36
|
*/
|
|
40
|
-
|
|
37
|
+
export const FormatChunk = {
|
|
41
38
|
len: 40,
|
|
42
39
|
get: (buf, off) => {
|
|
43
40
|
return {
|
package/lib/dsf/DsfParser.d.ts
CHANGED
package/lib/dsf/DsfParser.js
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const DsfChunk_1 = require("./DsfChunk");
|
|
7
|
-
const ID3v2Parser_1 = require("../id3v2/ID3v2Parser");
|
|
8
|
-
const debug = (0, debug_1.default)('music-metadata:parser:DSF');
|
|
1
|
+
import initDebug from 'debug';
|
|
2
|
+
import { AbstractID3Parser } from '../id3v2/AbstractID3Parser.js';
|
|
3
|
+
import { ChunkHeader, DsdChunk, FormatChunk } from './DsfChunk.js';
|
|
4
|
+
import { ID3v2Parser } from "../id3v2/ID3v2Parser.js";
|
|
5
|
+
const debug = initDebug('music-metadata:parser:DSF');
|
|
9
6
|
/**
|
|
10
7
|
* DSF (dsd stream file) File Parser
|
|
11
8
|
* Ref: https://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
|
|
12
9
|
*/
|
|
13
|
-
class DsfParser extends
|
|
10
|
+
export class DsfParser extends AbstractID3Parser {
|
|
14
11
|
async postId3v2Parse() {
|
|
15
12
|
const p0 = this.tokenizer.position; // mark start position, normally 0
|
|
16
|
-
const chunkHeader = await this.tokenizer.readToken(
|
|
13
|
+
const chunkHeader = await this.tokenizer.readToken(ChunkHeader);
|
|
17
14
|
if (chunkHeader.id !== 'DSD ')
|
|
18
15
|
throw new Error('Invalid chunk signature');
|
|
19
16
|
this.metadata.setFormat('container', 'DSF');
|
|
20
17
|
this.metadata.setFormat('lossless', true);
|
|
21
|
-
const dsdChunk = await this.tokenizer.readToken(
|
|
18
|
+
const dsdChunk = await this.tokenizer.readToken(DsdChunk);
|
|
22
19
|
if (dsdChunk.metadataPointer === BigInt(0)) {
|
|
23
20
|
debug(`No ID3v2 tag present`);
|
|
24
21
|
}
|
|
@@ -27,16 +24,16 @@ class DsfParser extends AbstractID3Parser_1.AbstractID3Parser {
|
|
|
27
24
|
await this.parseChunks(dsdChunk.fileSize - chunkHeader.size);
|
|
28
25
|
// Jump to ID3 header
|
|
29
26
|
await this.tokenizer.ignore(Number(dsdChunk.metadataPointer) - this.tokenizer.position - p0);
|
|
30
|
-
return new
|
|
27
|
+
return new ID3v2Parser().parse(this.metadata, this.tokenizer, this.options);
|
|
31
28
|
}
|
|
32
29
|
}
|
|
33
30
|
async parseChunks(bytesRemaining) {
|
|
34
|
-
while (bytesRemaining >=
|
|
35
|
-
const chunkHeader = await this.tokenizer.readToken(
|
|
31
|
+
while (bytesRemaining >= ChunkHeader.len) {
|
|
32
|
+
const chunkHeader = await this.tokenizer.readToken(ChunkHeader);
|
|
36
33
|
debug(`Parsing chunk name=${chunkHeader.id} size=${chunkHeader.size}`);
|
|
37
34
|
switch (chunkHeader.id) {
|
|
38
35
|
case 'fmt ':
|
|
39
|
-
const formatChunk = await this.tokenizer.readToken(
|
|
36
|
+
const formatChunk = await this.tokenizer.readToken(FormatChunk);
|
|
40
37
|
this.metadata.setFormat('numberOfChannels', formatChunk.channelNum);
|
|
41
38
|
this.metadata.setFormat('sampleRate', formatChunk.samplingFrequency);
|
|
42
39
|
this.metadata.setFormat('bitsPerSample', formatChunk.bitsPerSample);
|
|
@@ -46,11 +43,10 @@ class DsfParser extends AbstractID3Parser_1.AbstractID3Parser {
|
|
|
46
43
|
this.metadata.setFormat('bitrate', bitrate);
|
|
47
44
|
return; // We got what we want, stop further processing of chunks
|
|
48
45
|
default:
|
|
49
|
-
this.tokenizer.ignore(Number(chunkHeader.size) -
|
|
46
|
+
this.tokenizer.ignore(Number(chunkHeader.size) - ChunkHeader.len);
|
|
50
47
|
break;
|
|
51
48
|
}
|
|
52
49
|
bytesRemaining -= chunkHeader.size;
|
|
53
50
|
}
|
|
54
51
|
}
|
|
55
52
|
}
|
|
56
|
-
exports.DsfParser = DsfParser;
|
package/lib/flac/FlacParser.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ITokenizer } from 'strtok3/
|
|
2
|
-
import { AbstractID3Parser } from '../id3v2/AbstractID3Parser';
|
|
3
|
-
import { INativeMetadataCollector } from '../common/MetadataCollector';
|
|
4
|
-
import { IOptions } from '../type';
|
|
5
|
-
import { ITokenParser } from '../ParserFactory';
|
|
1
|
+
import { ITokenizer } from 'strtok3/core';
|
|
2
|
+
import { AbstractID3Parser } from '../id3v2/AbstractID3Parser.js';
|
|
3
|
+
import { INativeMetadataCollector } from '../common/MetadataCollector.js';
|
|
4
|
+
import { IOptions } from '../type.js';
|
|
5
|
+
import { ITokenParser } from '../ParserFactory.js';
|
|
6
6
|
export declare class FlacParser extends AbstractID3Parser {
|
|
7
7
|
private vorbisParser;
|
|
8
8
|
private padding;
|
package/lib/flac/FlacParser.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const VorbisParser_1 = require("../ogg/vorbis/VorbisParser");
|
|
11
|
-
const VorbisDecoder_1 = require("../ogg/vorbis/VorbisDecoder");
|
|
12
|
-
const debug = (0, debug_1.default)('music-metadata:parser:FLAC');
|
|
1
|
+
import { UINT16_BE, UINT24_BE, Uint8ArrayType } from 'token-types';
|
|
2
|
+
import initDebug from 'debug';
|
|
3
|
+
import * as util from '../common/Util.js';
|
|
4
|
+
import { VorbisPictureToken } from '../ogg/vorbis/Vorbis.js';
|
|
5
|
+
import { AbstractID3Parser } from '../id3v2/AbstractID3Parser.js';
|
|
6
|
+
import { FourCcToken } from '../common/FourCC.js';
|
|
7
|
+
import { VorbisParser } from '../ogg/vorbis/VorbisParser.js';
|
|
8
|
+
import { VorbisDecoder } from '../ogg/vorbis/VorbisDecoder.js';
|
|
9
|
+
const debug = initDebug('music-metadata:parser:FLAC');
|
|
13
10
|
/**
|
|
14
11
|
* FLAC supports up to 128 kinds of metadata blocks; currently the following are defined:
|
|
15
12
|
* ref: https://xiph.org/flac/format.html#metadata_block
|
|
@@ -24,7 +21,7 @@ var BlockType;
|
|
|
24
21
|
BlockType[BlockType["CUESHEET"] = 5] = "CUESHEET";
|
|
25
22
|
BlockType[BlockType["PICTURE"] = 6] = "PICTURE";
|
|
26
23
|
})(BlockType || (BlockType = {}));
|
|
27
|
-
class FlacParser extends
|
|
24
|
+
export class FlacParser extends AbstractID3Parser {
|
|
28
25
|
constructor() {
|
|
29
26
|
super(...arguments);
|
|
30
27
|
this.padding = 0;
|
|
@@ -37,11 +34,11 @@ class FlacParser extends AbstractID3Parser_1.AbstractID3Parser {
|
|
|
37
34
|
*/
|
|
38
35
|
init(metadata, tokenizer, options) {
|
|
39
36
|
super.init(metadata, tokenizer, options);
|
|
40
|
-
this.vorbisParser = new
|
|
37
|
+
this.vorbisParser = new VorbisParser(metadata, options);
|
|
41
38
|
return this;
|
|
42
39
|
}
|
|
43
40
|
async postId3v2Parse() {
|
|
44
|
-
const fourCC = await this.tokenizer.readToken(
|
|
41
|
+
const fourCC = await this.tokenizer.readToken(FourCcToken);
|
|
45
42
|
if (fourCC.toString() !== 'fLaC') {
|
|
46
43
|
throw new Error('Invalid FLAC preamble');
|
|
47
44
|
}
|
|
@@ -103,8 +100,8 @@ class FlacParser extends AbstractID3Parser_1.AbstractID3Parser {
|
|
|
103
100
|
* Ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-640004.2.3
|
|
104
101
|
*/
|
|
105
102
|
async parseComment(dataLen) {
|
|
106
|
-
const data = await this.tokenizer.readToken(new
|
|
107
|
-
const decoder = new
|
|
103
|
+
const data = await this.tokenizer.readToken(new Uint8ArrayType(dataLen));
|
|
104
|
+
const decoder = new VorbisDecoder(data, 0);
|
|
108
105
|
decoder.readStringUtf8(); // vendor (skip)
|
|
109
106
|
const commentListLength = decoder.readInt32();
|
|
110
107
|
for (let i = 0; i < commentListLength; i++) {
|
|
@@ -117,12 +114,11 @@ class FlacParser extends AbstractID3Parser_1.AbstractID3Parser {
|
|
|
117
114
|
return this.tokenizer.ignore(dataLen);
|
|
118
115
|
}
|
|
119
116
|
else {
|
|
120
|
-
const picture = await this.tokenizer.readToken(new
|
|
117
|
+
const picture = await this.tokenizer.readToken(new VorbisPictureToken(dataLen));
|
|
121
118
|
this.vorbisParser.addTag('METADATA_BLOCK_PICTURE', picture);
|
|
122
119
|
}
|
|
123
120
|
}
|
|
124
121
|
}
|
|
125
|
-
exports.FlacParser = FlacParser;
|
|
126
122
|
class Metadata {
|
|
127
123
|
}
|
|
128
124
|
Metadata.BlockHeader = {
|
|
@@ -131,7 +127,7 @@ Metadata.BlockHeader = {
|
|
|
131
127
|
return {
|
|
132
128
|
lastBlock: util.getBit(buf, off, 7),
|
|
133
129
|
type: util.getBitAllignedNumber(buf, off, 1, 7),
|
|
134
|
-
length:
|
|
130
|
+
length: UINT24_BE.get(buf, off + 1)
|
|
135
131
|
};
|
|
136
132
|
}
|
|
137
133
|
};
|
|
@@ -144,20 +140,20 @@ Metadata.BlockStreamInfo = {
|
|
|
144
140
|
get: (buf, off) => {
|
|
145
141
|
return {
|
|
146
142
|
// The minimum block size (in samples) used in the stream.
|
|
147
|
-
minimumBlockSize:
|
|
143
|
+
minimumBlockSize: UINT16_BE.get(buf, off),
|
|
148
144
|
// The maximum block size (in samples) used in the stream.
|
|
149
145
|
// (Minimum blocksize == maximum blocksize) implies a fixed-blocksize stream.
|
|
150
|
-
maximumBlockSize:
|
|
146
|
+
maximumBlockSize: UINT16_BE.get(buf, off + 2) / 1000,
|
|
151
147
|
// The minimum frame size (in bytes) used in the stream.
|
|
152
148
|
// May be 0 to imply the value is not known.
|
|
153
|
-
minimumFrameSize:
|
|
149
|
+
minimumFrameSize: UINT24_BE.get(buf, off + 4),
|
|
154
150
|
// The maximum frame size (in bytes) used in the stream.
|
|
155
151
|
// May be 0 to imply the value is not known.
|
|
156
|
-
maximumFrameSize:
|
|
152
|
+
maximumFrameSize: UINT24_BE.get(buf, off + 7),
|
|
157
153
|
// Sample rate in Hz. Though 20 bits are available,
|
|
158
154
|
// the maximum sample rate is limited by the structure of frame headers to 655350Hz.
|
|
159
155
|
// Also, a value of 0 is invalid.
|
|
160
|
-
sampleRate:
|
|
156
|
+
sampleRate: UINT24_BE.get(buf, off + 10) >> 4,
|
|
161
157
|
// probably slower: sampleRate: common.getBitAllignedNumber(buf, off + 10, 0, 20),
|
|
162
158
|
// (number of channels)-1. FLAC supports from 1 to 8 channels
|
|
163
159
|
channels: util.getBitAllignedNumber(buf, off + 12, 4, 3) + 1,
|
|
@@ -169,7 +165,7 @@ Metadata.BlockStreamInfo = {
|
|
|
169
165
|
// A value of zero here means the number of total samples is unknown.
|
|
170
166
|
totalSamples: util.getBitAllignedNumber(buf, off + 13, 4, 36),
|
|
171
167
|
// the MD5 hash of the file (see notes for usage... it's a littly tricky)
|
|
172
|
-
fileMD5: new
|
|
168
|
+
fileMD5: new Uint8ArrayType(16).get(buf, off + 18)
|
|
173
169
|
};
|
|
174
170
|
}
|
|
175
171
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BasicParser } from '../common/BasicParser';
|
|
2
|
-
import { IRandomReader } from '../type';
|
|
1
|
+
import { BasicParser } from '../common/BasicParser.js';
|
|
2
|
+
import { IRandomReader } from '../type.js';
|
|
3
3
|
/**
|
|
4
4
|
* ID3v1 Genre mappings
|
|
5
5
|
* Ref: https://de.wikipedia.org/wiki/Liste_der_ID3v1-Genres
|
package/lib/id3v1/ID3v1Parser.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
const BasicParser_1 = require("../common/BasicParser");
|
|
8
|
-
const APEv2Parser_1 = require("../apev2/APEv2Parser");
|
|
9
|
-
const debug = (0, debug_1.default)('music-metadata:parser:ID3v1');
|
|
1
|
+
import initDebug from 'debug';
|
|
2
|
+
import { StringType, UINT8 } from 'token-types';
|
|
3
|
+
import * as util from '../common/Util.js';
|
|
4
|
+
import { BasicParser } from '../common/BasicParser.js';
|
|
5
|
+
import { APEv2Parser } from '../apev2/APEv2Parser.js';
|
|
6
|
+
const debug = initDebug('music-metadata:parser:ID3v1');
|
|
10
7
|
/**
|
|
11
8
|
* ID3v1 Genre mappings
|
|
12
9
|
* Ref: https://de.wikipedia.org/wiki/Liste_der_ID3v1-Genres
|
|
13
10
|
*/
|
|
14
|
-
|
|
11
|
+
export const Genres = [
|
|
15
12
|
'Blues', 'Classic Rock', 'Country', 'Dance', 'Disco', 'Funk', 'Grunge', 'Hip-Hop',
|
|
16
13
|
'Jazz', 'Metal', 'New Age', 'Oldies', 'Other', 'Pop', 'R&B', 'Rap', 'Reggae', 'Rock',
|
|
17
14
|
'Techno', 'Industrial', 'Alternative', 'Ska', 'Death Metal', 'Pranks', 'Soundtrack',
|
|
@@ -62,14 +59,14 @@ const Iid3v1Token = {
|
|
|
62
59
|
year: new Id3v1StringType(4).get(buf, off + 93),
|
|
63
60
|
comment: new Id3v1StringType(28).get(buf, off + 97),
|
|
64
61
|
// ID3v1.1 separator for track
|
|
65
|
-
zeroByte:
|
|
62
|
+
zeroByte: UINT8.get(buf, off + 127),
|
|
66
63
|
// track: ID3v1.1 field added by Michael Mutschler
|
|
67
|
-
track:
|
|
68
|
-
genre:
|
|
64
|
+
track: UINT8.get(buf, off + 126),
|
|
65
|
+
genre: UINT8.get(buf, off + 127)
|
|
69
66
|
} : null;
|
|
70
67
|
}
|
|
71
68
|
};
|
|
72
|
-
class Id3v1StringType extends
|
|
69
|
+
class Id3v1StringType extends StringType {
|
|
73
70
|
constructor(len) {
|
|
74
71
|
super(len, 'binary');
|
|
75
72
|
}
|
|
@@ -80,10 +77,10 @@ class Id3v1StringType extends token_types_1.StringType {
|
|
|
80
77
|
return value.length > 0 ? value : undefined;
|
|
81
78
|
}
|
|
82
79
|
}
|
|
83
|
-
class ID3v1Parser extends
|
|
80
|
+
export class ID3v1Parser extends BasicParser {
|
|
84
81
|
static getGenre(genreIndex) {
|
|
85
|
-
if (genreIndex <
|
|
86
|
-
return
|
|
82
|
+
if (genreIndex < Genres.length) {
|
|
83
|
+
return Genres[genreIndex];
|
|
87
84
|
}
|
|
88
85
|
return undefined; // ToDO: generate warning
|
|
89
86
|
}
|
|
@@ -94,7 +91,7 @@ class ID3v1Parser extends BasicParser_1.BasicParser {
|
|
|
94
91
|
}
|
|
95
92
|
if (this.options.apeHeader) {
|
|
96
93
|
this.tokenizer.ignore(this.options.apeHeader.offset - this.tokenizer.position);
|
|
97
|
-
const apeParser = new
|
|
94
|
+
const apeParser = new APEv2Parser();
|
|
98
95
|
apeParser.init(this.metadata, this.tokenizer, this.options);
|
|
99
96
|
await apeParser.parseTags(this.options.apeHeader.footer);
|
|
100
97
|
}
|
|
@@ -122,8 +119,7 @@ class ID3v1Parser extends BasicParser_1.BasicParser {
|
|
|
122
119
|
this.metadata.addTag('ID3v1', id, value);
|
|
123
120
|
}
|
|
124
121
|
}
|
|
125
|
-
|
|
126
|
-
async function hasID3v1Header(reader) {
|
|
122
|
+
export async function hasID3v1Header(reader) {
|
|
127
123
|
if (reader.fileSize >= 128) {
|
|
128
124
|
const tag = Buffer.alloc(3);
|
|
129
125
|
await reader.randomRead(tag, 0, tag.length, reader.fileSize - 128);
|
|
@@ -131,4 +127,3 @@ async function hasID3v1Header(reader) {
|
|
|
131
127
|
}
|
|
132
128
|
return false;
|
|
133
129
|
}
|
|
134
|
-
exports.hasID3v1Header = hasID3v1Header;
|