Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[project-s]再生周りの機能を追加 #1184

Merged
merged 12 commits into from
Mar 1, 2023
Merged
117 changes: 99 additions & 18 deletions src/components/Sing/ToolBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,37 @@
<img :src="selectedStyleIconPath" class="singer-avatar" />
</div>
<div class="sing-player">
<button type="button" class="sing-button-temp">戻る</button>
<button type="button" class="sing-button-temp">再生</button>
<div class="sing-player-position">00:00</div>
<q-btn
flat
round
class="sing-transport-button"
icon="skip_previous"
@click="seek(0)"
></q-btn>
<q-btn
v-if="!nowPlaying"
round
class="sing-playback-button"
icon="play_arrow"
@click="play"
></q-btn>
<q-btn
v-else
round
class="sing-playback-button"
icon="stop"
@click="stop"
></q-btn>
<q-btn flat round class="sing-transport-button" icon="loop"></q-btn>
<div class="sing-playback-position">{{ playbackPositionStr }}</div>
<q-input
type="number"
:model-value="tempoInputBuffer"
dense
hide-bottom-space
class="sing-tempo"
@update:model-value="setTempoInputBuffer"
@change="setTempo()"
@change="setTempo"
>
<template v-slot:prepend>
<div />
Expand All @@ -31,7 +51,7 @@
hide-bottom-space
class="sing-time-signature"
@update:model-value="setBeatsInputBuffer"
@change="setTimeSignature()"
@change="setTimeSignature"
>
<template v-slot:prepend>
<div />
Expand All @@ -45,15 +65,15 @@
hide-bottom-space
class="sing-time-signature"
@update:model-value="setBeatTypeInputBuffer"
@change="setTimeSignature()"
@change="setTimeSignature"
>
<template v-slot:prepend>
<div />
</template>
</q-input>
</div>
<div class="sing-setting">
<input type="range" min="0" max="100" class="sing-volume" />
<q-slider v-model.number="volume" class="sing-volume" />
<select class="sing-snap">
<option>1/16</option>
</select>
Expand Down Expand Up @@ -105,7 +125,7 @@ export default defineComponent({

const setTempoInputBuffer = (tempoStr: string) => {
const tempo = Number(tempoStr);
if (Number.isNaN(tempo) || tempo <= 0) return;
if (!Number.isFinite(tempo) || tempo <= 0) return;
tempoInputBuffer.value = tempo;
};
const setBeatsInputBuffer = (beatsStr: string) => {
Expand All @@ -119,31 +139,58 @@ export default defineComponent({
beatTypeInputBuffer.value = beatType;
};

const playbackPositionStr = ref("");

const updatePlayPos = () => {
const playPos = store.getters.GET_PLAYBACK_POSITION();
const playTime = store.getters.POSITION_TO_TIME(playPos);

const intPlayTime = Math.floor(playTime);
const min = Math.floor(intPlayTime / 60);
const minStr = String(min).padStart(2, "0");
const secStr = String(intPlayTime - min * 60).padStart(2, "0");
const match = String(playTime).match(/\.(\d+)$/);
const milliSecStr = (match?.[1] ?? "0").padEnd(3, "0").substring(0, 3);

playbackPositionStr.value = `${minStr}:${secStr}.${milliSecStr}`;
};
sigprogramming marked this conversation as resolved.
Show resolved Hide resolved

const tempos = computed(() => store.state.score?.tempos);
const timeSignatures = computed(() => store.state.score?.timeSignatures);
const nowPlaying = computed(() => store.state.nowPlaying);

watch(
tempos,
() => {
tempoInputBuffer.value = tempos.value?.[0].tempo ?? 0;
updatePlayPos();
},
{ deep: true }
);
watch(
timeSignatures,
() => {
beatsInputBuffer.value = timeSignatures.value?.[0].beats ?? 0;
},
{ deep: true }
);
watch(
timeSignatures,
() => {
beatTypeInputBuffer.value = timeSignatures.value?.[0].beatType ?? 0;
updatePlayPos();
},
{ deep: true }
);

let requestId: number | undefined = undefined;
watch(nowPlaying, (newState) => {
if (newState) {
const updateView = () => {
updatePlayPos();
requestId = window.requestAnimationFrame(updateView);
};
updateView();
} else if (requestId !== undefined) {
window.cancelAnimationFrame(requestId);
requestId = undefined;
}
});

const setTempo = async () => {
const tempo = tempoInputBuffer.value;
if (tempo === 0) return;
Expand All @@ -168,6 +215,28 @@ export default defineComponent({
});
};

const play = () => {
store.dispatch("SING_PLAY_AUDIO");
};

const stop = () => {
store.dispatch("SING_STOP_AUDIO");
};

const seek = async (position: number) => {
await store.dispatch("SET_PLAYBACK_POSITION", { position });
updatePlayPos();
};

const volume = computed({
get() {
return store.state.volume * 100;
},
set(value: number) {
store.dispatch("SET_VOLUME", { volume: value / 100 });
},
});

return {
isShowSinger,
toggleShowSinger,
Expand All @@ -180,6 +249,12 @@ export default defineComponent({
setBeatTypeInputBuffer,
setTempo,
setTimeSignature,
playbackPositionStr,
nowPlaying,
play,
stop,
seek,
volume,
};
},
});
Expand Down Expand Up @@ -228,12 +303,17 @@ export default defineComponent({
display: flex;
}

.sing-button-temp {
.sing-transport-button {
margin: 0 1px;
}

.sing-playback-button {
margin: 0 4px;
}

.sing-tempo {
margin: 0 4px;
margin-left: 16px;
margin-right: 4px;
width: 64px;
}

Expand All @@ -242,9 +322,10 @@ export default defineComponent({
width: 36px;
}

.sing-player-position {
.sing-playback-position {
font-size: 18px;
margin: 0 4px;
min-width: 82px;
}

.sing-setting {
Expand All @@ -254,7 +335,7 @@ export default defineComponent({
}

.sing-volume {
margin-right: 4px;
margin-right: 10px;
width: 72px;
}
</style>
5 changes: 5 additions & 0 deletions src/helpers/singHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,8 @@ export const midiKeys = [...Array(128)]
};
})
.reverse();

export function round(value: number, digits: number) {
const powerOf10 = 10 ** digits;
return Math.round(value * powerOf10) / powerOf10;
}
Loading