@openclaw/whatsapp 2026.9.34 → 2026.9.36
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/dist/.source-module-urls/c3803b0fa58e9b1fe1f7418a46193ebc53b9c744f6359f04d40d05af48c1dce2.json +1 -0
- package/node_modules/baileys/node_modules/music-metadata/README.md +35 -32
- package/node_modules/baileys/node_modules/music-metadata/lib/ParserFactory.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ParserFactory.js +17 -13
- package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffParser.js +19 -12
- package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffToken.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/aiff/AiffToken.js +2 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Parser.d.ts +4 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Parser.js +59 -16
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2TagMapper.js +1 -0
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Token.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/apev2/APEv2Token.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfGuid.js +56 -50
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfObject.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfObject.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfParser.js +15 -7
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfTagMapper.d.ts +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/asf/AsfTagMapper.js +21 -4
- package/node_modules/baileys/node_modules/music-metadata/lib/common/CaseInsensitiveTagMap.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/CombinedTagMapper.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/common/CombinedTagMapper.js +6 -6
- package/node_modules/baileys/node_modules/music-metadata/lib/common/FourCC.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/common/GenericTagMapper.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/GenericTagTypes.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/MetadataCollector.d.ts +3 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/common/MetadataCollector.js +28 -9
- package/node_modules/baileys/node_modules/music-metadata/lib/common/Util.js +25 -17
- package/node_modules/baileys/node_modules/music-metadata/lib/core.d.ts +4 -4
- package/node_modules/baileys/node_modules/music-metadata/lib/core.js +18 -11
- package/node_modules/baileys/node_modules/music-metadata/lib/dsdiff/DsdiffParser.js +29 -16
- package/node_modules/baileys/node_modules/music-metadata/lib/dsf/DsfChunk.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/dsf/DsfParser.js +3 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/EbmlIterator.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/EbmlIterator.js +35 -6
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/types.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ebml/types.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacParser.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacParser.js +6 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacToken.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/flac/FlacToken.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v1/ID3v1Parser.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v1/ID3v1Parser.js +212 -42
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/AbstractID3Parser.js +5 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameHeader.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameHeader.js +8 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameParser.d.ts +2 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/FrameParser.js +53 -22
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v22TagMapper.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v22TagMapper.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v24TagMapper.js +3 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2ChapterToken.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Parser.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Parser.js +32 -16
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Token.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/id3v2/ID3v2Token.js +2 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/index.js +6 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/lrc/LyricsParser.js +3 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/matroska/MatroskaDtd.js +7 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/matroska/MatroskaParser.js +22 -11
- package/node_modules/baileys/node_modules/music-metadata/lib/matroska/types.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/Atom.d.ts +4 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/Atom.js +44 -11
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/AtomToken.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/AtomToken.js +30 -8
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4Parser.d.ts +2 -0
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4Parser.js +79 -54
- package/node_modules/baileys/node_modules/music-metadata/lib/mp4/MP4TagMapper.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/MpegLoader.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/MpegParser.js +41 -19
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/ReplayGainDataFormat.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/ReplayGainDataFormat.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/mpeg/XingTag.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/MusepackParser.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/BitReader.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/MpcSv7Parser.js +4 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv7/StreamVersion7.js +3 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv8/MpcSv8Parser.js +7 -5
- package/node_modules/baileys/node_modules/music-metadata/lib/musepack/sv8/StreamVersion8.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/OggParser.js +16 -12
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/OggToken.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/flac/FlacStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/flac/FlacStream.js +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/opus/OpusStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/opus/OpusStream.js +8 -4
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/speex/SpeexStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/speex/SpeexStream.js +2 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/theora/TheoraStream.d.ts +2 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/Vorbis.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisDecoder.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisStream.d.ts +3 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisStream.js +14 -9
- package/node_modules/baileys/node_modules/music-metadata/lib/ogg/vorbis/VorbisTagMapper.js +4 -0
- package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffChunk.d.ts +3 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffChunk.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/riff/RiffInfoTagMap.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/type.d.ts +3 -3
- package/node_modules/baileys/node_modules/music-metadata/lib/type.js +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveChunk.d.ts +1 -1
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveChunk.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveParser.d.ts +6 -2
- package/node_modules/baileys/node_modules/music-metadata/lib/wav/WaveParser.js +75 -22
- package/node_modules/baileys/node_modules/music-metadata/lib/wavpack/WavPackParser.js +22 -13
- package/node_modules/baileys/node_modules/music-metadata/lib/wavpack/WavPackToken.js +3 -2
- package/node_modules/baileys/node_modules/music-metadata/package.json +3 -2
- package/package.json +4 -4
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import { textDecode } from '@borewit/text-codec';
|
|
1
2
|
import initDebug from 'debug';
|
|
2
3
|
import * as Token from 'token-types';
|
|
4
|
+
import { uint8ArrayToHex } from 'uint8array-extras';
|
|
3
5
|
import { BasicParser } from '../common/BasicParser.js';
|
|
4
6
|
import { Genres } from '../id3v1/ID3v1Parser.js';
|
|
7
|
+
import { TrackType } from '../type.js';
|
|
5
8
|
import { Atom } from './Atom.js';
|
|
6
9
|
import * as AtomToken from './AtomToken.js';
|
|
7
10
|
import { ChapterTrackReferenceBox, Mp4ContentError } from './AtomToken.js';
|
|
8
|
-
import { TrackType } from '../type.js';
|
|
9
|
-
import { uint8ArrayToHex } from 'uint8array-extras';
|
|
10
|
-
import { textDecode } from '@borewit/text-codec';
|
|
11
11
|
const debug = initDebug('music-metadata:parser:MP4');
|
|
12
12
|
const tagFormat = 'iTunes';
|
|
13
13
|
const encoderDict = {
|
|
@@ -122,7 +122,7 @@ export class MP4Parser extends BasicParser {
|
|
|
122
122
|
* Ref: https://developer.apple.com/library/archive/documentation/QuickTime/QTFF/QTFFChap2/qtff2.html#//apple_ref/doc/uid/TP40000939-CH204-56313
|
|
123
123
|
*/
|
|
124
124
|
mvhd: async (len) => {
|
|
125
|
-
const mvhd = await this.
|
|
125
|
+
const mvhd = await this.readToken(new AtomToken.MvhdAtom(len));
|
|
126
126
|
this.metadata.setFormat('creationTime', mvhd.creationTime);
|
|
127
127
|
this.metadata.setFormat('modificationTime', mvhd.modificationTime);
|
|
128
128
|
},
|
|
@@ -153,9 +153,12 @@ export class MP4Parser extends BasicParser {
|
|
|
153
153
|
await this.tokenizer.ignore(len);
|
|
154
154
|
},
|
|
155
155
|
ftyp: async (len) => {
|
|
156
|
+
if (len < 8 || len % AtomToken.ftyp.len !== 0) {
|
|
157
|
+
throw new Mp4ContentError(`Invalid ftyp payload length: ${len}`);
|
|
158
|
+
}
|
|
156
159
|
const types = [];
|
|
157
160
|
while (len > 0) {
|
|
158
|
-
const ftype = await this.
|
|
161
|
+
const ftype = await this.readToken(AtomToken.ftyp);
|
|
159
162
|
len -= AtomToken.ftyp.len;
|
|
160
163
|
const value = ftype.type.replace(/\W/g, '');
|
|
161
164
|
if (value.length > 0) {
|
|
@@ -170,7 +173,7 @@ export class MP4Parser extends BasicParser {
|
|
|
170
173
|
* Parse sample description atom
|
|
171
174
|
*/
|
|
172
175
|
stsd: async (len) => {
|
|
173
|
-
const stsd = await this.
|
|
176
|
+
const stsd = await this.readToken(new AtomToken.StsdAtom(len));
|
|
174
177
|
const trackDescription = this.getTrackDescription();
|
|
175
178
|
trackDescription.soundSampleDescription = stsd.table.map(dfEntry => this.parseSoundSampleDescription(dfEntry));
|
|
176
179
|
},
|
|
@@ -178,13 +181,13 @@ export class MP4Parser extends BasicParser {
|
|
|
178
181
|
* Parse sample-sizes atom ('stsz')
|
|
179
182
|
*/
|
|
180
183
|
stsz: async (len) => {
|
|
181
|
-
const stsz = await this.
|
|
184
|
+
const stsz = await this.readToken(new AtomToken.StszAtom(len));
|
|
182
185
|
const td = this.getTrackDescription();
|
|
183
186
|
td.sampleSize = stsz.sampleSize;
|
|
184
187
|
td.sampleSizeTable = stsz.entries;
|
|
185
188
|
},
|
|
186
189
|
date: async (len) => {
|
|
187
|
-
const date = await this.
|
|
190
|
+
const date = await this.readToken(new Token.StringType(len, 'utf-8'));
|
|
188
191
|
await this.addTag('date', date);
|
|
189
192
|
}
|
|
190
193
|
};
|
|
@@ -197,12 +200,23 @@ export class MP4Parser extends BasicParser {
|
|
|
197
200
|
}
|
|
198
201
|
return Number(token.get(array, 0));
|
|
199
202
|
}
|
|
203
|
+
// Metadata and sample tables are buffered; media data is skipped separately.
|
|
204
|
+
// A bound is also necessary for streams whose total size is unknown.
|
|
205
|
+
validatePayloadLength(length) {
|
|
206
|
+
if (!Number.isSafeInteger(length) || length < 0 || length > 64 * 1024 * 1024) {
|
|
207
|
+
throw new Mp4ContentError(`Atom payload exceeds the 64 MiB buffering limit: ${length}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async readToken(token) {
|
|
211
|
+
this.validatePayloadLength(token.len);
|
|
212
|
+
return this.tokenizer.readToken(token);
|
|
213
|
+
}
|
|
200
214
|
async parse() {
|
|
201
215
|
this.hasVideoTrack = false;
|
|
202
216
|
this.hasAudioTrack = true;
|
|
203
217
|
this.tracks.clear();
|
|
204
|
-
let remainingFileSize = this.tokenizer.fileInfo.size
|
|
205
|
-
while (
|
|
218
|
+
let remainingFileSize = this.tokenizer.fileInfo.size ?? Number.POSITIVE_INFINITY;
|
|
219
|
+
while (remainingFileSize > 0) {
|
|
206
220
|
try {
|
|
207
221
|
const token = await this.tokenizer.peekToken(AtomToken.Header);
|
|
208
222
|
if (token.name === '\0\0\0\0') {
|
|
@@ -218,12 +232,13 @@ export class MP4Parser extends BasicParser {
|
|
|
218
232
|
debug(errMsg);
|
|
219
233
|
this.addWarning(errMsg);
|
|
220
234
|
}
|
|
221
|
-
else
|
|
235
|
+
else {
|
|
222
236
|
throw error;
|
|
237
|
+
}
|
|
223
238
|
break;
|
|
224
239
|
}
|
|
225
240
|
const rootAtom = await Atom.readAtom(this.tokenizer, (atom, remaining) => this.handleAtom(atom, remaining), null, remainingFileSize);
|
|
226
|
-
remainingFileSize
|
|
241
|
+
remainingFileSize = rootAtom.header.length === 0n ? 0 : remainingFileSize - Number(rootAtom.header.length);
|
|
227
242
|
}
|
|
228
243
|
// Post process metadata
|
|
229
244
|
const formatList = [];
|
|
@@ -279,10 +294,10 @@ export class MP4Parser extends BasicParser {
|
|
|
279
294
|
const dur = sample.sampleDuration ?? fragment.header.defaultSampleDuration ?? 0;
|
|
280
295
|
const size = sample.sampleSize ?? fragment.header.defaultSampleSize ?? 0;
|
|
281
296
|
if (dur === 0) {
|
|
282
|
-
throw new Error(
|
|
297
|
+
throw new Error('Missing sampleDuration and no defaultSampleDuration in track fragment header');
|
|
283
298
|
}
|
|
284
299
|
if (size === 0) {
|
|
285
|
-
throw new Error(
|
|
300
|
+
throw new Error('Missing sampleSize and no defaultSampleSize in track fragment header');
|
|
286
301
|
}
|
|
287
302
|
totalTimeUnits += dur;
|
|
288
303
|
audioTrack.sizeInBytes += size;
|
|
@@ -321,7 +336,7 @@ export class MP4Parser extends BasicParser {
|
|
|
321
336
|
if (firstAudioTrack.duration) {
|
|
322
337
|
this.metadata.setFormat('duration', firstAudioTrack.duration);
|
|
323
338
|
if (firstAudioTrack.sizeInBytes) {
|
|
324
|
-
this.metadata.setFormat('bitrate', 8 * firstAudioTrack.sizeInBytes / firstAudioTrack.duration);
|
|
339
|
+
this.metadata.setFormat('bitrate', (8 * firstAudioTrack.sizeInBytes) / firstAudioTrack.duration);
|
|
325
340
|
}
|
|
326
341
|
}
|
|
327
342
|
}
|
|
@@ -349,8 +364,10 @@ export class MP4Parser extends BasicParser {
|
|
|
349
364
|
}
|
|
350
365
|
}
|
|
351
366
|
}
|
|
352
|
-
// const payloadLength = atom.getPayloadLength(remaining);
|
|
353
367
|
if (this.atomParsers[atom.header.name]) {
|
|
368
|
+
if (atom.header.name !== 'mdat') {
|
|
369
|
+
this.validatePayloadLength(remaining);
|
|
370
|
+
}
|
|
354
371
|
return this.atomParsers[atom.header.name](remaining);
|
|
355
372
|
}
|
|
356
373
|
debug(`No parser for atom path=${atom.atomPath}, payload-len=${remaining}, ignoring atom`);
|
|
@@ -375,27 +392,27 @@ export class MP4Parser extends BasicParser {
|
|
|
375
392
|
*/
|
|
376
393
|
parseMetadataItemData(metaAtom) {
|
|
377
394
|
let tagKey = metaAtom.header.name;
|
|
378
|
-
return metaAtom.readAtoms(this.tokenizer, async (child
|
|
379
|
-
const payLoadLength = child.getPayloadLength(
|
|
395
|
+
return metaAtom.readAtoms(this.tokenizer, async (child) => {
|
|
396
|
+
const payLoadLength = child.getPayloadLength();
|
|
380
397
|
switch (child.header.name) {
|
|
381
398
|
case 'data': // value atom
|
|
382
399
|
return this.parseValueAtom(tagKey, child);
|
|
383
400
|
case 'name': // name atom (optional)
|
|
384
401
|
case 'mean':
|
|
385
402
|
case 'rate': {
|
|
386
|
-
const name = await this.
|
|
403
|
+
const name = await this.readToken(new AtomToken.NameAtom(payLoadLength));
|
|
387
404
|
tagKey += `:${name.name}`;
|
|
388
405
|
break;
|
|
389
406
|
}
|
|
390
407
|
default: {
|
|
391
|
-
const uint8Array = await this.
|
|
408
|
+
const uint8Array = await this.readToken(new Token.Uint8ArrayType(payLoadLength));
|
|
392
409
|
this.addWarning(`Unsupported meta-item: ${tagKey}[${child.header.name}] => value=${uint8ArrayToHex(uint8Array)} ascii=${textDecode(uint8Array, 'ascii')}`);
|
|
393
410
|
}
|
|
394
411
|
}
|
|
395
|
-
}, metaAtom.getPayloadLength(
|
|
412
|
+
}, metaAtom.getPayloadLength());
|
|
396
413
|
}
|
|
397
414
|
async parseValueAtom(tagKey, metaAtom) {
|
|
398
|
-
const dataAtom = await this.
|
|
415
|
+
const dataAtom = await this.readToken(new AtomToken.DataAtom(metaAtom.getPayloadLength()));
|
|
399
416
|
if (dataAtom.type.set !== 0) {
|
|
400
417
|
throw new Mp4ContentError(`Unsupported type-set != 0: ${dataAtom.type.set}`);
|
|
401
418
|
}
|
|
@@ -433,16 +450,18 @@ export class MP4Parser extends BasicParser {
|
|
|
433
450
|
await this.addTag(tagKey, textDecode(dataAtom.value));
|
|
434
451
|
break;
|
|
435
452
|
case 13: // JPEG
|
|
436
|
-
if (this.options.skipCovers)
|
|
453
|
+
if (this.options.skipCovers) {
|
|
437
454
|
break;
|
|
455
|
+
}
|
|
438
456
|
await this.addTag(tagKey, {
|
|
439
457
|
format: 'image/jpeg',
|
|
440
458
|
data: Uint8Array.from(dataAtom.value)
|
|
441
459
|
});
|
|
442
460
|
break;
|
|
443
461
|
case 14: // PNG
|
|
444
|
-
if (this.options.skipCovers)
|
|
462
|
+
if (this.options.skipCovers) {
|
|
445
463
|
break;
|
|
464
|
+
}
|
|
446
465
|
await this.addTag(tagKey, {
|
|
447
466
|
format: 'image/png',
|
|
448
467
|
data: Uint8Array.from(dataAtom.value)
|
|
@@ -473,19 +492,19 @@ export class MP4Parser extends BasicParser {
|
|
|
473
492
|
media: {},
|
|
474
493
|
fragments: []
|
|
475
494
|
};
|
|
476
|
-
await trakBox.readAtoms(this.tokenizer, async (child
|
|
477
|
-
const payLoadLength = child.getPayloadLength(
|
|
495
|
+
await trakBox.readAtoms(this.tokenizer, async (child) => {
|
|
496
|
+
const payLoadLength = child.getPayloadLength();
|
|
478
497
|
switch (child.header.name) {
|
|
479
498
|
case 'chap': {
|
|
480
|
-
const chap = await this.
|
|
499
|
+
const chap = await this.readToken(new ChapterTrackReferenceBox(payLoadLength));
|
|
481
500
|
track.chapterList = chap;
|
|
482
501
|
break;
|
|
483
502
|
}
|
|
484
503
|
case 'tkhd': // TrackHeaderBox
|
|
485
|
-
track.header = await this.
|
|
504
|
+
track.header = await this.readToken(new AtomToken.TrackHeaderAtom(payLoadLength));
|
|
486
505
|
break;
|
|
487
506
|
case 'hdlr': // TrackHeaderBox
|
|
488
|
-
track.handler = await this.
|
|
507
|
+
track.handler = await this.readToken(new AtomToken.HandlerBox(payLoadLength));
|
|
489
508
|
track.isAudio = () => track.handler.handlerType === 'audi' || track.handler.handlerType === 'soun';
|
|
490
509
|
track.isVideo = () => track.handler.handlerType === 'vide';
|
|
491
510
|
if (track.isAudio()) {
|
|
@@ -495,33 +514,37 @@ export class MP4Parser extends BasicParser {
|
|
|
495
514
|
this.hasVideoTrack = true;
|
|
496
515
|
}
|
|
497
516
|
break;
|
|
498
|
-
case 'mdhd': {
|
|
499
|
-
|
|
517
|
+
case 'mdhd': {
|
|
518
|
+
// Parse media header (mdhd) box
|
|
519
|
+
const mdhd_data = await this.readToken(new AtomToken.MdhdAtom(payLoadLength));
|
|
500
520
|
track.media.header = mdhd_data;
|
|
501
521
|
break;
|
|
502
522
|
}
|
|
503
523
|
case 'stco': {
|
|
504
|
-
const stco = await this.
|
|
524
|
+
const stco = await this.readToken(new AtomToken.StcoAtom(payLoadLength));
|
|
505
525
|
track.chunkOffsetTable = stco.entries; // remember chunk offsets
|
|
506
526
|
break;
|
|
507
527
|
}
|
|
508
|
-
case 'stsc': {
|
|
509
|
-
|
|
528
|
+
case 'stsc': {
|
|
529
|
+
// sample-to-Chunk box
|
|
530
|
+
const stsc = await this.readToken(new AtomToken.StscAtom(payLoadLength));
|
|
510
531
|
track.sampleToChunkTable = stsc.entries;
|
|
511
532
|
break;
|
|
512
533
|
}
|
|
513
|
-
case 'stsd': {
|
|
514
|
-
|
|
534
|
+
case 'stsd': {
|
|
535
|
+
// sample description box
|
|
536
|
+
const stsd = await this.readToken(new AtomToken.StsdAtom(payLoadLength));
|
|
515
537
|
track.soundSampleDescription = stsd.table.map(dfEntry => this.parseSoundSampleDescription(dfEntry));
|
|
516
538
|
break;
|
|
517
539
|
}
|
|
518
|
-
case 'stts': {
|
|
519
|
-
|
|
540
|
+
case 'stts': {
|
|
541
|
+
// time-to-sample table
|
|
542
|
+
const stts = await this.readToken(new AtomToken.SttsAtom(payLoadLength));
|
|
520
543
|
track.timeToSampleTable = stts.entries;
|
|
521
544
|
break;
|
|
522
545
|
}
|
|
523
546
|
case 'stsz': {
|
|
524
|
-
const stsz = await this.
|
|
547
|
+
const stsz = await this.readToken(new AtomToken.StszAtom(payLoadLength));
|
|
525
548
|
track.sampleSize = stsz.sampleSize;
|
|
526
549
|
track.sampleSizeTable = stsz.entries;
|
|
527
550
|
break;
|
|
@@ -537,26 +560,28 @@ export class MP4Parser extends BasicParser {
|
|
|
537
560
|
await this.tokenizer.ignore(payLoadLength);
|
|
538
561
|
}
|
|
539
562
|
}
|
|
540
|
-
}, trakBox.getPayloadLength(
|
|
563
|
+
}, trakBox.getPayloadLength());
|
|
541
564
|
// Register track
|
|
542
565
|
this.tracks.set(track.header.trackId, track);
|
|
543
566
|
}
|
|
544
567
|
parseTrackFragmentBox(trafBox) {
|
|
545
568
|
let tfhd;
|
|
546
|
-
return trafBox.readAtoms(this.tokenizer, async (child
|
|
547
|
-
const payLoadLength = child.getPayloadLength(
|
|
569
|
+
return trafBox.readAtoms(this.tokenizer, async (child) => {
|
|
570
|
+
const payLoadLength = child.getPayloadLength();
|
|
548
571
|
switch (child.header.name) {
|
|
549
|
-
case 'tfhd': {
|
|
550
|
-
|
|
551
|
-
|
|
572
|
+
case 'tfhd': {
|
|
573
|
+
// TrackFragmentHeaderBox
|
|
574
|
+
const fragmentHeaderBox = new AtomToken.TrackFragmentHeaderBox(child.getPayloadLength());
|
|
575
|
+
tfhd = await this.readToken(fragmentHeaderBox);
|
|
552
576
|
break;
|
|
553
577
|
}
|
|
554
578
|
case 'tfdt': // TrackFragmentBaseMediaDecodeTimeBo
|
|
555
579
|
await this.tokenizer.ignore(payLoadLength);
|
|
556
580
|
break;
|
|
557
|
-
case 'trun': {
|
|
581
|
+
case 'trun': {
|
|
582
|
+
// TrackRunBox
|
|
558
583
|
const trackRunBox = new AtomToken.TrackRunBox(payLoadLength);
|
|
559
|
-
const trun = await this.
|
|
584
|
+
const trun = await this.readToken(trackRunBox);
|
|
560
585
|
if (tfhd) {
|
|
561
586
|
const track = this.tracks.get(tfhd.trackId);
|
|
562
587
|
track?.fragments.push({ header: tfhd, trackRun: trun });
|
|
@@ -568,7 +593,7 @@ export class MP4Parser extends BasicParser {
|
|
|
568
593
|
await this.tokenizer.ignore(payLoadLength);
|
|
569
594
|
}
|
|
570
595
|
}
|
|
571
|
-
}, trafBox.getPayloadLength(
|
|
596
|
+
}, trafBox.getPayloadLength());
|
|
572
597
|
}
|
|
573
598
|
/**
|
|
574
599
|
* @param sampleDescription
|
|
@@ -603,22 +628,22 @@ export class MP4Parser extends BasicParser {
|
|
|
603
628
|
}
|
|
604
629
|
async parseChapterTrack(chapterTrack, track, len) {
|
|
605
630
|
if (!chapterTrack.sampleSize) {
|
|
606
|
-
if (chapterTrack.chunkOffsetTable.length !== chapterTrack.sampleSizeTable.length)
|
|
631
|
+
if (chapterTrack.chunkOffsetTable.length !== chapterTrack.sampleSizeTable.length) {
|
|
607
632
|
throw new Error('Expected equal chunk-offset-table & sample-size-table length.');
|
|
633
|
+
}
|
|
608
634
|
}
|
|
609
635
|
const chapters = [];
|
|
610
636
|
for (let i = 0; i < chapterTrack.chunkOffsetTable.length && len > 0; ++i) {
|
|
611
|
-
const start = chapterTrack.timeToSampleTable
|
|
612
|
-
.slice(0, i)
|
|
613
|
-
.reduce((acc, cur) => acc + cur.duration, 0);
|
|
637
|
+
const start = chapterTrack.timeToSampleTable.slice(0, i).reduce((acc, cur) => acc + cur.duration, 0);
|
|
614
638
|
const chunkOffset = chapterTrack.chunkOffsetTable[i];
|
|
615
639
|
const nextChunkLen = chunkOffset - this.tokenizer.position;
|
|
616
640
|
const sampleSize = chapterTrack.sampleSize > 0 ? chapterTrack.sampleSize : chapterTrack.sampleSizeTable[i];
|
|
617
641
|
len -= nextChunkLen + sampleSize;
|
|
618
|
-
if (len < 0)
|
|
642
|
+
if (len < 0) {
|
|
619
643
|
throw new Mp4ContentError('Chapter chunk exceeding token length');
|
|
644
|
+
}
|
|
620
645
|
await this.tokenizer.ignore(nextChunkLen);
|
|
621
|
-
const title = await this.
|
|
646
|
+
const title = await this.readToken(new AtomToken.ChapterText(sampleSize));
|
|
622
647
|
debug(`Chapter ${i + 1}: ${title}`);
|
|
623
648
|
const chapter = {
|
|
624
649
|
title,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CaseInsensitiveTagMap } from '../common/CaseInsensitiveTagMap.js';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { INativeMetadataCollector } from '../common/MetadataCollector.js';
|
|
3
|
+
import type { ITag } from '../type.js';
|
|
4
4
|
export declare const tagType = "iTunes";
|
|
5
5
|
export declare class MP4TagMapper extends CaseInsensitiveTagMap {
|
|
6
6
|
constructor();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const mpegParserLoader = {
|
|
2
2
|
parserType: 'mpeg',
|
|
3
|
-
extensions: ['.mp2', '.mp3', '.m2a', '.aac', 'aacp'],
|
|
3
|
+
extensions: ['.mp1', '.mp2', '.mp3', '.m2a', '.aac', 'aacp'],
|
|
4
4
|
mimeTypes: ['audio/mpeg', 'audio/mp3', 'audio/aacs', 'audio/aacp'],
|
|
5
5
|
async load() {
|
|
6
6
|
return (await import('./MpegParser.js')).MpegParser;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as Token from 'token-types';
|
|
2
|
-
import { EndOfStreamError } from 'strtok3';
|
|
3
1
|
import initDebug from 'debug';
|
|
2
|
+
import { EndOfStreamError } from 'strtok3';
|
|
3
|
+
import * as Token from 'token-types';
|
|
4
4
|
import * as common from '../common/Util.js';
|
|
5
5
|
import { AbstractID3Parser } from '../id3v2/AbstractID3Parser.js';
|
|
6
|
-
import { InfoTagHeaderTag, LameEncoderVersion, readXingHeader } from './XingTag.js';
|
|
7
6
|
import { makeUnexpectedFileContentError } from '../ParseError.js';
|
|
7
|
+
import { InfoTagHeaderTag, LameEncoderVersion, readXingHeader } from './XingTag.js';
|
|
8
8
|
const debug = initDebug('music-metadata:parser:mpeg');
|
|
9
9
|
export class MpegContentError extends makeUnexpectedFileContentError('MPEG') {
|
|
10
10
|
}
|
|
@@ -31,7 +31,22 @@ const MPEG4 = {
|
|
|
31
31
|
* https://wiki.multimedia.cx/index.php/MPEG-4_Audio#Sampling_Frequencies
|
|
32
32
|
*/
|
|
33
33
|
SamplingFrequencies: [
|
|
34
|
-
96000,
|
|
34
|
+
96000,
|
|
35
|
+
88200,
|
|
36
|
+
64000,
|
|
37
|
+
48000,
|
|
38
|
+
44100,
|
|
39
|
+
32000,
|
|
40
|
+
24000,
|
|
41
|
+
22050,
|
|
42
|
+
16000,
|
|
43
|
+
12000,
|
|
44
|
+
11025,
|
|
45
|
+
8000,
|
|
46
|
+
7350,
|
|
47
|
+
null,
|
|
48
|
+
null,
|
|
49
|
+
null
|
|
35
50
|
]
|
|
36
51
|
/**
|
|
37
52
|
* Channel Configurations
|
|
@@ -87,14 +102,15 @@ class MpegFrameHeader {
|
|
|
87
102
|
this.isProtectedByCRC = !common.isBitSet(buf, off + 1, 7);
|
|
88
103
|
}
|
|
89
104
|
calcDuration(numFrames) {
|
|
90
|
-
return this.samplingRate == null ? null : (numFrames * this.calcSamplesPerFrame() / this.samplingRate
|
|
105
|
+
return this.samplingRate == null ? null : (numFrames * this.calcSamplesPerFrame()) / this.samplingRate;
|
|
91
106
|
}
|
|
92
107
|
calcSamplesPerFrame() {
|
|
93
108
|
return MpegFrameHeader.samplesInFrameTable[this.version === 1 ? 0 : 1][this.layer];
|
|
94
109
|
}
|
|
95
110
|
calculateSideInfoLength() {
|
|
96
|
-
if (this.layer !== 3)
|
|
111
|
+
if (this.layer !== 3) {
|
|
97
112
|
return 2;
|
|
113
|
+
}
|
|
98
114
|
if (this.channelModeIndex === 3) {
|
|
99
115
|
// mono
|
|
100
116
|
if (this.version === 1) {
|
|
@@ -153,7 +169,7 @@ class MpegFrameHeader {
|
|
|
153
169
|
}
|
|
154
170
|
}
|
|
155
171
|
parseAdtsHeader(buf, off) {
|
|
156
|
-
debug(
|
|
172
|
+
debug('layer=0 => ADTS');
|
|
157
173
|
this.version = this.versionIndex === 2 ? 4 : 2;
|
|
158
174
|
this.container = `ADTS/MPEG-${this.version}`;
|
|
159
175
|
const profileIndex = common.getBitAllignedNumber(buf, off + 2, 0, 2);
|
|
@@ -170,7 +186,8 @@ class MpegFrameHeader {
|
|
|
170
186
|
}
|
|
171
187
|
calcBitrate() {
|
|
172
188
|
if (this.bitrateIndex === 0x00 || // free
|
|
173
|
-
this.bitrateIndex ===
|
|
189
|
+
this.bitrateIndex === 0x0f) {
|
|
190
|
+
// reserved
|
|
174
191
|
return null;
|
|
175
192
|
}
|
|
176
193
|
if (this.version && this.bitrateIndex) {
|
|
@@ -180,13 +197,14 @@ class MpegFrameHeader {
|
|
|
180
197
|
return null;
|
|
181
198
|
}
|
|
182
199
|
calcSamplingRate() {
|
|
183
|
-
if (this.sampRateFreqIndex === 0x03 || this.version === null || this.sampRateFreqIndex == null)
|
|
200
|
+
if (this.sampRateFreqIndex === 0x03 || this.version === null || this.sampRateFreqIndex == null) {
|
|
184
201
|
return null; // 'reserved'
|
|
202
|
+
}
|
|
185
203
|
return MpegFrameHeader.sampling_rate_freq_index[this.version][this.sampRateFreqIndex];
|
|
186
204
|
}
|
|
187
205
|
}
|
|
188
|
-
MpegFrameHeader.SyncByte1 =
|
|
189
|
-
MpegFrameHeader.SyncByte2 =
|
|
206
|
+
MpegFrameHeader.SyncByte1 = 0xff;
|
|
207
|
+
MpegFrameHeader.SyncByte2 = 0xe0;
|
|
190
208
|
MpegFrameHeader.VersionID = [2.5, null, 2, 1];
|
|
191
209
|
MpegFrameHeader.LayerDescription = [0, 3, 2, 1];
|
|
192
210
|
MpegFrameHeader.ChannelMode = ['stereo', 'joint_stereo', 'dual_channel', 'mono'];
|
|
@@ -264,7 +282,7 @@ export class MpegParser extends AbstractID3Parser {
|
|
|
264
282
|
}
|
|
265
283
|
catch (err) {
|
|
266
284
|
if (err instanceof EndOfStreamError) {
|
|
267
|
-
debug(
|
|
285
|
+
debug('End-of-stream');
|
|
268
286
|
if (this.calculateEofDuration) {
|
|
269
287
|
if (this.samplesPerFrame !== null) {
|
|
270
288
|
const numberOfSamples = this.frameCount * this.samplesPerFrame;
|
|
@@ -292,7 +310,7 @@ export class MpegParser extends AbstractID3Parser {
|
|
|
292
310
|
if (format.duration && this.tokenizer.fileInfo.size) {
|
|
293
311
|
const mpegSize = this.tokenizer.fileInfo.size - this.mpegOffset - (hasID3v1 ? 128 : 0);
|
|
294
312
|
if (format.codecProfile && format.codecProfile[0] === 'V') {
|
|
295
|
-
this.metadata.setFormat('bitrate', mpegSize * 8 / format.duration);
|
|
313
|
+
this.metadata.setFormat('bitrate', (mpegSize * 8) / format.duration);
|
|
296
314
|
}
|
|
297
315
|
}
|
|
298
316
|
if (this.tokenizer.fileInfo.size && format.codecProfile === 'CBR') {
|
|
@@ -302,7 +320,7 @@ export class MpegParser extends AbstractID3Parser {
|
|
|
302
320
|
this.metadata.setFormat('numberOfSamples', numberOfSamples);
|
|
303
321
|
if (format.sampleRate && !format.duration) {
|
|
304
322
|
const duration = numberOfSamples / format.sampleRate;
|
|
305
|
-
debug(
|
|
323
|
+
debug('Calculate CBR duration based on file size: %s', duration);
|
|
306
324
|
this.metadata.setFormat('duration', duration);
|
|
307
325
|
}
|
|
308
326
|
}
|
|
@@ -318,7 +336,7 @@ export class MpegParser extends AbstractID3Parser {
|
|
|
318
336
|
throw new EndOfStreamError();
|
|
319
337
|
}
|
|
320
338
|
while (true) {
|
|
321
|
-
if (gotFirstSync && (this.syncPeek.buf[bo] &
|
|
339
|
+
if (gotFirstSync && (this.syncPeek.buf[bo] & 0xe0) === 0xe0) {
|
|
322
340
|
this.buf_frame_header[0] = MpegFrameHeader.SyncByte1;
|
|
323
341
|
this.buf_frame_header[1] = this.syncPeek.buf[bo];
|
|
324
342
|
await this.tokenizer.ignore(bo);
|
|
@@ -372,7 +390,9 @@ export class MpegParser extends AbstractID3Parser {
|
|
|
372
390
|
this.metadata.setFormat('lossless', false);
|
|
373
391
|
this.metadata.setFormat('sampleRate', header.samplingRate);
|
|
374
392
|
this.frameCount++;
|
|
375
|
-
return header.version !== null && header.version >= 2 && header.layer === 0
|
|
393
|
+
return header.version !== null && header.version >= 2 && header.layer === 0
|
|
394
|
+
? this.parseAdts(header)
|
|
395
|
+
: this.parseAudioFrameHeader(header);
|
|
376
396
|
}
|
|
377
397
|
/**
|
|
378
398
|
* @return {Promise<boolean>} true if parser should quit
|
|
@@ -391,7 +411,7 @@ export class MpegParser extends AbstractID3Parser {
|
|
|
391
411
|
debug(`samples_per_frame=${samples_per_frame}`);
|
|
392
412
|
const bps = samples_per_frame / 8.0;
|
|
393
413
|
if (header.bitrate !== null && header.samplingRate != null) {
|
|
394
|
-
const fsize = (bps * header.bitrate / header.samplingRate
|
|
414
|
+
const fsize = (bps * header.bitrate) / header.samplingRate + (header.padding ? slot_size : 0);
|
|
395
415
|
this.frame_size = Math.floor(fsize);
|
|
396
416
|
}
|
|
397
417
|
this.audioFrameHeader = header;
|
|
@@ -410,8 +430,9 @@ export class MpegParser extends AbstractID3Parser {
|
|
|
410
430
|
// Actual calculation will be done in finalize
|
|
411
431
|
this.samplesPerFrame = samples_per_frame;
|
|
412
432
|
this.metadata.setFormat('codecProfile', 'CBR');
|
|
413
|
-
if (this.tokenizer.fileInfo.size)
|
|
433
|
+
if (this.tokenizer.fileInfo.size) {
|
|
414
434
|
return true; // Will calculate duration based on the file size
|
|
435
|
+
}
|
|
415
436
|
}
|
|
416
437
|
else if (this.metadata.format.duration) {
|
|
417
438
|
return true; // We already got the duration, stop processing MPEG stream any further
|
|
@@ -556,8 +577,9 @@ export class MpegParser extends AbstractID3Parser {
|
|
|
556
577
|
return infoTag;
|
|
557
578
|
}
|
|
558
579
|
async skipFrameData(frameDataLeft) {
|
|
559
|
-
if (frameDataLeft < 0)
|
|
580
|
+
if (frameDataLeft < 0) {
|
|
560
581
|
throw new MpegContentError('frame-data-left cannot be negative');
|
|
582
|
+
}
|
|
561
583
|
await this.tokenizer.ignore(frameDataLeft);
|
|
562
584
|
}
|
|
563
585
|
areAllSame(array) {
|
|
@@ -21,7 +21,7 @@ declare const NameCode: {
|
|
|
21
21
|
*/
|
|
22
22
|
audiophile: number;
|
|
23
23
|
};
|
|
24
|
-
type NameCode = typeof NameCode[keyof typeof NameCode];
|
|
24
|
+
type NameCode = (typeof NameCode)[keyof typeof NameCode];
|
|
25
25
|
/**
|
|
26
26
|
* https://github.com/Borewit/music-metadata/wiki/Replay-Gain-Data-Format#originator-code
|
|
27
27
|
*/
|
|
@@ -47,7 +47,7 @@ declare const ReplayGainOriginator: {
|
|
|
47
47
|
*/
|
|
48
48
|
rms_average: number;
|
|
49
49
|
};
|
|
50
|
-
type ReplayGainOriginator = typeof ReplayGainOriginator[keyof typeof ReplayGainOriginator];
|
|
50
|
+
type ReplayGainOriginator = (typeof ReplayGainOriginator)[keyof typeof ReplayGainOriginator];
|
|
51
51
|
/**
|
|
52
52
|
* Replay Gain Data Format
|
|
53
53
|
*
|
|
@@ -56,7 +56,7 @@ export const ReplayGain = {
|
|
|
56
56
|
return {
|
|
57
57
|
type: common.getBitAllignedNumber(buf, off, 0, 3),
|
|
58
58
|
origin: common.getBitAllignedNumber(buf, off, 3, 3),
|
|
59
|
-
adjustment:
|
|
59
|
+
adjustment: sign ? -gain_adj : gain_adj
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
return undefined;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import initDebug from 'debug';
|
|
2
2
|
import * as Token from 'token-types';
|
|
3
3
|
import { AbstractID3Parser } from '../id3v2/AbstractID3Parser.js';
|
|
4
|
-
import { MpcSv8Parser } from './sv8/MpcSv8Parser.js';
|
|
5
|
-
import { MpcSv7Parser } from './sv7/MpcSv7Parser.js';
|
|
6
4
|
import { MusepackContentError } from './MusepackConentError.js';
|
|
5
|
+
import { MpcSv7Parser } from './sv7/MpcSv7Parser.js';
|
|
6
|
+
import { MpcSv8Parser } from './sv8/MpcSv8Parser.js';
|
|
7
7
|
const debug = initDebug('music-metadata:parser:musepack');
|
|
8
8
|
export class MusepackParser extends AbstractID3Parser {
|
|
9
9
|
async postId3v2Parse() {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import initDebug from 'debug';
|
|
2
|
-
import { BasicParser } from '../../common/BasicParser.js';
|
|
3
2
|
import { tryParseApeHeader } from '../../apev2/APEv2Parser.js';
|
|
3
|
+
import { BasicParser } from '../../common/BasicParser.js';
|
|
4
|
+
import { MusepackContentError } from '../MusepackConentError.js';
|
|
4
5
|
import { BitReader } from './BitReader.js';
|
|
5
6
|
import * as SV7 from './StreamVersion7.js';
|
|
6
|
-
import { MusepackContentError } from '../MusepackConentError.js';
|
|
7
7
|
const debug = initDebug('music-metadata:parser:musepack');
|
|
8
8
|
export class MpcSv7Parser extends BasicParser {
|
|
9
9
|
constructor() {
|
|
@@ -14,8 +14,9 @@ export class MpcSv7Parser extends BasicParser {
|
|
|
14
14
|
}
|
|
15
15
|
async parse() {
|
|
16
16
|
const header = await this.tokenizer.readToken(SV7.Header);
|
|
17
|
-
if (header.signature !== 'MP+')
|
|
17
|
+
if (header.signature !== 'MP+') {
|
|
18
18
|
throw new MusepackContentError('Unexpected magic number');
|
|
19
|
+
}
|
|
19
20
|
debug(`stream-version=${header.streamMajorVersion}.${header.streamMinorVersion}`);
|
|
20
21
|
this.metadata.setFormat('container', 'Musepack, SV7');
|
|
21
22
|
this.metadata.setFormat('sampleRate', header.sampleFrequency);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { textDecode } from '@borewit/text-codec';
|
|
1
2
|
import * as Token from 'token-types';
|
|
2
3
|
import * as util from '../../common/Util.js';
|
|
3
|
-
import { textDecode } from '@borewit/text-codec';
|
|
4
4
|
/**
|
|
5
5
|
* BASIC STRUCTURE
|
|
6
6
|
*/
|
|
@@ -30,10 +30,10 @@ export const Header = {
|
|
|
30
30
|
albumPeak: Token.UINT16_LE.get(buf, off + 16),
|
|
31
31
|
albumGain: Token.UINT16_LE.get(buf, off + 18),
|
|
32
32
|
// word
|
|
33
|
-
lastFrameLength: (Token.UINT32_LE.get(buf, off + 20) >>> 20) &
|
|
33
|
+
lastFrameLength: (Token.UINT32_LE.get(buf, off + 20) >>> 20) & 0x7ff,
|
|
34
34
|
trueGapless: util.isBitSet(buf, off + 23, 0)
|
|
35
35
|
};
|
|
36
|
-
header.lastFrameLength = header.trueGapless ? (Token.UINT32_LE.get(buf, 20) >>> 20) &
|
|
36
|
+
header.lastFrameLength = header.trueGapless ? (Token.UINT32_LE.get(buf, 20) >>> 20) & 0x7ff : 0;
|
|
37
37
|
return header;
|
|
38
38
|
}
|
|
39
39
|
};
|