music-metadata
Version:
Music metadata parser for Node.js, supporting virtual any audio and tag format.
55 lines • 2.24 kB
JavaScript
import * as Token from 'token-types';
import { VorbisParser } from '../vorbis/VorbisParser.js';
import * as Opus from './Opus.js';
import { OpusContentError } from './Opus.js';
/**
* Opus parser
* Internet Engineering Task Force (IETF) - RFC 6716
* Used by OggParser
*/
export class OpusParser extends VorbisParser {
constructor(metadata, options, tokenizer) {
super(metadata, options);
this.idHeader = null;
this.lastPos = -1;
this.tokenizer = tokenizer;
}
/**
* Parse first Opus Ogg page
* @param {IPageHeader} header
* @param {Uint8Array} pageData
*/
parseFirstPage(header, pageData) {
this.metadata.setFormat('codec', 'Opus');
// Parse Opus ID Header
this.idHeader = new Opus.IdHeader(pageData.length).get(pageData, 0);
if (this.idHeader.magicSignature !== "OpusHead")
throw new OpusContentError("Illegal ogg/Opus magic-signature");
this.metadata.setFormat('sampleRate', this.idHeader.inputSampleRate);
this.metadata.setFormat('numberOfChannels', this.idHeader.channelCount);
}
async parseFullPage(pageData) {
const magicSignature = new Token.StringType(8, 'ascii').get(pageData, 0);
switch (magicSignature) {
case 'OpusTags':
await this.parseUserCommentList(pageData, 8);
this.lastPos = this.tokenizer.position - pageData.length;
break;
default:
break;
}
}
calculateDuration(header) {
if (this.metadata.format.sampleRate && header.absoluteGranulePosition >= 0) {
// Calculate duration
const pos_48bit = header.absoluteGranulePosition - this.idHeader.preSkip;
this.metadata.setFormat('numberOfSamples', pos_48bit);
this.metadata.setFormat('duration', pos_48bit / 48000);
if (this.lastPos !== -1 && this.tokenizer.fileInfo.size && this.metadata.format.duration) {
const dataSize = this.tokenizer.fileInfo.size - this.lastPos;
this.metadata.setFormat('bitrate', 8 * dataSize / this.metadata.format.duration);
}
}
}
}
//# sourceMappingURL=OpusParser.js.map