Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
public parse(tokenizer: strtok3.ITokenizer, options: IOptions): Promise {
this.tokenizer = tokenizer;
this.vorbisParser = new VorbisParser();
this.vorbisStream = new VorbisStream();
return strtok3.fromStream(this.vorbisStream).then((vorbisTokenizer) => {
// ToDo: should be provided with level-2 tokenizer
const vorbis = this.vorbisParser.parse(vorbisTokenizer, options).then((metadata) => {
if (metadata.format.sampleRate) {
// Calculate duration
metadata.format.duration = this.header.absoluteGranulePosition / metadata.format.sampleRate;
}
return metadata;
});
const ogg = this.parsePage().catch((err) => {
if (err === StreamReader.EndOfStream) {
// console.log("EndOfStream: ogg");
this.vorbisStream.append(null);
} else throw err;
debug('WAVE/non-PCM format=' + fmt.wFormatTag);
subFormat = 'non-PCM (' + fmt.wFormatTag + ')';
}
this.metadata.setFormat('codec', subFormat);
this.metadata.setFormat('bitsPerSample', fmt.wBitsPerSample);
this.metadata.setFormat('sampleRate', fmt.nSamplesPerSec);
this.metadata.setFormat('numberOfChannels', fmt.nChannels);
this.metadata.setFormat('bitrate', fmt.nBlockAlign * fmt.nSamplesPerSec * 8);
this.blockAlign = fmt.nBlockAlign;
break;
case 'id3 ': // The way Picard, FooBar currently stores, ID3 meta-data
case 'ID3 ': // The way Mp3Tags stores ID3 meta-data
const id3_data = await this.tokenizer.readToken(new Token.BufferType(header.chunkSize));
const id3stream = new ID3Stream(id3_data);
const rst = strtok3.fromStream(id3stream);
await new ID3v2Parser().parse(this.metadata, rst, this.options);
break;
case 'data': // PCM-data
if (this.metadata.format.lossless !== false) {
this.metadata.setFormat('lossless', true);
}
const numberOfSamples = this.fact ? this.fact.dwSampleLength : (header.chunkSize / this.blockAlign);
this.metadata.setFormat('numberOfSamples', numberOfSamples);
this.metadata.setFormat('duration', numberOfSamples / this.metadata.format.sampleRate);
this.metadata.setFormat('bitrate', this.metadata.format.numberOfChannels * this.blockAlign * this.metadata.format.sampleRate); // ToDo: check me
await this.tokenizer.ignore(header.chunkSize);
break;
default:
switch (header.chunkID) {
case 'COMM': // The Common Chunk
const common = await this.tokenizer.readToken(new AiffToken.Common(header, this.isCompressed));
this.metadata.setFormat('bitsPerSample', common.sampleSize);
this.metadata.setFormat('sampleRate', common.sampleRate);
this.metadata.setFormat('numberOfChannels', common.numChannels);
this.metadata.setFormat('numberOfSamples', common.numSampleFrames);
this.metadata.setFormat('duration', common.numSampleFrames / common.sampleRate);
this.metadata.setFormat('codec', common.compressionName);
return header.chunkSize;
case 'ID3 ': // ID3-meta-data
const id3_data = await this.tokenizer.readToken(new Token.BufferType(header.chunkSize));
const id3stream = new ID3Stream(id3_data);
const rst = strtok3.fromStream(id3stream);
await new ID3v2Parser().parse(this.metadata, rst, this.options);
return header.chunkSize;
case 'SSND': // Sound Data Chunk
if (this.metadata.format.duration) {
this.metadata.setFormat('bitrate', 8 * header.chunkSize / this.metadata.format.duration);
}
return 0;
default:
return 0;
}
}
case 'FVER': // 3.1 FORMAT VERSION CHUNK
const version = await this.tokenizer.readToken(Token.UINT32_LE);
debug(`DSDIFF version=${version}`);
break;
case 'PROP': // 3.2 PROPERTY CHUNK
const propType = await this.tokenizer.readToken(FourCcToken);
assert.strictEqual(propType, 'SND ');
await this.handleSoundPropertyChunks(header.chunkSize - FourCcToken.len);
break;
case 'ID3': // Unofficial ID3 tag support
const id3_data = await this.tokenizer.readToken(new Token.BufferType(header.chunkSize));
const id3stream = new ID3Stream(id3_data);
const rst = strtok3.fromStream(id3stream);
await new ID3v2Parser().parse(this.metadata, rst, this.options);
break;
default:
debug(`Ignore chunk[ID=${header.chunkID}, size=${header.chunkSize}]`);
break;
case 'DSD':
this.metadata.setFormat('numberOfSamples', header.chunkSize * 8 / this.metadata.format.numberOfChannels);
this.metadata.setFormat('duration', this.metadata.format.numberOfSamples / this.metadata.format.sampleRate);
break;
}
const remaining = header.chunkSize - (this.tokenizer.position - p0);
if (remaining > 0) {
debug(`After Parsing chunk, remaining ${remaining} bytes`);
private async sync(): Promise {
let gotFirstSync = false;
while (true) {
let bo = 0;
this.syncPeek.len = await this.tokenizer.peekBuffer(this.syncPeek.buf, 0, maxPeekLen, this.tokenizer.position, true);
if (this.syncPeek.len <= 256) {
throw new EndOfStreamError();
}
while (true) {
if (gotFirstSync && (this.syncPeek.buf[bo] & 0xE0) === 0xE0) {
this.buf_frame_header[0] = MpegFrameHeader.SyncByte1;
this.buf_frame_header[1] = this.syncPeek.buf[bo];
await this.tokenizer.ignore(bo);
debug(`Sync at offset=${this.tokenizer.position - 1}, frameCount=${this.frameCount}`);
if (this.syncFrameCount === this.frameCount) {
debug(`Re-synced MPEG stream, frameCount=${this.frameCount}`);
this.frameCount = 0;
this.frame_size = 0;
}
this.syncFrameCount = this.frameCount;
return; // sync
} else {
gotFirstSync = false;
it('should parse a raw ID3v2.3 header', () => {
const filePath = path.join(samplePath, 'MusicBrainz - Beth Hart - Sinner\'s Prayer.id3v23');
const metadata = new MetadataCollector({});
return strtok.fromFile(filePath).then(tokenizer => {
return new ID3v2Parser().parse(metadata, tokenizer, {}).then(() => {
assert.strictEqual(33, metadata.native['ID3v2.3'].length);
const id3v23 = mm.orderTags(metadata.native['ID3v2.3']);
assert.isDefined(id3v23.UFID, 'check if ID3v2.3-UFID is set');
});
});
});
private static parseTagFooter(metadata: INativeMetadataCollector, buffer: Buffer, options: IOptions): Promise {
const footer = TagFooter.get(buffer, buffer.length - TagFooter.len);
assert.strictEqual(footer.ID, preamble, 'APEv2 Footer preamble');
strtok3.fromBuffer(buffer);
const apeParser = new APEv2Parser();
apeParser.init(metadata, strtok3.fromBuffer(buffer), options);
return apeParser.parseTags(footer);
}
private static parseTagFooter(metadata: INativeMetadataCollector, buffer: Buffer, options: IOptions): Promise {
const footer = TagFooter.get(buffer, buffer.length - TagFooter.len);
assert.strictEqual(footer.ID, preamble, 'APEv2 Footer preamble');
strtok3.fromBuffer(buffer);
const apeParser = new APEv2Parser();
apeParser.init(metadata, strtok3.fromBuffer(buffer), options);
return apeParser.parseTags(footer);
}
async function fromStream(stream) {
const tokenizer = await strtok3.fromStream(stream);
try {
return await fromTokenizer(tokenizer);
} finally {
await tokenizer.close();
}
}
export function parseStream(stream: Stream.Readable, mimeType?: string, options: IOptions = {}): Promise {
return parseFromTokenizer(strtok3.fromStream(stream), mimeType, options);
}