You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.2 KiB
134 lines
3.2 KiB
import { Now } from '../../utils'
|
|
import BitBuffer from '../buffer'
|
|
import BaseDecoder from './decoder'
|
|
|
|
export default class MP2WASM extends BaseDecoder {
|
|
constructor(options) {
|
|
super(options)
|
|
|
|
this.onDecodeCallback = options.onAudioDecode
|
|
this.module = options.wasmModule
|
|
|
|
this.bufferSize = options.audioBufferSize || 128 * 1024
|
|
this.bufferMode = options.streaming
|
|
? BitBuffer.MODE.EVICT
|
|
: BitBuffer.MODE.EXPAND
|
|
|
|
this.sampleRate = 0
|
|
}
|
|
|
|
initializeWasmDecoder() {
|
|
if (!this.module.instance) {
|
|
console.warn('JSMpeg: WASM module not compiled yet')
|
|
return
|
|
}
|
|
this.instance = this.module.instance
|
|
this.functions = this.module.instance.exports
|
|
this.decoder = this.functions._mp2_decoder_create(
|
|
this.bufferSize,
|
|
this.bufferMode
|
|
)
|
|
}
|
|
|
|
destroy() {
|
|
if (!this.decoder) {
|
|
return
|
|
}
|
|
this.functions._mp2_decoder_destroy(this.decoder)
|
|
}
|
|
|
|
bufferGetIndex() {
|
|
if (!this.decoder) {
|
|
return
|
|
}
|
|
return this.functions._mp2_decoder_get_index(this.decoder)
|
|
}
|
|
|
|
bufferSetIndex(index) {
|
|
if (!this.decoder) {
|
|
return
|
|
}
|
|
this.functions._mp2_decoder_set_index(this.decoder, index)
|
|
}
|
|
|
|
bufferWrite(buffers) {
|
|
if (!this.decoder) {
|
|
this.initializeWasmDecoder()
|
|
}
|
|
|
|
let totalLength = 0
|
|
for (let i = 0; i < buffers.length; i++) {
|
|
totalLength += buffers[i].length
|
|
}
|
|
|
|
let ptr = this.functions._mp2_decoder_get_write_ptr(
|
|
this.decoder,
|
|
totalLength
|
|
)
|
|
for (let i = 0; i < buffers.length; i++) {
|
|
this.instance.heapU8.set(buffers[i], ptr)
|
|
ptr += buffers[i].length
|
|
}
|
|
|
|
this.functions._mp2_decoder_did_write(this.decoder, totalLength)
|
|
return totalLength
|
|
}
|
|
|
|
decode() {
|
|
const startTime = Now()
|
|
|
|
if (!this.decoder) {
|
|
return false
|
|
}
|
|
|
|
const decodedBytes = this.functions._mp2_decoder_decode(this.decoder)
|
|
if (decodedBytes === 0) {
|
|
return false
|
|
}
|
|
|
|
if (!this.sampleRate) {
|
|
this.sampleRate = this.functions._mp2_decoder_get_sample_rate(
|
|
this.decoder
|
|
)
|
|
}
|
|
|
|
if (this.destination) {
|
|
// Create a Float32 View into the modules output channel data
|
|
const leftPtr = this.functions._mp2_decoder_get_left_channel_ptr(
|
|
this.decoder
|
|
)
|
|
const rightPtr = this.functions._mp2_decoder_get_right_channel_ptr(
|
|
this.decoder
|
|
)
|
|
|
|
const leftOffset = leftPtr / Float32Array.BYTES_PER_ELEMENT
|
|
const rightOffset = rightPtr / Float32Array.BYTES_PER_ELEMENT
|
|
|
|
const left = this.instance.heapF32.subarray(
|
|
leftOffset,
|
|
leftOffset + MP2WASM.SAMPLES_PER_FRAME
|
|
)
|
|
const right = this.instance.heapF32.subarray(
|
|
rightOffset,
|
|
rightOffset + MP2WASM.SAMPLES_PER_FRAME
|
|
)
|
|
|
|
this.destination.play(this.sampleRate, left, right)
|
|
}
|
|
|
|
this.advanceDecodedTime(MP2WASM.SAMPLES_PER_FRAME / this.sampleRate)
|
|
|
|
const elapsedTime = Now() - startTime
|
|
if (this.onDecodeCallback) {
|
|
this.onDecodeCallback(this, elapsedTime)
|
|
}
|
|
return true
|
|
}
|
|
|
|
getCurrentTime() {
|
|
const enqueuedTime = this.destination ? this.destination.enqueuedTime : 0
|
|
return this.decodedTime - enqueuedTime
|
|
}
|
|
|
|
static SAMPLES_PER_FRAME = 1152
|
|
}
|