import * as initDebug from 'debug' ; import { BasicParser } from '../../common/BasicParser' ; import { APEv2Parser } from '../../apev2/APEv2Parser' ; import { FourCcToken } from '../../common/FourCC' ; import * as SV8 from './StreamVersion8' ; const debug = initDebug ( 'music-metadata:parser:musepack' ) ; export class MpcSv8Parser extends BasicParser { private audioLength : number = 0 ; public async parse ( ) { const signature = await this . tokenizer . readToken ( FourCcToken ) ; if ( signature !== 'MPCK' ) throw new Error ( 'Invalid Magic number' ) ; this . metadata . setFormat ( 'container' , 'Musepack, SV8' ) ; return this . parsePacket ( ) ; } private async parsePacket ( ) { const sv8reader = new SV8 . StreamReader ( this . tokenizer ) ; do { const header = await sv8reader . readPacketHeader ( ) ; debug ( `packet-header key=${ header . key }, payloadLength=${ header . payloadLength }` ) ; switch ( header . key ) { case 'SH' : const sh = await sv8reader . readStreamHeader ( header . payloadLength ) ; this . metadata . setFormat ( 'numberOfSamples' , sh . sampleCount ) ; this . metadata . setFormat ( 'sampleRate' , sh . sampleFrequency ) ; this . metadata . setFormat ( 'duration' , sh . sampleCount / sh . sampleFrequency ) ; this . metadata . setFormat ( 'numberOfChannels' , sh . channelCount ) ; break ; case 'AP' : this . audioLength += header . payloadLength ; await this . tokenizer . ignore ( header . payloadLength ) ; break ; case 'RG' : case 'EI' : case 'SO' : case 'ST' : case 'CT' : await this . tokenizer . ignore ( header . payloadLength ) ; break ; case 'SE' : this . metadata . setFormat ( 'bitrate' , this . audioLength * 8 / this . metadata . format . duration ) ; return APEv2Parser . tryParseApeHeader ( this . metadata , this . tokenizer , this . options ) ; default : throw new Error ( `Unexpected header: ${ header . key }` ) ; } } while ( true ) ; } }