App-MHFS
view release on metacpan or search on metacpan
share/public_html/static/music_worklet_inprogress/decoder/mhfscl.js view on Meta::CPAN
}
if(setPicture) {
mhfscltrack.picture = {
type : pictureType,
mime : MHFSCL.Module.UTF8ToString(picture.get('mime'), picture.get('mimeSize')),
pictureSize : picture.get('pictureDataSize'),
pPicture : picture.get('pictureData')
};
}
}
};
const MHFSCLTrack = async function(gsignal, theURL, DLMGR) {
if(!MHFSCL.ready) {
console.log('MHFSCLTrack, waiting for MHFSCL to be ready');
await waitForEvent(MHFSCL, 'ready');
}
const that = {};
that.CHUNKSIZE = 262144;
that.url = theURL;
DLMGR ||= DefDownloadManager(that.CHUNKSIZE);
that._downloadChunk = async function(start, mysignal) {
if(start % that.CHUNKSIZE)
{
throw("start is not a multiple of CHUNKSIZE: " + start);
}
const chunk = await DLMGR.GetChunk(theURL, start, mysignal);
that.filesize = chunk.filesize;
return chunk;
};
that._storeChunk = function(chunk, start) {
let blockptr = MHFSCL.Module._mhfs_cl_track_add_block(that.ptr, start, that.filesize);
if(!blockptr)
{
throw("failed MHFSCL.Module._mhfs_cl_track_add_block");
}
let dataHeap = new Uint8Array(MHFSCL.Module.HEAPU8.buffer, blockptr, chunk.data.byteLength);
dataHeap.set(chunk.data);
};
that.downloadAndStoreChunk = async function(start, mysignal) {
const chunk = await that._downloadChunk(start, mysignal);
that._storeChunk(chunk, start);
return chunk;
};
that.close = function() {
if(that.ptr){
if(that.initialized) {
MHFSCL.Module._mhfs_cl_track_deinit(that.ptr);
}
MHFSCL.Module._free(that.ptr);
that.ptr = null;
}
};
that.seek = function(pcmFrameIndex) {
if(!MHFSCL.Module._mhfs_cl_track_seek_to_pcm_frame(that.ptr, pcmFrameIndex)) throw("Failed to seek to " + pcmFrameIndex);
};
that.seekSecs = function(floatseconds) {
that.seek(Math.floor(floatseconds * that.sampleRate));
};
that._openPictureIfExists = function() {
if(!that.picture) {
return undefined;
}
that.picture.hash = MHFSCL.Module._mhfs_cl_djb2(that.picture.pPicture, that.picture.pictureSize);
that.picture.toURL = function() {
const srcData = new Uint8Array(MHFSCL.Module.HEAPU8.buffer, that.picture.pPicture, that.picture.pictureSize);
const picData = new Uint8Array(srcData);
const blobert = new Blob([picData.buffer], {
'type' : that.picture.mime
});
const url = URL.createObjectURL(blobert);
return url;
};
return that.picture;
};
// allocate memory for the mhfs_cl_track and return data
const alignedTrackSize = MHFSCL.AlignedSize(MHFSCL.mhfs_cl_track.sizeof);
that.ptr = MHFSCL.Module._malloc(alignedTrackSize + MHFSCL.mhfs_cl_track_return_data.sizeof);
if(!that.ptr) throw("failed malloc");
const rd = MHFSCL.mhfs_cl_track_return_data.from(that.ptr + alignedTrackSize);
const thatid = MHFSCLObjectMap.addData(that);
const pFullFilename = MHFSCL.Module.stringToNewUTF8(theURL);
let pMime;
try {
// initialize the track
let start = 0;
const firstreq = await that._downloadChunk(start, gsignal);
const mime = firstreq.headers['Content-Type'] || '';
pMime = MHFSCL.Module.stringToNewUTF8(mime);
const totalPCMFrames = BigInt(firstreq.headers['X-MHFS-totalPCMFrameCount'] || 0);
MHFSCL.Module._mhfs_cl_track_init(that.ptr, that.CHUNKSIZE);
that.initialized = true;
that._storeChunk(firstreq, start);
// load enough of the track that the metadata loads
for(;;) {
that.picture = null;
const code = MHFSCL.Module._mhfs_cl_track_load_metadata(that.ptr, rd.ptr, pMime, pFullFilename, totalPCMFrames, MHFSCL.pMHFSCLTrackOnMeta, thatid);
if(code === MHFSCL.MHFS_CL_SUCCESS) {
break;
}
if(code !== MHFSCL.MHFS_CL_NEED_MORE_DATA){
that.close();
throw("Failed opening MHFSCLTrack");
}
start = rd.get('needed_offset');
await that.downloadAndStoreChunk(start, gsignal);
}
}
catch(error) {
that.close();
throw(error);
share/public_html/static/music_worklet_inprogress/decoder/mhfscl.js view on Meta::CPAN
}
};
that.with(size);
return that;
};
// allocates size bytes for each item. creates array of ptrs to point to the data
// [[ptr0, ptr1, ptr...][data0][data1][data...]]
const MHFSCLArrsAlloc = function(nitems, size) {
const that = {};
that.nitems = nitems;
that.ptrarrsize = nitems * MHFSCL.PTRSIZE;
that.size = 0;
that.free = function() {
if(that.alloc) {
that.alloc.free();
that.alloc = null;
}
that.nitems = 0;
that.ptrarrsize = 0;
that.size = 0;
};
that.setptrs = function(size) {
const myarr = new Uint32Array(MHFSCL.Module.HEAPU8.buffer, that.alloc.ptr, that.nitems);
let dataptr = that.alloc.ptr + that.ptrarrsize;
for( let i = 0; i < that.nitems; i++) {
myarr[i] = dataptr;
dataptr += size;
}
};
that.with = function(sz) {
sz = MHFSCL.AlignedSize(sz);
if(that.alloc && (sz <= that.size)) {
return that.alloc.ptr;
}
that.alloc = MHFSCLAllocation(that.ptrarrsize + (nitems * sz));
that.size = sz;
that.setptrs(sz);
return that.alloc.ptr;
};
that.with(size);
return that;
};
const MHFSCLDecoder = async function(outputSampleRate, outputChannelCount) {
if(!MHFSCL.ready) {
console.log('MHFSCLDecoder, waiting for MHFSCL to be ready');
await waitForEvent(MHFSCL, 'ready');
}
const that = {};
that.ptr = MHFSCL.Module._mhfs_cl_decoder_open(outputSampleRate, outputChannelCount, outputSampleRate);
if(! that.ptr) throw("Failed to open decoder");
that.outputSampleRate = outputSampleRate;
that.outputChannelCount = outputChannelCount;
that.f32_size = 4;
that.pcm_float_frame_size = that.f32_size * that.outputChannelCount;
that.returnDataAlloc = MHFSCLAllocation(MHFSCL.mhfs_cl_track_return_data.sizeof);
that.deinterleaveDataAlloc = MHFSCLArrsAlloc(outputChannelCount, that.outputSampleRate*that.f32_size);
//that.DM = DownloadManager(262144);
that.rd = MHFSCL.mhfs_cl_track_return_data.from(that.returnDataAlloc.ptr);
that.flush = async function() {
MHFSCL.Module._mhfs_cl_decoder_flush(that.ptr);
};
that.closeCurrentTrack = async function() {
if(that.track) {
that.track.close();
that.track = null;
}
};
that.close = async function(){
await that.closeCurrentTrack();
MHFSCL.Module._mhfs_cl_decoder_close(that.ptr);
that.ptr = 0;
that.returnDataAlloc.free();
that.deinterleaveDataAlloc.free();
};
// modifies track
that.openTrack = async function(signal, intrack, starttime) {
let doseek = starttime;
do {
const url = intrack.url;
if(that.track) {
if(that.track.url === url) {
doseek = 1;
break;
}
await that.track.close();
that.track = null;
if(signal.aborted) {
throw("abort after closing track");
}
}
that.track = await MHFSCLTrack(signal, url, that.DM);
} while(0);
if(doseek) {
that.track.seekSecs(starttime);
}
if(signal.aborted) {
console.log('');
await that.track.close();
that.track = null;
throw("abort after open track success");
}
return { duration : that.track.duration, mediametadata : that.track.mediametadata };
};
that.seek_input_pcm_frames = async function(pcmFrameIndex) {
if(!that.track) throw("nothing to seek on");
that.track.seek(pcmFrameIndex);
};
that.seek = async function(floatseconds) {
if(!that.track) throw("nothing to seek on");
that.track.seekSecs(floatseconds);
}
that.read_pcm_frames_f32_deinterleaved = async function(todec, destdata, mysignal) {
while(1) {
// attempt to decode the samples
const code = MHFSCL.Module._mhfs_cl_decoder_read_pcm_frames_f32_deinterleaved(that.ptr, that.track.ptr, todec, destdata, that.rd.ptr);
// success, retdata is frames read
if(code === MHFSCL.MHFS_CL_SUCCESS)
{
return that.rd.get('frames_read');
}
if(code !== MHFSCL.MHFS_CL_NEED_MORE_DATA)
{
throw("mhfs_cl_decoder_read_pcm_frames_f32_deinterleaved failed");
}
// download more data
await that.track.downloadAndStoreChunk(that.rd.get('needed_offset'), mysignal);
}
};
that.read_pcm_frames_f32_AudioBuffer = async function(todec, mysignal) {
let theerror;
let returnval;
const destdata = that.deinterleaveDataAlloc.with(todec*that.f32_size);
try {
const frames = await that.read_pcm_frames_f32_deinterleaved(todec, destdata, mysignal);
if(frames) {
const audiobuffer = new AudioBuffer({'length' : frames, 'numberOfChannels' : that.outputChannelCount, 'sampleRate' : that.outputSampleRate});
const chanPtrs = new Uint32Array(MHFSCL.Module.HEAPU8.buffer, destdata, that.outputChannelCount);
for( let i = 0; i < that.outputChannelCount; i++) {
const buf = new Float32Array(MHFSCL.Module.HEAPU8.buffer, chanPtrs[i], frames);
audiobuffer.copyToChannel(buf, i);
}
returnval = audiobuffer;
}
}
catch(error) {
theerror = error;
}
finally {
if(theerror) throw(theerror);
return returnval;
}
};
that.read_pcm_frames_f32_arrs = async function(todec, mysignal) {
let theerror;
let returnval;
const destdata = that.deinterleaveDataAlloc.with(todec*that.f32_size);
try {
const frames = await that.read_pcm_frames_f32_deinterleaved(todec, destdata, mysignal);
if(frames) {
const chanPtrs = new Uint32Array(MHFSCL.Module.HEAPU8.buffer, destdata, that.outputChannelCount);
const obj = { 'length' : frames, 'chanData' : []};
for( let i = 0; i < that.outputChannelCount; i++) {
obj.chanData[i] = new Float32Array(MHFSCL.Module.HEAPU8.buffer, chanPtrs[i], frames);
}
returnval = obj;
}
}
catch(error) {
theerror = error;
}
finally {
if(theerror) throw(theerror);
return returnval;
}
};
return that;
};
export { MHFSCLDecoder };
const ExposeType_LoadTypes = function(BINDTO, wasmMod, loadType) {
const currentObject = [BINDTO];
let mainindex = 0;
BINDTO[wasmMod.UTF8ToString(loadType(mainindex, 1))] = loadType(mainindex, 2); // load ET_TT_CONST_IV)
while(1) {
const typeType = loadType(mainindex, 0);
if(typeType === 0) break;
if(typeType === BINDTO.ET_TT_CONST_IV) {
BINDTO[wasmMod.UTF8ToString(loadType(mainindex, 1))] = loadType(mainindex, 2);
}
else if(typeType === BINDTO.ET_TT_CONST_CSTRING) {
BINDTO[wasmMod.UTF8ToString(loadType(mainindex, 1))] = wasmMod.UTF8ToString(loadType(mainindex, 2));
}
else if(typeType === BINDTO.ET_TT_ST) {
const struct = { name: wasmMod.UTF8ToString(loadType(mainindex, 1)), size: loadType(mainindex, 2), members : {}};
currentObject.push(struct);
}
else if(typeType === BINDTO.ET_TT_ST_END) {
const structmeta = currentObject.pop();
const structPrototype = {
members : structmeta.members,
get : function(memberName) {
const ptr = (this.ptr + this.members[memberName].offset);
if(this.members[memberName].type === BINDTO.ET_TT_UINT32) {
return wasmMod.HEAPU32[ptr >> 2];
}
else if(this.members[memberName].type === BINDTO.ET_TT_UINT64) {
return BigInt(wasmMod.HEAPU32[ptr >> 2]) + (BigInt(wasmMod.HEAPU32[(ptr+4) >> 2]) << BigInt(32));
}
else if(this.members[memberName].type === BINDTO.ET_TT_UINT16) {
return wasmMod.HEAPU16[ptr >> 1];
}
else if(this.members[memberName].type === BINDTO.ET_TT_UINT8) {
return wasmMod.HEAPU8[ptr];
}
throw("ENOTIMPLEMENTED");
}
};
const struct = function(ptr) {
this.ptr = ptr;
};
struct.prototype = structPrototype;
struct.prototype.constructor = struct;
( run in 0.416 second using v1.01-cache-2.11-cpan-e1769b4cff6 )