This commit is contained in:
Your Name
2026-08-17 13:59:12 +08:00
parent 79601ea176
commit 49309b7c57
62 changed files with 82 additions and 47023 deletions
@@ -1,238 +1,2 @@
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
const common_vendor = require("../../common/vendor.js");
class AudioPool {
constructor(src, size, volume = 1) {
__publicField(this, "list", []);
__publicField(this, "cursor", 0);
__publicField(this, "warmedUp", false);
__publicField(this, "targetVolume", 1);
this.src = src;
this.size = size;
this.targetVolume = volume;
}
create() {
for (let i = 0; i < this.size; i++) {
const ctx = common_vendor.index.createInnerAudioContext();
ctx.src = this.src;
ctx.obeyMuteSwitch = false;
ctx.autoplay = false;
ctx.volume = this.targetVolume;
this.list.push(ctx);
}
}
setVolume(volume) {
this.targetVolume = Math.max(0, Math.min(1, volume));
this.list.forEach((ctx) => {
try {
ctx.volume = this.targetVolume;
} catch (_) {
}
});
}
/**
* 预热:短暂播放,让音频文件下载/解码到内存
* 真正首次 play 不会再卡冷启动
*/
warmUp() {
if (this.warmedUp)
return;
if (this.list.length === 0)
this.create();
this.list.forEach((ctx) => {
try {
ctx.volume = 0;
ctx.play();
setTimeout(() => {
try {
ctx.stop();
ctx.volume = this.targetVolume;
} catch (_) {
}
}, 60);
} catch (_) {
}
});
this.warmedUp = true;
}
play() {
if (this.list.length === 0) {
this.create();
this.warmUp();
}
const ctx = this.list[this.cursor];
this.cursor = (this.cursor + 1) % this.list.length;
try {
this.list.forEach((c) => {
try {
c.stop();
} catch (_) {
}
});
ctx.play();
} catch (_) {
try {
ctx.play();
} catch (__) {
}
}
}
destroy() {
this.list.forEach((ctx) => {
var _a;
try {
(_a = ctx.destroy) == null ? void 0 : _a.call(ctx);
} catch (_) {
}
});
this.list = [];
this.warmedUp = false;
}
}
const DEFAULT_CLICK_SRC = "https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260526/20260526105128557ef8669.mp3";
function useMetronome(options = {}) {
const {
initialBpm = 80,
bpmMin = 40,
bpmMax = 240,
clickSrc = DEFAULT_CLICK_SRC,
accentSrc,
poolSize = 4,
volume = 1,
silent = false,
onBeat
} = options;
const bpm = common_vendor.ref(initialBpm);
const isPlaying = common_vendor.ref(false);
const beatIndex = common_vendor.ref(0);
const isAccent = common_vendor.ref(false);
const accentEveryRef = common_vendor.ref(options.accentEvery ?? 4);
const intervalMs = common_vendor.computed(() => 6e4 / bpm.value);
let clickPool = null;
let accentPool = null;
let timer = null;
let nextTickAt = 0;
const ensureAudio = () => {
if (silent)
return;
if (!clickPool) {
clickPool = new AudioPool(clickSrc, poolSize, volume);
clickPool.warmUp();
}
if (accentSrc && !accentPool) {
accentPool = new AudioPool(accentSrc, Math.max(2, Math.ceil(poolSize / 2)), volume);
accentPool.warmUp();
}
};
const playSound = (accent) => {
if (accent && accentPool) {
accentPool.play();
} else if (clickPool) {
clickPool.play();
}
};
const tick = () => {
if (!isPlaying.value)
return;
const every = Math.max(1, accentEveryRef.value);
const accent = beatIndex.value % every === 0;
isAccent.value = accent;
playSound(accent);
onBeat == null ? void 0 : onBeat(beatIndex.value, accent);
beatIndex.value++;
nextTickAt += intervalMs.value;
const nextDelay = Math.max(0, nextTickAt - Date.now());
timer = setTimeout(tick, nextDelay);
};
const start = () => {
if (isPlaying.value)
return;
ensureAudio();
isPlaying.value = true;
beatIndex.value = 0;
nextTickAt = Date.now();
tick();
};
const stop = () => {
isPlaying.value = false;
if (timer) {
clearTimeout(timer);
timer = null;
}
};
const setBpm = (val) => {
bpm.value = Math.max(bpmMin, Math.min(bpmMax, Math.round(val)));
};
const setAccentEvery = (n) => {
accentEveryRef.value = Math.max(1, Math.min(16, Math.round(n)));
beatIndex.value = 0;
};
const updateAudioSrc = (newClickSrc, newAccentSrc) => {
const wasPlaying = isPlaying.value;
if (wasPlaying)
stop();
clickPool == null ? void 0 : clickPool.destroy();
accentPool == null ? void 0 : accentPool.destroy();
clickPool = null;
accentPool = null;
clickPool = new AudioPool(newClickSrc, poolSize);
if (newAccentSrc) {
accentPool = new AudioPool(newAccentSrc, Math.max(2, Math.ceil(poolSize / 2)));
}
const previewCtx = common_vendor.index.createInnerAudioContext();
previewCtx.src = newClickSrc;
previewCtx.obeyMuteSwitch = false;
previewCtx.volume = 0.4;
try {
previewCtx.play();
setTimeout(() => {
var _a;
try {
(_a = previewCtx.destroy) == null ? void 0 : _a.call(previewCtx);
} catch (_) {
}
}, 500);
} catch (_) {
}
if (wasPlaying)
start();
};
const preload = () => {
try {
common_vendor.index.setInnerAudioOption({
obeyMuteSwitch: false,
mixWithOther: true
});
} catch (_) {
}
ensureAudio();
};
common_vendor.onUnmounted(() => {
stop();
clickPool == null ? void 0 : clickPool.destroy();
accentPool == null ? void 0 : accentPool.destroy();
clickPool = null;
accentPool = null;
});
return {
bpm,
isPlaying,
beatIndex,
isAccent,
intervalMs,
accentEvery: accentEveryRef,
start,
stop,
setBpm,
setAccentEvery,
updateAudioSrc,
preload
};
}
exports.useMetronome = useMetronome;
"use strict";var R=Object.defineProperty;var B=(l,t,e)=>t in l?R(l,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):l[t]=e;var m=(l,t,e)=>(B(l,typeof t!="symbol"?t+"":t,e),e);const i=require("../../common/vendor.js");class d{constructor(t,e,o=1){m(this,"list",[]);m(this,"cursor",0);m(this,"warmedUp",!1);m(this,"targetVolume",1);this.src=t,this.size=e,this.targetVolume=o}create(){for(let t=0;t<this.size;t++){const e=i.index.createInnerAudioContext();e.src=this.src,e.obeyMuteSwitch=!1,e.autoplay=!1,e.volume=this.targetVolume,this.list.push(e)}}setVolume(t){this.targetVolume=Math.max(0,Math.min(1,t)),this.list.forEach(e=>{try{e.volume=this.targetVolume}catch{}})}warmUp(){this.warmedUp||(this.list.length===0&&this.create(),this.list.forEach(t=>{try{t.volume=0,t.play(),setTimeout(()=>{try{t.stop(),t.volume=this.targetVolume}catch{}},60)}catch{}}),this.warmedUp=!0)}play(){this.list.length===0&&(this.create(),this.warmUp());const t=this.list[this.cursor];this.cursor=(this.cursor+1)%this.list.length;try{this.list.forEach(e=>{try{e.stop()}catch{}}),t.play()}catch{try{t.play()}catch{}}}destroy(){this.list.forEach(t=>{var e;try{(e=t.destroy)==null||e.call(t)}catch{}}),this.list=[],this.warmedUp=!1}}const F="https://gz-1349751149.cos.ap-guangzhou.myqcloud.com/uploads/file/20260526/20260526105128557ef8669.mp3";function K(l={}){const{initialBpm:t=80,bpmMin:e=40,bpmMax:o=240,clickSrc:z=F,accentSrc:U,poolSize:f=4,volume:A=1,silent:I=!1,onBeat:v}=l,M=i.ref(t),u=i.ref(!1),c=i.ref(0),E=i.ref(!1),w=i.ref(l.accentEvery??4),b=i.computed(()=>6e4/M.value);let s=null,a=null,y=null,g=0;const S=()=>{I||(s||(s=new d(z,f,A),s.warmUp()),U&&!a&&(a=new d(U,Math.max(2,Math.ceil(f/2)),A),a.warmUp()))},D=r=>{r&&a?a.play():s&&s.play()},V=()=>{if(!u.value)return;const r=Math.max(1,w.value),h=c.value%r===0;E.value=h,D(h),v==null||v(c.value,h),c.value++,g+=b.value;const p=Math.max(0,g-Date.now());y=setTimeout(V,p)},T=()=>{u.value||(S(),u.value=!0,c.value=0,g=Date.now(),V())},_=()=>{u.value=!1,y&&(clearTimeout(y),y=null)},C=r=>{M.value=Math.max(e,Math.min(o,Math.round(r)))},q=r=>{w.value=Math.max(1,Math.min(16,Math.round(r))),c.value=0},L=(r,h)=>{const p=u.value;p&&_(),s==null||s.destroy(),a==null||a.destroy(),s=null,a=null,s=new d(r,f),h&&(a=new d(h,Math.max(2,Math.ceil(f/2))));const n=i.index.createInnerAudioContext();n.src=r,n.obeyMuteSwitch=!1,n.volume=.4;try{n.play(),setTimeout(()=>{var x;try{(x=n.destroy)==null||x.call(n)}catch{}},500)}catch{}p&&T()},O=()=>{try{i.index.setInnerAudioOption({obeyMuteSwitch:!1,mixWithOther:!0})}catch{}S()};return i.onUnmounted(()=>{_(),s==null||s.destroy(),a==null||a.destroy(),s=null,a=null}),{bpm:M,isPlaying:u,beatIndex:c,isAccent:E,intervalMs:b,accentEvery:w,start:T,stop:_,setBpm:C,setAccentEvery:q,updateAudioSrc:L,preload:O}}exports.useMetronome=K;
//# sourceMappingURL=../../../.sourcemap/mp-weixin/training/hooks/useMetronome.js.map