
Research
Security News
Lazarus Strikes npm Again with New Wave of Malicious Packages
The Socket Research Team has discovered six new malicious npm packages linked to North Korea’s Lazarus Group, designed to steal credentials and deploy backdoors.
@wasm-audio-decoders/flac
Advanced tools
@wasm-audio-decoders/flac is an npm package that provides WebAssembly (WASM) based decoding for FLAC audio files. This allows for efficient and high-performance decoding of FLAC files directly in JavaScript environments, such as web browsers or Node.js.
Decode FLAC file to PCM
This feature allows you to decode a FLAC file into PCM (Pulse Code Modulation) data, which is a raw audio format. The code sample demonstrates how to read a FLAC file from the filesystem and decode it using the FlacDecoder class.
const { FlacDecoder } = require('@wasm-audio-decoders/flac');
const fs = require('fs');
async function decodeFlac() {
const decoder = new FlacDecoder();
const flacData = fs.readFileSync('path/to/your/file.flac');
const pcmData = await decoder.decode(flacData);
console.log(pcmData);
}
decodeFlac();
Stream FLAC file decoding
This feature allows you to decode a FLAC file in a streaming manner, which is useful for handling large files or streaming data. The code sample demonstrates how to create a read stream from a FLAC file and decode it chunk by chunk.
const { FlacDecoder } = require('@wasm-audio-decoders/flac');
const fs = require('fs');
async function streamDecodeFlac() {
const decoder = new FlacDecoder();
const readStream = fs.createReadStream('path/to/your/file.flac');
for await (const chunk of readStream) {
const pcmChunk = await decoder.decode(chunk);
console.log(pcmChunk);
}
}
streamDecodeFlac();
flac.js is a JavaScript library for decoding FLAC audio files. It is similar to @wasm-audio-decoders/flac in that it provides functionality to decode FLAC files, but it is implemented purely in JavaScript without using WebAssembly, which may result in lower performance compared to @wasm-audio-decoders/flac.
audiobuffer-to-wav is a package that converts AudioBuffer data to WAV format. While it does not decode FLAC files directly, it can be used in conjunction with a FLAC decoder to convert the decoded PCM data into WAV format. This package is useful for converting audio data into a more widely supported format.
node-flac is a Node.js package that provides bindings to the FLAC command-line tools. It allows for encoding and decoding of FLAC files using the native FLAC tools, which can offer high performance. However, it requires the FLAC tools to be installed on the system, unlike @wasm-audio-decoders/flac which is self-contained.
@wasm-audio-decoders/flac
@wasm-audio-decoders/flac
is a Web Assembly FLAC / Ogg FLAC audio decoder.
libFLAC
and codec-parser
See the homepage of this repository for more Web Assembly audio decoders like this one.
Install from NPM.
Run npm i @wasm-audio-decoders/flac
import { FLACDecoder } from '@wasm-audio-decoders/flac';
const decoder = new FLACDecoder();
Or download the build and include it as a script.
<script src="flac-decoder.min.js"></script>
<script>
const decoder = new window["flac-decoder"].FLACDecoder();
</script>
Create a new instance and wait for the WASM to finish compiling. Decoding can be done on the main thread synchronously, or in a web worker asynchronously.
Main thread synchronous decoding
import { FLACDecoder } from '@wasm-audio-decoders/flac';
const decoder = new FLACDecoder();
// wait for the WASM to be compiled
await decoder.ready;
Web Worker asynchronous decoding
import { FLACDecoderWebWorker } from '@wasm-audio-decoders/flac';
const decoder = new FLACDecoderWebWorker();
// wait for the WASM to be compiled
await decoder.ready;
Begin decoding FLAC or Ogg FLAC data.
// Decode an individual Opus frame
const {channelData, samplesDecoded, sampleRate, bitDepth} = decoder.decode(flacData);
When done decoding, reset the decoder to decode a new stream, or free up the memory being used by the WASM module if you have no more audio to decode.
// `reset()` clears the decoder state and allows you do decode a new stream of FLAC data.
await decoder.reset();
// `free()` de-allocates the memory used by the decoder. You will need to create a new instance after calling `free()` to start decoding again.
decoder.free();
Decoded audio is always returned in the below structure.
{
channelData: [
leftAudio, // Float32Array of PCM samples for the left channel
rightAudio, // Float32Array of PCM samples for the right channel
... // additional channels
],
samplesDecoded: 1234, // number of PCM samples that were decoded per channel
sampleRate: 48000, // sample rate of the decoded PCM
bitDepth: 24, // bit depth of the original FLAC file
errors: [ // array containing descriptions for any decode errors
{
message: "Error: FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC; State: FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC",
frameLength: 400, // length of the frame or data in bytes that encountered an error
frameNumber: 5, // position of error relative to total frames decoded
inputBytes: 11606, // position of error relative to total input bytes
outputSamples: 20480, // position of error relative to total output samples
}
]
}
Each Float32Array within channelData
can be used directly in the WebAudio API for playback.
Decoding will proceed through any errors. Any errors encountered may result in gaps in the decoded audio.
Each channel is assigned to a speaker location in a conventional surround arrangement. Specific locations depend on the number of channels, and are given below in order of the corresponding channel indices. This set of surround options and speaker location orderings is the same as those used by the Vorbis codec.
See: https://datatracker.ietf.org/doc/html/rfc7845.html#section-5.1.1.2
FLACDecoder
Class that decodes FLAC synchronously on the main thread.
const decoder = new FLACDecoder();
decoder.ready
async
decoder.decode(flacData)
async
flacData
Uint8Array containing FLAC or Ogg FLAC data.decoder.flush()
async
decode
method to retrieve any remaining data in the buffer.decoder.decodeFile(flacData)
async
flacData
Uint8Array containing FLAC or Ogg FLAC data.decoder.decodeFrames(flacFrames)
async
flacData
Array of Uint8Array containing FLAC frames.decoder.reset()
async
decoder.free()
free()
, the current instance is made unusable, and a new instance will need to be created to decode additional FLAC data.FLACDecoderWebWorker
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.
const decoder = new FLACDecoderWebWorker();
decoder.ready
async
decoder.decode(flacData)
async
flacData
Uint8Array containing FLAC or Ogg FLAC data.decoder.flush()
async
decode
method to retrieve any remaining data in the buffer.decoder.decodeFile(flacData)
async
flacData
Uint8Array containing FLAC or Ogg FLAC data.decoder.decodeFrames(flacFrames)
async
flacData
Array of Uint8Array containing FLAC frames.decoder.reset()
async
decoder.free()
*async
free()
, the current instance is made unusable, and a new instance will need to be created to decode additional FLAC data.FLACDecoderWebWorker
uses async functions to send operations to the web worker without blocking the main thread. To fully take advantage of the concurrency provided by web workers, your code should avoid using await
on decode operations where it will block the main thread.
Each method call on a FLACDecoderWebWorker
instance will queue up an operation to the web worker. Operations will complete within the web worker thread one at a time and in the same order in which the methods were called.
Good Main thread is not blocked during each decode operation. The example playAudio
function is called when each decode operation completes. Also, the next decode operation can begin while playAudio
is doing work on the main thread.
const playAudio = ({ channelData, samplesDecoded, sampleRate }) => {
// does something to play the audio data.
}
decoder.decode(data1).then(playAudio);
decoder.decode(data2).then(playAudio);
decoder.decode(data3).then(playAudio);
// do some other operations while the audio is decoded
Bad Main thread is being blocked by await
during each decode operation. Synchronous code is halted while decoding completes, negating the benefits of using a webworker.
const decoded1 = await decoder.decode(data1); // blocks the main thread
playAudio(decoded1);
const decoded2 = await decoder.decode(data2); // blocks the main thread
playAudio(decoded2);
const decoded3 = await decoder.decode(data3); // blocks the main thread
playAudio(decoded3);
FLACDecoderWebWorker
This example shows how to decode multiple files using a single FLACDecoderWebWorker
instance. This code iterates over an array of input files (Array of Uint8Arrays) and queues up each file to be decoded one at a time.
First, wait for the decoder to become ready by calling decoder.ready
.
For each iteration, decode()
is called, it's result is pushed to the decodedFiles
array, and decoder.reset()
is called to prepare the decoder for a new file. These operations are queued up to the decoder instance and will complete one after another.
Finally, a call to decoder.free()
is queued to clean up the memory stored by the decoder. This resolves when it and all of the other operations before it complete.
It's important to note that there is only one await
operations in this example. Decoding can happen asynchronously and you only need to await
when you need to use the results of the decode operation.
const inputFiles = [file1, file2, file3] // Array of Uint8Array file data
const decoder = new FLACDecoderWebWorker();
const decodedFiles = [];
const decodePromise = decoder.ready // wait for the decoder to be ready
.then(() => {
for (const file of inputFiles) {
decoder.decode(file) // queue the decode operation
.then((result) => decodedFiles.push(result)); // save the decode result after decode completes
decoder.reset(); // queue the reset operation
}
})
.then(() => decoder.free()); // queue the free operation that will execute after the above operations
// do sync operations here
// await when you need to have the all of the audio data decoded
await decodePromise;
FLACDecoderWebWorker
This example shows how to decode multiple files using multiple instances of FLACDecoderWebWorker
. This code iterates over an array of input files (Array of Uint8Arrays) and spawns a new FLACDecoderWebWorker
instance for each file and decodes the file. If you want to take full advantage of multi-core devices, this is the approach you will want to take since it will parallelize the decoding
For each input file, a new decoder is created, and the file is decoded using the decode()
after decoder.ready
is resolved. The result of the decode()
operation is returned, and a finally()
function on the promise calls decoder.free()
to free up the instance after the decode operations are completed.
Finally, Promise.all()
wraps this array of promises and resolves when all decode operations are complete.
It's important to note that there is only one await
operation in this example. Decoding can happen asynchronously and you only need to await
when you need to use the results of the decode operation.
const inputFiles = [file1, file2, file3] // Array of Uint8Array file data
// loops through each Uint8Array in `inputFiles` and decodes the files in separate threads
const decodePromise = Promise.all(
inputFiles.map((file) => {
const decoder = new FLACDecoderWebWorker();
return decoder.ready
.then(() => decoder.decode(file)) // decode the input file
.finally(() => decoder.free()); // free the decoder after resolving the decode result
})
);
// do sync operations here
// await when you need to have the all of the audio data decoded
const decodedFiles = await decodePromise;
FAQs
Web Assembly streaming FLAC decoder
The npm package @wasm-audio-decoders/flac receives a total of 247,883 weekly downloads. As such, @wasm-audio-decoders/flac popularity was classified as popular.
We found that @wasm-audio-decoders/flac demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
The Socket Research Team has discovered six new malicious npm packages linked to North Korea’s Lazarus Group, designed to steal credentials and deploy backdoors.
Security News
Socket CEO Feross Aboukhadijeh discusses the open web, open source security, and how Socket tackles software supply chain attacks on The Pair Program podcast.
Security News
Opengrep continues building momentum with the alpha release of its Playground tool, demonstrating the project's rapid evolution just two months after its initial launch.