music-metadata 10.0.0 → 10.1.0

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 (121) hide show
  1. package/README.md +4 -3
  2. package/lib/ParserFactory.d.ts +20 -28
  3. package/lib/ParserFactory.js +204 -207
  4. package/lib/aiff/AiffParser.js +20 -18
  5. package/lib/aiff/AiffToken.d.ts +14 -2
  6. package/lib/aiff/AiffToken.js +12 -0
  7. package/lib/apev2/APEv2Parser.d.ts +4 -4
  8. package/lib/apev2/APEv2Parser.js +20 -12
  9. package/lib/apev2/APEv2Token.d.ts +2 -4
  10. package/lib/apev2/APEv2Token.js +1 -4
  11. package/lib/asf/AsfObject.d.ts +7 -16
  12. package/lib/asf/AsfObject.js +8 -34
  13. package/lib/asf/AsfParser.js +17 -10
  14. package/lib/asf/AsfTagMapper.d.ts +1 -1
  15. package/lib/asf/AsfTagMapper.js +3 -2
  16. package/lib/asf/AsfUtil.d.ts +3 -11
  17. package/lib/asf/AsfUtil.js +29 -30
  18. package/lib/asf/GUID.js +6 -9
  19. package/lib/common/BasicParser.d.ts +4 -4
  20. package/lib/common/BasicParser.js +6 -0
  21. package/lib/common/CaseInsensitiveTagMap.d.ts +1 -1
  22. package/lib/common/CombinedTagMapper.d.ts +5 -5
  23. package/lib/common/CombinedTagMapper.js +1 -1
  24. package/lib/common/FourCC.d.ts +1 -1
  25. package/lib/common/GenericTagMapper.d.ts +8 -8
  26. package/lib/common/GenericTagMapper.js +4 -4
  27. package/lib/common/GenericTagTypes.d.ts +5 -4
  28. package/lib/common/GenericTagTypes.js +2 -2
  29. package/lib/common/MetadataCollector.d.ts +9 -9
  30. package/lib/common/MetadataCollector.js +24 -17
  31. package/lib/common/RandomFileReader.d.ts +1 -1
  32. package/lib/common/RandomFileReader.js +1 -1
  33. package/lib/common/RandomUint8ArrayReader.d.ts +1 -1
  34. package/lib/common/Util.d.ts +2 -6
  35. package/lib/common/Util.js +9 -11
  36. package/lib/core.d.ts +7 -9
  37. package/lib/core.js +10 -7
  38. package/lib/dsdiff/DsdiffParser.js +26 -14
  39. package/lib/dsdiff/DsdiffToken.d.ts +2 -2
  40. package/lib/dsdiff/DsdiffToken.js +1 -0
  41. package/lib/dsf/DsfChunk.js +1 -0
  42. package/lib/dsf/DsfParser.js +4 -2
  43. package/lib/flac/FlacParser.d.ts +3 -3
  44. package/lib/flac/FlacParser.js +9 -12
  45. package/lib/id3v1/ID3v1Parser.d.ts +1 -1
  46. package/lib/id3v1/ID3v1Parser.js +7 -4
  47. package/lib/id3v2/AbstractID3Parser.d.ts +1 -1
  48. package/lib/id3v2/AbstractID3Parser.js +2 -1
  49. package/lib/id3v2/FrameParser.d.ts +28 -3
  50. package/lib/id3v2/FrameParser.js +50 -28
  51. package/lib/id3v2/ID3v22TagMapper.d.ts +1 -1
  52. package/lib/id3v2/ID3v24TagMapper.d.ts +2 -1
  53. package/lib/id3v2/ID3v24TagMapper.js +23 -16
  54. package/lib/id3v2/ID3v2Parser.d.ts +2 -2
  55. package/lib/id3v2/ID3v2Parser.js +19 -8
  56. package/lib/iff/index.js +1 -0
  57. package/lib/index.d.ts +5 -6
  58. package/lib/index.js +7 -8
  59. package/lib/lyrics3/Lyrics3.d.ts +1 -1
  60. package/lib/lyrics3/Lyrics3.js +1 -1
  61. package/lib/matroska/MatroskaDtd.d.ts +1 -1
  62. package/lib/matroska/MatroskaDtd.js +139 -138
  63. package/lib/matroska/MatroskaParser.d.ts +4 -4
  64. package/lib/matroska/MatroskaParser.js +12 -12
  65. package/lib/matroska/types.d.ts +6 -4
  66. package/lib/mp4/Atom.d.ts +3 -3
  67. package/lib/mp4/Atom.js +4 -7
  68. package/lib/mp4/AtomToken.js +2 -1
  69. package/lib/mp4/MP4Parser.js +29 -20
  70. package/lib/mp4/MP4TagMapper.d.ts +2 -2
  71. package/lib/mp4/MP4TagMapper.js +1 -1
  72. package/lib/mpeg/ExtendedLameHeader.d.ts +4 -4
  73. package/lib/mpeg/ExtendedLameHeader.js +2 -1
  74. package/lib/mpeg/MpegParser.d.ts +1 -1
  75. package/lib/mpeg/MpegParser.js +145 -96
  76. package/lib/mpeg/ReplayGainDataFormat.d.ts +1 -1
  77. package/lib/mpeg/ReplayGainDataFormat.js +1 -0
  78. package/lib/mpeg/XingTag.d.ts +4 -4
  79. package/lib/mpeg/XingTag.js +5 -4
  80. package/lib/musepack/index.js +1 -0
  81. package/lib/musepack/sv7/BitReader.js +14 -17
  82. package/lib/musepack/sv7/MpcSv7Parser.js +6 -1
  83. package/lib/musepack/sv7/StreamVersion7.js +1 -0
  84. package/lib/musepack/sv8/MpcSv8Parser.js +6 -2
  85. package/lib/musepack/sv8/StreamVersion8.d.ts +1 -1
  86. package/lib/musepack/sv8/StreamVersion8.js +1 -0
  87. package/lib/ogg/Ogg.d.ts +1 -1
  88. package/lib/ogg/Ogg.js +1 -0
  89. package/lib/ogg/OggParser.d.ts +3 -3
  90. package/lib/ogg/OggParser.js +25 -16
  91. package/lib/ogg/opus/Opus.d.ts +1 -1
  92. package/lib/ogg/opus/Opus.js +1 -0
  93. package/lib/ogg/opus/OpusParser.d.ts +4 -4
  94. package/lib/ogg/opus/OpusParser.js +2 -0
  95. package/lib/ogg/speex/Speex.js +1 -0
  96. package/lib/ogg/speex/SpeexParser.d.ts +4 -4
  97. package/lib/ogg/speex/SpeexParser.js +1 -0
  98. package/lib/ogg/theora/Theora.js +1 -0
  99. package/lib/ogg/theora/TheoraParser.d.ts +4 -4
  100. package/lib/ogg/theora/TheoraParser.js +1 -0
  101. package/lib/ogg/vorbis/Vorbis.d.ts +3 -3
  102. package/lib/ogg/vorbis/Vorbis.js +22 -11
  103. package/lib/ogg/vorbis/VorbisDecoder.d.ts +1 -1
  104. package/lib/ogg/vorbis/VorbisDecoder.js +1 -0
  105. package/lib/ogg/vorbis/VorbisParser.d.ts +4 -4
  106. package/lib/ogg/vorbis/VorbisParser.js +3 -2
  107. package/lib/ogg/vorbis/VorbisTagMapper.d.ts +2 -2
  108. package/lib/ogg/vorbis/VorbisTagMapper.js +2 -2
  109. package/lib/riff/RiffChunk.d.ts +3 -3
  110. package/lib/riff/RiffChunk.js +1 -0
  111. package/lib/riff/RiffInfoTagMap.d.ts +1 -1
  112. package/lib/type.d.ts +35 -25
  113. package/lib/wav/BwfChunk.js +1 -0
  114. package/lib/wav/WaveChunk.d.ts +1 -1
  115. package/lib/wav/WaveChunk.js +1 -0
  116. package/lib/wav/WaveParser.js +27 -17
  117. package/lib/wavpack/WavPackParser.d.ts +1 -1
  118. package/lib/wavpack/WavPackParser.js +22 -13
  119. package/lib/wavpack/WavPackToken.d.ts +13 -17
  120. package/lib/wavpack/WavPackToken.js +22 -23
  121. package/package.json +15 -28
package/README.md CHANGED
@@ -251,7 +251,7 @@ Or with async/await if you prefer:
251
251
  Parse metadata from an audio file, where the audio file is held in a [Buffer](https://nodejs.org/api/buffer.html).
252
252
 
253
253
  ```ts
254
- parseBuffer(buffer: Buffer, fileInfo?: IFileInfo | string, opts?: IOptions = {}): Promise<IAudioMetadata>
254
+ parseBuffer(buffer: Uint8Array, fileInfo?: IFileInfo | string, opts?: IOptions = {}): Promise<IAudioMetadata>
255
255
  ```
256
256
 
257
257
  Example:
@@ -270,7 +270,6 @@ import { parseBuffer } from 'music-metadata';
270
270
 
271
271
  #### parseFromTokenizer function
272
272
  This is a low level function, reading from a [strtok3](https://github.com/Borewit/strtok3) ITokenizer interface.
273
- [music-metadata-browser](https://github.com/Borewit/music-metadata-browser) is depended on this function.
274
273
 
275
274
  This also enables special read modules like:
276
275
  - [streaming-http-token-reader](https://github.com/Borewit/streaming-http-token-reader) for chunked HTTP(S) reading, using [HTTP range requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests).
@@ -452,7 +451,9 @@ export interface IPicture {
452
451
 
453
452
  To assign `img` HTML-object you can do something like:
454
453
  ```js
455
- img.src = `data:${picture.format};base64,${picture.data.toString('base64')}`;
454
+ import {uint8ArrayToBase64} from 'uint8array-extras';
455
+
456
+ img.src = `data:${picture.format};base64,${uint8ArrayToBase64(picture.data)}`;
456
457
  ```
457
458
 
458
459
  ## Frequently Asked Questions
@@ -1,5 +1,6 @@
1
- import { INativeMetadataCollector } from './common/MetadataCollector.js';
2
- import { IOptions, IAudioMetadata, ParserType } from './type.js';
1
+ import { type MediaType } from 'media-typer';
2
+ import { type INativeMetadataCollector } from './common/MetadataCollector.js';
3
+ import type { IOptions, IAudioMetadata, ParserType } from './type.js';
3
4
  import type { ITokenizer } from 'strtok3';
4
5
  export interface ITokenParser {
5
6
  /**
@@ -16,33 +17,24 @@ export interface ITokenParser {
16
17
  */
17
18
  parse(): Promise<void>;
18
19
  }
19
- export declare function parseHttpContentType(contentType: string): {
20
- type: string;
21
- subtype: string;
22
- suffix?: string;
20
+ interface IContentType extends MediaType {
23
21
  parameters: {
24
22
  [id: string]: string;
25
23
  };
26
- };
27
- export declare class ParserFactory {
28
- /**
29
- * Parse metadata from tokenizer
30
- * @param tokenizer - Tokenizer
31
- * @param opts - Options
32
- * @returns Native metadata
33
- */
34
- static parseOnContentType(tokenizer: ITokenizer, opts: IOptions): Promise<IAudioMetadata>;
35
- static parse(tokenizer: ITokenizer, parserId: ParserType, opts: IOptions): Promise<IAudioMetadata>;
36
- /**
37
- * @param filePath - Path, filename or extension to audio file
38
- * @return Parser sub-module name
39
- */
40
- static getParserIdForExtension(filePath: string): ParserType;
41
- static loadParser(moduleName: ParserType): Promise<ITokenParser>;
42
- private static getExtension;
43
- /**
44
- * @param httpContentType - HTTP Content-Type, extension, path or filename
45
- * @returns Parser sub-module name
46
- */
47
- private static getParserIdForMimeType;
48
24
  }
25
+ export declare function parseHttpContentType(contentType: string): IContentType;
26
+ /**
27
+ * Parse metadata from tokenizer
28
+ * @param tokenizer - Tokenizer
29
+ * @param opts - Options
30
+ * @returns Native metadata
31
+ */
32
+ export declare function parseOnContentType(tokenizer: ITokenizer, opts?: IOptions): Promise<IAudioMetadata>;
33
+ export declare function parse(tokenizer: ITokenizer, parserId?: ParserType, opts?: IOptions): Promise<IAudioMetadata>;
34
+ /**
35
+ * @param filePath - Path, filename or extension to audio file
36
+ * @return Parser submodule name
37
+ */
38
+ export declare function getParserIdForExtension(filePath: string | undefined): ParserType | undefined;
39
+ export declare function loadParser(moduleName: ParserType): Promise<ITokenParser>;
40
+ export {};
@@ -1,6 +1,6 @@
1
1
  import { fileTypeFromBuffer } from 'file-type';
2
2
  import ContentType from 'content-type';
3
- import MimeType from 'media-typer';
3
+ import { parse as mimeTypeParse } from 'media-typer';
4
4
  import initDebug from 'debug';
5
5
  import { MetadataCollector } from './common/MetadataCollector.js';
6
6
  import { AIFFParser } from './aiff/AiffParser.js';
@@ -19,7 +19,7 @@ import { MatroskaParser } from './matroska/MatroskaParser.js';
19
19
  const debug = initDebug('music-metadata:parser:factory');
20
20
  export function parseHttpContentType(contentType) {
21
21
  const type = ContentType.parse(contentType);
22
- const mime = MimeType.parse(type.type);
22
+ const mime = mimeTypeParse(type.type);
23
23
  return {
24
24
  type: mime.type,
25
25
  subtype: mime.subtype,
@@ -27,221 +27,218 @@ export function parseHttpContentType(contentType) {
27
27
  parameters: type.parameters
28
28
  };
29
29
  }
30
- async function parse(tokenizer, parserId, opts = {}) {
31
- // Parser found, execute parser
32
- const parser = await ParserFactory.loadParser(parserId);
33
- const metadata = new MetadataCollector(opts);
34
- await parser.init(metadata, tokenizer, opts).parse();
35
- return metadata.toCommonMetadata();
30
+ /**
31
+ * Parse metadata from tokenizer
32
+ * @param tokenizer - Tokenizer
33
+ * @param opts - Options
34
+ * @returns Native metadata
35
+ */
36
+ export async function parseOnContentType(tokenizer, opts) {
37
+ const { mimeType, path, url } = tokenizer.fileInfo;
38
+ // Resolve parser based on MIME-type or file extension
39
+ const parserId = getParserIdForMimeType(mimeType) || getParserIdForExtension(path) || getParserIdForExtension(url);
40
+ if (!parserId) {
41
+ debug(`No parser found for MIME-type / extension: ${mimeType}`);
42
+ }
43
+ return parse(tokenizer, parserId, opts);
36
44
  }
37
- export class ParserFactory {
38
- /**
39
- * Parse metadata from tokenizer
40
- * @param tokenizer - Tokenizer
41
- * @param opts - Options
42
- * @returns Native metadata
43
- */
44
- static async parseOnContentType(tokenizer, opts) {
45
- const { mimeType, path, url } = await tokenizer.fileInfo;
46
- // Resolve parser based on MIME-type or file extension
47
- const parserId = ParserFactory.getParserIdForMimeType(mimeType) || ParserFactory.getParserIdForExtension(path) || ParserFactory.getParserIdForExtension(url);
48
- if (!parserId) {
49
- debug('No parser found for MIME-type / extension: ' + mimeType);
45
+ export async function parse(tokenizer, parserId, opts) {
46
+ if (!parserId) {
47
+ // Parser could not be determined on MIME-type or extension
48
+ debug('Guess parser on content...');
49
+ const buf = new Uint8Array(4100);
50
+ await tokenizer.peekBuffer(buf, { mayBeLess: true });
51
+ if (tokenizer.fileInfo.path) {
52
+ parserId = getParserIdForExtension(tokenizer.fileInfo.path);
50
53
  }
51
- return this.parse(tokenizer, parserId, opts);
52
- }
53
- static async parse(tokenizer, parserId, opts) {
54
54
  if (!parserId) {
55
- // Parser could not be determined on MIME-type or extension
56
- debug('Guess parser on content...');
57
- const buf = new Uint8Array(4100);
58
- await tokenizer.peekBuffer(buf, { mayBeLess: true });
59
- if (tokenizer.fileInfo.path) {
60
- parserId = this.getParserIdForExtension(tokenizer.fileInfo.path);
55
+ const guessedType = await fileTypeFromBuffer(buf);
56
+ if (!guessedType) {
57
+ throw new Error('Failed to determine audio format');
61
58
  }
59
+ debug(`Guessed file type is mime=${guessedType.mime}, extension=${guessedType.ext}`);
60
+ parserId = getParserIdForMimeType(guessedType.mime);
62
61
  if (!parserId) {
63
- const guessedType = await fileTypeFromBuffer(buf);
64
- if (!guessedType) {
65
- throw new Error('Failed to determine audio format');
66
- }
67
- debug(`Guessed file type is mime=${guessedType.mime}, extension=${guessedType.ext}`);
68
- parserId = ParserFactory.getParserIdForMimeType(guessedType.mime);
69
- if (!parserId) {
70
- throw new Error('Guessed MIME-type not supported: ' + guessedType.mime);
71
- }
62
+ throw new Error(`Guessed MIME-type not supported: ${guessedType.mime}`);
72
63
  }
73
64
  }
74
- // Parser found, execute parser
75
- return parse(tokenizer, parserId, opts);
76
65
  }
77
- /**
78
- * @param filePath - Path, filename or extension to audio file
79
- * @return Parser sub-module name
80
- */
81
- static getParserIdForExtension(filePath) {
82
- if (!filePath)
83
- return;
84
- const extension = this.getExtension(filePath).toLocaleLowerCase() || filePath;
85
- switch (extension) {
86
- case '.mp2':
87
- case '.mp3':
88
- case '.m2a':
89
- case '.aac': // Assume it is ADTS-container
90
- return 'mpeg';
91
- case '.ape':
92
- return 'apev2';
93
- case '.mp4':
94
- case '.m4a':
95
- case '.m4b':
96
- case '.m4pa':
97
- case '.m4v':
98
- case '.m4r':
99
- case '.3gp':
100
- return 'mp4';
101
- case '.wma':
102
- case '.wmv':
103
- case '.asf':
104
- return 'asf';
105
- case '.flac':
106
- return 'flac';
107
- case '.ogg':
108
- case '.ogv':
109
- case '.oga':
110
- case '.ogm':
111
- case '.ogx':
112
- case '.opus': // recommended filename extension for Ogg Opus
113
- case '.spx': // recommended filename extension for Ogg Speex
114
- return 'ogg';
115
- case '.aif':
116
- case '.aiff':
117
- case '.aifc':
118
- return 'aiff';
119
- case '.wav':
120
- case '.bwf': // Broadcast Wave Format
121
- return 'riff';
122
- case '.wv':
123
- case '.wvp':
124
- return 'wavpack';
125
- case '.mpc':
126
- return 'musepack';
127
- case '.dsf':
128
- return 'dsf';
129
- case '.dff':
130
- return 'dsdiff';
131
- case '.mka':
132
- case '.mkv':
133
- case '.mk3d':
134
- case '.mks':
135
- case '.webm':
136
- return 'matroska';
137
- }
66
+ // Parser found, execute parser
67
+ const parser = await loadParser(parserId);
68
+ const metadata = new MetadataCollector(opts);
69
+ await parser.init(metadata, tokenizer, opts !== null && opts !== void 0 ? opts : {}).parse();
70
+ return metadata.toCommonMetadata();
71
+ }
72
+ /**
73
+ * @param filePath - Path, filename or extension to audio file
74
+ * @return Parser submodule name
75
+ */
76
+ export function getParserIdForExtension(filePath) {
77
+ if (!filePath)
78
+ return;
79
+ const extension = getExtension(filePath).toLocaleLowerCase() || filePath;
80
+ switch (extension) {
81
+ case '.mp2':
82
+ case '.mp3':
83
+ case '.m2a':
84
+ case '.aac': // Assume it is ADTS-container
85
+ return 'mpeg';
86
+ case '.ape':
87
+ return 'apev2';
88
+ case '.mp4':
89
+ case '.m4a':
90
+ case '.m4b':
91
+ case '.m4pa':
92
+ case '.m4v':
93
+ case '.m4r':
94
+ case '.3gp':
95
+ return 'mp4';
96
+ case '.wma':
97
+ case '.wmv':
98
+ case '.asf':
99
+ return 'asf';
100
+ case '.flac':
101
+ return 'flac';
102
+ case '.ogg':
103
+ case '.ogv':
104
+ case '.oga':
105
+ case '.ogm':
106
+ case '.ogx':
107
+ case '.opus': // recommended filename extension for Ogg Opus
108
+ case '.spx': // recommended filename extension for Ogg Speex
109
+ return 'ogg';
110
+ case '.aif':
111
+ case '.aiff':
112
+ case '.aifc':
113
+ return 'aiff';
114
+ case '.wav':
115
+ case '.bwf': // Broadcast Wave Format
116
+ return 'riff';
117
+ case '.wv':
118
+ case '.wvp':
119
+ return 'wavpack';
120
+ case '.mpc':
121
+ return 'musepack';
122
+ case '.dsf':
123
+ return 'dsf';
124
+ case '.dff':
125
+ return 'dsdiff';
126
+ case '.mka':
127
+ case '.mkv':
128
+ case '.mk3d':
129
+ case '.mks':
130
+ case '.webm':
131
+ return 'matroska';
138
132
  }
139
- static async loadParser(moduleName) {
140
- switch (moduleName) {
141
- case 'aiff': return new AIFFParser();
142
- case 'adts':
143
- case 'mpeg':
144
- return new MpegParser();
145
- case 'apev2': return new APEv2Parser();
146
- case 'asf': return new AsfParser();
147
- case 'dsf': return new DsfParser();
148
- case 'dsdiff': return new DsdiffParser();
149
- case 'flac': return new FlacParser();
150
- case 'mp4': return new MP4Parser();
151
- case 'musepack': return new MusepackParser();
152
- case 'ogg': return new OggParser();
153
- case 'riff': return new WaveParser();
154
- case 'wavpack': return new WavPackParser();
155
- case 'matroska': return new MatroskaParser();
156
- default:
157
- throw new Error(`Unknown parser type: ${moduleName}`);
158
- }
133
+ }
134
+ export async function loadParser(moduleName) {
135
+ switch (moduleName) {
136
+ case 'aiff': return new AIFFParser();
137
+ case 'adts':
138
+ case 'mpeg':
139
+ return new MpegParser();
140
+ case 'apev2': return new APEv2Parser();
141
+ case 'asf': return new AsfParser();
142
+ case 'dsf': return new DsfParser();
143
+ case 'dsdiff': return new DsdiffParser();
144
+ case 'flac': return new FlacParser();
145
+ case 'mp4': return new MP4Parser();
146
+ case 'musepack': return new MusepackParser();
147
+ case 'ogg': return new OggParser();
148
+ case 'riff': return new WaveParser();
149
+ case 'wavpack': return new WavPackParser();
150
+ case 'matroska': return new MatroskaParser();
151
+ default:
152
+ throw new Error(`Unknown parser type: ${moduleName}`);
159
153
  }
160
- static getExtension(fname) {
161
- const i = fname.lastIndexOf('.');
162
- return i === -1 ? '' : fname.slice(i);
154
+ }
155
+ function getExtension(fname) {
156
+ const i = fname.lastIndexOf('.');
157
+ return i === -1 ? '' : fname.slice(i);
158
+ }
159
+ /**
160
+ * @param httpContentType - HTTP Content-Type, extension, path or filename
161
+ * @returns Parser submodule name
162
+ */
163
+ function getParserIdForMimeType(httpContentType) {
164
+ let mime;
165
+ if (!httpContentType)
166
+ return;
167
+ try {
168
+ mime = parseHttpContentType(httpContentType);
163
169
  }
164
- /**
165
- * @param httpContentType - HTTP Content-Type, extension, path or filename
166
- * @returns Parser sub-module name
167
- */
168
- static getParserIdForMimeType(httpContentType) {
169
- let mime;
170
- try {
171
- mime = parseHttpContentType(httpContentType);
172
- }
173
- catch (err) {
174
- debug(`Invalid HTTP Content-Type header value: ${httpContentType}`);
175
- return;
176
- }
177
- const subType = mime.subtype.indexOf('x-') === 0 ? mime.subtype.substring(2) : mime.subtype;
178
- switch (mime.type) {
179
- case 'audio':
180
- switch (subType) {
181
- case 'mp3': // Incorrect MIME-type, Chrome, in Web API File object
182
- case 'mpeg':
183
- return 'mpeg';
184
- case 'aac':
185
- case 'aacp':
186
- return 'adts';
187
- case 'flac':
188
- return 'flac';
189
- case 'ape':
190
- case 'monkeys-audio':
191
- return 'apev2';
192
- case 'mp4':
193
- case 'm4a':
194
- return 'mp4';
195
- case 'ogg': // RFC 7845
196
- case 'opus': // RFC 6716
197
- case 'speex': // RFC 5574
198
- return 'ogg';
199
- case 'ms-wma':
200
- case 'ms-wmv':
201
- case 'ms-asf':
202
- return 'asf';
203
- case 'aiff':
204
- case 'aif':
205
- case 'aifc':
206
- return 'aiff';
207
- case 'vnd.wave':
208
- case 'wav':
209
- case 'wave':
210
- return 'riff';
211
- case 'wavpack':
212
- return 'wavpack';
213
- case 'musepack':
214
- return 'musepack';
215
- case 'matroska':
216
- case 'webm':
217
- return 'matroska';
218
- case 'dsf':
219
- return 'dsf';
220
- }
221
- break;
222
- case 'video':
223
- switch (subType) {
224
- case 'ms-asf':
225
- case 'ms-wmv':
226
- return 'asf';
227
- case 'm4v':
228
- case 'mp4':
229
- return 'mp4';
230
- case 'ogg':
231
- return 'ogg';
232
- case 'matroska':
233
- case 'webm':
234
- return 'matroska';
235
- }
236
- break;
237
- case 'application':
238
- switch (subType) {
239
- case 'vnd.ms-asf':
240
- return 'asf';
241
- case 'ogg':
242
- return 'ogg';
243
- }
244
- break;
245
- }
170
+ catch (err) {
171
+ debug(`Invalid HTTP Content-Type header value: ${httpContentType}`);
172
+ return;
173
+ }
174
+ const subType = mime.subtype.indexOf('x-') === 0 ? mime.subtype.substring(2) : mime.subtype;
175
+ switch (mime.type) {
176
+ case 'audio':
177
+ switch (subType) {
178
+ case 'mp3': // Incorrect MIME-type, Chrome, in Web API File object
179
+ case 'mpeg':
180
+ return 'mpeg';
181
+ case 'aac':
182
+ case 'aacp':
183
+ return 'adts';
184
+ case 'flac':
185
+ return 'flac';
186
+ case 'ape':
187
+ case 'monkeys-audio':
188
+ return 'apev2';
189
+ case 'mp4':
190
+ case 'm4a':
191
+ return 'mp4';
192
+ case 'ogg': // RFC 7845
193
+ case 'opus': // RFC 6716
194
+ case 'speex': // RFC 5574
195
+ return 'ogg';
196
+ case 'ms-wma':
197
+ case 'ms-wmv':
198
+ case 'ms-asf':
199
+ return 'asf';
200
+ case 'aiff':
201
+ case 'aif':
202
+ case 'aifc':
203
+ return 'aiff';
204
+ case 'vnd.wave':
205
+ case 'wav':
206
+ case 'wave':
207
+ return 'riff';
208
+ case 'wavpack':
209
+ return 'wavpack';
210
+ case 'musepack':
211
+ return 'musepack';
212
+ case 'matroska':
213
+ case 'webm':
214
+ return 'matroska';
215
+ case 'dsf':
216
+ return 'dsf';
217
+ }
218
+ break;
219
+ case 'video':
220
+ switch (subType) {
221
+ case 'ms-asf':
222
+ case 'ms-wmv':
223
+ return 'asf';
224
+ case 'm4v':
225
+ case 'mp4':
226
+ return 'mp4';
227
+ case 'ogg':
228
+ return 'ogg';
229
+ case 'matroska':
230
+ case 'webm':
231
+ return 'matroska';
232
+ }
233
+ break;
234
+ case 'application':
235
+ switch (subType) {
236
+ case 'vnd.ms-asf':
237
+ return 'asf';
238
+ case 'ogg':
239
+ return 'ogg';
240
+ }
241
+ break;
246
242
  }
247
243
  }
244
+ //# sourceMappingURL=ParserFactory.js.map
@@ -6,18 +6,8 @@ import { FourCcToken } from '../common/FourCC.js';
6
6
  import { BasicParser } from '../common/BasicParser.js';
7
7
  import * as AiffToken from './AiffToken.js';
8
8
  import * as iff from '../iff/index.js';
9
+ import { compressionTypes } from './AiffToken.js';
9
10
  const debug = initDebug('music-metadata:parser:aiff');
10
- const compressionTypes = {
11
- NONE: 'not compressed PCM Apple Computer',
12
- sowt: 'PCM (byte swapped)',
13
- fl32: '32-bit floating point IEEE 32-bit float',
14
- fl64: '64-bit floating point IEEE 64-bit float Apple Computer',
15
- alaw: 'ALaw 2:1 8-bit ITU-T G.711 A-law',
16
- ulaw: 'µLaw 2:1 8-bit ITU-T G.711 µ-law Apple Computer',
17
- ULAW: 'CCITT G.711 u-law 8-bit ITU-T G.711 µ-law',
18
- ALAW: 'CCITT G.711 A-law 8-bit ITU-T G.711 A-law',
19
- FL32: 'Float 32 IEEE 32-bit float '
20
- };
21
11
  /**
22
12
  * AIFF - Audio Interchange File Format
23
13
  *
@@ -26,6 +16,10 @@ const compressionTypes = {
26
16
  * - http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/Docs/AIFF-1.3.pdf
27
17
  */
28
18
  export class AIFFParser extends BasicParser {
19
+ constructor() {
20
+ super(...arguments);
21
+ this.isCompressed = null;
22
+ }
29
23
  async parse() {
30
24
  const header = await this.tokenizer.readToken(iff.Header);
31
25
  if (header.chunkID !== 'FORM')
@@ -41,12 +35,12 @@ export class AIFFParser extends BasicParser {
41
35
  this.isCompressed = true;
42
36
  break;
43
37
  default:
44
- throw Error('Unsupported AIFF type: ' + type);
38
+ throw new Error(`Unsupported AIFF type: ${type}`);
45
39
  }
46
40
  this.metadata.setFormat('lossless', !this.isCompressed);
47
41
  try {
48
42
  while (!this.tokenizer.fileInfo.size || this.tokenizer.fileInfo.size - this.tokenizer.position >= iff.Header.len) {
49
- debug('Reading AIFF chunk at offset=' + this.tokenizer.position);
43
+ debug(`Reading AIFF chunk at offset=${this.tokenizer.position}`);
50
44
  const chunkHeader = await this.tokenizer.readToken(iff.Header);
51
45
  const nextChunk = 2 * Math.round(chunkHeader.chunkSize / 2);
52
46
  const bytesRead = await this.readData(chunkHeader);
@@ -55,7 +49,7 @@ export class AIFFParser extends BasicParser {
55
49
  }
56
50
  catch (err) {
57
51
  if (err instanceof strtok3.EndOfStreamError) {
58
- debug(`End-of-stream`);
52
+ debug("End-of-stream");
59
53
  }
60
54
  else {
61
55
  throw err;
@@ -65,20 +59,27 @@ export class AIFFParser extends BasicParser {
65
59
  async readData(header) {
66
60
  var _a;
67
61
  switch (header.chunkID) {
68
- case 'COMM': // The Common Chunk
62
+ case 'COMM': { // The Common Chunk
63
+ if (this.isCompressed === null) {
64
+ throw new Error('Failed to parse AIFF.COMM chunk when compression type is unknown');
65
+ }
69
66
  const common = await this.tokenizer.readToken(new AiffToken.Common(header, this.isCompressed));
70
67
  this.metadata.setFormat('bitsPerSample', common.sampleSize);
71
68
  this.metadata.setFormat('sampleRate', common.sampleRate);
72
69
  this.metadata.setFormat('numberOfChannels', common.numChannels);
73
70
  this.metadata.setFormat('numberOfSamples', common.numSampleFrames);
74
71
  this.metadata.setFormat('duration', common.numSampleFrames / common.sampleRate);
75
- this.metadata.setFormat('codec', (_a = common.compressionName) !== null && _a !== void 0 ? _a : compressionTypes[common.compressionType]);
72
+ if (common.compressionName || common.compressionType) {
73
+ this.metadata.setFormat('codec', (_a = common.compressionName) !== null && _a !== void 0 ? _a : compressionTypes[common.compressionType]);
74
+ }
76
75
  return header.chunkSize;
77
- case 'ID3 ': // ID3-meta-data
76
+ }
77
+ case 'ID3 ': { // ID3-meta-data
78
78
  const id3_data = await this.tokenizer.readToken(new Token.Uint8ArrayType(header.chunkSize));
79
79
  const rst = strtok3.fromBuffer(id3_data);
80
80
  await new ID3v2Parser().parse(this.metadata, rst, this.options);
81
81
  return header.chunkSize;
82
+ }
82
83
  case 'SSND': // Sound Data Chunk
83
84
  if (this.metadata.format.duration) {
84
85
  this.metadata.setFormat('bitrate', 8 * header.chunkSize / this.metadata.format.duration);
@@ -96,8 +97,9 @@ export class AIFFParser extends BasicParser {
96
97
  }
97
98
  async readTextChunk(header) {
98
99
  const value = await this.tokenizer.readToken(new Token.StringType(header.chunkSize, 'ascii'));
99
- const values = value.split('\0').map(v => v.trim()).filter(v => v && v.length);
100
+ const values = value.split('\0').map(v => v.trim()).filter(v => v === null || v === void 0 ? void 0 : v.length);
100
101
  await Promise.all(values.map(v => this.metadata.addTag('AIFF', header.chunkID, v)));
101
102
  return header.chunkSize;
102
103
  }
103
104
  }
105
+ //# sourceMappingURL=AiffParser.js.map