supersonic-scsynth 0.21.5 → 0.21.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/supersonic.js +1 -1
- package/dist/wasm/scsynth-nrt.wasm +0 -0
- package/package.json +1 -1
package/dist/supersonic.js
CHANGED
|
@@ -9,7 +9,7 @@ new SuperSonic({
|
|
|
9
9
|
new SuperSonic({
|
|
10
10
|
workerBaseURL: "/supersonic/workers/",
|
|
11
11
|
wasmBaseURL: "/supersonic/wasm/"
|
|
12
|
-
})`);let n={...me,...e.scsynthOptions},a=e.mode||"postMessage";this.#t={mode:a,snapshotIntervalMs:e.snapshotIntervalMs??25,wasmUrl:e.wasmUrl||r+"scsynth-nrt.wasm",wasmBaseURL:r,workletUrl:e.workletUrl||s+"scsynth_audio_worklet.js",workerBaseURL:s,audioContext:e.audioContext||null,autoConnect:e.autoConnect!==!1,audioContextOptions:{latencyHint:"interactive",sampleRate:48e3},memory:pe,worldOptions:n,preschedulerCapacity:e.preschedulerCapacity||65536,activityEvent:{maxLineLength:e.activityEvent?.maxLineLength??200,scsynth:e.activityEvent?.scsynth??null,oscIn:e.activityEvent?.oscIn??null,oscOut:e.activityEvent?.oscOut??null},debug:e.debug??!1,debugScsynth:e.debugScsynth??!1,debugOscIn:e.debugOscIn??!1,debugOscOut:e.debugOscOut??!1,activityConsoleLog:{maxLineLength:e.activityConsoleLog?.maxLineLength??200,scsynth:e.activityConsoleLog?.scsynth??null,oscIn:e.activityConsoleLog?.oscIn??null,oscOut:e.activityConsoleLog?.oscOut??null}},this.#g=e.sampleBaseURL||(t?`${t}samples/`:null)||j.sampleBaseURL,this.#E=e.synthdefBaseURL||(t?`${t}synthdefs/`:null)||j.synthdefBaseURL,this.#y={maxRetries:e.fetchMaxRetries??3,baseDelay:e.fetchRetryDelay??1e3},this.#b=new P({onLoadingEvent:(c,l)=>this.#u(c,l),maxRetries:this.#y.maxRetries,baseDelay:this.#y.baseDelay}),this.bootStats={initStartTime:null,initDuration:null}}get initialized(){return this.#c}get initializing(){return this.#w}get mode(){return this.#t.mode}on(e,t){if(typeof t!="function")throw new Error("Callback must be a function");return this.#R.has(e)||this.#R.set(e,new Set),this.#R.get(e).add(t),()=>this.off(e,t)}off(e,t){let s=this.#R.get(e);return s&&s.delete(t),this}once(e,t){let s=(...r)=>{this.off(e,s),t(...r)};return this.on(e,s)}removeAllListeners(e){return e===void 0?this.#R.clear():this.#R.delete(e),this}#u(e,...t){let s=this.#R.get(e);if(s)for(let r of s)try{r(...t)}catch(n){console.error(`[SuperSonic] Error in ${e} listener:`,n)}}async init(e={}){if(!this.#c)return this.#m?this.#m:(this.#m=this.#se(e),this.#m)}async#se(e){this.#t={...this.#t,...e,audioContextOptions:{...this.#t.audioContextOptions,...e.audioContextOptions||{}}},this.#w=!0,this.bootStats.initStartTime=performance.now();try{this.#ae(),this.#ce(),this.#G(),this.#le(),this.#q();let t=await this.#Z();await this.#Y(t),await this.#Q(),this.#N(),await this.#j()}catch(t){throw this.#w=!1,this.#m=null,console.error("[SuperSonic] Initialization failed:",t),this.#u("error",t),t}}getMetrics(){return this.#X()}setMetricsInterval(e){this.#V=e,this.#N()}stopMetricsPolling(){this.#x()}async#re(){if(!this.#s||!this.#B)return!1;try{await this.#s.resume()}catch{}let e=this.#B[0];await new Promise(r=>setTimeout(r,200));let s=this.#B[0]>e;return s&&this.#ee(),s}async recover(){if(!this.#c)return!1;if(await this.#re())return!0;this.#u("recover:start");let e=await this.#ie();return this.#u("recover:complete",{success:e}),e}async#ie(){if(!this.#c)return!1;let e=new Map(this.loadedSynthDefs),t=this.#o?.getAllocatedBuffers()||[];await this.#ne(),await this.#oe();for(let[s,r]of e)try{await this.send("/d_recv",r)}catch(n){console.error(`[SuperSonic] Failed to restore synthdef ${s}:`,n)}for(let s of t)try{if(this.#t.mode==="postMessage"&&s.source)s.source.type==="file"?await this.loadSample(s.bufnum,s.source.path,s.source.startFrame||0,s.source.numFrames||0):console.warn(`[SuperSonic] Unknown buffer source type: ${s.source.type}`);else{let r=crypto.randomUUID();await this.send("/b_allocPtr",s.bufnum,s.ptr,s.numFrames,s.numChannels,s.sampleRate,r)}}catch(r){console.error(`[SuperSonic] Failed to restore buffer ${s.bufnum}:`,r)}return(e.size>0||t.length>0)&&await this.sync(),!0}async#ne(){this.#z(),this.#x(),this.#l?.clear(),this.#l=null,this.#n&&(this.#n.cancelAll(),this.#n.terminate(),this.#n=null),this.#i&&(this.#i.disconnect(),this.#i=null),this.#s&&(await this.#s.close(),this.#s=null),this.#c=!1,this.loadedSynthDefs.clear(),this.#m=null,this.#a=null,this.#r=null,this.#C=null,this.#T=null,this.#B=null,this.#M=null,this.#O=null,this.#I=null,this.#p=void 0}async#oe(){this.#w=!0,this.bootStats.initStartTime=performance.now();try{this.#G(),this.#o&&this.#o.updateAudioContext(this.#s),this.#q();let e=await this.#Z();await this.#Y(e),await this.#Q(),this.#N(),await this.#j()}catch(e){throw this.#w=!1,this.#m=null,console.error("[SuperSonic] Partial init failed:",e),this.#u("error",e),e}}getTree(){if(!this.#c)return{nodeCount:0,version:0,nodes:[]};let e,t;if(this.#t.mode==="postMessage"){if(!this.#_||!this.#r)return{nodeCount:0,version:0,nodes:[]};e=this.#_,t=this.#r.METRICS_SIZE}else{if(!this.#e||!this.#r)return{nodeCount:0,version:0,nodes:[]};e=this.#e,t=this.#a+this.#r.NODE_TREE_START}let s=this.#r,r=new Uint32Array(e,t,2),n=r[0],a=r[1],c=t+s.NODE_TREE_HEADER_SIZE,l=s.NODE_TREE_MAX_NODES,u=s.NODE_TREE_ENTRY_SIZE,f=s.NODE_TREE_DEF_NAME_SIZE,h=new DataView(e,c,l*u),g=new TextDecoder("utf-8"),p=[],m=0;for(let S=0;S<l&&m<n;S++){let d=S*u,w=h.getInt32(d,!0);if(w===-1)continue;m++;let y=c+d+24,_=new Uint8Array(e,y,f),E=new Uint8Array(f);E.set(_);let b=E.indexOf(0);b===-1&&(b=f);let A=g.decode(E.subarray(0,b));p.push({id:w,parentId:h.getInt32(d+4,!0),isGroup:h.getInt32(d+8,!0)===1,prevId:h.getInt32(d+12,!0),nextId:h.getInt32(d+16,!0),headId:h.getInt32(d+20,!0),defName:A})}return{nodeCount:n,version:a,nodes:p}}get bufferConstants(){return this.#r}get ringBufferBase(){return this.#a}get sharedBuffer(){return this.#e}startCapture(){if(!this.#c||!this.#e||!this.#r)throw new Error("SuperSonic not initialized");let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,4);Atomics.store(s,1,0),Atomics.store(s,0,1)}stopCapture(){if(!this.#c||!this.#e||!this.#r)throw new Error("SuperSonic not initialized");let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,4);Atomics.store(s,0,0);let r=Atomics.load(s,1),n=s[2],a=s[3],c=t+e.AUDIO_CAPTURE_HEADER_SIZE,l=new Float32Array(this.#e,c,r*a),u=new Float32Array(r),f=a>1?new Float32Array(r):null;for(let h=0;h<r;h++)u[h]=l[h*a],f&&(f[h]=l[h*a+1]);return{sampleRate:n,channels:a,frames:r,left:u,right:f}}isCaptureEnabled(){if(!this.#c||!this.#e||!this.#r)return!1;let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,1);return Atomics.load(s,0)===1}getCaptureFrames(){if(!this.#c||!this.#e||!this.#r)return 0;let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,2);return Atomics.load(s,1)}getMaxCaptureDuration(){if(!this.#r)return 0;let e=this.#r;return e.AUDIO_CAPTURE_FRAMES/(e.AUDIO_CAPTURE_SAMPLE_RATE||48e3)}async send(e,...t){if(this.#U("send OSC messages"),e==="/d_load"||e==="/d_loadDir")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Use loadSynthDef() or send /d_recv with synthdef bytes instead.`);if(e==="/b_read"||e==="/b_readChannel")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Use loadSample() to load audio into a buffer.`);if(e==="/b_write"||e==="/b_close")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Writing audio files is not available in the browser.`);if(e==="/clearSched")throw new Error("/clearSched is not supported in SuperSonic. Bundle scheduling works differently in the browser AudioWorklet environment.");if(e==="/dumpOSC")throw new Error("/dumpOSC is not supported in SuperSonic. Use browser developer tools to inspect OSC messages.");if(e==="/error")throw new Error("/error is not supported in SuperSonic. Error notifications are always enabled.");if(e==="/d_recv"){let a=t[0];if(a instanceof Uint8Array||a instanceof ArrayBuffer){let c=a instanceof ArrayBuffer?new Uint8Array(a):a,l=Y(c)||"unknown";this.loadedSynthDefs.set(l,c)}}if(e==="/d_free")for(let a of t)typeof a=="string"&&this.loadedSynthDefs.delete(a);else e==="/d_freeAll"&&this.loadedSynthDefs.clear();let s=t.map(a=>{if(typeof a=="string")return{type:"s",value:a};if(typeof a=="number")return{type:Number.isInteger(a)?"i":"f",value:a};if(a instanceof Uint8Array||a instanceof ArrayBuffer)return{type:"b",value:a instanceof ArrayBuffer?new Uint8Array(a):a};throw new Error(`Unsupported argument type: ${typeof a}`)}),r={address:e,args:s},n=i.osc.encode(r);if(this.#t.debug||this.#t.debugOscOut){let a=this.#t.activityConsoleLog.oscOut??this.#t.activityConsoleLog.maxLineLength,c=t.map(l=>{if(l instanceof Uint8Array||l instanceof ArrayBuffer)return`<${l.byteLength||l.length} bytes>`;let u=JSON.stringify(l);return u.length>a?u.slice(0,a)+"...":u}).join(", ");console.log(`[OSC \u2192] ${e}${c?" "+c:""}`)}return this.sendOSC(n)}async sendOSC(e,t={}){this.#U("send OSC data");let s=this.#be(e),r=await this.#Ae(s);if(this.#L("mainMessagesSent"),this.#L("mainBytesSent",r.length),this.#u("message:sent",r),this.#C?.tryWrite(r)){this.#L("preschedulerBypassed");return}let n=this.#Te(r);if(this.#t.mode==="postMessage"&&!n){this.#i.port.postMessage({type:"osc",oscData:r});return}let a=this.#r?.scheduler_slot_size;if(n&&a&&r.length>a)throw new Error(`OSC bundle too large to schedule (${r.length} > ${a} bytes). Use immediate timestamp (0 or 1) for large messages, or reduce bundle size.`);let c={...t};n&&(c.audioTimeS=n.audioTimeS,c.currentTimeS=n.currentTimeS),this.#n.send(r,c)}cancelTag(e){this.#U("cancel by tag"),this.#n.cancelTag(e)}cancelSession(e){this.#U("cancel by session"),this.#n.cancelSession(e)}cancelSessionTag(e,t){this.#U("cancel by session and tag"),this.#n.cancelSessionTag(e,t)}cancelAllScheduled(){this.#U("cancel all scheduled"),this.#n.cancelAll()}get node(){return this.#h}get osc(){return this.#n}async loadSynthDef(e){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t;if(this.#we(e))t=e;else{if(!this.#E)throw new Error("synthdefBaseURL not configured. Either provide a full path or set synthdefBaseURL in constructor options.");t=`${this.#E}${e}.scsyndef`}let s=Y(t);try{let r=await this.#b.fetch(t,{type:"synthdef",name:s}),n=new Uint8Array(r);return await this.send("/d_recv",n),{name:s,size:n.length}}catch(r){throw console.error("[SuperSonic] Failed to load synthdef:",r),r}}async loadSynthDefs(e){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t={};await Promise.all(e.map(async r=>{try{await this.loadSynthDef(r),t[r]={success:!0}}catch(n){console.error(`[SuperSonic] Failed to load ${r}:`,n),t[r]={success:!1,error:n.message}}}));let s=Object.values(t).filter(r=>r.success).length;return t}async loadSample(e,t,s=0,r=0){this.#U("load samples");let n=await this.#o.prepareFromFile({bufnum:e,path:t,startFrame:s,numFrames:r});return await this.send("/b_allocPtr",e,n.ptr,n.numFrames,n.numChannels,n.sampleRate,n.uuid),n.allocationComplete}async sync(e=Math.floor(Math.random()*2147483647)){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t=new Promise((s,r)=>{let n=setTimeout(()=>{this.#l&&this.#l.delete(e),r(new Error("Timeout waiting for /synced response"))},1e4),a=c=>{clearTimeout(n),this.#l.delete(e),s()};this.#l||(this.#l=new Map),this.#l.set(e,a)});await this.send("/sync",e),await t,this.#t.mode==="postMessage"&&await new Promise(s=>setTimeout(s,this.#t.snapshotIntervalMs*2))}getInfo(){return this.#U("get info"),{sampleRate:this.#s.sampleRate,numBuffers:this.#t.worldOptions.numBuffers,totalMemory:this.#t.memory.totalMemory,wasmHeapSize:this.#t.memory.wasmHeapSize,bufferPoolSize:this.#t.memory.bufferPoolSize,bootTimeMs:this.bootStats.initDuration,capabilities:{...this.#A},version:this.#v}}async shutdown(){!this.#c&&!this.#w||(this.#u("shutdown"),this.#z(),this.#x(),this.#l?.clear(),this.#l=null,this.#n&&(this.#n.cancelAll(),this.#n.terminate(),this.#n=null),this.#i&&(this.#i.disconnect(),this.#i=null),this.#s&&(await this.#s.close(),this.#s=null),this.#o&&(this.#o.destroy(),this.#o=null),this.#d=null,this.#C=null,this.#e=null,this.#c=!1,this.loadedSynthDefs.clear(),this.#m=null,this.#f=null,this.#a=null,this.#r=null,this.#T=null,this.#B=null,this.#M=null,this.#O=null,this.#I=null,this.#_=null,this.#H=0,this.#p=void 0,this.bootStats={initStartTime:null,initDuration:null})}async destroy(){this.#u("destroy"),await this.shutdown(),this.#P=null,this.#R.clear()}async reset(e={}){await this.shutdown(),await this.init(e)}#ae(){this.#A={audioWorklet:typeof AudioWorklet<"u",sharedArrayBuffer:typeof SharedArrayBuffer<"u",crossOriginIsolated:window.crossOriginIsolated===!0,atomics:typeof Atomics<"u",webWorker:typeof Worker<"u"};let e=this.#t.mode,t=["audioWorklet","webWorker"];e==="sab"&&t.push("sharedArrayBuffer","crossOriginIsolated","atomics");let s=t.filter(r=>!this.#A[r]);if(s.length>0){let r=new Error(`Missing required features for ${e} mode: ${s.join(", ")}`);throw e==="sab"&&!this.#A.crossOriginIsolated&&(this.#A.sharedArrayBuffer?r.message+=`
|
|
12
|
+
})`);let n={...me,...e.scsynthOptions},a=e.mode||"postMessage";this.#t={mode:a,snapshotIntervalMs:e.snapshotIntervalMs??25,wasmUrl:e.wasmUrl||r+"scsynth-nrt.wasm",wasmBaseURL:r,workletUrl:e.workletUrl||s+"scsynth_audio_worklet.js",workerBaseURL:s,audioContext:e.audioContext||null,autoConnect:e.autoConnect!==!1,audioContextOptions:{latencyHint:"interactive",sampleRate:48e3},memory:pe,worldOptions:n,preschedulerCapacity:e.preschedulerCapacity||65536,activityEvent:{maxLineLength:e.activityEvent?.maxLineLength??200,scsynth:e.activityEvent?.scsynth??null,oscIn:e.activityEvent?.oscIn??null,oscOut:e.activityEvent?.oscOut??null},debug:e.debug??!1,debugScsynth:e.debugScsynth??!1,debugOscIn:e.debugOscIn??!1,debugOscOut:e.debugOscOut??!1,activityConsoleLog:{maxLineLength:e.activityConsoleLog?.maxLineLength??200,scsynth:e.activityConsoleLog?.scsynth??null,oscIn:e.activityConsoleLog?.oscIn??null,oscOut:e.activityConsoleLog?.oscOut??null}},this.#g=e.sampleBaseURL||j.sampleBaseURL||(t?`${t}samples/`:null),this.#E=e.synthdefBaseURL||j.synthdefBaseURL||(t?`${t}synthdefs/`:null),this.#y={maxRetries:e.fetchMaxRetries??3,baseDelay:e.fetchRetryDelay??1e3},this.#b=new P({onLoadingEvent:(c,l)=>this.#u(c,l),maxRetries:this.#y.maxRetries,baseDelay:this.#y.baseDelay}),this.bootStats={initStartTime:null,initDuration:null}}get initialized(){return this.#c}get initializing(){return this.#w}get mode(){return this.#t.mode}on(e,t){if(typeof t!="function")throw new Error("Callback must be a function");return this.#R.has(e)||this.#R.set(e,new Set),this.#R.get(e).add(t),()=>this.off(e,t)}off(e,t){let s=this.#R.get(e);return s&&s.delete(t),this}once(e,t){let s=(...r)=>{this.off(e,s),t(...r)};return this.on(e,s)}removeAllListeners(e){return e===void 0?this.#R.clear():this.#R.delete(e),this}#u(e,...t){let s=this.#R.get(e);if(s)for(let r of s)try{r(...t)}catch(n){console.error(`[SuperSonic] Error in ${e} listener:`,n)}}async init(e={}){if(!this.#c)return this.#m?this.#m:(this.#m=this.#se(e),this.#m)}async#se(e){this.#t={...this.#t,...e,audioContextOptions:{...this.#t.audioContextOptions,...e.audioContextOptions||{}}},this.#w=!0,this.bootStats.initStartTime=performance.now();try{this.#ae(),this.#ce(),this.#G(),this.#le(),this.#q();let t=await this.#Z();await this.#Y(t),await this.#Q(),this.#N(),await this.#j()}catch(t){throw this.#w=!1,this.#m=null,console.error("[SuperSonic] Initialization failed:",t),this.#u("error",t),t}}getMetrics(){return this.#X()}setMetricsInterval(e){this.#V=e,this.#N()}stopMetricsPolling(){this.#x()}async#re(){if(!this.#s||!this.#B)return!1;try{await this.#s.resume()}catch{}let e=this.#B[0];await new Promise(r=>setTimeout(r,200));let s=this.#B[0]>e;return s&&this.#ee(),s}async recover(){if(!this.#c)return!1;if(await this.#re())return!0;this.#u("recover:start");let e=await this.#ie();return this.#u("recover:complete",{success:e}),e}async#ie(){if(!this.#c)return!1;let e=new Map(this.loadedSynthDefs),t=this.#o?.getAllocatedBuffers()||[];await this.#ne(),await this.#oe();for(let[s,r]of e)try{await this.send("/d_recv",r)}catch(n){console.error(`[SuperSonic] Failed to restore synthdef ${s}:`,n)}for(let s of t)try{if(this.#t.mode==="postMessage"&&s.source)s.source.type==="file"?await this.loadSample(s.bufnum,s.source.path,s.source.startFrame||0,s.source.numFrames||0):console.warn(`[SuperSonic] Unknown buffer source type: ${s.source.type}`);else{let r=crypto.randomUUID();await this.send("/b_allocPtr",s.bufnum,s.ptr,s.numFrames,s.numChannels,s.sampleRate,r)}}catch(r){console.error(`[SuperSonic] Failed to restore buffer ${s.bufnum}:`,r)}return(e.size>0||t.length>0)&&await this.sync(),!0}async#ne(){this.#z(),this.#x(),this.#l?.clear(),this.#l=null,this.#n&&(this.#n.cancelAll(),this.#n.terminate(),this.#n=null),this.#i&&(this.#i.disconnect(),this.#i=null),this.#s&&(await this.#s.close(),this.#s=null),this.#c=!1,this.loadedSynthDefs.clear(),this.#m=null,this.#a=null,this.#r=null,this.#C=null,this.#T=null,this.#B=null,this.#M=null,this.#O=null,this.#I=null,this.#p=void 0}async#oe(){this.#w=!0,this.bootStats.initStartTime=performance.now();try{this.#G(),this.#o&&this.#o.updateAudioContext(this.#s),this.#q();let e=await this.#Z();await this.#Y(e),await this.#Q(),this.#N(),await this.#j()}catch(e){throw this.#w=!1,this.#m=null,console.error("[SuperSonic] Partial init failed:",e),this.#u("error",e),e}}getTree(){if(!this.#c)return{nodeCount:0,version:0,nodes:[]};let e,t;if(this.#t.mode==="postMessage"){if(!this.#_||!this.#r)return{nodeCount:0,version:0,nodes:[]};e=this.#_,t=this.#r.METRICS_SIZE}else{if(!this.#e||!this.#r)return{nodeCount:0,version:0,nodes:[]};e=this.#e,t=this.#a+this.#r.NODE_TREE_START}let s=this.#r,r=new Uint32Array(e,t,2),n=r[0],a=r[1],c=t+s.NODE_TREE_HEADER_SIZE,l=s.NODE_TREE_MAX_NODES,u=s.NODE_TREE_ENTRY_SIZE,f=s.NODE_TREE_DEF_NAME_SIZE,h=new DataView(e,c,l*u),g=new TextDecoder("utf-8"),p=[],m=0;for(let S=0;S<l&&m<n;S++){let d=S*u,w=h.getInt32(d,!0);if(w===-1)continue;m++;let y=c+d+24,_=new Uint8Array(e,y,f),E=new Uint8Array(f);E.set(_);let b=E.indexOf(0);b===-1&&(b=f);let A=g.decode(E.subarray(0,b));p.push({id:w,parentId:h.getInt32(d+4,!0),isGroup:h.getInt32(d+8,!0)===1,prevId:h.getInt32(d+12,!0),nextId:h.getInt32(d+16,!0),headId:h.getInt32(d+20,!0),defName:A})}return{nodeCount:n,version:a,nodes:p}}get bufferConstants(){return this.#r}get ringBufferBase(){return this.#a}get sharedBuffer(){return this.#e}startCapture(){if(!this.#c||!this.#e||!this.#r)throw new Error("SuperSonic not initialized");let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,4);Atomics.store(s,1,0),Atomics.store(s,0,1)}stopCapture(){if(!this.#c||!this.#e||!this.#r)throw new Error("SuperSonic not initialized");let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,4);Atomics.store(s,0,0);let r=Atomics.load(s,1),n=s[2],a=s[3],c=t+e.AUDIO_CAPTURE_HEADER_SIZE,l=new Float32Array(this.#e,c,r*a),u=new Float32Array(r),f=a>1?new Float32Array(r):null;for(let h=0;h<r;h++)u[h]=l[h*a],f&&(f[h]=l[h*a+1]);return{sampleRate:n,channels:a,frames:r,left:u,right:f}}isCaptureEnabled(){if(!this.#c||!this.#e||!this.#r)return!1;let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,1);return Atomics.load(s,0)===1}getCaptureFrames(){if(!this.#c||!this.#e||!this.#r)return 0;let e=this.#r,t=this.#a+e.AUDIO_CAPTURE_START,s=new Uint32Array(this.#e,t,2);return Atomics.load(s,1)}getMaxCaptureDuration(){if(!this.#r)return 0;let e=this.#r;return e.AUDIO_CAPTURE_FRAMES/(e.AUDIO_CAPTURE_SAMPLE_RATE||48e3)}async send(e,...t){if(this.#U("send OSC messages"),e==="/d_load"||e==="/d_loadDir")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Use loadSynthDef() or send /d_recv with synthdef bytes instead.`);if(e==="/b_read"||e==="/b_readChannel")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Use loadSample() to load audio into a buffer.`);if(e==="/b_write"||e==="/b_close")throw new Error(`${e} is not supported in SuperSonic (no filesystem). Writing audio files is not available in the browser.`);if(e==="/clearSched")throw new Error("/clearSched is not supported in SuperSonic. Bundle scheduling works differently in the browser AudioWorklet environment.");if(e==="/dumpOSC")throw new Error("/dumpOSC is not supported in SuperSonic. Use browser developer tools to inspect OSC messages.");if(e==="/error")throw new Error("/error is not supported in SuperSonic. Error notifications are always enabled.");if(e==="/d_recv"){let a=t[0];if(a instanceof Uint8Array||a instanceof ArrayBuffer){let c=a instanceof ArrayBuffer?new Uint8Array(a):a,l=Y(c)||"unknown";this.loadedSynthDefs.set(l,c)}}if(e==="/d_free")for(let a of t)typeof a=="string"&&this.loadedSynthDefs.delete(a);else e==="/d_freeAll"&&this.loadedSynthDefs.clear();let s=t.map(a=>{if(typeof a=="string")return{type:"s",value:a};if(typeof a=="number")return{type:Number.isInteger(a)?"i":"f",value:a};if(a instanceof Uint8Array||a instanceof ArrayBuffer)return{type:"b",value:a instanceof ArrayBuffer?new Uint8Array(a):a};throw new Error(`Unsupported argument type: ${typeof a}`)}),r={address:e,args:s},n=i.osc.encode(r);if(this.#t.debug||this.#t.debugOscOut){let a=this.#t.activityConsoleLog.oscOut??this.#t.activityConsoleLog.maxLineLength,c=t.map(l=>{if(l instanceof Uint8Array||l instanceof ArrayBuffer)return`<${l.byteLength||l.length} bytes>`;let u=JSON.stringify(l);return u.length>a?u.slice(0,a)+"...":u}).join(", ");console.log(`[OSC \u2192] ${e}${c?" "+c:""}`)}return this.sendOSC(n)}async sendOSC(e,t={}){this.#U("send OSC data");let s=this.#be(e),r=await this.#Ae(s);if(this.#L("mainMessagesSent"),this.#L("mainBytesSent",r.length),this.#u("message:sent",r),this.#C?.tryWrite(r)){this.#L("preschedulerBypassed");return}let n=this.#Te(r);if(this.#t.mode==="postMessage"&&!n){this.#i.port.postMessage({type:"osc",oscData:r});return}let a=this.#r?.scheduler_slot_size;if(n&&a&&r.length>a)throw new Error(`OSC bundle too large to schedule (${r.length} > ${a} bytes). Use immediate timestamp (0 or 1) for large messages, or reduce bundle size.`);let c={...t};n&&(c.audioTimeS=n.audioTimeS,c.currentTimeS=n.currentTimeS),this.#n.send(r,c)}cancelTag(e){this.#U("cancel by tag"),this.#n.cancelTag(e)}cancelSession(e){this.#U("cancel by session"),this.#n.cancelSession(e)}cancelSessionTag(e,t){this.#U("cancel by session and tag"),this.#n.cancelSessionTag(e,t)}cancelAllScheduled(){this.#U("cancel all scheduled"),this.#n.cancelAll()}get node(){return this.#h}get osc(){return this.#n}async loadSynthDef(e){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t;if(this.#we(e))t=e;else{if(!this.#E)throw new Error("synthdefBaseURL not configured. Either provide a full path or set synthdefBaseURL in constructor options.");t=`${this.#E}${e}.scsyndef`}let s=Y(t);try{let r=await this.#b.fetch(t,{type:"synthdef",name:s}),n=new Uint8Array(r);return await this.send("/d_recv",n),{name:s,size:n.length}}catch(r){throw console.error("[SuperSonic] Failed to load synthdef:",r),r}}async loadSynthDefs(e){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t={};await Promise.all(e.map(async r=>{try{await this.loadSynthDef(r),t[r]={success:!0}}catch(n){console.error(`[SuperSonic] Failed to load ${r}:`,n),t[r]={success:!1,error:n.message}}}));let s=Object.values(t).filter(r=>r.success).length;return t}async loadSample(e,t,s=0,r=0){this.#U("load samples");let n=await this.#o.prepareFromFile({bufnum:e,path:t,startFrame:s,numFrames:r});return await this.send("/b_allocPtr",e,n.ptr,n.numFrames,n.numChannels,n.sampleRate,n.uuid),n.allocationComplete}async sync(e=Math.floor(Math.random()*2147483647)){if(!this.#c)throw new Error("SuperSonic not initialized. Call init() first.");let t=new Promise((s,r)=>{let n=setTimeout(()=>{this.#l&&this.#l.delete(e),r(new Error("Timeout waiting for /synced response"))},1e4),a=c=>{clearTimeout(n),this.#l.delete(e),s()};this.#l||(this.#l=new Map),this.#l.set(e,a)});await this.send("/sync",e),await t,this.#t.mode==="postMessage"&&await new Promise(s=>setTimeout(s,this.#t.snapshotIntervalMs*2))}getInfo(){return this.#U("get info"),{sampleRate:this.#s.sampleRate,numBuffers:this.#t.worldOptions.numBuffers,totalMemory:this.#t.memory.totalMemory,wasmHeapSize:this.#t.memory.wasmHeapSize,bufferPoolSize:this.#t.memory.bufferPoolSize,bootTimeMs:this.bootStats.initDuration,capabilities:{...this.#A},version:this.#v}}async shutdown(){!this.#c&&!this.#w||(this.#u("shutdown"),this.#z(),this.#x(),this.#l?.clear(),this.#l=null,this.#n&&(this.#n.cancelAll(),this.#n.terminate(),this.#n=null),this.#i&&(this.#i.disconnect(),this.#i=null),this.#s&&(await this.#s.close(),this.#s=null),this.#o&&(this.#o.destroy(),this.#o=null),this.#d=null,this.#C=null,this.#e=null,this.#c=!1,this.loadedSynthDefs.clear(),this.#m=null,this.#f=null,this.#a=null,this.#r=null,this.#T=null,this.#B=null,this.#M=null,this.#O=null,this.#I=null,this.#_=null,this.#H=0,this.#p=void 0,this.bootStats={initStartTime:null,initDuration:null})}async destroy(){this.#u("destroy"),await this.shutdown(),this.#P=null,this.#R.clear()}async reset(e={}){await this.shutdown(),await this.init(e)}#ae(){this.#A={audioWorklet:typeof AudioWorklet<"u",sharedArrayBuffer:typeof SharedArrayBuffer<"u",crossOriginIsolated:window.crossOriginIsolated===!0,atomics:typeof Atomics<"u",webWorker:typeof Worker<"u"};let e=this.#t.mode,t=["audioWorklet","webWorker"];e==="sab"&&t.push("sharedArrayBuffer","crossOriginIsolated","atomics");let s=t.filter(r=>!this.#A[r]);if(s.length>0){let r=new Error(`Missing required features for ${e} mode: ${s.join(", ")}`);throw e==="sab"&&!this.#A.crossOriginIsolated&&(this.#A.sharedArrayBuffer?r.message+=`
|
|
13
13
|
|
|
14
14
|
SharedArrayBuffer is available but cross-origin isolation is not enabled. Please ensure COOP and COEP headers are set correctly:
|
|
15
15
|
Cross-Origin-Opener-Policy: same-origin
|
|
Binary file
|
package/package.json
CHANGED