music-metadata 7.12.2 → 7.12.5

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 (155) hide show
  1. package/LICENSE.txt +9 -9
  2. package/README.md +434 -434
  3. package/lib/ParserFactory.d.ts +48 -48
  4. package/lib/ParserFactory.js +252 -252
  5. package/lib/aiff/AiffParser.d.ts +14 -14
  6. package/lib/aiff/AiffParser.js +84 -84
  7. package/lib/aiff/AiffToken.d.ts +22 -22
  8. package/lib/aiff/AiffToken.js +43 -43
  9. package/lib/apev2/APEv2Parser.d.ts +30 -30
  10. package/lib/apev2/APEv2Parser.js +164 -164
  11. package/lib/apev2/APEv2TagMapper.d.ts +4 -4
  12. package/lib/apev2/APEv2TagMapper.js +86 -86
  13. package/lib/apev2/APEv2Token.d.ts +100 -100
  14. package/lib/apev2/APEv2Token.js +126 -126
  15. package/lib/asf/AsfObject.d.ts +319 -319
  16. package/lib/asf/AsfObject.js +381 -381
  17. package/lib/asf/AsfParser.d.ts +17 -17
  18. package/lib/asf/AsfParser.js +135 -135
  19. package/lib/asf/AsfTagMapper.d.ts +7 -7
  20. package/lib/asf/AsfTagMapper.js +95 -95
  21. package/lib/asf/AsfUtil.d.ts +13 -13
  22. package/lib/asf/AsfUtil.js +38 -38
  23. package/lib/asf/GUID.d.ts +84 -84
  24. package/lib/asf/GUID.js +121 -121
  25. package/lib/common/BasicParser.d.ts +17 -17
  26. package/lib/common/BasicParser.js +18 -18
  27. package/lib/common/CaseInsensitiveTagMap.d.ts +10 -10
  28. package/lib/common/CaseInsensitiveTagMap.js +21 -21
  29. package/lib/common/CombinedTagMapper.d.ts +19 -19
  30. package/lib/common/CombinedTagMapper.js +51 -51
  31. package/lib/common/FourCC.d.ts +6 -6
  32. package/lib/common/FourCC.js +28 -28
  33. package/lib/common/GenericTagMapper.d.ts +51 -51
  34. package/lib/common/GenericTagMapper.js +55 -55
  35. package/lib/common/GenericTagTypes.d.ts +33 -33
  36. package/lib/common/GenericTagTypes.js +131 -131
  37. package/lib/common/MetadataCollector.d.ts +76 -76
  38. package/lib/common/MetadataCollector.js +275 -275
  39. package/lib/common/RandomFileReader.d.ts +22 -22
  40. package/lib/common/RandomFileReader.js +34 -34
  41. package/lib/common/RandomUint8ArrayReader.d.ts +18 -18
  42. package/lib/common/RandomUint8ArrayReader.js +25 -25
  43. package/lib/common/Util.d.ts +57 -57
  44. package/lib/common/Util.js +157 -157
  45. package/lib/core.d.ts +48 -48
  46. package/lib/core.js +90 -90
  47. package/lib/dsdiff/DsdiffParser.d.ts +14 -14
  48. package/lib/dsdiff/DsdiffParser.js +143 -143
  49. package/lib/dsdiff/DsdiffToken.d.ts +9 -9
  50. package/lib/dsdiff/DsdiffToken.js +21 -21
  51. package/lib/dsf/DsfChunk.d.ts +86 -86
  52. package/lib/dsf/DsfChunk.js +54 -54
  53. package/lib/dsf/DsfParser.d.ts +9 -9
  54. package/lib/dsf/DsfParser.js +56 -56
  55. package/lib/flac/FlacParser.d.ts +28 -28
  56. package/lib/flac/FlacParser.js +175 -175
  57. package/lib/id3v1/ID3v1Parser.d.ts +13 -13
  58. package/lib/id3v1/ID3v1Parser.js +134 -134
  59. package/lib/id3v1/ID3v1TagMap.d.ts +4 -4
  60. package/lib/id3v1/ID3v1TagMap.js +22 -22
  61. package/lib/id3v2/AbstractID3Parser.d.ts +17 -17
  62. package/lib/id3v2/AbstractID3Parser.js +60 -60
  63. package/lib/id3v2/FrameParser.d.ts +31 -31
  64. package/lib/id3v2/FrameParser.js +329 -329
  65. package/lib/id3v2/ID3v22TagMapper.d.ts +9 -9
  66. package/lib/id3v2/ID3v22TagMapper.js +55 -55
  67. package/lib/id3v2/ID3v24TagMapper.d.ts +14 -14
  68. package/lib/id3v2/ID3v24TagMapper.js +193 -193
  69. package/lib/id3v2/ID3v2Parser.d.ts +28 -28
  70. package/lib/id3v2/ID3v2Parser.js +182 -182
  71. package/lib/id3v2/ID3v2Token.d.ts +73 -73
  72. package/lib/id3v2/ID3v2Token.js +106 -106
  73. package/lib/iff/index.d.ts +33 -33
  74. package/lib/iff/index.js +19 -19
  75. package/lib/index.d.ts +45 -45
  76. package/lib/index.js +74 -74
  77. package/lib/lyrics3/Lyrics3.d.ts +3 -3
  78. package/lib/lyrics3/Lyrics3.js +17 -17
  79. package/lib/matroska/MatroskaDtd.d.ts +8 -8
  80. package/lib/matroska/MatroskaDtd.js +279 -279
  81. package/lib/matroska/MatroskaParser.d.ts +37 -37
  82. package/lib/matroska/MatroskaParser.js +235 -235
  83. package/lib/matroska/MatroskaTagMapper.d.ts +4 -4
  84. package/lib/matroska/MatroskaTagMapper.js +35 -35
  85. package/lib/matroska/types.d.ts +175 -175
  86. package/lib/matroska/types.js +32 -32
  87. package/lib/mp4/Atom.d.ts +16 -16
  88. package/lib/mp4/Atom.js +70 -70
  89. package/lib/mp4/AtomToken.d.ts +395 -395
  90. package/lib/mp4/AtomToken.js +406 -406
  91. package/lib/mp4/MP4Parser.d.ts +30 -30
  92. package/lib/mp4/MP4Parser.js +511 -511
  93. package/lib/mp4/MP4TagMapper.d.ts +5 -5
  94. package/lib/mp4/MP4TagMapper.js +115 -115
  95. package/lib/mpeg/ExtendedLameHeader.d.ts +27 -27
  96. package/lib/mpeg/ExtendedLameHeader.js +31 -31
  97. package/lib/mpeg/MpegParser.d.ts +49 -49
  98. package/lib/mpeg/MpegParser.js +524 -524
  99. package/lib/mpeg/ReplayGainDataFormat.d.ts +55 -55
  100. package/lib/mpeg/ReplayGainDataFormat.js +69 -69
  101. package/lib/mpeg/XingTag.d.ts +45 -45
  102. package/lib/mpeg/XingTag.js +69 -69
  103. package/lib/musepack/index.d.ts +5 -5
  104. package/lib/musepack/index.js +32 -32
  105. package/lib/musepack/sv7/BitReader.d.ts +13 -13
  106. package/lib/musepack/sv7/BitReader.js +54 -54
  107. package/lib/musepack/sv7/MpcSv7Parser.d.ts +8 -8
  108. package/lib/musepack/sv7/MpcSv7Parser.js +46 -46
  109. package/lib/musepack/sv7/StreamVersion7.d.ts +28 -28
  110. package/lib/musepack/sv7/StreamVersion7.js +41 -41
  111. package/lib/musepack/sv8/MpcSv8Parser.d.ts +6 -6
  112. package/lib/musepack/sv8/MpcSv8Parser.js +55 -55
  113. package/lib/musepack/sv8/StreamVersion8.d.ts +40 -40
  114. package/lib/musepack/sv8/StreamVersion8.js +80 -80
  115. package/lib/ogg/Ogg.d.ts +72 -72
  116. package/lib/ogg/Ogg.js +2 -2
  117. package/lib/ogg/OggParser.d.ts +23 -23
  118. package/lib/ogg/OggParser.js +126 -126
  119. package/lib/ogg/opus/Opus.d.ts +48 -48
  120. package/lib/ogg/opus/Opus.js +28 -28
  121. package/lib/ogg/opus/OpusParser.d.ts +25 -25
  122. package/lib/ogg/opus/OpusParser.js +56 -56
  123. package/lib/ogg/speex/Speex.d.ts +36 -36
  124. package/lib/ogg/speex/Speex.js +31 -31
  125. package/lib/ogg/speex/SpeexParser.d.ts +22 -22
  126. package/lib/ogg/speex/SpeexParser.js +35 -35
  127. package/lib/ogg/theora/Theora.d.ts +20 -20
  128. package/lib/ogg/theora/Theora.js +23 -23
  129. package/lib/ogg/theora/TheoraParser.d.ts +28 -28
  130. package/lib/ogg/theora/TheoraParser.js +44 -44
  131. package/lib/ogg/vorbis/Vorbis.d.ts +69 -69
  132. package/lib/ogg/vorbis/Vorbis.js +78 -78
  133. package/lib/ogg/vorbis/VorbisDecoder.d.ts +12 -12
  134. package/lib/ogg/vorbis/VorbisDecoder.js +32 -32
  135. package/lib/ogg/vorbis/VorbisParser.d.ts +36 -36
  136. package/lib/ogg/vorbis/VorbisParser.js +128 -128
  137. package/lib/ogg/vorbis/VorbisTagMapper.d.ts +7 -7
  138. package/lib/ogg/vorbis/VorbisTagMapper.js +132 -132
  139. package/lib/riff/RiffChunk.d.ts +16 -16
  140. package/lib/riff/RiffChunk.js +32 -32
  141. package/lib/riff/RiffInfoTagMap.d.ts +10 -10
  142. package/lib/riff/RiffInfoTagMap.js +37 -37
  143. package/lib/type.d.ts +592 -592
  144. package/lib/type.js +5 -5
  145. package/lib/wav/BwfChunk.d.ts +17 -17
  146. package/lib/wav/BwfChunk.js +29 -28
  147. package/lib/wav/WaveChunk.d.ts +64 -64
  148. package/lib/wav/WaveChunk.js +65 -65
  149. package/lib/wav/WaveParser.d.ts +24 -24
  150. package/lib/wav/WaveParser.js +158 -156
  151. package/lib/wavpack/WavPackParser.d.ts +14 -14
  152. package/lib/wavpack/WavPackParser.js +99 -99
  153. package/lib/wavpack/WavPackToken.d.ts +64 -64
  154. package/lib/wavpack/WavPackToken.js +76 -76
  155. package/package.json +152 -150
@@ -1,156 +1,158 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WaveParser = void 0;
4
- const strtok3 = require("strtok3/lib/core");
5
- const Token = require("token-types");
6
- const debug_1 = require("debug");
7
- const riff = require("../riff/RiffChunk");
8
- const WaveChunk = require("./../wav/WaveChunk");
9
- const ID3v2Parser_1 = require("../id3v2/ID3v2Parser");
10
- const util = require("../common/Util");
11
- const FourCC_1 = require("../common/FourCC");
12
- const BasicParser_1 = require("../common/BasicParser");
13
- const BwfChunk_1 = require("../wav/BwfChunk");
14
- const debug = (0, debug_1.default)('music-metadata:parser:RIFF');
15
- /**
16
- * Resource Interchange File Format (RIFF) Parser
17
- *
18
- * WAVE PCM soundfile format
19
- *
20
- * Ref:
21
- * - http://www.johnloomis.org/cpe102/asgn/asgn1/riff.html
22
- * - http://soundfile.sapp.org/doc/WaveFormat
23
- *
24
- * ToDo: Split WAVE part from RIFF parser
25
- */
26
- class WaveParser extends BasicParser_1.BasicParser {
27
- async parse() {
28
- const riffHeader = await this.tokenizer.readToken(riff.Header);
29
- debug(`pos=${this.tokenizer.position}, parse: chunkID=${riffHeader.chunkID}`);
30
- if (riffHeader.chunkID !== 'RIFF')
31
- return; // Not RIFF format
32
- return this.parseRiffChunk(riffHeader.chunkSize).catch(err => {
33
- if (!(err instanceof strtok3.EndOfStreamError)) {
34
- throw err;
35
- }
36
- });
37
- }
38
- async parseRiffChunk(chunkSize) {
39
- const type = await this.tokenizer.readToken(FourCC_1.FourCcToken);
40
- this.metadata.setFormat('container', type);
41
- switch (type) {
42
- case 'WAVE':
43
- return this.readWaveChunk(chunkSize - FourCC_1.FourCcToken.len);
44
- default:
45
- throw new Error(`Unsupported RIFF format: RIFF/${type}`);
46
- }
47
- }
48
- async readWaveChunk(remaining) {
49
- while (remaining >= riff.Header.len) {
50
- const header = await this.tokenizer.readToken(riff.Header);
51
- remaining -= riff.Header.len + header.chunkSize;
52
- if (header.chunkSize > remaining) {
53
- this.metadata.addWarning('Data chunk size exceeds file size');
54
- }
55
- this.header = header;
56
- debug(`pos=${this.tokenizer.position}, readChunk: chunkID=RIFF/WAVE/${header.chunkID}`);
57
- switch (header.chunkID) {
58
- case 'LIST':
59
- await this.parseListTag(header);
60
- break;
61
- case 'fact': // extended Format chunk,
62
- this.metadata.setFormat('lossless', false);
63
- this.fact = await this.tokenizer.readToken(new WaveChunk.FactChunk(header));
64
- break;
65
- case 'fmt ': // The Util Chunk, non-PCM Formats
66
- const fmt = await this.tokenizer.readToken(new WaveChunk.Format(header));
67
- let subFormat = WaveChunk.WaveFormat[fmt.wFormatTag];
68
- if (!subFormat) {
69
- debug('WAVE/non-PCM format=' + fmt.wFormatTag);
70
- subFormat = 'non-PCM (' + fmt.wFormatTag + ')';
71
- }
72
- this.metadata.setFormat('codec', subFormat);
73
- this.metadata.setFormat('bitsPerSample', fmt.wBitsPerSample);
74
- this.metadata.setFormat('sampleRate', fmt.nSamplesPerSec);
75
- this.metadata.setFormat('numberOfChannels', fmt.nChannels);
76
- this.metadata.setFormat('bitrate', fmt.nBlockAlign * fmt.nSamplesPerSec * 8);
77
- this.blockAlign = fmt.nBlockAlign;
78
- break;
79
- case 'id3 ': // The way Picard, FooBar currently stores, ID3 meta-data
80
- case 'ID3 ': // The way Mp3Tags stores ID3 meta-data
81
- const id3_data = await this.tokenizer.readToken(new Token.Uint8ArrayType(header.chunkSize));
82
- const rst = strtok3.fromBuffer(id3_data);
83
- await new ID3v2Parser_1.ID3v2Parser().parse(this.metadata, rst, this.options);
84
- break;
85
- case 'data': // PCM-data
86
- if (this.metadata.format.lossless !== false) {
87
- this.metadata.setFormat('lossless', true);
88
- }
89
- let chunkSize = header.chunkSize;
90
- if (this.tokenizer.fileInfo.size) {
91
- const calcRemaining = this.tokenizer.fileInfo.size - this.tokenizer.position;
92
- if (calcRemaining < chunkSize) {
93
- this.metadata.addWarning('data chunk length exceeding file length');
94
- chunkSize = calcRemaining;
95
- }
96
- }
97
- const numberOfSamples = this.fact ? this.fact.dwSampleLength : (chunkSize === 0xffffffff ? undefined : chunkSize / this.blockAlign);
98
- if (numberOfSamples) {
99
- this.metadata.setFormat('numberOfSamples', numberOfSamples);
100
- this.metadata.setFormat('duration', numberOfSamples / this.metadata.format.sampleRate);
101
- }
102
- this.metadata.setFormat('bitrate', this.metadata.format.numberOfChannels * this.blockAlign * this.metadata.format.sampleRate); // ToDo: check me
103
- await this.tokenizer.ignore(header.chunkSize);
104
- break;
105
- case 'bext': // Broadcast Audio Extension chunk https://tech.ebu.ch/docs/tech/tech3285.pdf
106
- const bext = await this.tokenizer.readToken(BwfChunk_1.BroadcastAudioExtensionChunk);
107
- Object.keys(bext).forEach(key => {
108
- this.metadata.addTag('exif', 'bext.' + key, bext[key]);
109
- });
110
- break;
111
- case '\x00\x00\x00\x00': // padding ??
112
- debug(`Ignore padding chunk: RIFF/${header.chunkID} of ${header.chunkSize} bytes`);
113
- this.metadata.addWarning('Ignore chunk: RIFF/' + header.chunkID);
114
- await this.tokenizer.ignore(header.chunkSize);
115
- break;
116
- default:
117
- debug(`Ignore chunk: RIFF/${header.chunkID} of ${header.chunkSize} bytes`);
118
- this.metadata.addWarning('Ignore chunk: RIFF/' + header.chunkID);
119
- await this.tokenizer.ignore(header.chunkSize);
120
- }
121
- if (this.header.chunkSize % 2 === 1) {
122
- debug('Read odd padding byte'); // https://wiki.multimedia.cx/index.php/RIFF
123
- await this.tokenizer.ignore(1);
124
- }
125
- }
126
- }
127
- async parseListTag(listHeader) {
128
- const listType = await this.tokenizer.readToken(new Token.StringType(4, 'binary'));
129
- debug('pos=%s, parseListTag: chunkID=RIFF/WAVE/LIST/%s', this.tokenizer.position, listType);
130
- switch (listType) {
131
- case 'INFO':
132
- return this.parseRiffInfoTags(listHeader.chunkSize - 4);
133
- case 'adtl':
134
- default:
135
- this.metadata.addWarning('Ignore chunk: RIFF/WAVE/LIST/' + listType);
136
- debug('Ignoring chunkID=RIFF/WAVE/LIST/' + listType);
137
- return this.tokenizer.ignore(listHeader.chunkSize - 4).then();
138
- }
139
- }
140
- async parseRiffInfoTags(chunkSize) {
141
- while (chunkSize >= 8) {
142
- const header = await this.tokenizer.readToken(riff.Header);
143
- const valueToken = new riff.ListInfoTagValue(header);
144
- const value = await this.tokenizer.readToken(valueToken);
145
- this.addTag(header.chunkID, util.stripNulls(value));
146
- chunkSize -= (8 + valueToken.len);
147
- }
148
- if (chunkSize !== 0) {
149
- throw Error('Illegal remaining size: ' + chunkSize);
150
- }
151
- }
152
- addTag(id, value) {
153
- this.metadata.addTag('exif', id, value);
154
- }
155
- }
156
- exports.WaveParser = WaveParser;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WaveParser = void 0;
4
+ const strtok3 = require("strtok3/lib/core");
5
+ const Token = require("token-types");
6
+ const debug_1 = require("debug");
7
+ const riff = require("../riff/RiffChunk");
8
+ const WaveChunk = require("./../wav/WaveChunk");
9
+ const ID3v2Parser_1 = require("../id3v2/ID3v2Parser");
10
+ const util = require("../common/Util");
11
+ const FourCC_1 = require("../common/FourCC");
12
+ const BasicParser_1 = require("../common/BasicParser");
13
+ const BwfChunk_1 = require("../wav/BwfChunk");
14
+ const debug = (0, debug_1.default)('music-metadata:parser:RIFF');
15
+ /**
16
+ * Resource Interchange File Format (RIFF) Parser
17
+ *
18
+ * WAVE PCM soundfile format
19
+ *
20
+ * Ref:
21
+ * - http://www.johnloomis.org/cpe102/asgn/asgn1/riff.html
22
+ * - http://soundfile.sapp.org/doc/WaveFormat
23
+ *
24
+ * ToDo: Split WAVE part from RIFF parser
25
+ */
26
+ class WaveParser extends BasicParser_1.BasicParser {
27
+ async parse() {
28
+ const riffHeader = await this.tokenizer.readToken(riff.Header);
29
+ debug(`pos=${this.tokenizer.position}, parse: chunkID=${riffHeader.chunkID}`);
30
+ if (riffHeader.chunkID !== 'RIFF')
31
+ return; // Not RIFF format
32
+ return this.parseRiffChunk(riffHeader.chunkSize).catch(err => {
33
+ if (!(err instanceof strtok3.EndOfStreamError)) {
34
+ throw err;
35
+ }
36
+ });
37
+ }
38
+ async parseRiffChunk(chunkSize) {
39
+ const type = await this.tokenizer.readToken(FourCC_1.FourCcToken);
40
+ this.metadata.setFormat('container', type);
41
+ switch (type) {
42
+ case 'WAVE':
43
+ return this.readWaveChunk(chunkSize - FourCC_1.FourCcToken.len);
44
+ default:
45
+ throw new Error(`Unsupported RIFF format: RIFF/${type}`);
46
+ }
47
+ }
48
+ async readWaveChunk(remaining) {
49
+ while (remaining >= riff.Header.len) {
50
+ const header = await this.tokenizer.readToken(riff.Header);
51
+ remaining -= riff.Header.len + header.chunkSize;
52
+ if (header.chunkSize > remaining) {
53
+ this.metadata.addWarning('Data chunk size exceeds file size');
54
+ }
55
+ this.header = header;
56
+ debug(`pos=${this.tokenizer.position}, readChunk: chunkID=RIFF/WAVE/${header.chunkID}`);
57
+ switch (header.chunkID) {
58
+ case 'LIST':
59
+ await this.parseListTag(header);
60
+ break;
61
+ case 'fact': // extended Format chunk,
62
+ this.metadata.setFormat('lossless', false);
63
+ this.fact = await this.tokenizer.readToken(new WaveChunk.FactChunk(header));
64
+ break;
65
+ case 'fmt ': // The Util Chunk, non-PCM Formats
66
+ const fmt = await this.tokenizer.readToken(new WaveChunk.Format(header));
67
+ let subFormat = WaveChunk.WaveFormat[fmt.wFormatTag];
68
+ if (!subFormat) {
69
+ debug('WAVE/non-PCM format=' + fmt.wFormatTag);
70
+ subFormat = 'non-PCM (' + fmt.wFormatTag + ')';
71
+ }
72
+ this.metadata.setFormat('codec', subFormat);
73
+ this.metadata.setFormat('bitsPerSample', fmt.wBitsPerSample);
74
+ this.metadata.setFormat('sampleRate', fmt.nSamplesPerSec);
75
+ this.metadata.setFormat('numberOfChannels', fmt.nChannels);
76
+ this.metadata.setFormat('bitrate', fmt.nBlockAlign * fmt.nSamplesPerSec * 8);
77
+ this.blockAlign = fmt.nBlockAlign;
78
+ break;
79
+ case 'id3 ': // The way Picard, FooBar currently stores, ID3 meta-data
80
+ case 'ID3 ': // The way Mp3Tags stores ID3 meta-data
81
+ const id3_data = await this.tokenizer.readToken(new Token.Uint8ArrayType(header.chunkSize));
82
+ const rst = strtok3.fromBuffer(id3_data);
83
+ await new ID3v2Parser_1.ID3v2Parser().parse(this.metadata, rst, this.options);
84
+ break;
85
+ case 'data': // PCM-data
86
+ if (this.metadata.format.lossless !== false) {
87
+ this.metadata.setFormat('lossless', true);
88
+ }
89
+ let chunkSize = header.chunkSize;
90
+ if (this.tokenizer.fileInfo.size) {
91
+ const calcRemaining = this.tokenizer.fileInfo.size - this.tokenizer.position;
92
+ if (calcRemaining < chunkSize) {
93
+ this.metadata.addWarning('data chunk length exceeding file length');
94
+ chunkSize = calcRemaining;
95
+ }
96
+ }
97
+ const numberOfSamples = this.fact ? this.fact.dwSampleLength : (chunkSize === 0xffffffff ? undefined : chunkSize / this.blockAlign);
98
+ if (numberOfSamples) {
99
+ this.metadata.setFormat('numberOfSamples', numberOfSamples);
100
+ this.metadata.setFormat('duration', numberOfSamples / this.metadata.format.sampleRate);
101
+ }
102
+ this.metadata.setFormat('bitrate', this.metadata.format.numberOfChannels * this.blockAlign * this.metadata.format.sampleRate); // ToDo: check me
103
+ await this.tokenizer.ignore(header.chunkSize);
104
+ break;
105
+ case 'bext': // Broadcast Audio Extension chunk https://tech.ebu.ch/docs/tech/tech3285.pdf
106
+ const bext = await this.tokenizer.readToken(BwfChunk_1.BroadcastAudioExtensionChunk);
107
+ Object.keys(bext).forEach(key => {
108
+ this.metadata.addTag('exif', 'bext.' + key, bext[key]);
109
+ });
110
+ const bextRemaining = header.chunkSize - BwfChunk_1.BroadcastAudioExtensionChunk.len;
111
+ await this.tokenizer.ignore(bextRemaining);
112
+ break;
113
+ case '\x00\x00\x00\x00': // padding ??
114
+ debug(`Ignore padding chunk: RIFF/${header.chunkID} of ${header.chunkSize} bytes`);
115
+ this.metadata.addWarning('Ignore chunk: RIFF/' + header.chunkID);
116
+ await this.tokenizer.ignore(header.chunkSize);
117
+ break;
118
+ default:
119
+ debug(`Ignore chunk: RIFF/${header.chunkID} of ${header.chunkSize} bytes`);
120
+ this.metadata.addWarning('Ignore chunk: RIFF/' + header.chunkID);
121
+ await this.tokenizer.ignore(header.chunkSize);
122
+ }
123
+ if (this.header.chunkSize % 2 === 1) {
124
+ debug('Read odd padding byte'); // https://wiki.multimedia.cx/index.php/RIFF
125
+ await this.tokenizer.ignore(1);
126
+ }
127
+ }
128
+ }
129
+ async parseListTag(listHeader) {
130
+ const listType = await this.tokenizer.readToken(new Token.StringType(4, 'binary'));
131
+ debug('pos=%s, parseListTag: chunkID=RIFF/WAVE/LIST/%s', this.tokenizer.position, listType);
132
+ switch (listType) {
133
+ case 'INFO':
134
+ return this.parseRiffInfoTags(listHeader.chunkSize - 4);
135
+ case 'adtl':
136
+ default:
137
+ this.metadata.addWarning('Ignore chunk: RIFF/WAVE/LIST/' + listType);
138
+ debug('Ignoring chunkID=RIFF/WAVE/LIST/' + listType);
139
+ return this.tokenizer.ignore(listHeader.chunkSize - 4).then();
140
+ }
141
+ }
142
+ async parseRiffInfoTags(chunkSize) {
143
+ while (chunkSize >= 8) {
144
+ const header = await this.tokenizer.readToken(riff.Header);
145
+ const valueToken = new riff.ListInfoTagValue(header);
146
+ const value = await this.tokenizer.readToken(valueToken);
147
+ this.addTag(header.chunkID, util.stripNulls(value));
148
+ chunkSize -= (8 + valueToken.len);
149
+ }
150
+ if (chunkSize !== 0) {
151
+ throw Error('Illegal remaining size: ' + chunkSize);
152
+ }
153
+ }
154
+ addTag(id, value) {
155
+ this.metadata.addTag('exif', id, value);
156
+ }
157
+ }
158
+ exports.WaveParser = WaveParser;
@@ -1,14 +1,14 @@
1
- import { BasicParser } from '../common/BasicParser';
2
- /**
3
- * WavPack Parser
4
- */
5
- export declare class WavPackParser extends BasicParser {
6
- private audioDataSize;
7
- parse(): Promise<void>;
8
- parseWavPackBlocks(): Promise<void>;
9
- /**
10
- * Ref: http://www.wavpack.com/WavPack5FileFormat.pdf, 3.0 Metadata Sub-blocks
11
- * @param remainingLength
12
- */
13
- private parseMetadataSubBlock;
14
- }
1
+ import { BasicParser } from '../common/BasicParser';
2
+ /**
3
+ * WavPack Parser
4
+ */
5
+ export declare class WavPackParser extends BasicParser {
6
+ private audioDataSize;
7
+ parse(): Promise<void>;
8
+ parseWavPackBlocks(): Promise<void>;
9
+ /**
10
+ * Ref: http://www.wavpack.com/WavPack5FileFormat.pdf, 3.0 Metadata Sub-blocks
11
+ * @param remainingLength
12
+ */
13
+ private parseMetadataSubBlock;
14
+ }
@@ -1,99 +1,99 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WavPackParser = void 0;
4
- const Token = require("token-types");
5
- const APEv2Parser_1 = require("../apev2/APEv2Parser");
6
- const FourCC_1 = require("../common/FourCC");
7
- const BasicParser_1 = require("../common/BasicParser");
8
- const WavPackToken_1 = require("./WavPackToken");
9
- const debug_1 = require("debug");
10
- const debug = (0, debug_1.default)('music-metadata:parser:WavPack');
11
- /**
12
- * WavPack Parser
13
- */
14
- class WavPackParser extends BasicParser_1.BasicParser {
15
- async parse() {
16
- this.audioDataSize = 0;
17
- // First parse all WavPack blocks
18
- await this.parseWavPackBlocks();
19
- // try to parse APEv2 header
20
- return APEv2Parser_1.APEv2Parser.tryParseApeHeader(this.metadata, this.tokenizer, this.options);
21
- }
22
- async parseWavPackBlocks() {
23
- do {
24
- const blockId = await this.tokenizer.peekToken(FourCC_1.FourCcToken);
25
- if (blockId !== 'wvpk')
26
- break;
27
- const header = await this.tokenizer.readToken(WavPackToken_1.WavPack.BlockHeaderToken);
28
- if (header.BlockID !== 'wvpk')
29
- throw new Error('Invalid WavPack Block-ID');
30
- debug(`WavPack header blockIndex=${header.blockIndex}, len=${WavPackToken_1.WavPack.BlockHeaderToken.len}`);
31
- if (header.blockIndex === 0 && !this.metadata.format.container) {
32
- this.metadata.setFormat('container', 'WavPack');
33
- this.metadata.setFormat('lossless', !header.flags.isHybrid);
34
- // tagTypes: this.type,
35
- this.metadata.setFormat('bitsPerSample', header.flags.bitsPerSample);
36
- if (!header.flags.isDSD) {
37
- // In case isDSD, these values will ne set in ID_DSD_BLOCK
38
- this.metadata.setFormat('sampleRate', header.flags.samplingRate);
39
- this.metadata.setFormat('duration', header.totalSamples / header.flags.samplingRate);
40
- }
41
- this.metadata.setFormat('numberOfChannels', header.flags.isMono ? 1 : 2);
42
- this.metadata.setFormat('numberOfSamples', header.totalSamples);
43
- this.metadata.setFormat('codec', header.flags.isDSD ? 'DSD' : 'PCM');
44
- }
45
- const ignoreBytes = header.blockSize - (WavPackToken_1.WavPack.BlockHeaderToken.len - 8);
46
- await (header.blockIndex === 0 ? this.parseMetadataSubBlock(header, ignoreBytes) : this.tokenizer.ignore(ignoreBytes));
47
- if (header.blockSamples > 0) {
48
- this.audioDataSize += header.blockSize; // Count audio data for bit-rate calculation
49
- }
50
- } while (!this.tokenizer.fileInfo.size || this.tokenizer.fileInfo.size - this.tokenizer.position >= WavPackToken_1.WavPack.BlockHeaderToken.len);
51
- this.metadata.setFormat('bitrate', this.audioDataSize * 8 / this.metadata.format.duration);
52
- }
53
- /**
54
- * Ref: http://www.wavpack.com/WavPack5FileFormat.pdf, 3.0 Metadata Sub-blocks
55
- * @param remainingLength
56
- */
57
- async parseMetadataSubBlock(header, remainingLength) {
58
- while (remainingLength > WavPackToken_1.WavPack.MetadataIdToken.len) {
59
- const id = await this.tokenizer.readToken(WavPackToken_1.WavPack.MetadataIdToken);
60
- const dataSizeInWords = await this.tokenizer.readNumber(id.largeBlock ? Token.UINT24_LE : Token.UINT8);
61
- const data = Buffer.alloc(dataSizeInWords * 2 - (id.isOddSize ? 1 : 0));
62
- await this.tokenizer.readBuffer(data);
63
- debug(`Metadata Sub-Blocks functionId=0x${id.functionId.toString(16)}, id.largeBlock=${id.largeBlock},data-size=${data.length}`);
64
- switch (id.functionId) {
65
- case 0x0: // ID_DUMMY: could be used to pad WavPack blocks
66
- break;
67
- case 0xe: // ID_DSD_BLOCK
68
- debug('ID_DSD_BLOCK');
69
- // https://github.com/dbry/WavPack/issues/71#issuecomment-483094813
70
- const mp = 1 << data.readUInt8(0);
71
- const samplingRate = header.flags.samplingRate * mp * 8; // ToDo: second factor should be read from DSD-metadata block https://github.com/dbry/WavPack/issues/71#issuecomment-483094813
72
- if (!header.flags.isDSD)
73
- throw new Error('Only expect DSD block if DSD-flag is set');
74
- this.metadata.setFormat('sampleRate', samplingRate);
75
- this.metadata.setFormat('duration', header.totalSamples / samplingRate);
76
- break;
77
- case 0x24: // ID_ALT_TRAILER: maybe used to embed original ID3 tag header
78
- debug('ID_ALT_TRAILER: trailer for non-wav files');
79
- break;
80
- case 0x26: // ID_MD5_CHECKSUM
81
- this.metadata.setFormat('audioMD5', data);
82
- break;
83
- case 0x2f: // ID_BLOCK_CHECKSUM
84
- debug(`ID_BLOCK_CHECKSUM: checksum=${data.toString('hex')}`);
85
- break;
86
- default:
87
- debug(`Ignore unsupported meta-sub-block-id functionId=0x${id.functionId.toString(16)}`);
88
- break;
89
- }
90
- remainingLength -= WavPackToken_1.WavPack.MetadataIdToken.len + (id.largeBlock ? Token.UINT24_LE.len : Token.UINT8.len) + dataSizeInWords * 2;
91
- debug(`remainingLength=${remainingLength}`);
92
- if (id.isOddSize)
93
- this.tokenizer.ignore(1);
94
- }
95
- if (remainingLength !== 0)
96
- throw new Error('metadata-sub-block should fit it remaining length');
97
- }
98
- }
99
- exports.WavPackParser = WavPackParser;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WavPackParser = void 0;
4
+ const Token = require("token-types");
5
+ const APEv2Parser_1 = require("../apev2/APEv2Parser");
6
+ const FourCC_1 = require("../common/FourCC");
7
+ const BasicParser_1 = require("../common/BasicParser");
8
+ const WavPackToken_1 = require("./WavPackToken");
9
+ const debug_1 = require("debug");
10
+ const debug = (0, debug_1.default)('music-metadata:parser:WavPack');
11
+ /**
12
+ * WavPack Parser
13
+ */
14
+ class WavPackParser extends BasicParser_1.BasicParser {
15
+ async parse() {
16
+ this.audioDataSize = 0;
17
+ // First parse all WavPack blocks
18
+ await this.parseWavPackBlocks();
19
+ // try to parse APEv2 header
20
+ return APEv2Parser_1.APEv2Parser.tryParseApeHeader(this.metadata, this.tokenizer, this.options);
21
+ }
22
+ async parseWavPackBlocks() {
23
+ do {
24
+ const blockId = await this.tokenizer.peekToken(FourCC_1.FourCcToken);
25
+ if (blockId !== 'wvpk')
26
+ break;
27
+ const header = await this.tokenizer.readToken(WavPackToken_1.WavPack.BlockHeaderToken);
28
+ if (header.BlockID !== 'wvpk')
29
+ throw new Error('Invalid WavPack Block-ID');
30
+ debug(`WavPack header blockIndex=${header.blockIndex}, len=${WavPackToken_1.WavPack.BlockHeaderToken.len}`);
31
+ if (header.blockIndex === 0 && !this.metadata.format.container) {
32
+ this.metadata.setFormat('container', 'WavPack');
33
+ this.metadata.setFormat('lossless', !header.flags.isHybrid);
34
+ // tagTypes: this.type,
35
+ this.metadata.setFormat('bitsPerSample', header.flags.bitsPerSample);
36
+ if (!header.flags.isDSD) {
37
+ // In case isDSD, these values will ne set in ID_DSD_BLOCK
38
+ this.metadata.setFormat('sampleRate', header.flags.samplingRate);
39
+ this.metadata.setFormat('duration', header.totalSamples / header.flags.samplingRate);
40
+ }
41
+ this.metadata.setFormat('numberOfChannels', header.flags.isMono ? 1 : 2);
42
+ this.metadata.setFormat('numberOfSamples', header.totalSamples);
43
+ this.metadata.setFormat('codec', header.flags.isDSD ? 'DSD' : 'PCM');
44
+ }
45
+ const ignoreBytes = header.blockSize - (WavPackToken_1.WavPack.BlockHeaderToken.len - 8);
46
+ await (header.blockIndex === 0 ? this.parseMetadataSubBlock(header, ignoreBytes) : this.tokenizer.ignore(ignoreBytes));
47
+ if (header.blockSamples > 0) {
48
+ this.audioDataSize += header.blockSize; // Count audio data for bit-rate calculation
49
+ }
50
+ } while (!this.tokenizer.fileInfo.size || this.tokenizer.fileInfo.size - this.tokenizer.position >= WavPackToken_1.WavPack.BlockHeaderToken.len);
51
+ this.metadata.setFormat('bitrate', this.audioDataSize * 8 / this.metadata.format.duration);
52
+ }
53
+ /**
54
+ * Ref: http://www.wavpack.com/WavPack5FileFormat.pdf, 3.0 Metadata Sub-blocks
55
+ * @param remainingLength
56
+ */
57
+ async parseMetadataSubBlock(header, remainingLength) {
58
+ while (remainingLength > WavPackToken_1.WavPack.MetadataIdToken.len) {
59
+ const id = await this.tokenizer.readToken(WavPackToken_1.WavPack.MetadataIdToken);
60
+ const dataSizeInWords = await this.tokenizer.readNumber(id.largeBlock ? Token.UINT24_LE : Token.UINT8);
61
+ const data = Buffer.alloc(dataSizeInWords * 2 - (id.isOddSize ? 1 : 0));
62
+ await this.tokenizer.readBuffer(data);
63
+ debug(`Metadata Sub-Blocks functionId=0x${id.functionId.toString(16)}, id.largeBlock=${id.largeBlock},data-size=${data.length}`);
64
+ switch (id.functionId) {
65
+ case 0x0: // ID_DUMMY: could be used to pad WavPack blocks
66
+ break;
67
+ case 0xe: // ID_DSD_BLOCK
68
+ debug('ID_DSD_BLOCK');
69
+ // https://github.com/dbry/WavPack/issues/71#issuecomment-483094813
70
+ const mp = 1 << data.readUInt8(0);
71
+ const samplingRate = header.flags.samplingRate * mp * 8; // ToDo: second factor should be read from DSD-metadata block https://github.com/dbry/WavPack/issues/71#issuecomment-483094813
72
+ if (!header.flags.isDSD)
73
+ throw new Error('Only expect DSD block if DSD-flag is set');
74
+ this.metadata.setFormat('sampleRate', samplingRate);
75
+ this.metadata.setFormat('duration', header.totalSamples / samplingRate);
76
+ break;
77
+ case 0x24: // ID_ALT_TRAILER: maybe used to embed original ID3 tag header
78
+ debug('ID_ALT_TRAILER: trailer for non-wav files');
79
+ break;
80
+ case 0x26: // ID_MD5_CHECKSUM
81
+ this.metadata.setFormat('audioMD5', data);
82
+ break;
83
+ case 0x2f: // ID_BLOCK_CHECKSUM
84
+ debug(`ID_BLOCK_CHECKSUM: checksum=${data.toString('hex')}`);
85
+ break;
86
+ default:
87
+ debug(`Ignore unsupported meta-sub-block-id functionId=0x${id.functionId.toString(16)}`);
88
+ break;
89
+ }
90
+ remainingLength -= WavPackToken_1.WavPack.MetadataIdToken.len + (id.largeBlock ? Token.UINT24_LE.len : Token.UINT8.len) + dataSizeInWords * 2;
91
+ debug(`remainingLength=${remainingLength}`);
92
+ if (id.isOddSize)
93
+ this.tokenizer.ignore(1);
94
+ }
95
+ if (remainingLength !== 0)
96
+ throw new Error('metadata-sub-block should fit it remaining length');
97
+ }
98
+ }
99
+ exports.WavPackParser = WavPackParser;