Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

ogg-opus-decoder

Package Overview
Dependencies
Maintainers
1
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ogg-opus-decoder - npm Package Compare versions

Comparing version 1.6.6 to 1.6.7

2

package.json
{
"name": "ogg-opus-decoder",
"version": "1.6.6",
"version": "1.6.7",
"description": "Web Assembly streaming Ogg Opus decoder",

@@ -5,0 +5,0 @@ "type": "module",

# `ogg-opus-decoder`
`ogg-opus-decoder` is a Web Assembly Ogg Opus audio decoder.
* 108.2 KiB minified bundle size
* 108.0 KiB minified bundle size
* Browser and NodeJS support

@@ -6,0 +6,0 @@ * Built in Web Worker support

@@ -14,102 +14,5 @@ import { WASMAudioDecoderCommon } from "@wasm-audio-decoders/common";

samples,
data,
} from "codec-parser";
class DecoderState {
constructor(instance) {
this._instance = instance;
this._sampleRate = this._instance._sampleRate;
this._decoderOperations = [];
this._errors = [];
this._decoded = [];
this._channelsDecoded = 0;
this._totalSamples = 0;
}
get decoded() {
return this._instance.ready
.then(() => Promise.all(this._decoderOperations))
.then(() => [
this._errors,
this._decoded,
this._channelsDecoded,
this._totalSamples,
this._sampleRate,
]);
}
async _instantiateDecoder(header) {
this._preSkip = header[preSkip];
this._instance._decoder = new this._instance._decoderClass({
channels: header[channels],
streamCount: header[streamCount],
coupledStreamCount: header[coupledStreamCount],
channelMappingTable: header[channelMappingTable],
preSkip: Math.round((this._preSkip / 48000) * this._sampleRate),
sampleRate: this._sampleRate,
forceStereo: this._instance._forceStereo,
});
this._instance._ready = this._instance._decoder.ready;
}
async _sendToDecoder(oggPage) {
const dataFrames = oggPage[codecFrames].map((f) => f.data);
const { channelData, samplesDecoded, errors } =
await this._instance._decoder.decodeFrames(dataFrames);
this._totalSamples += samplesDecoded;
if (
this._beginningSampleOffset === undefined &&
Number(oggPage[absoluteGranulePosition]) > -1
) {
this._beginningSampleOffset =
oggPage[absoluteGranulePosition] -
BigInt(oggPage[samples]) +
BigInt(this._preSkip);
}
// in cases where BigInt isn't supported, don't do any absoluteGranulePosition logic (i.e. old iOS versions)
if (oggPage[isLastPage] && oggPage[absoluteGranulePosition] !== undefined) {
const totalDecodedSamples =
(this._totalSamples / this._sampleRate) * 48000;
const totalOggSamples = Number(
oggPage[absoluteGranulePosition] - this._beginningSampleOffset,
);
// trim any extra samples that are decoded beyond the absoluteGranulePosition, relative to where we started in the stream
const samplesToTrim = Math.round(
((totalDecodedSamples - totalOggSamples) / 48000) * this._sampleRate,
);
for (let i = 0; i < channelData.length; i++)
channelData[i] = channelData[i].subarray(
0,
samplesDecoded - samplesToTrim,
);
this._totalSamples -= samplesToTrim;
}
this._decoded.push(channelData);
this._errors = this._errors.concat(errors);
this._channelsDecoded = channelData.length;
}
async _decode(oggPage) {
const frames = oggPage[codecFrames];
if (frames.length) {
if (!this._instance._decoder && frames[0][header])
this._instantiateDecoder(frames[0][header]);
await this._instance.ready;
this._decoderOperations.push(this._sendToDecoder(oggPage));
}
}
}
export default class OggOpusDecoder {

@@ -146,2 +49,20 @@ constructor(options = {}) {

async _instantiateDecoder(header) {
this._totalSamplesDecoded = 0;
this._preSkip = header[preSkip];
this._channels = this._forceStereo ? 2 : header[channels];
this._beginningSampleOffset = null;
this._decoder = new this._decoderClass({
channels: header[channels],
streamCount: header[streamCount],
coupledStreamCount: header[coupledStreamCount],
channelMappingTable: header[channelMappingTable],
preSkip: Math.round((this._preSkip / 48000) * this._sampleRate),
sampleRate: this._sampleRate,
forceStereo: this._forceStereo,
});
await this._decoder.ready;
}
get ready() {

@@ -159,42 +80,106 @@ return this._ready;

async _flush(decoderState) {
for (const oggPage of this._codecParser.flush()) {
decoderState._decode(oggPage);
}
async _decode(oggPages) {
let allErrors = [],
allChannelData = [],
samplesThisDecode = 0;
const decoded = await decoderState.decoded;
this._init();
for await (const oggPage of oggPages) {
// only decode Ogg pages that have codec frames
const frames = oggPage[codecFrames].map((f) => f[data]);
return decoded;
}
if (frames.length) {
// wait until there is an Opus header before instantiating
if (!this._decoder)
await this._instantiateDecoder(oggPage[codecFrames][0][header]);
async _decode(oggOpusData, decoderState) {
for (const oggPage of this._codecParser.parseChunk(oggOpusData)) {
decoderState._decode(oggPage);
const { channelData, samplesDecoded, errors } =
await this._decoder.decodeFrames(frames);
this._totalSamplesDecoded += samplesDecoded;
// record beginning sample offset for absoluteGranulePosition logic
if (
this._beginningSampleOffset === null &&
Number(oggPage[absoluteGranulePosition]) > -1
) {
this._beginningSampleOffset =
oggPage[absoluteGranulePosition] -
BigInt(oggPage[samples]) +
BigInt(this._preSkip);
}
if (oggPage[isLastPage]) {
// in cases where BigInt isn't supported, don't do any absoluteGranulePosition logic (i.e. old iOS versions)
if (oggPage[absoluteGranulePosition] !== undefined) {
const totalDecodedSamples_48000 =
(this._totalSamplesDecoded / this._sampleRate) * 48000;
const totalOggSamples_48000 = Number(
oggPage[absoluteGranulePosition] - this._beginningSampleOffset,
);
// trim any extra samples that are decoded beyond the absoluteGranulePosition, relative to where we started in the stream
const samplesToTrim = Math.round(
((totalDecodedSamples_48000 - totalOggSamples_48000) / 48000) *
this._sampleRate,
);
for (let i = 0; i < channelData.length; i++) {
channelData[i] = channelData[i].subarray(
0,
samplesDecoded - samplesToTrim,
);
}
samplesThisDecode -= samplesToTrim;
}
// reached the end of an ogg stream, reset the decoder
this._init();
}
allErrors.push(...errors);
allChannelData.push(channelData);
samplesThisDecode += samplesDecoded;
}
}
return decoderState.decoded;
return [
allErrors,
allChannelData,
this._channels,
samplesThisDecode,
this._sampleRate,
16,
];
}
_parse(oggOpusData) {
return [...this._codecParser.parseChunk(oggOpusData)];
}
_flush() {
return [...this._codecParser.flush()];
}
async decode(oggOpusData) {
return WASMAudioDecoderCommon.getDecodedAudioMultiChannel(
...(await this._decode(oggOpusData, new DecoderState(this))),
);
const decoded = await this._decode(this._parse(oggOpusData));
return WASMAudioDecoderCommon.getDecodedAudioMultiChannel(...decoded);
}
async decodeFile(oggOpusData) {
const decoderState = new DecoderState(this);
const decoded = await this._decode([
...this._parse(oggOpusData),
...this._flush(),
]);
this._init();
return WASMAudioDecoderCommon.getDecodedAudioMultiChannel(
...(await this._decode(oggOpusData, decoderState).then(() =>
this._flush(decoderState),
)),
);
return WASMAudioDecoderCommon.getDecodedAudioMultiChannel(...decoded);
}
async flush() {
return WASMAudioDecoderCommon.getDecodedAudioMultiChannel(
...(await this._flush(new DecoderState(this))),
);
const decoded = await this._decode(this._flush());
this._init();
return WASMAudioDecoderCommon.getDecodedAudioMultiChannel(...decoded);
}
}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc