agdi 3.3.5 → 3.3.7
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 +13 -0
- package/dist/APEv2Parser-EU45AV6X.js +14 -0
- package/dist/AiffParser-FOX7GQ42.js +189 -0
- package/dist/AsfParser-HD5CSGIO.js +610 -0
- package/dist/DsdiffParser-OJREDMBI.js +188 -0
- package/dist/DsfParser-2YL4ARJ7.js +110 -0
- package/dist/FlacParser-IVV4RYF6.js +15 -0
- package/dist/MP4Parser-NLX4A2YN.js +1140 -0
- package/dist/MatroskaParser-4OEK43GF.js +654 -0
- package/dist/MpegParser-PXKEUF2B.js +642 -0
- package/dist/MusepackParser-54QGYRLY.js +322 -0
- package/dist/OggParser-KRV5QCGZ.js +435 -0
- package/dist/WavPackParser-XPZSQFVS.js +203 -0
- package/dist/WaveParser-27IS2RAI.js +294 -0
- package/dist/chunk-2B4QMSZW.js +311 -0
- package/dist/chunk-3JKZUGPJ.js +70 -0
- package/dist/chunk-4VNS5WPM.js +42 -0
- package/dist/chunk-65JVFJ3X.js +729 -0
- package/dist/chunk-6OKLAJRQ.js +0 -0
- package/dist/chunk-AGSFUVRG.js +439 -0
- package/dist/chunk-GD35BJSH.js +177 -0
- package/dist/chunk-HNLU36CC.js +702 -0
- package/dist/{chunk-M2FF7ETI.js → chunk-J6OLLWVT.js} +1 -1
- package/dist/chunk-LREP5CZP.js +146 -0
- package/dist/chunk-M54HVABG.js +34 -0
- package/dist/{chunk-S45VXJEO.js → chunk-OPFFFAQC.js} +19 -1
- package/dist/chunk-VGOIHW7D.js +1529 -0
- package/dist/chunk-YIHDW7JC.js +314 -0
- package/dist/config-D3QBUN2Y.js +13 -0
- package/dist/{config-ZFU7TSU2.js → config-K2XM6D4Z.js} +3 -2
- package/dist/{event-bus-Q3WCETQQ.js → event-bus-MO5SFUME.js} +1 -0
- package/dist/index.js +3273 -1274
- package/dist/lib-2XISBYT3.js +144950 -0
- package/dist/lib-HCGLI2GJ.js +4161 -0
- package/dist/{telemetry-service-OHU5NKON.js → telemetry-service-76YPOPDM.js} +8 -4
- package/package.json +6 -3
|
File without changes
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AbstractID3Parser
|
|
3
|
+
} from "./chunk-3JKZUGPJ.js";
|
|
4
|
+
import {
|
|
5
|
+
FourCcToken
|
|
6
|
+
} from "./chunk-YIHDW7JC.js";
|
|
7
|
+
import {
|
|
8
|
+
AttachedPictureType
|
|
9
|
+
} from "./chunk-LREP5CZP.js";
|
|
10
|
+
import {
|
|
11
|
+
getBit,
|
|
12
|
+
getBitAllignedNumber
|
|
13
|
+
} from "./chunk-GD35BJSH.js";
|
|
14
|
+
import {
|
|
15
|
+
StringType,
|
|
16
|
+
UINT16_BE,
|
|
17
|
+
UINT24_BE,
|
|
18
|
+
UINT32_BE,
|
|
19
|
+
UINT32_LE,
|
|
20
|
+
UINT8,
|
|
21
|
+
Uint8ArrayType,
|
|
22
|
+
makeUnexpectedFileContentError,
|
|
23
|
+
require_src,
|
|
24
|
+
textDecode
|
|
25
|
+
} from "./chunk-VGOIHW7D.js";
|
|
26
|
+
import {
|
|
27
|
+
__toESM
|
|
28
|
+
} from "./chunk-4VNS5WPM.js";
|
|
29
|
+
|
|
30
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/flac/FlacParser.js
|
|
31
|
+
var import_debug2 = __toESM(require_src(), 1);
|
|
32
|
+
|
|
33
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/ogg/vorbis/Vorbis.js
|
|
34
|
+
var VorbisPictureToken = class _VorbisPictureToken {
|
|
35
|
+
static fromBase64(base64str) {
|
|
36
|
+
return _VorbisPictureToken.fromBuffer(Uint8Array.from(atob(base64str), (c) => c.charCodeAt(0)));
|
|
37
|
+
}
|
|
38
|
+
static fromBuffer(buffer) {
|
|
39
|
+
const pic = new _VorbisPictureToken(buffer.length);
|
|
40
|
+
return pic.get(buffer, 0);
|
|
41
|
+
}
|
|
42
|
+
constructor(len) {
|
|
43
|
+
this.len = len;
|
|
44
|
+
}
|
|
45
|
+
get(buffer, offset) {
|
|
46
|
+
const type = AttachedPictureType[UINT32_BE.get(buffer, offset)];
|
|
47
|
+
offset += 4;
|
|
48
|
+
const mimeLen = UINT32_BE.get(buffer, offset);
|
|
49
|
+
offset += 4;
|
|
50
|
+
const format = new StringType(mimeLen, "utf-8").get(buffer, offset);
|
|
51
|
+
offset += mimeLen;
|
|
52
|
+
const descLen = UINT32_BE.get(buffer, offset);
|
|
53
|
+
offset += 4;
|
|
54
|
+
const description = new StringType(descLen, "utf-8").get(buffer, offset);
|
|
55
|
+
offset += descLen;
|
|
56
|
+
const width = UINT32_BE.get(buffer, offset);
|
|
57
|
+
offset += 4;
|
|
58
|
+
const height = UINT32_BE.get(buffer, offset);
|
|
59
|
+
offset += 4;
|
|
60
|
+
const colour_depth = UINT32_BE.get(buffer, offset);
|
|
61
|
+
offset += 4;
|
|
62
|
+
const indexed_color = UINT32_BE.get(buffer, offset);
|
|
63
|
+
offset += 4;
|
|
64
|
+
const picDataLen = UINT32_BE.get(buffer, offset);
|
|
65
|
+
offset += 4;
|
|
66
|
+
const data = buffer.slice(offset, offset + picDataLen);
|
|
67
|
+
return {
|
|
68
|
+
type,
|
|
69
|
+
format,
|
|
70
|
+
description,
|
|
71
|
+
width,
|
|
72
|
+
height,
|
|
73
|
+
colour_depth,
|
|
74
|
+
indexed_color,
|
|
75
|
+
data
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
var CommonHeader = {
|
|
80
|
+
len: 7,
|
|
81
|
+
get: (buf, off) => {
|
|
82
|
+
return {
|
|
83
|
+
packetType: UINT8.get(buf, off),
|
|
84
|
+
vorbis: new StringType(6, "ascii").get(buf, off + 1)
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
var IdentificationHeader = {
|
|
89
|
+
len: 23,
|
|
90
|
+
get: (uint8Array, off) => {
|
|
91
|
+
return {
|
|
92
|
+
version: UINT32_LE.get(uint8Array, off + 0),
|
|
93
|
+
channelMode: UINT8.get(uint8Array, off + 4),
|
|
94
|
+
sampleRate: UINT32_LE.get(uint8Array, off + 5),
|
|
95
|
+
bitrateMax: UINT32_LE.get(uint8Array, off + 9),
|
|
96
|
+
bitrateNominal: UINT32_LE.get(uint8Array, off + 13),
|
|
97
|
+
bitrateMin: UINT32_LE.get(uint8Array, off + 17)
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/ogg/vorbis/VorbisStream.js
|
|
103
|
+
var import_debug = __toESM(require_src(), 1);
|
|
104
|
+
|
|
105
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/ogg/vorbis/VorbisDecoder.js
|
|
106
|
+
var VorbisDecoder = class {
|
|
107
|
+
constructor(data, offset) {
|
|
108
|
+
this.data = data;
|
|
109
|
+
this.offset = offset;
|
|
110
|
+
}
|
|
111
|
+
readInt32() {
|
|
112
|
+
const value = UINT32_LE.get(this.data, this.offset);
|
|
113
|
+
this.offset += 4;
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
readStringUtf8() {
|
|
117
|
+
const len = this.readInt32();
|
|
118
|
+
const value = textDecode(this.data.subarray(this.offset, this.offset + len), "utf-8");
|
|
119
|
+
this.offset += len;
|
|
120
|
+
return value;
|
|
121
|
+
}
|
|
122
|
+
parseUserComment() {
|
|
123
|
+
const offset0 = this.offset;
|
|
124
|
+
const v = this.readStringUtf8();
|
|
125
|
+
const idx = v.indexOf("=");
|
|
126
|
+
return {
|
|
127
|
+
key: v.substring(0, idx).toUpperCase(),
|
|
128
|
+
value: v.substring(idx + 1),
|
|
129
|
+
len: this.offset - offset0
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/ogg/vorbis/VorbisStream.js
|
|
135
|
+
var debug = (0, import_debug.default)("music-metadata:parser:ogg:vorbis1");
|
|
136
|
+
var VorbisContentError = class extends makeUnexpectedFileContentError("Vorbis") {
|
|
137
|
+
};
|
|
138
|
+
var VorbisStream = class _VorbisStream {
|
|
139
|
+
constructor(metadata, options) {
|
|
140
|
+
this.pageSegments = [];
|
|
141
|
+
this.durationOnLastPage = true;
|
|
142
|
+
this.metadata = metadata;
|
|
143
|
+
this.options = options;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Vorbis 1 parser
|
|
147
|
+
* @param header Ogg Page Header
|
|
148
|
+
* @param pageData Page data
|
|
149
|
+
*/
|
|
150
|
+
async parsePage(header, pageData) {
|
|
151
|
+
this.lastPageHeader = header;
|
|
152
|
+
if (header.headerType.firstPage) {
|
|
153
|
+
this.parseFirstPage(header, pageData);
|
|
154
|
+
} else {
|
|
155
|
+
if (header.headerType.continued) {
|
|
156
|
+
if (this.pageSegments.length === 0) {
|
|
157
|
+
throw new VorbisContentError("Cannot continue on previous page");
|
|
158
|
+
}
|
|
159
|
+
this.pageSegments.push(pageData);
|
|
160
|
+
}
|
|
161
|
+
if (header.headerType.lastPage || !header.headerType.continued) {
|
|
162
|
+
if (this.pageSegments.length > 0) {
|
|
163
|
+
const fullPage = _VorbisStream.mergeUint8Arrays(this.pageSegments);
|
|
164
|
+
await this.parseFullPage(fullPage);
|
|
165
|
+
}
|
|
166
|
+
this.pageSegments = header.headerType.lastPage ? [] : [pageData];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
static mergeUint8Arrays(arrays) {
|
|
171
|
+
const totalSize = arrays.reduce((acc, e) => acc + e.length, 0);
|
|
172
|
+
const merged = new Uint8Array(totalSize);
|
|
173
|
+
arrays.forEach((array, i, _arrays) => {
|
|
174
|
+
const offset = _arrays.slice(0, i).reduce((acc, e) => acc + e.length, 0);
|
|
175
|
+
merged.set(array, offset);
|
|
176
|
+
});
|
|
177
|
+
return merged;
|
|
178
|
+
}
|
|
179
|
+
async flush() {
|
|
180
|
+
await this.parseFullPage(_VorbisStream.mergeUint8Arrays(this.pageSegments));
|
|
181
|
+
}
|
|
182
|
+
async parseUserComment(pageData, offset) {
|
|
183
|
+
const decoder = new VorbisDecoder(pageData, offset);
|
|
184
|
+
const tag = decoder.parseUserComment();
|
|
185
|
+
await this.addTag(tag.key, tag.value);
|
|
186
|
+
return tag.len;
|
|
187
|
+
}
|
|
188
|
+
async addTag(id, value) {
|
|
189
|
+
if (id === "METADATA_BLOCK_PICTURE" && typeof value === "string") {
|
|
190
|
+
if (this.options.skipCovers) {
|
|
191
|
+
debug("Ignore picture");
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
value = VorbisPictureToken.fromBase64(value);
|
|
195
|
+
debug(`Push picture: id=${id}, format=${value.format}`);
|
|
196
|
+
} else {
|
|
197
|
+
debug(`Push tag: id=${id}, value=${value}`);
|
|
198
|
+
}
|
|
199
|
+
await this.metadata.addTag("vorbis", id, value);
|
|
200
|
+
}
|
|
201
|
+
calculateDuration(_enfOfStream) {
|
|
202
|
+
if (this.lastPageHeader && this.metadata.format.sampleRate && this.lastPageHeader.absoluteGranulePosition >= 0) {
|
|
203
|
+
this.metadata.setFormat("numberOfSamples", this.lastPageHeader.absoluteGranulePosition);
|
|
204
|
+
this.metadata.setFormat("duration", this.lastPageHeader.absoluteGranulePosition / this.metadata.format.sampleRate);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Parse first Ogg/Vorbis page
|
|
209
|
+
* @param _header
|
|
210
|
+
* @param pageData
|
|
211
|
+
*/
|
|
212
|
+
parseFirstPage(_header, pageData) {
|
|
213
|
+
this.metadata.setFormat("codec", "Vorbis I");
|
|
214
|
+
this.metadata.setFormat("hasAudio", true);
|
|
215
|
+
debug("Parse first page");
|
|
216
|
+
const commonHeader = CommonHeader.get(pageData, 0);
|
|
217
|
+
if (commonHeader.vorbis !== "vorbis")
|
|
218
|
+
throw new VorbisContentError("Metadata does not look like Vorbis");
|
|
219
|
+
if (commonHeader.packetType === 1) {
|
|
220
|
+
const idHeader = IdentificationHeader.get(pageData, CommonHeader.len);
|
|
221
|
+
this.metadata.setFormat("sampleRate", idHeader.sampleRate);
|
|
222
|
+
this.metadata.setFormat("bitrate", idHeader.bitrateNominal);
|
|
223
|
+
this.metadata.setFormat("numberOfChannels", idHeader.channelMode);
|
|
224
|
+
debug("sample-rate=%s[hz], bitrate=%s[b/s], channel-mode=%s", idHeader.sampleRate, idHeader.bitrateNominal, idHeader.channelMode);
|
|
225
|
+
} else
|
|
226
|
+
throw new VorbisContentError("First Ogg page should be type 1: the identification header");
|
|
227
|
+
}
|
|
228
|
+
async parseFullPage(pageData) {
|
|
229
|
+
const commonHeader = CommonHeader.get(pageData, 0);
|
|
230
|
+
debug("Parse full page: type=%s, byteLength=%s", commonHeader.packetType, pageData.byteLength);
|
|
231
|
+
switch (commonHeader.packetType) {
|
|
232
|
+
case 3:
|
|
233
|
+
return this.parseUserCommentList(pageData, CommonHeader.len);
|
|
234
|
+
case 1:
|
|
235
|
+
// type 1: the identification header
|
|
236
|
+
case 5:
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Ref: https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-840005.2
|
|
242
|
+
*/
|
|
243
|
+
async parseUserCommentList(pageData, offset) {
|
|
244
|
+
const strLen = UINT32_LE.get(pageData, offset);
|
|
245
|
+
offset += 4;
|
|
246
|
+
offset += strLen;
|
|
247
|
+
let userCommentListLength = UINT32_LE.get(pageData, offset);
|
|
248
|
+
offset += 4;
|
|
249
|
+
while (userCommentListLength-- > 0) {
|
|
250
|
+
offset += await this.parseUserComment(pageData, offset);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/flac/FlacToken.js
|
|
256
|
+
var BlockType = {
|
|
257
|
+
STREAMINFO: 0,
|
|
258
|
+
// STREAMINFO
|
|
259
|
+
PADDING: 1,
|
|
260
|
+
// PADDING
|
|
261
|
+
APPLICATION: 2,
|
|
262
|
+
// APPLICATION
|
|
263
|
+
SEEKTABLE: 3,
|
|
264
|
+
// SEEKTABLE
|
|
265
|
+
VORBIS_COMMENT: 4,
|
|
266
|
+
// VORBIS_COMMENT
|
|
267
|
+
CUESHEET: 5,
|
|
268
|
+
// CUESHEET
|
|
269
|
+
PICTURE: 6
|
|
270
|
+
// PICTURE
|
|
271
|
+
};
|
|
272
|
+
var BlockHeader = {
|
|
273
|
+
len: 4,
|
|
274
|
+
get: (buf, off) => {
|
|
275
|
+
return {
|
|
276
|
+
lastBlock: getBit(buf, off, 7),
|
|
277
|
+
type: getBitAllignedNumber(buf, off, 1, 7),
|
|
278
|
+
length: UINT24_BE.get(buf, off + 1)
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
var BlockStreamInfo = {
|
|
283
|
+
len: 34,
|
|
284
|
+
get: (buf, off) => {
|
|
285
|
+
return {
|
|
286
|
+
// The minimum block size (in samples) used in the stream.
|
|
287
|
+
minimumBlockSize: UINT16_BE.get(buf, off),
|
|
288
|
+
// The maximum block size (in samples) used in the stream.
|
|
289
|
+
// (Minimum blocksize == maximum blocksize) implies a fixed-blocksize stream.
|
|
290
|
+
maximumBlockSize: UINT16_BE.get(buf, off + 2) / 1e3,
|
|
291
|
+
// The minimum frame size (in bytes) used in the stream.
|
|
292
|
+
// May be 0 to imply the value is not known.
|
|
293
|
+
minimumFrameSize: UINT24_BE.get(buf, off + 4),
|
|
294
|
+
// The maximum frame size (in bytes) used in the stream.
|
|
295
|
+
// May be 0 to imply the value is not known.
|
|
296
|
+
maximumFrameSize: UINT24_BE.get(buf, off + 7),
|
|
297
|
+
// Sample rate in Hz. Though 20 bits are available,
|
|
298
|
+
// the maximum sample rate is limited by the structure of frame headers to 655350Hz.
|
|
299
|
+
// Also, a value of 0 is invalid.
|
|
300
|
+
sampleRate: UINT24_BE.get(buf, off + 10) >> 4,
|
|
301
|
+
// probably slower: sampleRate: common.getBitAllignedNumber(buf, off + 10, 0, 20),
|
|
302
|
+
// (number of channels)-1. FLAC supports from 1 to 8 channels
|
|
303
|
+
channels: getBitAllignedNumber(buf, off + 12, 4, 3) + 1,
|
|
304
|
+
// bits per sample)-1.
|
|
305
|
+
// FLAC supports from 4 to 32 bits per sample. Currently the reference encoder and decoders only support up to 24 bits per sample.
|
|
306
|
+
bitsPerSample: getBitAllignedNumber(buf, off + 12, 7, 5) + 1,
|
|
307
|
+
// Total samples in stream.
|
|
308
|
+
// 'Samples' means inter-channel sample, i.e. one second of 44.1Khz audio will have 44100 samples regardless of the number of channels.
|
|
309
|
+
// A value of zero here means the number of total samples is unknown.
|
|
310
|
+
totalSamples: getBitAllignedNumber(buf, off + 13, 4, 36),
|
|
311
|
+
// the MD5 hash of the file (see notes for usage... it's a littly tricky)
|
|
312
|
+
fileMD5: new Uint8ArrayType(16).get(buf, off + 18)
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/flac/FlacParser.js
|
|
318
|
+
var debug2 = (0, import_debug2.default)("music-metadata:parser:FLAC");
|
|
319
|
+
var FlacContentError = class extends makeUnexpectedFileContentError("FLAC") {
|
|
320
|
+
};
|
|
321
|
+
var FlacParser = class extends AbstractID3Parser {
|
|
322
|
+
constructor() {
|
|
323
|
+
super(...arguments);
|
|
324
|
+
this.vorbisParser = new VorbisStream(this.metadata, this.options);
|
|
325
|
+
}
|
|
326
|
+
async postId3v2Parse() {
|
|
327
|
+
const fourCC = await this.tokenizer.readToken(FourCcToken);
|
|
328
|
+
if (fourCC.toString() !== "fLaC") {
|
|
329
|
+
throw new FlacContentError("Invalid FLAC preamble");
|
|
330
|
+
}
|
|
331
|
+
let blockHeader;
|
|
332
|
+
do {
|
|
333
|
+
blockHeader = await this.tokenizer.readToken(BlockHeader);
|
|
334
|
+
await this.parseDataBlock(blockHeader);
|
|
335
|
+
} while (!blockHeader.lastBlock);
|
|
336
|
+
if (this.tokenizer.fileInfo.size && this.metadata.format.duration) {
|
|
337
|
+
const dataSize = this.tokenizer.fileInfo.size - this.tokenizer.position;
|
|
338
|
+
this.metadata.setFormat("bitrate", 8 * dataSize / this.metadata.format.duration);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
async parseDataBlock(blockHeader) {
|
|
342
|
+
debug2(`blockHeader type=${blockHeader.type}, length=${blockHeader.length}`);
|
|
343
|
+
switch (blockHeader.type) {
|
|
344
|
+
case BlockType.STREAMINFO:
|
|
345
|
+
return this.readBlockStreamInfo(blockHeader.length);
|
|
346
|
+
case BlockType.PADDING:
|
|
347
|
+
break;
|
|
348
|
+
case BlockType.APPLICATION:
|
|
349
|
+
break;
|
|
350
|
+
case BlockType.SEEKTABLE:
|
|
351
|
+
break;
|
|
352
|
+
case BlockType.VORBIS_COMMENT:
|
|
353
|
+
return this.readComment(blockHeader.length);
|
|
354
|
+
case BlockType.CUESHEET:
|
|
355
|
+
break;
|
|
356
|
+
case BlockType.PICTURE:
|
|
357
|
+
await this.parsePicture(blockHeader.length);
|
|
358
|
+
return;
|
|
359
|
+
default:
|
|
360
|
+
this.metadata.addWarning(`Unknown block type: ${blockHeader.type}`);
|
|
361
|
+
}
|
|
362
|
+
return this.tokenizer.ignore(blockHeader.length).then();
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Parse STREAMINFO
|
|
366
|
+
*/
|
|
367
|
+
async readBlockStreamInfo(dataLen) {
|
|
368
|
+
if (dataLen !== BlockStreamInfo.len)
|
|
369
|
+
throw new FlacContentError("Unexpected block-stream-info length");
|
|
370
|
+
const streamInfo = await this.tokenizer.readToken(BlockStreamInfo);
|
|
371
|
+
this.metadata.setFormat("container", "FLAC");
|
|
372
|
+
this.processsStreamInfo(streamInfo);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Parse STREAMINFO
|
|
376
|
+
*/
|
|
377
|
+
processsStreamInfo(streamInfo) {
|
|
378
|
+
this.metadata.setFormat("codec", "FLAC");
|
|
379
|
+
this.metadata.setFormat("hasAudio", true);
|
|
380
|
+
this.metadata.setFormat("lossless", true);
|
|
381
|
+
this.metadata.setFormat("numberOfChannels", streamInfo.channels);
|
|
382
|
+
this.metadata.setFormat("bitsPerSample", streamInfo.bitsPerSample);
|
|
383
|
+
this.metadata.setFormat("sampleRate", streamInfo.sampleRate);
|
|
384
|
+
if (streamInfo.totalSamples > 0) {
|
|
385
|
+
this.metadata.setFormat("duration", streamInfo.totalSamples / streamInfo.sampleRate);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Read VORBIS_COMMENT from tokenizer
|
|
390
|
+
* Ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-640004.2.3
|
|
391
|
+
*/
|
|
392
|
+
async readComment(dataLen) {
|
|
393
|
+
const data = await this.tokenizer.readToken(new Uint8ArrayType(dataLen));
|
|
394
|
+
return this.parseComment(data);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Parse VORBIS_COMMENT
|
|
398
|
+
* Ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-640004.2.3
|
|
399
|
+
*/
|
|
400
|
+
async parseComment(data) {
|
|
401
|
+
const decoder = new VorbisDecoder(data, 0);
|
|
402
|
+
const vendor = decoder.readStringUtf8();
|
|
403
|
+
if (vendor.length > 0) {
|
|
404
|
+
this.metadata.setFormat("tool", vendor);
|
|
405
|
+
}
|
|
406
|
+
const commentListLength = decoder.readInt32();
|
|
407
|
+
const tags = new Array(commentListLength);
|
|
408
|
+
for (let i = 0; i < commentListLength; i++) {
|
|
409
|
+
tags[i] = decoder.parseUserComment();
|
|
410
|
+
}
|
|
411
|
+
await Promise.all(tags.map((tag) => {
|
|
412
|
+
if (tag.key === "ENCODER") {
|
|
413
|
+
this.metadata.setFormat("tool", tag.value);
|
|
414
|
+
}
|
|
415
|
+
return this.addTag(tag.key, tag.value);
|
|
416
|
+
}));
|
|
417
|
+
}
|
|
418
|
+
async parsePicture(dataLen) {
|
|
419
|
+
if (this.options.skipCovers) {
|
|
420
|
+
return this.tokenizer.ignore(dataLen);
|
|
421
|
+
}
|
|
422
|
+
return this.addPictureTag(await this.tokenizer.readToken(new VorbisPictureToken(dataLen)));
|
|
423
|
+
}
|
|
424
|
+
addPictureTag(picture) {
|
|
425
|
+
return this.addTag("METADATA_BLOCK_PICTURE", picture);
|
|
426
|
+
}
|
|
427
|
+
addTag(id, value) {
|
|
428
|
+
return this.vorbisParser.addTag(id, value);
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
export {
|
|
433
|
+
VorbisPictureToken,
|
|
434
|
+
VorbisStream,
|
|
435
|
+
BlockType,
|
|
436
|
+
BlockHeader,
|
|
437
|
+
BlockStreamInfo,
|
|
438
|
+
FlacParser
|
|
439
|
+
};
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FieldDecodingError,
|
|
3
|
+
StringType
|
|
4
|
+
} from "./chunk-VGOIHW7D.js";
|
|
5
|
+
|
|
6
|
+
// ../../node_modules/.pnpm/uint8array-extras@1.5.0/node_modules/uint8array-extras/index.js
|
|
7
|
+
var objectToString = Object.prototype.toString;
|
|
8
|
+
var uint8ArrayStringified = "[object Uint8Array]";
|
|
9
|
+
function isType(value, typeConstructor, typeStringified) {
|
|
10
|
+
if (!value) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
if (value.constructor === typeConstructor) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
return objectToString.call(value) === typeStringified;
|
|
17
|
+
}
|
|
18
|
+
function isUint8Array(value) {
|
|
19
|
+
return isType(value, Uint8Array, uint8ArrayStringified);
|
|
20
|
+
}
|
|
21
|
+
function assertUint8Array(value) {
|
|
22
|
+
if (!isUint8Array(value)) {
|
|
23
|
+
throw new TypeError(`Expected \`Uint8Array\`, got \`${typeof value}\``);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
var cachedDecoders = {
|
|
27
|
+
utf8: new globalThis.TextDecoder("utf8")
|
|
28
|
+
};
|
|
29
|
+
var cachedEncoder = new globalThis.TextEncoder();
|
|
30
|
+
var byteToHexLookupTable = Array.from({ length: 256 }, (_, index) => index.toString(16).padStart(2, "0"));
|
|
31
|
+
function uint8ArrayToHex(array) {
|
|
32
|
+
assertUint8Array(array);
|
|
33
|
+
let hexString = "";
|
|
34
|
+
for (let index = 0; index < array.length; index++) {
|
|
35
|
+
hexString += byteToHexLookupTable[array[index]];
|
|
36
|
+
}
|
|
37
|
+
return hexString;
|
|
38
|
+
}
|
|
39
|
+
function getUintBE(view) {
|
|
40
|
+
const { byteLength } = view;
|
|
41
|
+
if (byteLength === 6) {
|
|
42
|
+
return view.getUint16(0) * 2 ** 32 + view.getUint32(2);
|
|
43
|
+
}
|
|
44
|
+
if (byteLength === 5) {
|
|
45
|
+
return view.getUint8(0) * 2 ** 32 + view.getUint32(1);
|
|
46
|
+
}
|
|
47
|
+
if (byteLength === 4) {
|
|
48
|
+
return view.getUint32(0);
|
|
49
|
+
}
|
|
50
|
+
if (byteLength === 3) {
|
|
51
|
+
return view.getUint8(0) * 2 ** 16 + view.getUint16(1);
|
|
52
|
+
}
|
|
53
|
+
if (byteLength === 2) {
|
|
54
|
+
return view.getUint16(0);
|
|
55
|
+
}
|
|
56
|
+
if (byteLength === 1) {
|
|
57
|
+
return view.getUint8(0);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/common/Util.js
|
|
62
|
+
function getBit(buf, off, bit) {
|
|
63
|
+
return (buf[off] & 1 << bit) !== 0;
|
|
64
|
+
}
|
|
65
|
+
function findZero(uint8Array, encoding) {
|
|
66
|
+
const len = uint8Array.length;
|
|
67
|
+
if (encoding === "utf-16le") {
|
|
68
|
+
for (let i = 0; i + 1 < len; i += 2) {
|
|
69
|
+
if (uint8Array[i] === 0 && uint8Array[i + 1] === 0)
|
|
70
|
+
return i;
|
|
71
|
+
}
|
|
72
|
+
return len;
|
|
73
|
+
}
|
|
74
|
+
for (let i = 0; i < len; i++) {
|
|
75
|
+
if (uint8Array[i] === 0)
|
|
76
|
+
return i;
|
|
77
|
+
}
|
|
78
|
+
return len;
|
|
79
|
+
}
|
|
80
|
+
function trimRightNull(x) {
|
|
81
|
+
const pos0 = x.indexOf("\0");
|
|
82
|
+
return pos0 === -1 ? x : x.substring(0, pos0);
|
|
83
|
+
}
|
|
84
|
+
function swapBytes(uint8Array) {
|
|
85
|
+
const l = uint8Array.length;
|
|
86
|
+
if ((l & 1) !== 0)
|
|
87
|
+
throw new FieldDecodingError("Buffer length must be even");
|
|
88
|
+
for (let i = 0; i < l; i += 2) {
|
|
89
|
+
const a = uint8Array[i];
|
|
90
|
+
uint8Array[i] = uint8Array[i + 1];
|
|
91
|
+
uint8Array[i + 1] = a;
|
|
92
|
+
}
|
|
93
|
+
return uint8Array;
|
|
94
|
+
}
|
|
95
|
+
function decodeString(uint8Array, encoding) {
|
|
96
|
+
if (uint8Array[0] === 255 && uint8Array[1] === 254) {
|
|
97
|
+
return decodeString(uint8Array.subarray(2), encoding);
|
|
98
|
+
}
|
|
99
|
+
if (encoding === "utf-16le" && uint8Array[0] === 254 && uint8Array[1] === 255) {
|
|
100
|
+
if ((uint8Array.length & 1) !== 0)
|
|
101
|
+
throw new FieldDecodingError("Expected even number of octets for 16-bit unicode string");
|
|
102
|
+
return decodeString(swapBytes(uint8Array), encoding);
|
|
103
|
+
}
|
|
104
|
+
return new StringType(uint8Array.length, encoding).get(uint8Array, 0);
|
|
105
|
+
}
|
|
106
|
+
function stripNulls(str) {
|
|
107
|
+
str = str.replace(/^\x00+/g, "");
|
|
108
|
+
str = str.replace(/\x00+$/g, "");
|
|
109
|
+
return str;
|
|
110
|
+
}
|
|
111
|
+
function getBitAllignedNumber(source, byteOffset, bitOffset, len) {
|
|
112
|
+
const byteOff = byteOffset + ~~(bitOffset / 8);
|
|
113
|
+
const bitOff = bitOffset % 8;
|
|
114
|
+
let value = source[byteOff];
|
|
115
|
+
value &= 255 >> bitOff;
|
|
116
|
+
const bitsRead = 8 - bitOff;
|
|
117
|
+
const bitsLeft = len - bitsRead;
|
|
118
|
+
if (bitsLeft < 0) {
|
|
119
|
+
value >>= 8 - bitOff - len;
|
|
120
|
+
} else if (bitsLeft > 0) {
|
|
121
|
+
value <<= bitsLeft;
|
|
122
|
+
value |= getBitAllignedNumber(source, byteOffset, bitOffset + bitsRead, bitsLeft);
|
|
123
|
+
}
|
|
124
|
+
return value;
|
|
125
|
+
}
|
|
126
|
+
function isBitSet(source, byteOffset, bitOffset) {
|
|
127
|
+
return getBitAllignedNumber(source, byteOffset, bitOffset, 1) === 1;
|
|
128
|
+
}
|
|
129
|
+
function a2hex(str) {
|
|
130
|
+
const arr = [];
|
|
131
|
+
for (let i = 0, l = str.length; i < l; i++) {
|
|
132
|
+
const hex = Number(str.charCodeAt(i)).toString(16);
|
|
133
|
+
arr.push(hex.length === 1 ? `0${hex}` : hex);
|
|
134
|
+
}
|
|
135
|
+
return arr.join(" ");
|
|
136
|
+
}
|
|
137
|
+
function ratioToDb(ratio) {
|
|
138
|
+
return 10 * Math.log10(ratio);
|
|
139
|
+
}
|
|
140
|
+
function dbToRatio(dB) {
|
|
141
|
+
return 10 ** (dB / 10);
|
|
142
|
+
}
|
|
143
|
+
function toRatio(value) {
|
|
144
|
+
const ps = value.split(" ").map((p) => p.trim().toLowerCase());
|
|
145
|
+
if (ps.length >= 1) {
|
|
146
|
+
const v = Number.parseFloat(ps[0]);
|
|
147
|
+
return ps.length === 2 && ps[1] === "db" ? {
|
|
148
|
+
dB: v,
|
|
149
|
+
ratio: dbToRatio(v)
|
|
150
|
+
} : {
|
|
151
|
+
dB: ratioToDb(v),
|
|
152
|
+
ratio: v
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function decodeUintBE(uint8Array) {
|
|
157
|
+
if (uint8Array.length === 0) {
|
|
158
|
+
throw new Error("decodeUintBE: empty Uint8Array");
|
|
159
|
+
}
|
|
160
|
+
const view = new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength);
|
|
161
|
+
return getUintBE(view);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export {
|
|
165
|
+
uint8ArrayToHex,
|
|
166
|
+
getUintBE,
|
|
167
|
+
getBit,
|
|
168
|
+
findZero,
|
|
169
|
+
trimRightNull,
|
|
170
|
+
decodeString,
|
|
171
|
+
stripNulls,
|
|
172
|
+
getBitAllignedNumber,
|
|
173
|
+
isBitSet,
|
|
174
|
+
a2hex,
|
|
175
|
+
toRatio,
|
|
176
|
+
decodeUintBE
|
|
177
|
+
};
|