Hello, thank you for creating this library. I had some questions about how to use it.
From what I understand in wasm/index.js
, the encode/decode functions are synchronous and they block the main thread in browser/node. Is that true?
If so, is it possible to load this library from a worker, to make it async/non-blocking? I'll see if I can achieve it and report back here if successful.
Looking at other similar libraries, wasm-media-encoders, wasm-audio-decoders, and opusscript, I see their API is synchronous and blocking also. ffmpeg.wasm and lame-wasm are async.
That's interesting because I would have expected, for most purposes, async encode/decode is preferred for both browser and server side, so as not to block the main thread. For example, how AudioContext.decodeAudioData()
works.
Currently, I'm encountering some difficulties trying to encode (and decode back) an instance of AudioBuffer.
First, I noticed that if the sample rate is 44100
, the Encoder/Decoder constructor throws an error, opus: invalid argument
.
const { encode } = new Encoder({
channels: audioBuffer.numberOfChannels,
sample_rate: audioBuffer.sampleRate
})
If I force it to 48000
, it doesn't throw.
Next, I learned how to extract PCM data from an AudioBuffer using getChannelData()
.
const buffers = [] // Float32Array per channel
for (let i=0, len=audioBuffer.numberOfChannels; i < len; i++) {
buffers.push(audioBuffer.getChannelData(i))
}
When I pass a channel's data to encode()
, it throws RangeError: source array is too long
.
The error is from the first line of RawEncoder.encode()
in @evan/wasm/target/opus/deno.js
.
encode(buffer) {
bptrs.set(buffer = new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength));
return pptrs.slice(0, err(wasm.opus_encode(this.#ptr, bptr, buffer.length / 2 / this.channels, pptr, pptrl)));
}
..So I should convert my Float32Array
to an Uint8Array
before passing it to encode. Is that correct?
const channelData = buffers[0].buffer // Get ArrayBuffer from Float32Array
const pcm = new Uint8Array(channelData)
const opusData = encode(pcm)
The conversion seems to work, but still results in the same error, RangeError: source array is too long
.
EDIT: I'm guessing it's because I set the wrong sample rate when instantiating the encoder. And probably it's impossible (or unwise, haha) to try to up-scale from 44.1 to 48 kHz.
Well, I'll try to figure out these questions on my own, but if you have any thoughts, I'd appreciate it.