import { reactive } from 'vue'; import tockAndTick from './tockAndTick.json'; import { Howl } from 'howler'; import { initSelectScorePart, initSelectScorePartModal, setting, setting_modal } from './setting'; import { beatDesc } from './beat-desc'; const tickData = reactive({ list: [] as number[], len: 0, // 有几拍 afterBeat: 0, // 一小节里面有几拍 tickEnd: false, /** 节拍器时间 */ beatLengthInMilliseconds: 0, state: '', source1: '' as any, source2: '' as any, index: 0, show: false }); // console.log(setting, 'setting') let defaultSetting = { // playState: setting.playState, // speed: setting.speed, // scorePart: setting.scorePart } as any let diffTime = 0; // 每一次节拍时间差 const handlePlay = (i: number, source: any) => { let payBeatTime = new Date().getTime(); return new Promise(resolve => { if (tickData.tickEnd) { resolve(i); return; } let timeSppedEnum = 16.7; const proofTime = () => { if (defaultSetting.playState !== 'play') { return; } setTimeout(() => { if (tickData.tickEnd) { resolve(i); return; } const currentTime = new Date().getTime(); // 两次定时任务时间间隔 const diffTime = currentTime - payBeatTime; if (diffTime >= tickData.beatLengthInMilliseconds) { tickData.index++; if (source) source.play(); resolve(i); payBeatTime = currentTime; } else { if ( Math.abs(diffTime - tickData.beatLengthInMilliseconds) <= timeSppedEnum ) { // 为了处理最后循环时间,用循环耗时 for (let index = 0; index < 500000; index++) { let forTime = new Date().getTime(); if ( Math.abs(forTime - payBeatTime) >= tickData.beatLengthInMilliseconds ) { tickData.index++; if (source) source.play(); resolve(i); payBeatTime = forTime; break; } } } else { proofTime(); } } }, timeSppedEnum); }; proofTime(); }); }; /** 设置节拍器 * @param beatLengthInMilliseconds 节拍间隔时间 * @param beat 节拍数 */ export const handleInitTick = ( beatLengthInMilliseconds: number, beat: number, afterBeat: number ) => { tickData.state = ''; tickData.beatLengthInMilliseconds = beatLengthInMilliseconds; tickData.len = beat; tickData.afterBeat = afterBeat; }; /** 开始节拍器 * @param {boolean} 是否开启了设置 */ export const handleStartTick = async (settingStatus = false) => { const tempSetting = settingStatus ? setting_modal : setting defaultSetting = { playState: tempSetting.playState, speed: tempSetting.speed, scorePart: tempSetting.scorePart } tickData.show = true; tickData.tickEnd = false; if (tickData.state !== 'ok') { tickData.source1 = new Howl({ src: tockAndTick.tick }); tickData.source2 = new Howl({ src: tockAndTick.tock }); tickData.state = 'ok'; } tickData.index = 0; tickData.beatLengthInMilliseconds = (60 / defaultSetting.speed) * 1000; if (tickData.afterBeat === 8) { tickData.beatLengthInMilliseconds = tickData.beatLengthInMilliseconds * 0.5; } for (let i = 0; i < defaultSetting.scorePart.length; i++) { if (tickData.tickEnd) return false; const temp = defaultSetting.scorePart[i]; let len = temp.length; if (tickData.afterBeat === 8) { len = tickData.len; } for (let j = 0; j < len; j++) { // 提前结束, 直接放回false if (tickData.tickEnd) return false; const source = j === 0 ? tickData.source1 : j === len ? null : tickData.source2; await handlePlay(j, source); const tempJ = tickData.afterBeat === 8 ? Math.floor((j <= 0 ? 1 : j) / 3) : j if (settingStatus) { initSelectScorePartModal(i, tempJ) } else { initSelectScorePart(i, tempJ); } defaultSetting.playState = settingStatus ? setting_modal.playState : setting.playState if (defaultSetting.playState !== 'play') { hendleEndTick(settingStatus) } } } // console.log(+new Date() - startTime); tickData.show = false; handleStartTick(settingStatus); return true; }; /** 节拍器暂停 * @param {boolean} 是否开启了设置 */ export const hendleEndTick = (settingStatus = false) => { tickData.tickEnd = true; // 添加延期是因为播放时定时任务播放最多有16.7毫秒的延迟 if (settingStatus) { initSelectScorePartModal() } else { initSelectScorePart(); } };