122 lines
3.1 KiB
TypeScript
122 lines
3.1 KiB
TypeScript
import type { IGetToken } from 'strtok3';
|
|
import type { IChunkHeader } from '../iff/index.js';
|
|
import * as Token from 'token-types';
|
|
import { makeUnexpectedFileContentError } from '../ParseError.js';
|
|
|
|
export class WaveContentError extends makeUnexpectedFileContentError('Wave'){
|
|
}
|
|
|
|
/**
|
|
* Ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317599(v=vs.85).aspx
|
|
*/
|
|
export const WaveFormat = {
|
|
PCM: 0x0001,
|
|
// MPEG-4 and AAC Audio Types
|
|
ADPCM: 0x0002,
|
|
IEEE_FLOAT: 0x0003,
|
|
MPEG_ADTS_AAC: 0x1600,
|
|
MPEG_LOAS: 0x1602,
|
|
RAW_AAC1: 0x00FF,
|
|
// Dolby Audio Types
|
|
DOLBY_AC3_SPDIF: 0x0092,
|
|
DVM: 0x2000,
|
|
RAW_SPORT: 0x0240,
|
|
ESST_AC3: 0x0241,
|
|
DRM: 0x0009,
|
|
DTS2: 0x2001,
|
|
MPEG: 0x0050
|
|
};
|
|
export type WaveFormat = typeof WaveFormat[keyof typeof WaveFormat];
|
|
|
|
export const WaveFormatNameMap = {
|
|
[WaveFormat.PCM]: 'PCM',
|
|
[WaveFormat.ADPCM]: 'ADPCM',
|
|
[WaveFormat.IEEE_FLOAT]: 'IEEE_FLOAT',
|
|
[WaveFormat.MPEG_ADTS_AAC]: 'MPEG_ADTS_AAC',
|
|
[WaveFormat.MPEG_LOAS]: 'MPEG_LOAS',
|
|
[WaveFormat.RAW_AAC1]: 'RAW_AAC1',
|
|
[WaveFormat.DOLBY_AC3_SPDIF]: 'DOLBY_AC3_SPDIF',
|
|
[WaveFormat.DVM]: 'DVM',
|
|
[WaveFormat.RAW_SPORT]: 'RAW_SPORT',
|
|
[WaveFormat.ESST_AC3]: 'ESST_AC3',
|
|
[WaveFormat.DRM]: 'DRM',
|
|
[WaveFormat.DTS2]: 'DTS2',
|
|
[WaveFormat.MPEG]: 'MPEG'
|
|
};
|
|
|
|
/**
|
|
* "fmt" sub-chunk describes the sound data's format
|
|
* Ref: http://soundfile.sapp.org/doc/WaveFormat
|
|
*/
|
|
export interface IWaveFormat {
|
|
/**
|
|
* PCM = 1 (i.e. Linear quantization). Values other than 1 indicate some form of compression.
|
|
*/
|
|
wFormatTag: WaveFormat,
|
|
/**
|
|
* Mono = 1, Stereo = 2, etc.
|
|
*/
|
|
nChannels: number,
|
|
/**
|
|
* 8000, 44100, etc.
|
|
*/
|
|
nSamplesPerSec: number,
|
|
nAvgBytesPerSec: number,
|
|
nBlockAlign: number,
|
|
wBitsPerSample: number
|
|
}
|
|
|
|
/**
|
|
* format chunk; chunk-id is "fmt "
|
|
* http://soundfile.sapp.org/doc/WaveFormat/
|
|
*/
|
|
export class Format implements IGetToken<IWaveFormat> {
|
|
|
|
public len: number;
|
|
|
|
public constructor(header: IChunkHeader) {
|
|
if (header.chunkSize < 16)
|
|
throw new WaveContentError('Invalid chunk size');
|
|
this.len = header.chunkSize;
|
|
}
|
|
|
|
public get(buf: Uint8Array, off: number): IWaveFormat {
|
|
return {
|
|
wFormatTag: Token.UINT16_LE.get(buf, off),
|
|
nChannels: Token.UINT16_LE.get(buf,off + 2),
|
|
nSamplesPerSec: Token.UINT32_LE.get(buf,off + 4),
|
|
nAvgBytesPerSec: Token.UINT32_LE.get(buf,off + 8),
|
|
nBlockAlign: Token.UINT16_LE.get(buf,off + 12),
|
|
wBitsPerSample: Token.UINT16_LE.get(buf,off + 14)
|
|
};
|
|
}
|
|
}
|
|
|
|
export interface IFactChunk {
|
|
dwSampleLength: number;
|
|
}
|
|
|
|
/**
|
|
* Fact chunk; chunk-id is "fact"
|
|
* http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
|
|
* http://www.recordingblogs.com/wiki/fact-chunk-of-a-wave-file
|
|
*/
|
|
export class FactChunk implements IGetToken<IFactChunk> {
|
|
|
|
public len: number;
|
|
|
|
public constructor(header: IChunkHeader) {
|
|
if (header.chunkSize < 4) {
|
|
throw new WaveContentError('Invalid fact chunk size.');
|
|
}
|
|
this.len = header.chunkSize;
|
|
}
|
|
|
|
public get(buf: Uint8Array, off: number): IFactChunk {
|
|
return {
|
|
dwSampleLength: Token.UINT32_LE.get(buf, off)
|
|
};
|
|
}
|
|
|
|
}
|