@wasm-audio-decoders/flac
Advanced tools
Comparing version 0.1.14 to 0.2.0
{ | ||
"name": "@wasm-audio-decoders/flac", | ||
"version": "0.1.14", | ||
"version": "0.2.0", | ||
"description": "Web Assembly streaming FLAC decoder", | ||
@@ -5,0 +5,0 @@ "type": "module", |
# `@wasm-audio-decoders/flac` | ||
`@wasm-audio-decoders/flac` is a Web Assembly FLAC audio decoder. | ||
`@wasm-audio-decoders/flac` is a Web Assembly FLAC / Ogg FLAC audio decoder. | ||
* 64.6 KiB minified bundle size | ||
@@ -58,3 +58,3 @@ * Browser and NodeJS support | ||
1. Begin decoding FLAC data. | ||
1. Begin decoding FLAC or Ogg FLAC data. | ||
@@ -123,3 +123,3 @@ ```javascript | ||
Class that decodes FLAC data synchronously on the main thread. | ||
Class that decodes FLAC synchronously on the main thread. | ||
@@ -138,3 +138,3 @@ ### Options | ||
* `decoder.decode(flacData)` *async* | ||
* `flacData` Uint8Array containing FLAC data. | ||
* `flacData` Uint8Array containing FLAC or Ogg FLAC data. | ||
* Returns a promise that resolves with the decoded audio. | ||
@@ -146,3 +146,3 @@ * Use this when streaming audio into the decoder. | ||
* `decoder.decodeFile(flacData)` *async* | ||
* `flacData` Uint8Array containing FLAC data. | ||
* `flacData` Uint8Array containing FLAC or Ogg FLAC data. | ||
* Returns a promise that resolves with the decoded audio. | ||
@@ -162,3 +162,3 @@ * Use this when decoding an entire file. | ||
Class that decodes FLAC data asynchronously within a web worker. Decoding is performed in a separate, non-blocking thread. Each new instance spawns a new worker allowing you to run multiple workers for concurrent decoding of multiple streams. | ||
Class that decodes FLAC asynchronously within a web worker. Decoding is performed in a separate, non-blocking thread. Each new instance spawns a new worker allowing you to run multiple workers for concurrent decoding of multiple streams. | ||
@@ -177,3 +177,3 @@ ### Options | ||
* `decoder.decode(flacData)` *async* | ||
* `flacData` Uint8Array containing FLAC data. | ||
* `flacData` Uint8Array containing FLAC or Ogg FLAC data. | ||
* Returns a promise that resolves with the decoded audio. | ||
@@ -185,3 +185,3 @@ * Use this when streaming audio into the decoder. | ||
* `decoder.decodeFile(flacData)` *async* | ||
* `flacData` Uint8Array containing FLAC data. | ||
* `flacData` Uint8Array containing FLAC or Ogg FLAC data. | ||
* Returns a promise that resolves with the decoded audio. | ||
@@ -188,0 +188,0 @@ * Use this when decoding an entire file. |
import { WASMAudioDecoderCommon } from "@wasm-audio-decoders/common"; | ||
import CodecParser, { data } from "codec-parser"; | ||
import CodecParser, { | ||
data, | ||
absoluteGranulePosition, | ||
samples, | ||
codecFrames, | ||
isLastPage, | ||
} from "codec-parser"; | ||
@@ -177,2 +183,9 @@ import EmscriptenWASM from "./EmscriptenWasm.js"; | ||
const determineDecodeMethod = Symbol(); | ||
const decodeFlac = Symbol(); | ||
const decodeOggFlac = Symbol(); | ||
const placeholderDecodeMethod = Symbol(); | ||
const decodeMethod = Symbol(); | ||
const init = Symbol(); | ||
export default class FLACDecoder { | ||
@@ -190,13 +203,36 @@ constructor() { | ||
this._init(); | ||
this[init](); | ||
this[setDecoderClass](Decoder); | ||
} | ||
_init() { | ||
this._codecParser = new CodecParser("audio/flac", { | ||
onCodec: this._onCodec, | ||
enableFrameCRC32: false, | ||
}); | ||
[init]() { | ||
this[decodeMethod] = placeholderDecodeMethod; | ||
this._codecParser = null; | ||
this._beginningSampleOffset = undefined; | ||
} | ||
[determineDecodeMethod](data) { | ||
if (!this._codecParser && data.length >= 4) { | ||
let codec = "audio/"; | ||
if ( | ||
data[0] !== 0x4f || // O | ||
data[1] !== 0x67 || // g | ||
data[2] !== 0x67 || // g | ||
data[3] !== 0x53 // S | ||
) { | ||
codec += "flac"; | ||
this[decodeMethod] = decodeFlac; | ||
} else { | ||
codec += "ogg"; | ||
this[decodeMethod] = decodeOggFlac; | ||
} | ||
this._codecParser = new CodecParser(codec, { | ||
onCodec: this._onCodec, | ||
enableFrameCRC32: false, | ||
}); | ||
} | ||
} | ||
[setDecoderClass](decoderClass) { | ||
@@ -212,2 +248,44 @@ if (this._decoder) { | ||
[decodeFlac](flacFrames) { | ||
return this._decoder.decodeFrames(flacFrames.map((f) => f[data] || f)); | ||
} | ||
[decodeOggFlac](oggPages) { | ||
const frames = oggPages | ||
.map((page) => page[codecFrames].map((f) => f[data])) | ||
.flat(); | ||
const decoded = this._decoder.decodeFrames(frames); | ||
const oggPage = oggPages[oggPages.length - 1]; | ||
if (oggPages.length && Number(oggPage[absoluteGranulePosition]) > -1) { | ||
if (this._beginningSampleOffset === undefined) { | ||
this._beginningSampleOffset = | ||
oggPage[absoluteGranulePosition] - BigInt(oggPage[samples]); | ||
} | ||
if (oggPage[isLastPage]) { | ||
// trim any extra samples that are decoded beyond the absoluteGranulePosition, relative to where we started in the stream | ||
const samplesToTrim = | ||
decoded.samplesDecoded - Number(oggPage[absoluteGranulePosition]); | ||
if (samplesToTrim > 0) { | ||
for (let i = 0; i < decoded.channelData.length; i++) | ||
decoded.channelData[i] = decoded.channelData[i].subarray( | ||
0, | ||
decoded.samplesDecoded - samplesToTrim, | ||
); | ||
decoded.samplesDecoded -= samplesToTrim; | ||
} | ||
} | ||
} | ||
return decoded; | ||
} | ||
[placeholderDecodeMethod]() { | ||
return WASMAudioDecoderCommon.getDecodedAudio([], [], 0, 0, 0); | ||
} | ||
get ready() { | ||
@@ -218,3 +296,3 @@ return this._ready; | ||
async reset() { | ||
this._init(); | ||
this[init](); | ||
return this._decoder.reset(); | ||
@@ -228,11 +306,12 @@ } | ||
async decode(flacData) { | ||
return this._decoder.decodeFrames( | ||
[...this._codecParser.parseChunk(flacData)].map((f) => f[data]), | ||
); | ||
if (this[decodeMethod] === placeholderDecodeMethod) | ||
this[determineDecodeMethod](flacData); | ||
return this[this[decodeMethod]]([ | ||
...this._codecParser.parseChunk(flacData), | ||
]); | ||
} | ||
async flush() { | ||
const decoded = this._decoder.decodeFrames( | ||
[...this._codecParser.flush()].map((f) => f[data]), | ||
); | ||
const decoded = this[this[decodeMethod]]([...this._codecParser.flush()]); | ||
@@ -244,6 +323,8 @@ await this.reset(); | ||
async decodeFile(flacData) { | ||
const decoded = this._decoder.decodeFrames( | ||
[...this._codecParser.parseAll(flacData)].map((f) => f[data]), | ||
); | ||
this[determineDecodeMethod](flacData); | ||
const decoded = this[this[decodeMethod]]([ | ||
...this._codecParser.parseAll(flacData), | ||
]); | ||
await this.reset(); | ||
@@ -254,4 +335,4 @@ return decoded; | ||
async decodeFrames(flacFrames) { | ||
return this._decoder.decodeFrames(flacFrames); | ||
return this[decodeFlac](flacFrames); | ||
} | ||
} |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
192606
976