1import{r as m}from"./plan-Dx0rPacR.js";import{_ as q}from"./lazy-DrfuMF_V.js";import{t as W}from"./tool-history-DpG0hTNO.js";class x{static instance;context=null;masterGainNode=null;volume=1;isInitialized=!1;constructor(){}static getInstance(){return x.instance||(x.instance=new x),x.instance}getContext(){return this.context||(this.context=new AudioContext,this.masterGainNode=this.context.createGain(),this.masterGainNode.gain.value=this.volume,this.masterGainNode.connect(this.context.destination)),this.context}getMasterGainNode(){if(!this.masterGainNode){const t=this.getContext();this.masterGainNode=t.createGain(),this.masterGainNode.gain.value=this.volume,this.masterGainNode.connect(t.destination)}return this.masterGainNode}async resumeContext(){const t=this.getContext();if(t.state==="running")return!0;if(t.state==="suspended")try{await t.resume()}catch{return!1}return this.getContext().state==="running"}applyAudioSessionType(){"audioSession"in navigator&&(navigator.audioSession.type="playback")}warmupContext(){const t=this.getContext(),e=t.createBuffer(1,1,22050),i=t.createBufferSource();i.buffer=e,i.connect(this.getMasterGainNode());try{return i.start(0),i.onended=()=>{i.disconnect()},!0}catch{return i.disconnect(),!1}}async initialize(){this.applyAudioSessionType();const t=this.getContext();if(this.isInitialized&&t.state==="running")return!0;this.warmupContext();const e=await this.resumeContext();return this.isInitialized=e,e}async primePlaybackFromGesture(){return this.initialize()}setVolume(t){this.volume=t,this.masterGainNode&&(this.masterGainNode.gain.value=t)}}const L=x.getInstance(),U="fish-tool-audio-play";function K(l,t=!0,e="metadata"){const[i,d]=m.useState(null),o=m.useRef(null),h=m.useRef(null),r=m.useRef(0),n=m.useRef(!1),a=m.useRef(null),c=m.useRef(t);c.current=t;const[u,g]=m.useState(0),[v,p]=m.useState(0),[b,S]=m.useState(!1),[T,C]=m.useState(!!l),[R,k]=m.useState(!1),[Q,E]=m.useState(!1),w=m.useCallback(()=>{r.current+=1,n.current=!1,a.current=null,S(!1),k(!1),o.current&&!o.current.paused&&o.current.pause()},[]);m.useEffect(()=>{if(a.current=null,g(0),p(0),S(!1),n.current=!1,k(!1),E(!1),C(!!l),!l)return;const f=typeof l=="string"?l:URL.createObjectURL(l);typeof l!="string"&&d({source:l,url:f});const s=new Audio;o.current=s,h.current=f,s.preload=e;const y=()=>{Number.isFinite(s.duration)&&s.duration>0&&(a.current!==null&&c.current&&(s.currentTime=a.current*s.duration,a.current=null,p(s.currentTime)),g(s.duration),C(!1))},D=()=>p(Number.isFinite(s.currentTime)?s.currentTime:0),F=()=>n.current&&c.current&&document.visibilityState!=="hidden",_=()=>{F()&&!s.paused&&k(!0)},I=()=>{F()&&(S(!0),k(!1),E(!1))},A=()=>{r.current+=1,n.current=!1,S(!1),k(!1)},G=()=>{w(),C(!1),E(!0)},M=V=>{V.detail!==s&&(w(),s.currentTime!==0&&(s.currentTime=0),p(0))},N=()=>{document.visibilityState==="hidden"&&w()};return s.addEventListener("loadedmetadata",y),s.addEventListener("durationchange",y),s.addEventListener("canplay",y),s.addEventListener("timeupdate",D),s.addEventListener("play",_),s.addEventListener("waiting",_),s.addEventListener("playing",I),s.addEventListener("pause",A),s.addEventListener("ended",A),s.addEventListener("error",G),document.addEventListener(U,M),document.addEventListener("visibilitychange",N),e!=="none"&&(s.src=h.current,s.load()),()=>{r.current+=1,n.current=!1,s.paused||s.pause(),s.removeEventListener("loadedmetadata",y),s.removeEventListener("durationchange",y),s.removeEventListener("canplay",y),s.removeEventListener("timeupdate",D),s.removeEventListener("play",_),s.removeEventListener("waiting",_),s.removeEventListener("playing",I),s.removeEventListener("pause",A),s.removeEventListener("ended",A),s.removeEventListener("error",G),document.removeEventListener(U,M),document.removeEventListener("visibilitychange",N),s.removeAttribute("src"),s.load(),o.current=null,h.current=null,typeof l!="string"&&URL.revokeObjectURL(f)}},[l,e,w]),m.useEffect(()=>{t||w()},[t,w]);const P=m.useCallback(async()=>{const f=o.current;if(!f||!t||document.visibilityState==="hidden")return;if(n.current||!f.paused){w();return}const s=++r.current;n.current=!0,k(!0),E(!1),document.dispatchEvent(new CustomEvent(U,{detail:f}));const y=()=>s===r.current&&o.current===f&&c.current&&document.visibilityState!=="hidden";try{if(await L.initialize(),!y()||((!f.src||f.error)&&h.current&&(f.src=h.current,f.load()),await f.play(),!y()))return;E(!1)}catch{if(!y())return;w(),E(!0)}},[t,w]),B=m.useCallback(f=>{const s=o.current;if(!s||!c.current||document.visibilityState==="hidden"||!Number.isFinite(f))return;document.dispatchEvent(new CustomEvent(U,{detail:s}));const y=Math.max(0,Math.min(1,f));if(!Number.isFinite(s.duration)||s.duration<=0){a.current=y,n.current||P();return}const D=y*s.duration;
1s.currentTime=D,p(D),s.paused&&!n.current&&P()},[P]);return{audioUrl:typeof l=="string"?l:i?.source===l?i.url:null,duration:u,currentTime:v,isPlaying:b,isLoading:T,isPlaybackLoading:R,hasError:Q,togglePlayback:P,pause:w,seek:B}}class z{constructor(t,e={}){this.reader=t,this.options=e,this.options.sampleRate&&(this.sampleRate=this.options.sampleRate),this.format=this.options.format||"mp3",this.channels=this.options.channels||1,this.downloadByReader(),this.play=this.play.bind(this),this.pause=this.pause.bind(this),this.emit=this.emit.bind(this)}reader;options;format="mp3";channels=1;loadDone=!1;downloadFailed=!1;downloadError=null;playQueue=null;allData=[];sampleRate=44100;durationCache=-1;playStatus="stop";canplayEmitted=!1;processedChunks=0;minChunksBeforePlay=3;listeners={loadDone:[],stop:[],durationUpdate:[],timeupdate:[],canplay:[],chunkDecoded:[],error:[]};on(t,e){this.listeners[t]=this.listeners[t].filter(i=>i!==e),this.listeners[t].push(e),t==="loadDone"&&this.loadDone?queueMicrotask(()=>e()):t==="error"&&this.downloadFailed&&queueMicrotask(()=>e(this.downloadError))}off(t,e){this.listeners[t]=this.listeners[t].filter(i=>i!==e)}emit(t,...e){this.listeners[t].forEach(i=>i(...e))}computeTime(){if(this.allData.length===0)return;const t=this.allData.reduce((e,i)=>e+(i?.length||0),0);t!==0&&(this.durationCache=t/this.sampleRate,this.emit("durationUpdate",this.durationCache))}tryEmitCanplay(){this.canplayEmitted||(this.emit("canplay"),this.canplayEmitted=!0)}loadDoneHandle(){this.loadDone=!0,this.tryEmitCanplay(),this.emit("loadDone"),!this.options.lowPower&&this.computeTime()}async downloadByReader(){if(!(typeof window>"u"))try{this.format==="wav"||this.format==="pcm"?await this.processWavStream():await this.processMp3Stream()}catch(t){this.downloadFailed=!0,this.downloadError=t,this.emit("error",t)}}async processWavStream(){let t=0,e=new Uint8Array(0);performance.now();let i=!1,d={channels:this.channels,sampleRate:this.sampleRate},o=!1;for(;;){const{done:h,value:r}=await this.reader.read();if(h){this.loadDoneHandle();break}if(e=this.concatTypedArrays(e,r),t+=r.length,performance.now(),o){const n=Math.floor(e.length/2)*2;if(n>0){const a=e.slice(0,n);e=e.slice(n);const c=new Int16Array(a.buffer,a.byteOffset,a.length/2),u=this.int16ToFloat32(c);this.allData.push(u),this.processedChunks++,this.emitChunkDecoded(),this.playQueue&&this.playQueue.push(u),this.processedChunks>=this.minChunksBeforePlay&&this.tryEmitCanplay()}continue}if(!i&&e.length>=44){const n=H(e);n.isValid?(d=n.format,this.sampleRate=d.sampleRate,e=e.slice(44),i=!0):o=!0}if(i){const n=Math.floor(e.length/2)*2;if(n>0){const a=e.slice(0,n);e=e.slice(n);const c=new Int16Array(a.buffer,a.byteOffset,a.length/2),u=this.int16ToFloat32(c);this.allData.push(u),this.processedChunks++,this.emitChunkDecoded(),this.playQueue&&this.playQueue.push(u),this.processedChunks>=this.minChunksBeforePlay&&this.tryEmitCanplay()}}}}async processMp3Stream(){const{MPEGDecoderWebWorker:t}=await q(async()=>{const{MPEGDecoderWebWorker:r}=await import("./index-CmtmhtO4.js");return{MPEGDecoderWebWorker:r}},[],import.meta.url);let e=0,i=new Uint8Array(0);performance.now();const d=new t;let o=null;const h=[];for(;;){const{done:r,value:n}=await this.reader.read();if(r){await Promise.all(h),o?.then(()=>{d.free(),this.loadDoneHandle()});break}i=this.concatTypedArrays(i,n),e+=n.length,performance.now();const a=Math.floor(i.length/2)*2,c=i.slice(0,a);i=i.slice(a),o=d.ready.then(()=>{const u=d.decode(c).then(g=>{const{channelData:v}=g,[p]=v;this.allData.push(p),this.processedChunks++,this.emitChunkDecoded(),this.playQueue&&this.playQueue.push(p),this.processedChunks>=this.minChunksBeforePlay&&this.tryEmitCanplay()}).catch(g=>{console.error(g)});return h.push(u),u})}}waveformCache=null;emitChunkDecoded(){const t=this.allData.reduce((e,i)=>e+i.length,0);this.emit("chunkDecoded",this.processedChunks,t)}get totalSamples(){return this.allData.reduce((t,e)=>t+e.length,0)}get decodedDuration(){return this.sampleRate<=0?0:this.totalSamples/this.sampleRate}get loaded(){return this.loadDone}get processedChunkCount(){return this.processedChunks}getWaveformBars(t){if(this.allData.length===0)return[];if(this.waveformCache&&this.waveformCache.chunks===this.processedChunks&&this.waveformCache.bars.length===t)return this.waveformCache.bars;const e=this.totalSamples;if(e===0)return[];const i=Math.floor(e/t);if(i===0)return[];const d=[];for(let r=0;r<t;r++){const n=r*i;let a=0,c=0,u=i,g=0,v=0,p=0;for(;v<this.allData.length&&g+this.allData[v].length<=n;)g+=this.allData[v].length,v++;for(v<this.allData.length&&(p=n-g);u>0&&v<this.allData.length;){const b=this.allData[v],S=b.length-p,T=Math.min(u,S);for(let C=0;C<T;C++){const R=b[p+C];a+=R*R}c+=T,u-=T,p+=T,p>=b.length&&(v++,p=0)}d.push(c>0?Math.sqrt(a/c):0)}const o=Math.max(...d),h=d.map(r=>{if(o===0)return .1;const n=Math.pow(r/o,.7);return Math.max(.1,n)});return this.waveformCache={chunks:this.processedChunks,bars:h},h}concatTypedArrays(t,e){const i=new Uint8Array(t.length+e.length);return i.set(t,0),i.set(e,t.length),i}audioContext=null;volumeProxy=1;startTime=0;offsetTime=0;waitTimer=null;timeUpdateTimer=null;currentSource=null;requeuePlayList(t){if(t.length!==0){if(!this.playQueue){this.playQueue=t;return}this.playQueue.unshift(...t)}}trackInvalidSourceState(t,e){W("tts_audio_invalid_state_guard_hit",{action:t,playback_status:this.playStatus,error_name:e&&typeof e=="object"&&"name"in e?String(e.name):null,error_message:e instanceof Error?e.message:String(e??"")})}int16ToFloat32(t){const e=new Float32Array(t.length);for(let i=0;i<t.length;i++)e[i]=t[i]/32768;return e}
1timeUpdateFn(){this.playStatus==="playing"&&this.emit("timeupdate",this.currentTime)}async play(){if(!await L.initialize())return this.playStatus="stop",this.emit("stop"),this.emit("timeupdate",this.startTime),!1;if(this.playQueue&&this.playQueue.length===0)return this.loadDone?(this.stop(),!0):(this.playStatus="pending",this.waitTimer=setTimeout(this.play,100),!0);this.waitTimer=null,this.playQueue||(this.playQueue=this.allData.slice());const e=[];for(;this.playQueue.length>0;){const u=this.playQueue.shift();u&&e.push(u)}const i=e.reduce((u,g)=>u+(g?.length||0),0);if(i===0)return this.playStatus="pending",this.waitTimer=setTimeout(this.play,100),!0;const d=this.audioContext===null,o=this.decodedDuration;if(d&&o>0&&this.startTime>=o)return this.requeuePlayList(e),this.loadDone?(this.stop(),!0):(this.playStatus="pending",this.waitTimer=setTimeout(this.play,100),!0);this.audioContext===null&&(this.audioContext=L.getContext(),this.timeUpdateTimer=setInterval(this.timeUpdateFn.bind(this),200)),this.offsetTime=this.audioContext.currentTime;const h=new Float32Array(i);let r=0;e.forEach(u=>{h.set(u,r),r+=u.length});const n=this.audioContext.createBuffer(1,h.length,this.sampleRate);n.copyToChannel(h,0);const a=this.audioContext.createBufferSource();a.buffer=n;const c={node:a,started:!1,ended:!1};this.currentSource=c,a.connect(L.getMasterGainNode()),a.onended=()=>{c.ended=!0,this.currentSource===c&&(this.currentSource=null),this.playStatus==="playing"&&(this.startTime=this.currentTime,setTimeout(()=>{this.play()}))};try{d?a.start(0,this.startTime):a.start(),c.started=!0}catch(u){return this.currentSource=null,this.requeuePlayList(e),a.onended=null,a.disconnect(),this.trackInvalidSourceState("start_current_source",u),this.playStatus="stop",this.emit("stop"),this.emit("timeupdate",this.startTime),!1}return this.playStatus="playing",!0}clearAudioContext(){if(this.currentSource){const t=this.currentSource;if(this.currentSource=null,t.node.onended=null,t.started&&!t.ended)try{t.node.stop()}catch(e){this.trackInvalidSourceState("stop_current_source",e)}try{t.node.disconnect()}catch(e){this.trackInvalidSourceState("disconnect_current_source",e)}}this.audioContext=null,this.offsetTime=0,this.waitTimer&&(clearTimeout(this.waitTimer),this.waitTimer=null),this.timeUpdateTimer&&(clearInterval(this.timeUpdateTimer),this.timeUpdateTimer=null),this.playQueue=null}pause(){this.audioContext&&this.playStatus!=="pending"&&(this.startTime=this.currentTime),this.clearAudioContext(),this.playStatus="pause",this.emit("stop")}stop(){this.clearAudioContext(),this.startTime=0,this.playStatus="stop",this.emit("stop"),this.emit("timeupdate",0)}close(){this.audioContext?.close()}get duration(){return this.durationCache}get volume(){return this.volumeProxy}set volume(t){this.volumeProxy=t,L.setVolume(t)}set currentTime(t){if(this.playStatus==="playing"||this.playStatus==="pending"){this.stop(),this.startTime=t,this.play();return}this.startTime=t}get currentTime(){return this.playStatus==="playing"?(this.audioContext?.currentTime||0)+this.startTime-this.offsetTime:this.startTime}}function O(l,t){return new Promise((e,i)=>{let d=!1;const o=r=>{d||(d=!0,clearTimeout(h),r())},h=setTimeout(()=>o(()=>i(new Error("Timed out waiting for audio load"))),t);l.on("loadDone",()=>o(e)),l.on("error",r=>o(()=>i(r)))})}function H(l){const t=String.fromCharCode(...Array.from(l.slice(0,4))),e=String.fromCharCode(...Array.from(l.slice(8,12)));if(t==="RIFF"&&e==="WAVE"){const i=new DataView(l.buffer,l.byteOffset,44);return{isValid:!0,format:{channels:i.getUint16(22,!0),sampleRate:i.getUint32(24,!0),bitsPerSample:i.getUint16(34,!0)}}}return{isValid:!1}}const X=Object.freeze(Object.defineProperty({__proto__:null,AudioPlayer:z,waitForPlayerLoad:O},Symbol.toStringTag,{value:"Module"}));export{L as a,X as b,K as u,O as w};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.