agdi 3.3.6 → 3.3.8
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 +3966 -1203
- 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 +5 -2
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ID3v2Parser
|
|
3
|
+
} from "./chunk-65JVFJ3X.js";
|
|
4
|
+
import "./chunk-2B4QMSZW.js";
|
|
5
|
+
import {
|
|
6
|
+
FourCcToken
|
|
7
|
+
} from "./chunk-YIHDW7JC.js";
|
|
8
|
+
import {
|
|
9
|
+
EndOfStreamError,
|
|
10
|
+
fromBuffer
|
|
11
|
+
} from "./chunk-HNLU36CC.js";
|
|
12
|
+
import "./chunk-LREP5CZP.js";
|
|
13
|
+
import {
|
|
14
|
+
stripNulls
|
|
15
|
+
} from "./chunk-GD35BJSH.js";
|
|
16
|
+
import {
|
|
17
|
+
BasicParser,
|
|
18
|
+
StringType,
|
|
19
|
+
UINT16_LE,
|
|
20
|
+
UINT32_LE,
|
|
21
|
+
Uint8ArrayType,
|
|
22
|
+
makeUnexpectedFileContentError,
|
|
23
|
+
require_src
|
|
24
|
+
} from "./chunk-VGOIHW7D.js";
|
|
25
|
+
import {
|
|
26
|
+
__toESM
|
|
27
|
+
} from "./chunk-4VNS5WPM.js";
|
|
28
|
+
|
|
29
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/wav/WaveParser.js
|
|
30
|
+
var import_debug = __toESM(require_src(), 1);
|
|
31
|
+
|
|
32
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/riff/RiffChunk.js
|
|
33
|
+
var Header = {
|
|
34
|
+
len: 8,
|
|
35
|
+
get: (buf, off) => {
|
|
36
|
+
return {
|
|
37
|
+
// Group-ID
|
|
38
|
+
chunkID: new StringType(4, "latin1").get(buf, off),
|
|
39
|
+
// Size
|
|
40
|
+
chunkSize: UINT32_LE.get(buf, off + 4)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var ListInfoTagValue = class {
|
|
45
|
+
constructor(tagHeader) {
|
|
46
|
+
this.tagHeader = tagHeader;
|
|
47
|
+
this.len = tagHeader.chunkSize;
|
|
48
|
+
this.len += this.len & 1;
|
|
49
|
+
}
|
|
50
|
+
get(buf, off) {
|
|
51
|
+
return new StringType(this.tagHeader.chunkSize, "ascii").get(buf, off);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/wav/WaveChunk.js
|
|
56
|
+
var WaveContentError = class extends makeUnexpectedFileContentError("Wave") {
|
|
57
|
+
};
|
|
58
|
+
var WaveFormat = {
|
|
59
|
+
PCM: 1,
|
|
60
|
+
// MPEG-4 and AAC Audio Types
|
|
61
|
+
ADPCM: 2,
|
|
62
|
+
IEEE_FLOAT: 3,
|
|
63
|
+
MPEG_ADTS_AAC: 5632,
|
|
64
|
+
MPEG_LOAS: 5634,
|
|
65
|
+
RAW_AAC1: 255,
|
|
66
|
+
// Dolby Audio Types
|
|
67
|
+
DOLBY_AC3_SPDIF: 146,
|
|
68
|
+
DVM: 8192,
|
|
69
|
+
RAW_SPORT: 576,
|
|
70
|
+
ESST_AC3: 577,
|
|
71
|
+
DRM: 9,
|
|
72
|
+
DTS2: 8193,
|
|
73
|
+
MPEG: 80
|
|
74
|
+
};
|
|
75
|
+
var WaveFormatNameMap = {
|
|
76
|
+
[WaveFormat.PCM]: "PCM",
|
|
77
|
+
[WaveFormat.ADPCM]: "ADPCM",
|
|
78
|
+
[WaveFormat.IEEE_FLOAT]: "IEEE_FLOAT",
|
|
79
|
+
[WaveFormat.MPEG_ADTS_AAC]: "MPEG_ADTS_AAC",
|
|
80
|
+
[WaveFormat.MPEG_LOAS]: "MPEG_LOAS",
|
|
81
|
+
[WaveFormat.RAW_AAC1]: "RAW_AAC1",
|
|
82
|
+
[WaveFormat.DOLBY_AC3_SPDIF]: "DOLBY_AC3_SPDIF",
|
|
83
|
+
[WaveFormat.DVM]: "DVM",
|
|
84
|
+
[WaveFormat.RAW_SPORT]: "RAW_SPORT",
|
|
85
|
+
[WaveFormat.ESST_AC3]: "ESST_AC3",
|
|
86
|
+
[WaveFormat.DRM]: "DRM",
|
|
87
|
+
[WaveFormat.DTS2]: "DTS2",
|
|
88
|
+
[WaveFormat.MPEG]: "MPEG"
|
|
89
|
+
};
|
|
90
|
+
var Format = class {
|
|
91
|
+
constructor(header) {
|
|
92
|
+
if (header.chunkSize < 16)
|
|
93
|
+
throw new WaveContentError("Invalid chunk size");
|
|
94
|
+
this.len = header.chunkSize;
|
|
95
|
+
}
|
|
96
|
+
get(buf, off) {
|
|
97
|
+
return {
|
|
98
|
+
wFormatTag: UINT16_LE.get(buf, off),
|
|
99
|
+
nChannels: UINT16_LE.get(buf, off + 2),
|
|
100
|
+
nSamplesPerSec: UINT32_LE.get(buf, off + 4),
|
|
101
|
+
nAvgBytesPerSec: UINT32_LE.get(buf, off + 8),
|
|
102
|
+
nBlockAlign: UINT16_LE.get(buf, off + 12),
|
|
103
|
+
wBitsPerSample: UINT16_LE.get(buf, off + 14)
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
var FactChunk = class {
|
|
108
|
+
constructor(header) {
|
|
109
|
+
if (header.chunkSize < 4) {
|
|
110
|
+
throw new WaveContentError("Invalid fact chunk size.");
|
|
111
|
+
}
|
|
112
|
+
this.len = header.chunkSize;
|
|
113
|
+
}
|
|
114
|
+
get(buf, off) {
|
|
115
|
+
return {
|
|
116
|
+
dwSampleLength: UINT32_LE.get(buf, off)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/wav/BwfChunk.js
|
|
122
|
+
var BroadcastAudioExtensionChunk = {
|
|
123
|
+
len: 420,
|
|
124
|
+
get: (uint8array, off) => {
|
|
125
|
+
return {
|
|
126
|
+
description: stripNulls(new StringType(256, "ascii").get(uint8array, off)).trim(),
|
|
127
|
+
originator: stripNulls(new StringType(32, "ascii").get(uint8array, off + 256)).trim(),
|
|
128
|
+
originatorReference: stripNulls(new StringType(32, "ascii").get(uint8array, off + 288)).trim(),
|
|
129
|
+
originationDate: stripNulls(new StringType(10, "ascii").get(uint8array, off + 320)).trim(),
|
|
130
|
+
originationTime: stripNulls(new StringType(8, "ascii").get(uint8array, off + 330)).trim(),
|
|
131
|
+
timeReferenceLow: UINT32_LE.get(uint8array, off + 338),
|
|
132
|
+
timeReferenceHigh: UINT32_LE.get(uint8array, off + 342),
|
|
133
|
+
version: UINT16_LE.get(uint8array, off + 346),
|
|
134
|
+
umid: new Uint8ArrayType(64).get(uint8array, off + 348),
|
|
135
|
+
loudnessValue: UINT16_LE.get(uint8array, off + 412),
|
|
136
|
+
maxTruePeakLevel: UINT16_LE.get(uint8array, off + 414),
|
|
137
|
+
maxMomentaryLoudness: UINT16_LE.get(uint8array, off + 416),
|
|
138
|
+
maxShortTermLoudness: UINT16_LE.get(uint8array, off + 418)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/wav/WaveParser.js
|
|
144
|
+
var debug = (0, import_debug.default)("music-metadata:parser:RIFF");
|
|
145
|
+
var WaveParser = class extends BasicParser {
|
|
146
|
+
constructor() {
|
|
147
|
+
super(...arguments);
|
|
148
|
+
this.blockAlign = 0;
|
|
149
|
+
}
|
|
150
|
+
async parse() {
|
|
151
|
+
const riffHeader = await this.tokenizer.readToken(Header);
|
|
152
|
+
debug(`pos=${this.tokenizer.position}, parse: chunkID=${riffHeader.chunkID}`);
|
|
153
|
+
if (riffHeader.chunkID !== "RIFF")
|
|
154
|
+
return;
|
|
155
|
+
this.metadata.setAudioOnly();
|
|
156
|
+
return this.parseRiffChunk(riffHeader.chunkSize).catch((err) => {
|
|
157
|
+
if (!(err instanceof EndOfStreamError)) {
|
|
158
|
+
throw err;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
async parseRiffChunk(chunkSize) {
|
|
163
|
+
const type = await this.tokenizer.readToken(FourCcToken);
|
|
164
|
+
this.metadata.setFormat("container", type);
|
|
165
|
+
switch (type) {
|
|
166
|
+
case "WAVE":
|
|
167
|
+
return this.readWaveChunk(chunkSize - FourCcToken.len);
|
|
168
|
+
default:
|
|
169
|
+
throw new WaveContentError(`Unsupported RIFF format: RIFF/${type}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async readWaveChunk(remaining) {
|
|
173
|
+
while (remaining >= Header.len) {
|
|
174
|
+
const header = await this.tokenizer.readToken(Header);
|
|
175
|
+
remaining -= Header.len + header.chunkSize;
|
|
176
|
+
if (header.chunkSize > remaining) {
|
|
177
|
+
this.metadata.addWarning("Data chunk size exceeds file size");
|
|
178
|
+
}
|
|
179
|
+
this.header = header;
|
|
180
|
+
debug(`pos=${this.tokenizer.position}, readChunk: chunkID=RIFF/WAVE/${header.chunkID}`);
|
|
181
|
+
switch (header.chunkID) {
|
|
182
|
+
case "LIST":
|
|
183
|
+
await this.parseListTag(header);
|
|
184
|
+
break;
|
|
185
|
+
case "fact":
|
|
186
|
+
this.metadata.setFormat("lossless", false);
|
|
187
|
+
this.fact = await this.tokenizer.readToken(new FactChunk(header));
|
|
188
|
+
break;
|
|
189
|
+
case "fmt ": {
|
|
190
|
+
const fmt = await this.tokenizer.readToken(new Format(header));
|
|
191
|
+
let subFormat = WaveFormatNameMap[fmt.wFormatTag];
|
|
192
|
+
if (!subFormat) {
|
|
193
|
+
debug(`WAVE/non-PCM format=${fmt.wFormatTag}`);
|
|
194
|
+
subFormat = `non-PCM (${fmt.wFormatTag})`;
|
|
195
|
+
}
|
|
196
|
+
this.metadata.setFormat("codec", subFormat);
|
|
197
|
+
this.metadata.setFormat("bitsPerSample", fmt.wBitsPerSample);
|
|
198
|
+
this.metadata.setFormat("sampleRate", fmt.nSamplesPerSec);
|
|
199
|
+
this.metadata.setFormat("numberOfChannels", fmt.nChannels);
|
|
200
|
+
this.metadata.setFormat("bitrate", fmt.nBlockAlign * fmt.nSamplesPerSec * 8);
|
|
201
|
+
this.blockAlign = fmt.nBlockAlign;
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
case "id3 ":
|
|
205
|
+
// The way Picard, FooBar currently stores, ID3 meta-data
|
|
206
|
+
case "ID3 ": {
|
|
207
|
+
const id3_data = await this.tokenizer.readToken(new Uint8ArrayType(header.chunkSize));
|
|
208
|
+
const rst = fromBuffer(id3_data);
|
|
209
|
+
await new ID3v2Parser().parse(this.metadata, rst, this.options);
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case "data": {
|
|
213
|
+
if (this.metadata.format.lossless !== false) {
|
|
214
|
+
this.metadata.setFormat("lossless", true);
|
|
215
|
+
}
|
|
216
|
+
let chunkSize = header.chunkSize;
|
|
217
|
+
if (this.tokenizer.fileInfo.size) {
|
|
218
|
+
const calcRemaining = this.tokenizer.fileInfo.size - this.tokenizer.position;
|
|
219
|
+
if (calcRemaining < chunkSize) {
|
|
220
|
+
this.metadata.addWarning("data chunk length exceeding file length");
|
|
221
|
+
chunkSize = calcRemaining;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
const numberOfSamples = this.fact ? this.fact.dwSampleLength : chunkSize === 4294967295 ? void 0 : chunkSize / this.blockAlign;
|
|
225
|
+
if (numberOfSamples) {
|
|
226
|
+
this.metadata.setFormat("numberOfSamples", numberOfSamples);
|
|
227
|
+
if (this.metadata.format.sampleRate) {
|
|
228
|
+
this.metadata.setFormat("duration", numberOfSamples / this.metadata.format.sampleRate);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (this.metadata.format.codec === "ADPCM") {
|
|
232
|
+
this.metadata.setFormat("bitrate", 352e3);
|
|
233
|
+
} else if (this.metadata.format.sampleRate) {
|
|
234
|
+
this.metadata.setFormat("bitrate", this.blockAlign * this.metadata.format.sampleRate * 8);
|
|
235
|
+
}
|
|
236
|
+
await this.tokenizer.ignore(header.chunkSize);
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
case "bext": {
|
|
240
|
+
const bext = await this.tokenizer.readToken(BroadcastAudioExtensionChunk);
|
|
241
|
+
Object.keys(bext).forEach((key) => {
|
|
242
|
+
this.metadata.addTag("exif", `bext.${key}`, bext[key]);
|
|
243
|
+
});
|
|
244
|
+
const bextRemaining = header.chunkSize - BroadcastAudioExtensionChunk.len;
|
|
245
|
+
await this.tokenizer.ignore(bextRemaining);
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
case "\0\0\0\0":
|
|
249
|
+
debug(`Ignore padding chunk: RIFF/${header.chunkID} of ${header.chunkSize} bytes`);
|
|
250
|
+
this.metadata.addWarning(`Ignore chunk: RIFF/${header.chunkID}`);
|
|
251
|
+
await this.tokenizer.ignore(header.chunkSize);
|
|
252
|
+
break;
|
|
253
|
+
default:
|
|
254
|
+
debug(`Ignore chunk: RIFF/${header.chunkID} of ${header.chunkSize} bytes`);
|
|
255
|
+
this.metadata.addWarning(`Ignore chunk: RIFF/${header.chunkID}`);
|
|
256
|
+
await this.tokenizer.ignore(header.chunkSize);
|
|
257
|
+
}
|
|
258
|
+
if (this.header.chunkSize % 2 === 1) {
|
|
259
|
+
debug("Read odd padding byte");
|
|
260
|
+
await this.tokenizer.ignore(1);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
async parseListTag(listHeader) {
|
|
265
|
+
const listType = await this.tokenizer.readToken(new StringType(4, "latin1"));
|
|
266
|
+
debug("pos=%s, parseListTag: chunkID=RIFF/WAVE/LIST/%s", this.tokenizer.position, listType);
|
|
267
|
+
switch (listType) {
|
|
268
|
+
case "INFO":
|
|
269
|
+
return this.parseRiffInfoTags(listHeader.chunkSize - 4);
|
|
270
|
+
default:
|
|
271
|
+
this.metadata.addWarning(`Ignore chunk: RIFF/WAVE/LIST/${listType}`);
|
|
272
|
+
debug(`Ignoring chunkID=RIFF/WAVE/LIST/${listType}`);
|
|
273
|
+
return this.tokenizer.ignore(listHeader.chunkSize - 4).then();
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
async parseRiffInfoTags(chunkSize) {
|
|
277
|
+
while (chunkSize >= 8) {
|
|
278
|
+
const header = await this.tokenizer.readToken(Header);
|
|
279
|
+
const valueToken = new ListInfoTagValue(header);
|
|
280
|
+
const value = await this.tokenizer.readToken(valueToken);
|
|
281
|
+
this.addTag(header.chunkID, stripNulls(value));
|
|
282
|
+
chunkSize -= 8 + valueToken.len;
|
|
283
|
+
}
|
|
284
|
+
if (chunkSize !== 0) {
|
|
285
|
+
throw new WaveContentError(`Illegal remaining size: ${chunkSize}`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
addTag(id, value) {
|
|
289
|
+
this.metadata.addTag("exif", id, value);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
export {
|
|
293
|
+
WaveParser
|
|
294
|
+
};
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import {
|
|
2
|
+
APEv2Parser
|
|
3
|
+
} from "./chunk-YIHDW7JC.js";
|
|
4
|
+
import {
|
|
5
|
+
trimRightNull
|
|
6
|
+
} from "./chunk-GD35BJSH.js";
|
|
7
|
+
import {
|
|
8
|
+
BasicParser,
|
|
9
|
+
StringType,
|
|
10
|
+
UINT8,
|
|
11
|
+
require_src,
|
|
12
|
+
textDecode
|
|
13
|
+
} from "./chunk-VGOIHW7D.js";
|
|
14
|
+
import {
|
|
15
|
+
__toESM
|
|
16
|
+
} from "./chunk-4VNS5WPM.js";
|
|
17
|
+
|
|
18
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/id3v1/ID3v1Parser.js
|
|
19
|
+
var import_debug = __toESM(require_src(), 1);
|
|
20
|
+
var debug = (0, import_debug.default)("music-metadata:parser:ID3v1");
|
|
21
|
+
var Genres = [
|
|
22
|
+
"Blues",
|
|
23
|
+
"Classic Rock",
|
|
24
|
+
"Country",
|
|
25
|
+
"Dance",
|
|
26
|
+
"Disco",
|
|
27
|
+
"Funk",
|
|
28
|
+
"Grunge",
|
|
29
|
+
"Hip-Hop",
|
|
30
|
+
"Jazz",
|
|
31
|
+
"Metal",
|
|
32
|
+
"New Age",
|
|
33
|
+
"Oldies",
|
|
34
|
+
"Other",
|
|
35
|
+
"Pop",
|
|
36
|
+
"R&B",
|
|
37
|
+
"Rap",
|
|
38
|
+
"Reggae",
|
|
39
|
+
"Rock",
|
|
40
|
+
"Techno",
|
|
41
|
+
"Industrial",
|
|
42
|
+
"Alternative",
|
|
43
|
+
"Ska",
|
|
44
|
+
"Death Metal",
|
|
45
|
+
"Pranks",
|
|
46
|
+
"Soundtrack",
|
|
47
|
+
"Euro-Techno",
|
|
48
|
+
"Ambient",
|
|
49
|
+
"Trip-Hop",
|
|
50
|
+
"Vocal",
|
|
51
|
+
"Jazz+Funk",
|
|
52
|
+
"Fusion",
|
|
53
|
+
"Trance",
|
|
54
|
+
"Classical",
|
|
55
|
+
"Instrumental",
|
|
56
|
+
"Acid",
|
|
57
|
+
"House",
|
|
58
|
+
"Game",
|
|
59
|
+
"Sound Clip",
|
|
60
|
+
"Gospel",
|
|
61
|
+
"Noise",
|
|
62
|
+
"Alt. Rock",
|
|
63
|
+
"Bass",
|
|
64
|
+
"Soul",
|
|
65
|
+
"Punk",
|
|
66
|
+
"Space",
|
|
67
|
+
"Meditative",
|
|
68
|
+
"Instrumental Pop",
|
|
69
|
+
"Instrumental Rock",
|
|
70
|
+
"Ethnic",
|
|
71
|
+
"Gothic",
|
|
72
|
+
"Darkwave",
|
|
73
|
+
"Techno-Industrial",
|
|
74
|
+
"Electronic",
|
|
75
|
+
"Pop-Folk",
|
|
76
|
+
"Eurodance",
|
|
77
|
+
"Dream",
|
|
78
|
+
"Southern Rock",
|
|
79
|
+
"Comedy",
|
|
80
|
+
"Cult",
|
|
81
|
+
"Gangsta Rap",
|
|
82
|
+
"Top 40",
|
|
83
|
+
"Christian Rap",
|
|
84
|
+
"Pop/Funk",
|
|
85
|
+
"Jungle",
|
|
86
|
+
"Native American",
|
|
87
|
+
"Cabaret",
|
|
88
|
+
"New Wave",
|
|
89
|
+
"Psychedelic",
|
|
90
|
+
"Rave",
|
|
91
|
+
"Showtunes",
|
|
92
|
+
"Trailer",
|
|
93
|
+
"Lo-Fi",
|
|
94
|
+
"Tribal",
|
|
95
|
+
"Acid Punk",
|
|
96
|
+
"Acid Jazz",
|
|
97
|
+
"Polka",
|
|
98
|
+
"Retro",
|
|
99
|
+
"Musical",
|
|
100
|
+
"Rock & Roll",
|
|
101
|
+
"Hard Rock",
|
|
102
|
+
"Folk",
|
|
103
|
+
"Folk/Rock",
|
|
104
|
+
"National Folk",
|
|
105
|
+
"Swing",
|
|
106
|
+
"Fast-Fusion",
|
|
107
|
+
"Bebob",
|
|
108
|
+
"Latin",
|
|
109
|
+
"Revival",
|
|
110
|
+
"Celtic",
|
|
111
|
+
"Bluegrass",
|
|
112
|
+
"Avantgarde",
|
|
113
|
+
"Gothic Rock",
|
|
114
|
+
"Progressive Rock",
|
|
115
|
+
"Psychedelic Rock",
|
|
116
|
+
"Symphonic Rock",
|
|
117
|
+
"Slow Rock",
|
|
118
|
+
"Big Band",
|
|
119
|
+
"Chorus",
|
|
120
|
+
"Easy Listening",
|
|
121
|
+
"Acoustic",
|
|
122
|
+
"Humour",
|
|
123
|
+
"Speech",
|
|
124
|
+
"Chanson",
|
|
125
|
+
"Opera",
|
|
126
|
+
"Chamber Music",
|
|
127
|
+
"Sonata",
|
|
128
|
+
"Symphony",
|
|
129
|
+
"Booty Bass",
|
|
130
|
+
"Primus",
|
|
131
|
+
"Porn Groove",
|
|
132
|
+
"Satire",
|
|
133
|
+
"Slow Jam",
|
|
134
|
+
"Club",
|
|
135
|
+
"Tango",
|
|
136
|
+
"Samba",
|
|
137
|
+
"Folklore",
|
|
138
|
+
"Ballad",
|
|
139
|
+
"Power Ballad",
|
|
140
|
+
"Rhythmic Soul",
|
|
141
|
+
"Freestyle",
|
|
142
|
+
"Duet",
|
|
143
|
+
"Punk Rock",
|
|
144
|
+
"Drum Solo",
|
|
145
|
+
"A Cappella",
|
|
146
|
+
"Euro-House",
|
|
147
|
+
"Dance Hall",
|
|
148
|
+
"Goa",
|
|
149
|
+
"Drum & Bass",
|
|
150
|
+
"Club-House",
|
|
151
|
+
"Hardcore",
|
|
152
|
+
"Terror",
|
|
153
|
+
"Indie",
|
|
154
|
+
"BritPop",
|
|
155
|
+
"Negerpunk",
|
|
156
|
+
"Polsk Punk",
|
|
157
|
+
"Beat",
|
|
158
|
+
"Christian Gangsta Rap",
|
|
159
|
+
"Heavy Metal",
|
|
160
|
+
"Black Metal",
|
|
161
|
+
"Crossover",
|
|
162
|
+
"Contemporary Christian",
|
|
163
|
+
"Christian Rock",
|
|
164
|
+
"Merengue",
|
|
165
|
+
"Salsa",
|
|
166
|
+
"Thrash Metal",
|
|
167
|
+
"Anime",
|
|
168
|
+
"JPop",
|
|
169
|
+
"Synthpop",
|
|
170
|
+
"Abstract",
|
|
171
|
+
"Art Rock",
|
|
172
|
+
"Baroque",
|
|
173
|
+
"Bhangra",
|
|
174
|
+
"Big Beat",
|
|
175
|
+
"Breakbeat",
|
|
176
|
+
"Chillout",
|
|
177
|
+
"Downtempo",
|
|
178
|
+
"Dub",
|
|
179
|
+
"EBM",
|
|
180
|
+
"Eclectic",
|
|
181
|
+
"Electro",
|
|
182
|
+
"Electroclash",
|
|
183
|
+
"Emo",
|
|
184
|
+
"Experimental",
|
|
185
|
+
"Garage",
|
|
186
|
+
"Global",
|
|
187
|
+
"IDM",
|
|
188
|
+
"Illbient",
|
|
189
|
+
"Industro-Goth",
|
|
190
|
+
"Jam Band",
|
|
191
|
+
"Krautrock",
|
|
192
|
+
"Leftfield",
|
|
193
|
+
"Lounge",
|
|
194
|
+
"Math Rock",
|
|
195
|
+
"New Romantic",
|
|
196
|
+
"Nu-Breakz",
|
|
197
|
+
"Post-Punk",
|
|
198
|
+
"Post-Rock",
|
|
199
|
+
"Psytrance",
|
|
200
|
+
"Shoegaze",
|
|
201
|
+
"Space Rock",
|
|
202
|
+
"Trop Rock",
|
|
203
|
+
"World Music",
|
|
204
|
+
"Neoclassical",
|
|
205
|
+
"Audiobook",
|
|
206
|
+
"Audio Theatre",
|
|
207
|
+
"Neue Deutsche Welle",
|
|
208
|
+
"Podcast",
|
|
209
|
+
"Indie Rock",
|
|
210
|
+
"G-Funk",
|
|
211
|
+
"Dubstep",
|
|
212
|
+
"Garage Rock",
|
|
213
|
+
"Psybient"
|
|
214
|
+
];
|
|
215
|
+
var Iid3v1Token = {
|
|
216
|
+
len: 128,
|
|
217
|
+
/**
|
|
218
|
+
* @param buf Buffer possibly holding the 128 bytes ID3v1.1 metadata header
|
|
219
|
+
* @param off Offset in buffer in bytes
|
|
220
|
+
* @returns ID3v1.1 header if first 3 bytes equals 'TAG', otherwise null is returned
|
|
221
|
+
*/
|
|
222
|
+
get: (buf, off) => {
|
|
223
|
+
const header = new Id3v1StringType(3).get(buf, off);
|
|
224
|
+
return header === "TAG" ? {
|
|
225
|
+
header,
|
|
226
|
+
title: new Id3v1StringType(30).get(buf, off + 3),
|
|
227
|
+
artist: new Id3v1StringType(30).get(buf, off + 33),
|
|
228
|
+
album: new Id3v1StringType(30).get(buf, off + 63),
|
|
229
|
+
year: new Id3v1StringType(4).get(buf, off + 93),
|
|
230
|
+
comment: new Id3v1StringType(28).get(buf, off + 97),
|
|
231
|
+
// ID3v1.1 separator for track
|
|
232
|
+
zeroByte: UINT8.get(buf, off + 127),
|
|
233
|
+
// track: ID3v1.1 field added by Michael Mutschler
|
|
234
|
+
track: UINT8.get(buf, off + 126),
|
|
235
|
+
genre: UINT8.get(buf, off + 127)
|
|
236
|
+
} : null;
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
var Id3v1StringType = class {
|
|
240
|
+
constructor(len) {
|
|
241
|
+
this.len = len;
|
|
242
|
+
this.stringType = new StringType(len, "latin1");
|
|
243
|
+
}
|
|
244
|
+
get(buf, off) {
|
|
245
|
+
let value = this.stringType.get(buf, off);
|
|
246
|
+
value = trimRightNull(value);
|
|
247
|
+
value = value.trim();
|
|
248
|
+
return value.length > 0 ? value : void 0;
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
var ID3v1Parser = class _ID3v1Parser extends BasicParser {
|
|
252
|
+
constructor(metadata, tokenizer, options) {
|
|
253
|
+
super(metadata, tokenizer, options);
|
|
254
|
+
this.apeHeader = options.apeHeader;
|
|
255
|
+
}
|
|
256
|
+
static getGenre(genreIndex) {
|
|
257
|
+
if (genreIndex < Genres.length) {
|
|
258
|
+
return Genres[genreIndex];
|
|
259
|
+
}
|
|
260
|
+
return void 0;
|
|
261
|
+
}
|
|
262
|
+
async parse() {
|
|
263
|
+
if (!this.tokenizer.fileInfo.size) {
|
|
264
|
+
debug("Skip checking for ID3v1 because the file-size is unknown");
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (this.apeHeader) {
|
|
268
|
+
this.tokenizer.ignore(this.apeHeader.offset - this.tokenizer.position);
|
|
269
|
+
const apeParser = new APEv2Parser(this.metadata, this.tokenizer, this.options);
|
|
270
|
+
await apeParser.parseTags(this.apeHeader.footer);
|
|
271
|
+
}
|
|
272
|
+
const offset = this.tokenizer.fileInfo.size - Iid3v1Token.len;
|
|
273
|
+
if (this.tokenizer.position > offset) {
|
|
274
|
+
debug("Already consumed the last 128 bytes");
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const header = await this.tokenizer.readToken(Iid3v1Token, offset);
|
|
278
|
+
if (header) {
|
|
279
|
+
debug("ID3v1 header found at: pos=%s", this.tokenizer.fileInfo.size - Iid3v1Token.len);
|
|
280
|
+
const props = ["title", "artist", "album", "comment", "track", "year"];
|
|
281
|
+
for (const id of props) {
|
|
282
|
+
if (header[id] && header[id] !== "")
|
|
283
|
+
await this.addTag(id, header[id]);
|
|
284
|
+
}
|
|
285
|
+
const genre = _ID3v1Parser.getGenre(header.genre);
|
|
286
|
+
if (genre)
|
|
287
|
+
await this.addTag("genre", genre);
|
|
288
|
+
} else {
|
|
289
|
+
debug("ID3v1 header not found at: pos=%s", this.tokenizer.fileInfo.size - Iid3v1Token.len);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
async addTag(id, value) {
|
|
293
|
+
await this.metadata.addTag("ID3v1", id, value);
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
async function hasID3v1Header(tokenizer) {
|
|
297
|
+
if (tokenizer.fileInfo.size >= 128) {
|
|
298
|
+
const tag = new Uint8Array(3);
|
|
299
|
+
const position = tokenizer.position;
|
|
300
|
+
await tokenizer.readBuffer(tag, { position: tokenizer.fileInfo.size - 128 });
|
|
301
|
+
tokenizer.setPosition(position);
|
|
302
|
+
return textDecode(tag, "latin1") === "TAG";
|
|
303
|
+
}
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export {
|
|
308
|
+
Genres,
|
|
309
|
+
ID3v1Parser,
|
|
310
|
+
hasID3v1Header
|
|
311
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ID3v2Parser
|
|
3
|
+
} from "./chunk-65JVFJ3X.js";
|
|
4
|
+
import {
|
|
5
|
+
ID3v1Parser
|
|
6
|
+
} from "./chunk-2B4QMSZW.js";
|
|
7
|
+
import {
|
|
8
|
+
EndOfStreamError
|
|
9
|
+
} from "./chunk-HNLU36CC.js";
|
|
10
|
+
import {
|
|
11
|
+
ID3v2Header
|
|
12
|
+
} from "./chunk-LREP5CZP.js";
|
|
13
|
+
import {
|
|
14
|
+
BasicParser,
|
|
15
|
+
require_src
|
|
16
|
+
} from "./chunk-VGOIHW7D.js";
|
|
17
|
+
import {
|
|
18
|
+
__toESM
|
|
19
|
+
} from "./chunk-4VNS5WPM.js";
|
|
20
|
+
|
|
21
|
+
// ../../node_modules/.pnpm/music-metadata@11.12.0/node_modules/music-metadata/lib/id3v2/AbstractID3Parser.js
|
|
22
|
+
var import_debug = __toESM(require_src(), 1);
|
|
23
|
+
var debug = (0, import_debug.default)("music-metadata:parser:ID3");
|
|
24
|
+
var AbstractID3Parser = class extends BasicParser {
|
|
25
|
+
constructor() {
|
|
26
|
+
super(...arguments);
|
|
27
|
+
this.id3parser = new ID3v2Parser();
|
|
28
|
+
}
|
|
29
|
+
static async startsWithID3v2Header(tokenizer) {
|
|
30
|
+
return (await tokenizer.peekToken(ID3v2Header)).fileIdentifier === "ID3";
|
|
31
|
+
}
|
|
32
|
+
async parse() {
|
|
33
|
+
try {
|
|
34
|
+
await this.parseID3v2();
|
|
35
|
+
} catch (err) {
|
|
36
|
+
if (err instanceof EndOfStreamError) {
|
|
37
|
+
debug("End-of-stream");
|
|
38
|
+
} else {
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
finalize() {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
async parseID3v2() {
|
|
47
|
+
await this.tryReadId3v2Headers();
|
|
48
|
+
debug("End of ID3v2 header, go to MPEG-parser: pos=%s", this.tokenizer.position);
|
|
49
|
+
await this.postId3v2Parse();
|
|
50
|
+
if (this.options.skipPostHeaders && this.metadata.hasAny()) {
|
|
51
|
+
this.finalize();
|
|
52
|
+
} else {
|
|
53
|
+
const id3v1parser = new ID3v1Parser(this.metadata, this.tokenizer, this.options);
|
|
54
|
+
await id3v1parser.parse();
|
|
55
|
+
this.finalize();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async tryReadId3v2Headers() {
|
|
59
|
+
const id3Header = await this.tokenizer.peekToken(ID3v2Header);
|
|
60
|
+
if (id3Header.fileIdentifier === "ID3") {
|
|
61
|
+
debug("Found ID3v2 header, pos=%s", this.tokenizer.position);
|
|
62
|
+
await this.id3parser.parse(this.metadata, this.tokenizer, this.options);
|
|
63
|
+
return this.tryReadId3v2Headers();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export {
|
|
69
|
+
AbstractID3Parser
|
|
70
|
+
};
|