music-metadata 8.3.0 → 9.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/LICENSE.txt +9 -9
  2. package/README.md +519 -488
  3. package/lib/ParserFactory.d.ts +1 -1
  4. package/lib/ParserFactory.js +1 -2
  5. package/lib/aiff/AiffParser.js +3 -4
  6. package/lib/aiff/AiffToken.d.ts +2 -4
  7. package/lib/aiff/AiffToken.js +7 -7
  8. package/lib/apev2/APEv2Parser.d.ts +1 -1
  9. package/lib/apev2/APEv2Parser.js +10 -12
  10. package/lib/apev2/APEv2Token.d.ts +1 -1
  11. package/lib/asf/AsfObject.d.ts +15 -17
  12. package/lib/asf/AsfObject.js +51 -45
  13. package/lib/asf/AsfParser.js +6 -8
  14. package/lib/asf/AsfUtil.d.ts +1 -3
  15. package/lib/asf/AsfUtil.js +4 -5
  16. package/lib/asf/GUID.d.ts +4 -5
  17. package/lib/asf/GUID.js +14 -11
  18. package/lib/common/BasicParser.d.ts +1 -1
  19. package/lib/common/FourCC.d.ts +1 -1
  20. package/lib/common/FourCC.js +5 -3
  21. package/lib/common/MetadataCollector.d.ts +3 -3
  22. package/lib/common/MetadataCollector.js +7 -8
  23. package/lib/common/RandomFileReader.d.ts +2 -3
  24. package/lib/common/RandomFileReader.js +1 -1
  25. package/lib/common/Util.d.ts +1 -1
  26. package/lib/common/Util.js +4 -3
  27. package/lib/core.d.ts +16 -8
  28. package/lib/core.js +19 -5
  29. package/lib/dsdiff/DsdiffParser.js +1 -1
  30. package/lib/dsdiff/DsdiffToken.d.ts +1 -1
  31. package/lib/dsf/DsfChunk.d.ts +1 -1
  32. package/lib/flac/FlacParser.d.ts +1 -1
  33. package/lib/flac/FlacParser.js +6 -4
  34. package/lib/id3v1/ID3v1Parser.js +7 -7
  35. package/lib/id3v2/AbstractID3Parser.d.ts +1 -1
  36. package/lib/id3v2/AbstractID3Parser.js +1 -1
  37. package/lib/id3v2/FrameParser.js +3 -3
  38. package/lib/id3v2/ID3v24TagMapper.d.ts +2 -3
  39. package/lib/id3v2/ID3v24TagMapper.js +4 -4
  40. package/lib/id3v2/ID3v2Parser.d.ts +1 -1
  41. package/lib/id3v2/ID3v2Parser.js +10 -17
  42. package/lib/id3v2/ID3v2Token.d.ts +1 -1
  43. package/lib/id3v2/ID3v2Token.js +2 -2
  44. package/lib/iff/index.d.ts +1 -1
  45. package/lib/index.d.ts +1 -2
  46. package/lib/index.js +1 -1
  47. package/lib/lyrics3/Lyrics3.js +4 -4
  48. package/lib/matroska/MatroskaParser.d.ts +9 -2
  49. package/lib/matroska/MatroskaParser.js +44 -39
  50. package/lib/matroska/types.d.ts +13 -14
  51. package/lib/mp4/Atom.d.ts +1 -1
  52. package/lib/mp4/AtomToken.d.ts +11 -11
  53. package/lib/mp4/AtomToken.js +3 -2
  54. package/lib/mp4/MP4Parser.js +20 -19
  55. package/lib/mpeg/ExtendedLameHeader.d.ts +1 -1
  56. package/lib/mpeg/MpegParser.js +4 -4
  57. package/lib/mpeg/ReplayGainDataFormat.d.ts +1 -1
  58. package/lib/mpeg/XingTag.d.ts +2 -3
  59. package/lib/mpeg/XingTag.js +1 -1
  60. package/lib/musepack/index.js +1 -1
  61. package/lib/musepack/sv7/BitReader.d.ts +1 -1
  62. package/lib/musepack/sv7/StreamVersion7.d.ts +1 -1
  63. package/lib/musepack/sv7/StreamVersion7.js +1 -1
  64. package/lib/musepack/sv8/StreamVersion8.d.ts +1 -1
  65. package/lib/musepack/sv8/StreamVersion8.js +1 -1
  66. package/lib/ogg/Ogg.d.ts +2 -2
  67. package/lib/ogg/OggParser.d.ts +1 -1
  68. package/lib/ogg/OggParser.js +5 -5
  69. package/lib/ogg/opus/Opus.d.ts +1 -1
  70. package/lib/ogg/opus/Opus.js +6 -6
  71. package/lib/ogg/opus/OpusParser.d.ts +4 -5
  72. package/lib/ogg/opus/OpusParser.js +3 -3
  73. package/lib/ogg/speex/Speex.d.ts +1 -1
  74. package/lib/ogg/speex/Speex.js +13 -13
  75. package/lib/ogg/speex/SpeexParser.d.ts +3 -4
  76. package/lib/ogg/speex/SpeexParser.js +1 -1
  77. package/lib/ogg/theora/Theora.d.ts +1 -1
  78. package/lib/ogg/theora/Theora.js +6 -6
  79. package/lib/ogg/theora/TheoraParser.d.ts +4 -5
  80. package/lib/ogg/theora/TheoraParser.js +4 -4
  81. package/lib/ogg/vorbis/Vorbis.d.ts +3 -4
  82. package/lib/ogg/vorbis/Vorbis.js +11 -12
  83. package/lib/ogg/vorbis/VorbisDecoder.js +1 -1
  84. package/lib/ogg/vorbis/VorbisParser.d.ts +8 -8
  85. package/lib/ogg/vorbis/VorbisParser.js +21 -12
  86. package/lib/riff/RiffChunk.d.ts +1 -1
  87. package/lib/riff/RiffChunk.js +2 -2
  88. package/lib/type.d.ts +9 -11
  89. package/lib/wav/BwfChunk.d.ts +1 -1
  90. package/lib/wav/WaveChunk.d.ts +3 -4
  91. package/lib/wav/WaveChunk.js +8 -7
  92. package/lib/wav/WaveParser.js +2 -2
  93. package/lib/wavpack/WavPackParser.d.ts +1 -0
  94. package/lib/wavpack/WavPackParser.js +5 -3
  95. package/lib/wavpack/WavPackToken.d.ts +1 -1
  96. package/package.json +141 -140
@@ -1,4 +1,4 @@
1
- import { IGetToken } from 'strtok3/core';
1
+ import { IGetToken } from 'strtok3';
2
2
  import { BasicParser } from '../common/BasicParser.js';
3
3
  import * as Ogg from './Ogg.js';
4
4
  export declare class SegmentTable implements IGetToken<Ogg.ISegmentTable> {
@@ -1,5 +1,5 @@
1
1
  import * as Token from 'token-types';
2
- import { EndOfStreamError } from 'strtok3/core';
2
+ import { EndOfStreamError } from 'strtok3';
3
3
  import initDebug from 'debug';
4
4
  import * as util from '../common/Util.js';
5
5
  import { FourCcToken } from '../common/FourCC.js';
@@ -51,7 +51,7 @@ export class OggParser extends BasicParser {
51
51
  const pageData = await this.tokenizer.readToken(new Token.Uint8ArrayType(segmentTable.totalPageSize));
52
52
  debug('firstPage=%s, lastPage=%s, continued=%s', header.headerType.firstPage, header.headerType.lastPage, header.headerType.continued);
53
53
  if (header.headerType.firstPage) {
54
- const id = new Token.StringType(7, 'ascii').get(Buffer.from(pageData), 0);
54
+ const id = new TextDecoder('ascii').decode(pageData.subarray(0, 7));
55
55
  switch (id) {
56
56
  case '\x01vorbis': // Ogg/Vorbis
57
57
  debug('Set page consumer to Ogg/Vorbis');
@@ -74,7 +74,7 @@ export class OggParser extends BasicParser {
74
74
  throw new Error('gg audio-codec not recognized (id=' + id + ')');
75
75
  }
76
76
  }
77
- this.pageConsumer.parsePage(header, pageData);
77
+ await this.pageConsumer.parsePage(header, pageData);
78
78
  } while (!header.headerType.lastPage);
79
79
  }
80
80
  catch (err) {
@@ -90,7 +90,7 @@ export class OggParser extends BasicParser {
90
90
  if (this.pageNumber > 0) {
91
91
  // ignore this error: work-around if last OGG-page is not marked with last-page flag
92
92
  this.metadata.addWarning('Invalid FourCC ID, maybe last OGG-page is not marked with last-page flag');
93
- this.pageConsumer.flush();
93
+ await this.pageConsumer.flush();
94
94
  }
95
95
  }
96
96
  else {
@@ -110,7 +110,7 @@ OggParser.Header = {
110
110
  firstPage: util.getBit(buf, off + 5, 1),
111
111
  lastPage: util.getBit(buf, off + 5, 2)
112
112
  },
113
- // packet_flag: buf.readUInt8(off + 5),
113
+ // packet_flag: Token.UINT8.get(buf, off + 5),
114
114
  absoluteGranulePosition: Number(Token.UINT64_LE.get(buf, off + 6)),
115
115
  streamSerialNumber: Token.UINT32_LE.get(buf, off + 14),
116
116
  pageSequenceNo: Token.UINT32_LE.get(buf, off + 18),
@@ -1,4 +1,4 @@
1
- import { IGetToken } from 'strtok3/core';
1
+ import type { IGetToken } from 'strtok3';
2
2
  /**
3
3
  * Opus ID Header interface
4
4
  * Ref: https://wiki.xiph.org/OggOpus#ID_Header
@@ -13,12 +13,12 @@ export class IdHeader {
13
13
  get(buf, off) {
14
14
  return {
15
15
  magicSignature: new Token.StringType(8, 'ascii').get(buf, off + 0),
16
- version: buf.readUInt8(off + 8),
17
- channelCount: buf.readUInt8(off + 9),
18
- preSkip: buf.readInt16LE(off + 10),
19
- inputSampleRate: buf.readInt32LE(off + 12),
20
- outputGain: buf.readInt16LE(off + 16),
21
- channelMapping: buf.readUInt8(off + 18)
16
+ version: Token.UINT8.get(buf, off + 8),
17
+ channelCount: Token.UINT8.get(buf, off + 9),
18
+ preSkip: Token.UINT16_LE.get(buf, off + 10),
19
+ inputSampleRate: Token.UINT32_LE.get(buf, off + 12),
20
+ outputGain: Token.UINT16_LE.get(buf, off + 16),
21
+ channelMapping: Token.UINT8.get(buf, off + 18)
22
22
  };
23
23
  }
24
24
  }
@@ -1,5 +1,4 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import { ITokenizer } from 'strtok3/core';
1
+ import { ITokenizer } from 'strtok3';
3
2
  import { IPageHeader } from '../Ogg.js';
4
3
  import { VorbisParser } from '../vorbis/VorbisParser.js';
5
4
  import { IOptions } from '../../type.js';
@@ -17,9 +16,9 @@ export declare class OpusParser extends VorbisParser {
17
16
  /**
18
17
  * Parse first Opus Ogg page
19
18
  * @param {IPageHeader} header
20
- * @param {Buffer} pageData
19
+ * @param {Uint8Array} pageData
21
20
  */
22
- protected parseFirstPage(header: IPageHeader, pageData: Buffer): void;
23
- protected parseFullPage(pageData: Buffer): void;
21
+ protected parseFirstPage(header: IPageHeader, pageData: Uint8Array): void;
22
+ protected parseFullPage(pageData: Uint8Array): Promise<void>;
24
23
  calculateDuration(header: IPageHeader): void;
25
24
  }
@@ -15,7 +15,7 @@ export class OpusParser extends VorbisParser {
15
15
  /**
16
16
  * Parse first Opus Ogg page
17
17
  * @param {IPageHeader} header
18
- * @param {Buffer} pageData
18
+ * @param {Uint8Array} pageData
19
19
  */
20
20
  parseFirstPage(header, pageData) {
21
21
  this.metadata.setFormat('codec', 'Opus');
@@ -26,11 +26,11 @@ export class OpusParser extends VorbisParser {
26
26
  this.metadata.setFormat('sampleRate', this.idHeader.inputSampleRate);
27
27
  this.metadata.setFormat('numberOfChannels', this.idHeader.channelCount);
28
28
  }
29
- parseFullPage(pageData) {
29
+ async parseFullPage(pageData) {
30
30
  const magicSignature = new Token.StringType(8, 'ascii').get(pageData, 0);
31
31
  switch (magicSignature) {
32
32
  case 'OpusTags':
33
- this.parseUserCommentList(pageData, 8);
33
+ await this.parseUserCommentList(pageData, 8);
34
34
  this.lastPos = this.tokenizer.position - pageData.length;
35
35
  break;
36
36
  default:
@@ -1,4 +1,4 @@
1
- import { IGetToken } from 'strtok3/core';
1
+ import type { IGetToken } from 'strtok3';
2
2
  /**
3
3
  * Speex Header Packet
4
4
  * Ref: https://www.speex.org/docs/manual/speex-manual/node8.html#SECTION00830000000000000000
@@ -10,19 +10,19 @@ export const Header = {
10
10
  return {
11
11
  speex: new Token.StringType(8, 'ascii').get(buf, off + 0),
12
12
  version: util.trimRightNull(new Token.StringType(20, 'ascii').get(buf, off + 8)),
13
- version_id: buf.readInt32LE(off + 28),
14
- header_size: buf.readInt32LE(off + 32),
15
- rate: buf.readInt32LE(off + 36),
16
- mode: buf.readInt32LE(off + 40),
17
- mode_bitstream_version: buf.readInt32LE(off + 44),
18
- nb_channels: buf.readInt32LE(off + 48),
19
- bitrate: buf.readInt32LE(off + 52),
20
- frame_size: buf.readInt32LE(off + 56),
21
- vbr: buf.readInt32LE(off + 60),
22
- frames_per_packet: buf.readInt32LE(off + 64),
23
- extra_headers: buf.readInt32LE(off + 68),
24
- reserved1: buf.readInt32LE(off + 72),
25
- reserved2: buf.readInt32LE(off + 76)
13
+ version_id: Token.INT32_LE.get(buf, off + 28),
14
+ header_size: Token.INT32_LE.get(buf, off + 32),
15
+ rate: Token.INT32_LE.get(buf, off + 36),
16
+ mode: Token.INT32_LE.get(buf, off + 40),
17
+ mode_bitstream_version: Token.INT32_LE.get(buf, off + 44),
18
+ nb_channels: Token.INT32_LE.get(buf, off + 48),
19
+ bitrate: Token.INT32_LE.get(buf, off + 52),
20
+ frame_size: Token.INT32_LE.get(buf, off + 56),
21
+ vbr: Token.INT32_LE.get(buf, off + 60),
22
+ frames_per_packet: Token.INT32_LE.get(buf, off + 64),
23
+ extra_headers: Token.INT32_LE.get(buf, off + 68),
24
+ reserved1: Token.INT32_LE.get(buf, off + 72),
25
+ reserved2: Token.INT32_LE.get(buf, off + 76)
26
26
  };
27
27
  }
28
28
  };
@@ -1,5 +1,4 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import { ITokenizer } from 'strtok3/core';
1
+ import { ITokenizer } from 'strtok3';
3
2
  import { IPageHeader } from '../Ogg.js';
4
3
  import { VorbisParser } from '../vorbis/VorbisParser.js';
5
4
  import { IOptions } from '../../type.js';
@@ -16,7 +15,7 @@ export declare class SpeexParser extends VorbisParser {
16
15
  /**
17
16
  * Parse first Speex Ogg page
18
17
  * @param {IPageHeader} header
19
- * @param {Buffer} pageData
18
+ * @param {Uint8Array} pageData
20
19
  */
21
- protected parseFirstPage(header: IPageHeader, pageData: Buffer): void;
20
+ protected parseFirstPage(header: IPageHeader, pageData: Uint8Array): void;
22
21
  }
@@ -16,7 +16,7 @@ export class SpeexParser extends VorbisParser {
16
16
  /**
17
17
  * Parse first Speex Ogg page
18
18
  * @param {IPageHeader} header
19
- * @param {Buffer} pageData
19
+ * @param {Uint8Array} pageData
20
20
  */
21
21
  parseFirstPage(header, pageData) {
22
22
  debug('First Ogg/Speex page');
@@ -1,4 +1,4 @@
1
- import { IGetToken } from 'strtok3/core';
1
+ import type { IGetToken } from 'strtok3';
2
2
  /**
3
3
  * 6.2 Identification Header
4
4
  * Ref: https://theora.org/doc/Theora.pdf: 6.2 Identification Header Decode
@@ -8,13 +8,13 @@ export const IdentificationHeader = {
8
8
  get: (buf, off) => {
9
9
  return {
10
10
  id: new Token.StringType(7, 'ascii').get(buf, off),
11
- vmaj: buf.readUInt8(off + 7),
12
- vmin: buf.readUInt8(off + 8),
13
- vrev: buf.readUInt8(off + 9),
14
- vmbw: buf.readUInt16BE(off + 10),
15
- vmbh: buf.readUInt16BE(off + 17),
11
+ vmaj: Token.UINT8.get(buf, off + 7),
12
+ vmin: Token.UINT8.get(buf, off + 8),
13
+ vrev: Token.UINT8.get(buf, off + 9),
14
+ vmbw: Token.UINT16_BE.get(buf, off + 10),
15
+ vmbh: Token.UINT16_BE.get(buf, off + 17),
16
16
  nombr: Token.UINT24_BE.get(buf, off + 37),
17
- nqual: buf.readUInt8(off + 40)
17
+ nqual: Token.UINT8.get(buf, off + 40)
18
18
  };
19
19
  }
20
20
  };
@@ -1,5 +1,4 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import { ITokenizer } from 'strtok3/core';
1
+ import { ITokenizer } from 'strtok3';
3
2
  import * as Ogg from '../Ogg.js';
4
3
  import { IOptions } from '../../type.js';
5
4
  import { INativeMetadataCollector } from '../../common/MetadataCollector.js';
@@ -16,13 +15,13 @@ export declare class TheoraParser implements Ogg.IPageConsumer {
16
15
  * @param header Ogg Page Header
17
16
  * @param pageData Page data
18
17
  */
19
- parsePage(header: Ogg.IPageHeader, pageData: Buffer): void;
20
- flush(): void;
18
+ parsePage(header: Ogg.IPageHeader, pageData: Uint8Array): Promise<void>;
19
+ flush(): Promise<void>;
21
20
  calculateDuration(header: Ogg.IPageHeader): void;
22
21
  /**
23
22
  * Parse first Theora Ogg page. the initial identification header packet
24
23
  * @param {IPageHeader} header
25
24
  * @param {Buffer} pageData
26
25
  */
27
- protected parseFirstPage(header: Ogg.IPageHeader, pageData: Buffer): void;
26
+ protected parseFirstPage(header: Ogg.IPageHeader, pageData: Uint8Array): Promise<void>;
28
27
  }
@@ -15,12 +15,12 @@ export class TheoraParser {
15
15
  * @param header Ogg Page Header
16
16
  * @param pageData Page data
17
17
  */
18
- parsePage(header, pageData) {
18
+ async parsePage(header, pageData) {
19
19
  if (header.headerType.firstPage) {
20
- this.parseFirstPage(header, pageData);
20
+ await this.parseFirstPage(header, pageData);
21
21
  }
22
22
  }
23
- flush() {
23
+ async flush() {
24
24
  debug('flush');
25
25
  }
26
26
  calculateDuration(header) {
@@ -31,7 +31,7 @@ export class TheoraParser {
31
31
  * @param {IPageHeader} header
32
32
  * @param {Buffer} pageData
33
33
  */
34
- parseFirstPage(header, pageData) {
34
+ async parseFirstPage(header, pageData) {
35
35
  debug('First Ogg/Theora page');
36
36
  this.metadata.setFormat('codec', 'Theora');
37
37
  const idHeader = IdentificationHeader.get(pageData, 0);
@@ -1,6 +1,5 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import { IPicture } from '../../type.js';
3
- import { IGetToken } from 'strtok3/core';
2
+ import type { IGetToken } from 'strtok3';
4
3
  /**
5
4
  * Interface to parsed result of METADATA_BLOCK_PICTURE
6
5
  * Ref: https://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE
@@ -23,9 +22,9 @@ export interface IVorbisPicture extends IPicture {
23
22
  export declare class VorbisPictureToken implements IGetToken<IVorbisPicture> {
24
23
  len: any;
25
24
  static fromBase64(base64str: string): IVorbisPicture;
26
- static fromBuffer(buffer: Buffer): IVorbisPicture;
25
+ static fromBuffer(buffer: Uint8Array): IVorbisPicture;
27
26
  constructor(len: any);
28
- get(buffer: Buffer, offset: number): IVorbisPicture;
27
+ get(buffer: Uint8Array, offset: number): IVorbisPicture;
29
28
  }
30
29
  /**
31
30
  * Vorbis 1 decoding tokens
@@ -8,7 +8,7 @@ import { AttachedPictureType } from '../../id3v2/ID3v2Token.js';
8
8
  */
9
9
  export class VorbisPictureToken {
10
10
  static fromBase64(base64str) {
11
- return this.fromBuffer(Buffer.from(base64str, 'base64'));
11
+ return this.fromBuffer(Uint8Array.from(atob(base64str), c => c.charCodeAt(0)));
12
12
  }
13
13
  static fromBuffer(buffer) {
14
14
  const pic = new VorbisPictureToken(buffer.length);
@@ -20,15 +20,15 @@ export class VorbisPictureToken {
20
20
  get(buffer, offset) {
21
21
  const type = AttachedPictureType[Token.UINT32_BE.get(buffer, offset)];
22
22
  const mimeLen = Token.UINT32_BE.get(buffer, offset += 4);
23
- const format = buffer.toString('utf-8', offset += 4, offset + mimeLen);
23
+ const format = new Token.StringType(mimeLen, 'utf-8').get(buffer, offset += 4);
24
24
  const descLen = Token.UINT32_BE.get(buffer, offset += mimeLen);
25
- const description = buffer.toString('utf-8', offset += 4, offset + descLen);
25
+ const description = new Token.StringType(descLen, 'utf-8').get(buffer, offset += 4);
26
26
  const width = Token.UINT32_BE.get(buffer, offset += descLen);
27
27
  const height = Token.UINT32_BE.get(buffer, offset += 4);
28
28
  const colour_depth = Token.UINT32_BE.get(buffer, offset += 4);
29
29
  const indexed_color = Token.UINT32_BE.get(buffer, offset += 4);
30
30
  const picDataLen = Token.UINT32_BE.get(buffer, offset += 4);
31
- const data = Buffer.from(buffer.slice(offset += 4, offset + picDataLen));
31
+ const data = Uint8Array.from(buffer.slice(offset += 4, offset + picDataLen));
32
32
  return {
33
33
  type,
34
34
  format,
@@ -49,7 +49,7 @@ export const CommonHeader = {
49
49
  len: 7,
50
50
  get: (buf, off) => {
51
51
  return {
52
- packetType: buf.readUInt8(off),
52
+ packetType: Token.UINT8.get(buf, off),
53
53
  vorbis: new Token.StringType(6, 'ascii').get(buf, off + 1)
54
54
  };
55
55
  }
@@ -61,14 +61,13 @@ export const CommonHeader = {
61
61
  export const IdentificationHeader = {
62
62
  len: 23,
63
63
  get: (uint8Array, off) => {
64
- const dataView = new DataView(uint8Array.buffer, uint8Array.byteOffset);
65
64
  return {
66
- version: dataView.getUint32(off + 0, true),
67
- channelMode: dataView.getUint8(off + 4),
68
- sampleRate: dataView.getUint32(off + 5, true),
69
- bitrateMax: dataView.getUint32(off + 9, true),
70
- bitrateNominal: dataView.getUint32(off + 13, true),
71
- bitrateMin: dataView.getUint32(off + 17, true)
65
+ version: Token.UINT32_LE.get(uint8Array, off + 0),
66
+ channelMode: Token.UINT8.get(uint8Array, off + 4),
67
+ sampleRate: Token.UINT32_LE.get(uint8Array, off + 5),
68
+ bitrateMax: Token.UINT32_LE.get(uint8Array, off + 9),
69
+ bitrateNominal: Token.UINT32_LE.get(uint8Array, off + 13),
70
+ bitrateMin: Token.UINT32_LE.get(uint8Array, off + 17)
72
71
  };
73
72
  }
74
73
  };
@@ -11,7 +11,7 @@ export class VorbisDecoder {
11
11
  }
12
12
  readStringUtf8() {
13
13
  const len = this.readInt32();
14
- const value = Buffer.from(this.data).toString('utf-8', this.offset, this.offset + len);
14
+ const value = new TextDecoder('utf-8').decode(this.data.subarray(this.offset, this.offset + len));
15
15
  this.offset += len;
16
16
  return value;
17
17
  }
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import { IVorbisPicture } from './Vorbis.js';
3
2
  import { IPageConsumer, IPageHeader } from '../Ogg.js';
4
3
  import { IOptions } from '../../type.js';
@@ -17,20 +16,21 @@ export declare class VorbisParser implements IPageConsumer {
17
16
  * @param header Ogg Page Header
18
17
  * @param pageData Page data
19
18
  */
20
- parsePage(header: IPageHeader, pageData: Buffer): void;
21
- flush(): void;
22
- parseUserComment(pageData: Buffer, offset: number): number;
23
- addTag(id: string, value: string | IVorbisPicture): void;
19
+ parsePage(header: IPageHeader, pageData: Uint8Array): Promise<void>;
20
+ private static mergeUint8Arrays;
21
+ flush(): Promise<void>;
22
+ parseUserComment(pageData: Uint8Array, offset: number): Promise<number>;
23
+ addTag(id: string, value: string | IVorbisPicture): Promise<void>;
24
24
  calculateDuration(header: IPageHeader): void;
25
25
  /**
26
26
  * Parse first Ogg/Vorbis page
27
27
  * @param header
28
28
  * @param pageData
29
29
  */
30
- protected parseFirstPage(header: IPageHeader, pageData: Buffer): void;
31
- protected parseFullPage(pageData: Buffer): void;
30
+ protected parseFirstPage(header: IPageHeader, pageData: Uint8Array): void;
31
+ protected parseFullPage(pageData: Uint8Array): Promise<void>;
32
32
  /**
33
33
  * Ref: https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-840005.2
34
34
  */
35
- protected parseUserCommentList(pageData: Buffer, offset: number): void;
35
+ protected parseUserCommentList(pageData: Uint8Array, offset: number): Promise<void>;
36
36
  }
@@ -18,7 +18,7 @@ export class VorbisParser {
18
18
  * @param header Ogg Page Header
19
19
  * @param pageData Page data
20
20
  */
21
- parsePage(header, pageData) {
21
+ async parsePage(header, pageData) {
22
22
  if (header.headerType.firstPage) {
23
23
  this.parseFirstPage(header, pageData);
24
24
  }
@@ -32,8 +32,8 @@ export class VorbisParser {
32
32
  if (header.headerType.lastPage || !header.headerType.continued) {
33
33
  // Flush page segments
34
34
  if (this.pageSegments.length > 0) {
35
- const fullPage = Buffer.concat(this.pageSegments);
36
- this.parseFullPage(fullPage);
35
+ const fullPage = VorbisParser.mergeUint8Arrays(this.pageSegments);
36
+ await this.parseFullPage(fullPage);
37
37
  }
38
38
  // Reset page segments
39
39
  this.pageSegments = header.headerType.lastPage ? [] : [pageData];
@@ -43,16 +43,25 @@ export class VorbisParser {
43
43
  this.calculateDuration(header);
44
44
  }
45
45
  }
46
- flush() {
47
- this.parseFullPage(Buffer.concat(this.pageSegments));
46
+ static mergeUint8Arrays(arrays) {
47
+ const totalSize = arrays.reduce((acc, e) => acc + e.length, 0);
48
+ const merged = new Uint8Array(totalSize);
49
+ arrays.forEach((array, i, _arrays) => {
50
+ const offset = _arrays.slice(0, i).reduce((acc, e) => acc + e.length, 0);
51
+ merged.set(array, offset);
52
+ });
53
+ return merged;
48
54
  }
49
- parseUserComment(pageData, offset) {
55
+ async flush() {
56
+ await this.parseFullPage(VorbisParser.mergeUint8Arrays(this.pageSegments));
57
+ }
58
+ async parseUserComment(pageData, offset) {
50
59
  const decoder = new VorbisDecoder(pageData, offset);
51
60
  const tag = decoder.parseUserComment();
52
- this.addTag(tag.key, tag.value);
61
+ await this.addTag(tag.key, tag.value);
53
62
  return tag.len;
54
63
  }
55
- addTag(id, value) {
64
+ async addTag(id, value) {
56
65
  if (id === 'METADATA_BLOCK_PICTURE' && (typeof value === 'string')) {
57
66
  if (this.options.skipCovers) {
58
67
  debug(`Ignore picture`);
@@ -64,7 +73,7 @@ export class VorbisParser {
64
73
  else {
65
74
  debug(`Push tag: id=${id}, value=${value}`);
66
75
  }
67
- this.metadata.addTag('vorbis', id, value);
76
+ await this.metadata.addTag('vorbis', id, value);
68
77
  }
69
78
  calculateDuration(header) {
70
79
  if (this.metadata.format.sampleRate && header.absoluteGranulePosition >= 0) {
@@ -95,7 +104,7 @@ export class VorbisParser {
95
104
  else
96
105
  throw new Error('First Ogg page should be type 1: the identification header');
97
106
  }
98
- parseFullPage(pageData) {
107
+ async parseFullPage(pageData) {
99
108
  // New page
100
109
  const commonHeader = CommonHeader.get(pageData, 0);
101
110
  debug('Parse full page: type=%s, byteLength=%s', commonHeader.packetType, pageData.byteLength);
@@ -110,7 +119,7 @@ export class VorbisParser {
110
119
  /**
111
120
  * Ref: https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-840005.2
112
121
  */
113
- parseUserCommentList(pageData, offset) {
122
+ async parseUserCommentList(pageData, offset) {
114
123
  const strLen = Token.UINT32_LE.get(pageData, offset);
115
124
  offset += 4;
116
125
  // const vendorString = new Token.StringType(strLen, 'utf-8').get(pageData, offset);
@@ -118,7 +127,7 @@ export class VorbisParser {
118
127
  let userCommentListLength = Token.UINT32_LE.get(pageData, offset);
119
128
  offset += 4;
120
129
  while (userCommentListLength-- > 0) {
121
- offset += this.parseUserComment(pageData, offset);
130
+ offset += (await this.parseUserComment(pageData, offset));
122
131
  }
123
132
  }
124
133
  }
@@ -1,4 +1,4 @@
1
- import { IGetToken } from 'strtok3/core';
1
+ import type { IGetToken } from 'strtok3';
2
2
  import { IChunkHeader } from '../iff/index.js';
3
3
  export { IChunkHeader } from '../iff/index.js';
4
4
  /**
@@ -7,9 +7,9 @@ export const Header = {
7
7
  get: (buf, off) => {
8
8
  return {
9
9
  // Group-ID
10
- chunkID: buf.toString('binary', off, off + 4),
10
+ chunkID: new Token.StringType(4, 'latin1').get(buf, off),
11
11
  // Size
12
- chunkSize: Token.UINT32_LE.get(buf, 4)
12
+ chunkSize: Token.UINT32_LE.get(buf, off + 4)
13
13
  };
14
14
  }
15
15
  };
package/lib/type.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import { Buffer } from 'node:buffer';
3
1
  import { GenericTagId, TagType } from './common/GenericTagTypes.js';
4
2
  import { IFooter } from './apev2/APEv2Token.js';
5
3
  import { TrackType } from './matroska/types.js';
@@ -15,7 +13,7 @@ export interface IPicture {
15
13
  /**
16
14
  * Image data
17
15
  */
18
- data: Buffer;
16
+ data: Uint8Array;
19
17
  /**
20
18
  * Optional description
21
19
  */
@@ -366,7 +364,7 @@ export interface IAudioTrack {
366
364
  samplingFrequency?: number;
367
365
  outputSamplingFrequency?: number;
368
366
  channels?: number;
369
- channelPositions?: Buffer;
367
+ channelPositions?: Uint8Array;
370
368
  bitDepth?: number;
371
369
  }
372
370
  export interface IVideoTrack {
@@ -378,7 +376,7 @@ export interface IVideoTrack {
378
376
  displayHeight?: number;
379
377
  displayUnit?: number;
380
378
  aspectRatioType?: number;
381
- colourSpace?: Buffer;
379
+ colourSpace?: Uint8Array;
382
380
  gammaValue?: number;
383
381
  }
384
382
  export interface ITrackInfo {
@@ -445,7 +443,7 @@ export interface IFormat {
445
443
  /**
446
444
  * 16-byte MD5 of raw audio
447
445
  */
448
- readonly audioMD5?: Buffer;
446
+ readonly audioMD5?: Uint8Array;
449
447
  /**
450
448
  * Chapters in audio stream
451
449
  */
@@ -587,11 +585,11 @@ export interface IRandomReader {
587
585
  fileSize: number;
588
586
  /**
589
587
  * Read from a given position of an abstracted file or buffer.
590
- * @param buffer {Buffer} is the buffer that the data will be written to.
591
- * @param offset {number} is the offset in the buffer to start writing at.
592
- * @param length {number}is an integer specifying the number of bytes to read.
593
- * @param position {number} is an argument specifying where to begin reading from in the file.
588
+ * @param {Uint8Array} buffer the buffer that the data will be written to.
589
+ * @param {number} offset the offset in the buffer to start writing at.
590
+ * @param {number} length an integer specifying the number of bytes to read.
591
+ * @param {number} position an argument specifying where to begin reading from in the file.
594
592
  * @return {Promise<number>} bytes read
595
593
  */
596
- randomRead(buffer: Buffer, offset: number, length: number, position: number): Promise<number>;
594
+ randomRead(buffer: Uint8Array, offset: number, length: number, position: number): Promise<number>;
597
595
  }
@@ -1,4 +1,4 @@
1
- import { IGetToken } from 'strtok3/core';
1
+ import type { IGetToken } from 'strtok3';
2
2
  export interface IBroadcastAudioExtensionChunk {
3
3
  description: string;
4
4
  originator: string;
@@ -1,5 +1,4 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- import { IGetToken } from 'strtok3/core';
1
+ import type { IGetToken } from 'strtok3';
3
2
  import { IChunkHeader } from '../iff/index.js';
4
3
  /**
5
4
  * Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317599(v=vs.85).aspx
@@ -47,7 +46,7 @@ export interface IWaveFormat {
47
46
  export declare class Format implements IGetToken<IWaveFormat> {
48
47
  len: number;
49
48
  constructor(header: IChunkHeader);
50
- get(buf: Buffer, off: number): IWaveFormat;
49
+ get(buf: Uint8Array, off: number): IWaveFormat;
51
50
  }
52
51
  export interface IFactChunk {
53
52
  dwSampleLength: number;
@@ -60,5 +59,5 @@ export interface IFactChunk {
60
59
  export declare class FactChunk implements IGetToken<IFactChunk> {
61
60
  len: number;
62
61
  constructor(header: IChunkHeader);
63
- get(buf: Buffer, off: number): IFactChunk;
62
+ get(buf: Uint8Array, off: number): IFactChunk;
64
63
  }
@@ -1,3 +1,4 @@
1
+ import * as Token from 'token-types';
1
2
  /**
2
3
  * Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317599(v=vs.85).aspx
3
4
  */
@@ -31,12 +32,12 @@ export class Format {
31
32
  }
32
33
  get(buf, off) {
33
34
  return {
34
- wFormatTag: buf.readUInt16LE(off),
35
- nChannels: buf.readUInt16LE(off + 2),
36
- nSamplesPerSec: buf.readUInt32LE(off + 4),
37
- nAvgBytesPerSec: buf.readUInt32LE(off + 8),
38
- nBlockAlign: buf.readUInt16LE(off + 12),
39
- wBitsPerSample: buf.readUInt16LE(off + 14)
35
+ wFormatTag: Token.UINT16_LE.get(buf, off),
36
+ nChannels: Token.UINT16_LE.get(buf, off + 2),
37
+ nSamplesPerSec: Token.UINT32_LE.get(buf, off + 4),
38
+ nAvgBytesPerSec: Token.UINT32_LE.get(buf, off + 8),
39
+ nBlockAlign: Token.UINT16_LE.get(buf, off + 12),
40
+ wBitsPerSample: Token.UINT16_LE.get(buf, off + 14)
40
41
  };
41
42
  }
42
43
  }
@@ -54,7 +55,7 @@ export class FactChunk {
54
55
  }
55
56
  get(buf, off) {
56
57
  return {
57
- dwSampleLength: buf.readUInt32LE(off)
58
+ dwSampleLength: Token.UINT32_LE.get(buf, off)
58
59
  };
59
60
  }
60
61
  }
@@ -1,4 +1,4 @@
1
- import * as strtok3 from 'strtok3/core';
1
+ import * as strtok3 from 'strtok3';
2
2
  import * as Token from 'token-types';
3
3
  import initDebug from 'debug';
4
4
  import * as riff from '../riff/RiffChunk.js';
@@ -129,7 +129,7 @@ export class WaveParser extends BasicParser {
129
129
  }
130
130
  }
131
131
  async parseListTag(listHeader) {
132
- const listType = await this.tokenizer.readToken(new Token.StringType(4, 'binary'));
132
+ const listType = await this.tokenizer.readToken(new Token.StringType(4, 'latin1'));
133
133
  debug('pos=%s, parseListTag: chunkID=RIFF/WAVE/LIST/%s', this.tokenizer.position, listType);
134
134
  switch (listType) {
135
135
  case 'INFO':