import * as Token from 'token-types' ; import { IGetToken } from 'strtok3/lib/core' ; import { FourCcToken } from '../common/FourCC' ; /**
 * APETag versionIndex history / supported formats
 *
 *  1.0 (1000) - Original APE tag spec.  Fully supported by this code.
 *  2.0 (2000) - Refined APE tag spec (better streaming support, UTF StringEncoding). Fully supported by this code.
 *
 *  Notes:
 *  - also supports reading of ID3v1.1 tags
 *  - all saving done in the APE Tag format using CURRENT_APE_TAG_VERSION
 *
 * APE File Format Overview: (pieces in order -- only valid for the latest versionIndex APE files)
 *
 * JUNK - any amount of "junk" before the APE_DESCRIPTOR (so people that put ID3v2 tags on the files aren't hosed)
 * APE_DESCRIPTOR - defines the sizes (and offsets) of all the pieces, as well as the MD5 checksum
 * APE_HEADER - describes all of the necessary information about the APE file
 * SEEK TABLE - the table that represents seek offsets [optional]
 * HEADER DATA - the pre-audio data from the original file [optional]
 * APE FRAMES - the actual compressed audio (broken into frames for seekability)
 * TERMINATING DATA - the post-audio data from the original file [optional]
 * TAG - describes all the properties of the file [optional]
 */ export interface IDescriptor { ID : string ; version : number ; descriptorBytes : number ; headerBytes : number ; seekTableBytes : number ; headerDataBytes : number ; apeFrameDataBytes : number ; apeFrameDataBytesHigh : number ; terminatingDataBytes : number ; fileMD5 : Uint8Array ; } /**
 * APE_HEADER: describes all of the necessary information about the APE file
 */ export interface IHeader { compressionLevel : number ; formatFlags : number ; blocksPerFrame : number ; finalFrameBlocks : number ; totalFrames : number ; bitsPerSample : number ; channel : number ; sampleRate : number ; } export interface IFooter { ID : string ; version : number ; size : number ; fields : number ; flags : ITagFlags ; } export enum DataType { text_utf8 = 0 , binary = 1 , external_info = 2 , reserved = 3 } /**
 * APE_DESCRIPTOR: defines the sizes (and offsets) of all the pieces, as well as the MD5 checksum
 */ export const DescriptorParser = { len : 52 , get : ( buf , off ) => { return { ID : FourCcToken . get ( buf , off ) , version : Token . UINT32_LE . get ( buf , off + 4 ) / 1000 , descriptorBytes : Token . UINT32_LE . get ( buf , off + 8 ) , headerBytes : Token . UINT32_LE . get ( buf , off + 12 ) , seekTableBytes : Token . UINT32_LE . get ( buf , off + 16 ) , headerDataBytes : Token . UINT32_LE . get ( buf , off + 20 ) , apeFrameDataBytes : Token . UINT32_LE . get ( buf , off + 24 ) , apeFrameDataBytesHigh : Token . UINT32_LE . get ( buf , off + 28 ) , terminatingDataBytes : Token . UINT32_LE . get ( buf , off + 32 ) , fileMD5 : new Token . Uint8ArrayType ( 16 ) . get ( buf , off + 36 ) } ; } } ; /**
 * APE_HEADER: describes all of the necessary information about the APE file
 */ export const Header = { len : 24 , get : ( buf , off ) => { return { compressionLevel : Token . UINT16_LE . get ( buf , off ) , formatFlags : Token . UINT16_LE . get ( buf , off + 2 ) , blocksPerFrame : Token . UINT32_LE . get ( buf , off + 4 ) , finalFrameBlocks : Token . UINT32_LE . get ( buf , off + 8 ) , totalFrames : Token . UINT32_LE . get ( buf , off + 12 ) , bitsPerSample : Token . UINT16_LE . get ( buf , off + 16 ) , channel : Token . UINT16_LE . get ( buf , off + 18 ) , sampleRate : Token . UINT32_LE . get ( buf , off + 20 ) } ; } } ; /**
 * APE Tag Header/Footer Version 2.0
 * TAG: describes all the properties of the file [optional]
 */ export const TagFooter = { len : 32 , get : ( buf , off ) => { return { ID : new Token . StringType ( 8 , 'ascii' ) . get ( buf , off ) , version : Token . UINT32_LE . get ( buf , off + 8 ) , size : Token . UINT32_LE . get ( buf , off + 12 ) , fields : Token . UINT32_LE . get ( buf , off + 16 ) , flags : parseTagFlags ( Token . UINT32_LE . get ( buf , off + 20 ) ) } ; } } ; /**
 * APE Tag v2.0 Item Header
 */ export interface ITagItemHeader { size : number ; flags : ITagFlags ; } /**
 * APE Tag v2.0 Item Header
 */ export const TagItemHeader = { len : 8 , get : ( buf , off ) => { return { size : Token . UINT32_LE . get ( buf , off ) , flags : parseTagFlags ( Token . UINT32_LE . get ( buf , off + 4 ) ) } ; } } ; export const TagField = footer => { return new Token . Uint8ArrayType ( footer . size - TagFooter . len ) ; } ; export interface ITagFlags { containsHeader : boolean ; containsFooter : boolean ; isHeader : boolean ; readOnly : boolean ; dataType : DataType ; } export function parseTagFlags ( flags ) { return { containsHeader : isBitSet ( flags , 31 ) , containsFooter : isBitSet ( flags , 30 ) , isHeader : isBitSet ( flags , 31 ) , readOnly : isBitSet ( flags , 0 ) , dataType : ( flags & 6 ) >> 1 } ; } param num { number } param bit return { boolean } export function isBitSet ( num , bit ) { return ( num & 1 << bit ) !== 0 ; }