import * as Token from 'token-types' ; import { IGetToken } from 'strtok3/lib/core' ; import { FourCcToken } from '../common/FourCC' ; /**
 * WavPack Block Header
 *
 * 32-byte little-endian header at the front of every WavPack block
 *
 * Ref:
 *  http://www.wavpack.com/WavPack5FileFormat.pdf (page 2/6: 2.0 "Block Header")
 */ export interface IBlockHeader { BlockID : string ; blockSize : number ; version : number ; blockIndex : number ; totalSamples : number ; blockSamples : number ; flags : { bitsPerSample : number ; isMono : boolean ; isHybrid : boolean ; isJointStereo : boolean ; crossChannel : boolean ; hybridNoiseShaping : boolean ; floatingPoint : boolean ; samplingRate : number ; isDSD : boolean ; } ; crc : Uint8Array ; } export interface IMetadataId { /**
     * metadata function id
     */ functionId : number ; /**
     * If true, audio-decoder does not need to understand the metadata field
     */ isOptional : boolean ; /**
     * actual data byte length is 1 less
     */ isOddSize : boolean ; /**
     * large block (> 255 words)
     */ largeBlock : boolean ; } const SampleRates = [ 6000 , 8000 , 9600 , 11025 , 12000 , 16000 , 22050 , 24000 , 32000 , 44100 , 48000 , 64000 , 88200 , 96000 , 192000 , - 1 ] ; export class WavPack { /**
     * WavPack Block Header
     *
     * 32-byte little-endian header at the front of every WavPack block
     *
     * Ref: http://www.wavpack.com/WavPack5FileFormat.pdf (page 2/6: 2.0 "Block Header")
     */ public static BlockHeaderToken : IGetToken < IBlockHeader > = { len : 32 , get : ( buf , off ) => { const flags = Token . UINT32_LE . get ( buf , off + 24 ) ; const res = { BlockID : FourCcToken . get ( buf , off ) , blockSize : Token . UINT32_LE . get ( buf , off + 4 ) , version : Token . UINT16_LE . get ( buf , off + 8 ) , totalSamples : Token . UINT32_LE . get ( buf , off + 12 ) , blockIndex : Token . UINT32_LE . get ( buf , off + 16 ) , blockSamples : Token . UINT32_LE . get ( buf , off + 20 ) , flags : { bitsPerSample : ( 1 + WavPack . getBitAllignedNumber ( flags , 0 , 2 ) ) * 8 , isMono : WavPack . isBitSet ( flags , 2 ) , isHybrid : WavPack . isBitSet ( flags , 3 ) , isJointStereo : WavPack . isBitSet ( flags , 4 ) , crossChannel : WavPack . isBitSet ( flags , 5 ) , hybridNoiseShaping : WavPack . isBitSet ( flags , 6 ) , floatingPoint : WavPack . isBitSet ( flags , 7 ) , samplingRate : SampleRates [ WavPack . getBitAllignedNumber ( flags , 23 , 4 ) ] , isDSD : WavPack . isBitSet ( flags , 31 ) } , crc : new Token . Uint8ArrayType ( 4 ) . get ( buf , off + 28 ) } ; if ( res . flags . isDSD ) { res . totalSamples *= 8 ; } return res ; } } ; /**
     * 3.0 Metadata Sub-Blocks
     *  Ref: http://www.wavpack.com/WavPack5FileFormat.pdf (page 4/6: 3.0 "Metadata Sub-Block")
     */ public static MetadataIdToken : IGetToken < IMetadataId > = { len : 1 , get : ( buf , off ) => { return { functionId : WavPack . getBitAllignedNumber ( buf [ off ] , 0 , 6 ) , isOptional : WavPack . isBitSet ( buf [ off ] , 5 ) , isOddSize : WavPack . isBitSet ( buf [ off ] , 6 ) , largeBlock : WavPack . isBitSet ( buf [ off ] , 7 ) } ; } } ; private static isBitSet ( flags , bitOffset ) { return WavPack . getBitAllignedNumber ( flags , bitOffset , 1 ) === 1 ; } private static getBitAllignedNumber ( flags , bitOffset , len ) { return ( flags >>> bitOffset ) & ( 0xffffffff >>> ( 32 - len ) ) ; } }