jamp3
Version:
mp3, id3v1, id3v2 - reader & writer
143 lines (125 loc) • 3.38 kB
text/typescript
/* tslint:disable:no-bitwise */
// http://en.wikipedia.org/wiki/Synchsafe
import fs from 'fs';
import path from 'path';
import fse from 'fs-extra';
export function isBitSetAt(byte: number, bit: number) {
return (byte & 1 << bit) !== 0;
}
export function flags(names: Array<string>, values: Array<number>): {
[name: string]: boolean;
} {
const result: {
[name: string]: boolean;
} = {};
names.forEach((name, i) => {
result[name] = !!values[i];
});
return result;
}
export function unflags(names: Array<string>, flagsObj?: { [name: string]: boolean | undefined }): Array<number> {
return names.map(name => {
return flagsObj && flagsObj[name] ? 1 : 0;
});
}
export function synchsafe(input: number): number {
let out;
let mask = 0x7F;
while (mask ^ 0x7FFFFFFF) {
out = input & ~mask;
out = out << 1;
out = out | (input & mask);
mask = ((mask + 1) << 8) - 1;
input = out;
}
if (out === undefined) {
return 0;
}
return out;
}
export function unsynchsafe(input: number): number {
let out = 0, mask = 0x7F000000;
while (mask) {
out = out >> 1;
out = out | (input & mask);
mask = mask >> 8;
}
if (out === undefined) {
return 0;
}
return out;
}
export function log2(x: number): number {
return Math.log(x) * Math.LOG2E;
}
export function bitarray(byte: number): Array<number> {
return [128, 64, 32, 16, 8, 4, 2, 1].map(offset => (byte & offset) === offset ? 1 : 0);
}
export function unbitarray(bitsarray: Array<number>): number {
let result = 0;
for (let i = 0; i < 8; ++i) {
result = (result * 2) + (bitsarray[i] ? 1 : 0);
}
return result;
}
export function bitarray2(byte: number): Array<number> {
const b = []; // The binary representation
for (let i = 0; i < 8; ++i) {
b[7 - i] = (byte >> i) & 1;
}
return b;
}
export function isBit(field: number, nr: number): boolean {
return !!(field & nr);
}
export function removeZeroString(s: string): string {
for (let j = 0; j < s.length; j++) {
if (s.charCodeAt(j) === 0) {
s = s.slice(0, j);
break;
}
}
return s;
}
export function neededStoreBytes(num: number, min: number) {
let result = Math.ceil((Math.floor(log2(num) + 1) + 1) / 8);
result = Math.max(result, min);
return result;
}
export async function fileRangeToBuffer(filename: string, start: number, end: number): Promise<Buffer> {
const chunks: Array<Buffer> = [];
return new Promise<Buffer>((resolve, reject) => {
try {
const readStream = fs.createReadStream(filename, {start, end});
readStream.on('data', (chunk: Buffer) => {
chunks.push(chunk);
});
readStream.on('error', e => {
reject(e);
});
readStream.on('close', () => {
resolve(Buffer.concat(chunks));
});
} catch (e: any) {
return reject(e);
}
});
}
export async function collectFiles(dir: string, ext: Array<string>, recursive: boolean, onFileCB: (filename: string) => Promise<void>): Promise<void> {
const files1 = await fse.readdir(dir);
for (const f of files1) {
const sub = path.join(dir, f);
const stat = await fse.stat(sub);
if (stat.isDirectory()) {
if (recursive) {
await collectFiles(sub, ext, recursive, onFileCB);
}
} else if ((ext.indexOf(path.extname(f).toLowerCase()) >= 0)) {
await onFileCB(sub);
}
}
}
export function validCharKeyCode(c: number): boolean {
// /0-9 A-Z/
return ((c >= 48) && (c < 58)) || ((c >= 65) && (c < 91));
}