123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- import { reactive } from 'vue';
- import tockAndTick from './tockAndTick.json';
- import { Howl } from 'howler';
- import { initSelectScorePart, setting } from './setting';
- import { beatDesc } from './beat-desc';
- const beatData = reactive({
- list: [] as number[],
- len: 0,
- tickEnd: false,
- /** 节拍器时间 */
- beatLengthInMilliseconds: 0,
- loopTime: 0, // 循环时长
- state: '',
- source1: '' as any,
- source2: new Howl({
- src: tockAndTick.tock
- }) as any,
- index: 0,
- show: false
- });
- const handlePlay = (i: number, source: any, timer: any) => {
- let payBeatTime = new Date().getTime();
- return new Promise(resolve => {
- if (beatData.tickEnd) {
- resolve(i);
- return;
- }
- let timeSppedEnum = 16.7;
- const proofTime = () => {
- if (setting.playState !== 'play') {
- return;
- }
- setTimeout(() => {
- const currentTime = new Date().getTime();
- // 两次定时任务时间间隔
- const diffTime = currentTime - payBeatTime;
- if (diffTime >= beatData.loopTime) {
- beatData.index++;
- if (timer.type === 'sound') {
- if (source) source.play();
- }
- resolve(i);
- payBeatTime = currentTime;
- } else {
- if (Math.abs(diffTime - beatData.loopTime) <= timeSppedEnum) {
- // 为了处理最后循环时间,用循环耗时
- for (let index = 0; index < 500000; index++) {
- let forTime = new Date().getTime();
- if (Math.abs(forTime - payBeatTime) >= beatData.loopTime) {
- beatData.index++;
- if (timer.type === 'sound') {
- if (source) source.play();
- }
- resolve(i);
- payBeatTime = forTime;
- break;
- }
- }
- } else {
- proofTime();
- }
- }
- }, timeSppedEnum);
- };
- proofTime();
- });
- };
- /** 开始节拍器 */
- export const handleStartBeat = async () => {
- beatData.show = true;
- beatData.tickEnd = false;
- beatData.index = 0;
- beatData.beatLengthInMilliseconds = (60 / setting.speed) * 1000;
- // let startTime = +new Date();
- for (let i = 0; i < setting.scorePart.length; i++) {
- if (beatData.tickEnd) return false;
- for (let j = 0; j < setting.scorePart[i].length; j++) {
- if (beatData.tickEnd) return false;
- // 提前结束, 直接放回false
- const part = setting.scorePart[i][j];
- const params = {
- ...part,
- ...beatDesc[part.index + 1]
- };
- const single16th = beatData.beatLengthInMilliseconds;
- const source = beatData.source2;
- for (let g = 0; g < params.attribute.length; g++) {
- let time = 0;
- const attr = params.attribute[g];
- // 计算每一拍需要的时长
- // 四分音符 有延音
- switch (attr.number) {
- case 4:
- if (attr.point) {
- time = single16th * 0.5 * 3;
- } else {
- time = single16th;
- }
- break;
- case 8:
- // 连音
- if (params.liaison) {
- time = single16th * (1 / params.beatNum);
- } else if (attr.point) {
- time = single16th * 0.25 * 3;
- } else {
- time = single16th * 0.5;
- }
- break;
- case 16:
- if (params.liaison) {
- time = single16th * (1 / params.beatNum);
- } else {
- time = single16th * 0.25;
- }
- break;
- }
- await handlePlay(i, source, {
- time,
- type: attr.type
- });
- beatData.loopTime = time;
- initSelectScorePart(i, j);
- }
- }
- }
- // console.log(+new Date() - startTime);
- beatData.show = false;
- handleStartBeat();
- return true;
- };
- /** 设置节拍器
- * @param beatLengthInMilliseconds 节拍间隔时间
- * @param beat 节拍数
- */
- export const handleInitBeat = (
- beatLengthInMilliseconds: number,
- beat: number
- ) => {
- beatData.state = '';
- beatData.beatLengthInMilliseconds = beatLengthInMilliseconds;
- beatData.loopTime = beatLengthInMilliseconds;
- beatData.len = beat;
- };
- /** 节拍器暂停 */
- export const hendleEndBeat = () => {
- beatData.tickEnd = true;
- initSelectScorePart();
- };
|