|
@@ -0,0 +1,198 @@
|
|
|
|
+import { computed, defineComponent, onMounted, reactive, ref, watch } from "vue";
|
|
|
|
+import styles from "./index.module.less";
|
|
|
|
+import { getMidiCurrentTime, getMidiDuration, handleTogglePlayMidi, hanldeInitMidiData, hanldeSetMidiPlaybackRate, setMidiCurrentTime } from "./midiPlayer";
|
|
|
|
+import state, { IPlayState, onEnded, onLoadedmetadata, onPlay, onTimeupdate } from "/src/state";
|
|
|
|
+import { Howl } from "howler";
|
|
|
|
+
|
|
|
|
+const audioData = reactive({
|
|
|
|
+ songEle: null as unknown as Howl,
|
|
|
|
+ backgroundEle: null as unknown as Howl,
|
|
|
|
+ midiRender: false,
|
|
|
|
+});
|
|
|
|
+const midiRef = ref();
|
|
|
|
+/** 播放或暂停 */
|
|
|
|
+export const audioListStart = (type: "play" | "paused") => {
|
|
|
|
+ // 如果是midi播放
|
|
|
|
+ if (audioData.midiRender) {
|
|
|
|
+ handleTogglePlayMidi(type);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (type === "play") {
|
|
|
|
+ audioData.songEle?.play();
|
|
|
|
+ audioData.backgroundEle?.play();
|
|
|
|
+ } else if (type === "paused") {
|
|
|
|
+ audioData.songEle?.pause();
|
|
|
|
+ audioData.backgroundEle?.pause();
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+/** 设置倍数播放 */
|
|
|
|
+export const setAudioPlaybackRate = (rate: number) => {
|
|
|
|
+ // 如果是midi播放
|
|
|
|
+ if (audioData.midiRender) {
|
|
|
|
+ hanldeSetMidiPlaybackRate(rate);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ audioData.songEle?.rate(rate);
|
|
|
|
+ audioData.backgroundEle?.rate(rate);
|
|
|
|
+ // audioData.songEle && (audioData.songEle.playbackRate = rate);
|
|
|
|
+ // audioData.backgroundEle && (audioData.backgroundEle.playbackRate = rate);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/** 获取当前播放的时间 */
|
|
|
|
+export const getAudioCurrentTime = () => {
|
|
|
|
+ console.log(audioData.songEle);
|
|
|
|
+ // 如果是midi播放
|
|
|
|
+ if (audioData.midiRender) {
|
|
|
|
+ const c = getMidiCurrentTime();
|
|
|
|
+ return c;
|
|
|
|
+ }
|
|
|
|
+ console.log(audioData.songEle);
|
|
|
|
+ console.log(audioData.songEle?.seek(), audioData.backgroundEle?.seek());
|
|
|
|
+ return audioData.songEle?.seek(), audioData.backgroundEle?.seek() || 0;
|
|
|
|
+ // return audioData.songEle?.currentTime || audioData.backgroundEle?.currentTime || 0;
|
|
|
|
+};
|
|
|
|
+/** 获取曲谱的总时间 */
|
|
|
|
+export const getAudioDuration = () => {
|
|
|
|
+ // 如果是midi播放
|
|
|
|
+ if (audioData.midiRender) {
|
|
|
|
+ const d = getMidiDuration();
|
|
|
|
+ return d;
|
|
|
|
+ }
|
|
|
|
+ return audioData.songEle?.duration || audioData.backgroundEle?.duration || 0;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/** 设置播放的开始时间 */
|
|
|
|
+export const setAudioCurrentTime = (time: number, index = 0) => {
|
|
|
|
+ // 如果是midi播放
|
|
|
|
+ if (audioData.midiRender) {
|
|
|
|
+ setMidiCurrentTime(index);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ audioData.songEle?.seek(time);
|
|
|
|
+ audioData.backgroundEle?.seek(time);
|
|
|
|
+ // audioData.songEle && (audioData.songEle.currentTime = time);
|
|
|
|
+ // audioData.backgroundEle && (audioData.backgroundEle.currentTime = time);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/** 设置当前没有播放的音频静音 */
|
|
|
|
+export const toggleMutePlayAudio = (source: IPlayState, muted: boolean) => {
|
|
|
|
+ if (source === "music") {
|
|
|
|
+ if (audioData.songEle) {
|
|
|
|
+ // audioData.songEle.muted = muted;
|
|
|
|
+ audioData.songEle?.mute(true);
|
|
|
|
+ }
|
|
|
|
+ } else if (source === "background") {
|
|
|
|
+ if (audioData.backgroundEle) {
|
|
|
|
+ // audioData.backgroundEle.muted = muted;
|
|
|
|
+ audioData.backgroundEle?.mute(true);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/** 检测音源数量 */
|
|
|
|
+export const detectTheNumberOfSoundSources = () => {
|
|
|
|
+ let total = 0;
|
|
|
|
+ if (audioData.songEle) total += 1;
|
|
|
|
+ if (audioData.backgroundEle) total += 1;
|
|
|
|
+ return total;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+export default defineComponent({
|
|
|
|
+ name: "audio-list",
|
|
|
|
+ setup() {
|
|
|
|
+ /** 原音是否静音 */
|
|
|
|
+ const isMusicMuted = computed(() => {
|
|
|
|
+ return state.playSource === "music";
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ /** iframe 加载完成后, 加载midiURL */
|
|
|
|
+ const handleLoad = () => {
|
|
|
|
+ midiRef.value.contentWindow.handleRendered = () => {
|
|
|
|
+ audioData.midiRender = true;
|
|
|
|
+ };
|
|
|
|
+ hanldeInitMidiData(midiRef.value);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ watch(
|
|
|
|
+ () => state.playSource,
|
|
|
|
+ () => {
|
|
|
|
+ if (state.playSource === "music") {
|
|
|
|
+ audioData.songEle?.mute(false);
|
|
|
|
+ audioData.backgroundEle?.mute(true);
|
|
|
|
+ } else {
|
|
|
|
+ audioData.songEle?.mute(true);
|
|
|
|
+ audioData.backgroundEle?.mute(false);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ onMounted(() => {
|
|
|
|
+ if (state.music) {
|
|
|
|
+ audioData.songEle = new Howl({
|
|
|
|
+ src: [state.music],
|
|
|
|
+ format: ["mp3"],
|
|
|
|
+ onloaderror: () => {
|
|
|
|
+ audioData.songEle = null as any;
|
|
|
|
+ },
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ if (state.accompany) {
|
|
|
|
+ try {
|
|
|
|
+ audioData.backgroundEle = new Howl({
|
|
|
|
+ src: [state.accompany],
|
|
|
|
+ format: ["mp3"],
|
|
|
|
+ onloaderror: () => {
|
|
|
|
+ audioData.backgroundEle = null as any;
|
|
|
|
+ },
|
|
|
|
+ });
|
|
|
|
+ } catch (error) {}
|
|
|
|
+ }
|
|
|
|
+ if (audioData.songEle) {
|
|
|
|
+ audioData.songEle.on("play", onPlay);
|
|
|
|
+ audioData.backgroundEle?.mute(true)
|
|
|
|
+ } else if (audioData.backgroundEle) {
|
|
|
|
+ audioData.backgroundEle.on("play", onPlay);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // console.log(state.playMode, state.midiUrl);
|
|
|
|
+ return () => (
|
|
|
|
+ <div class={styles.audioList}>
|
|
|
|
+ {state.playMode === "MIDI" && state.speed != 0 && <iframe style={{ display: "none" }} ref={midiRef} src={`/midi/index.html`} onLoad={handleLoad} />}
|
|
|
|
+ {state.playMode !== "MIDI" && (
|
|
|
|
+ <div>
|
|
|
|
+ <audio
|
|
|
|
+ preload="auto"
|
|
|
|
+ ref={(el: any) => {
|
|
|
|
+ if (el) {
|
|
|
|
+ el.playbackRate = 3.0
|
|
|
|
+ // audioData.songEle = el as HTMLAudioElement;
|
|
|
|
+ }
|
|
|
|
+ }}
|
|
|
|
+ src={state.music}
|
|
|
|
+ onLoadedmetadata={onLoadedmetadata}
|
|
|
|
+ onPlay={onPlay}
|
|
|
|
+ onTimeupdate={onTimeupdate}
|
|
|
|
+ onEnded={onEnded}
|
|
|
|
+ controls
|
|
|
|
+ playsinline="false"
|
|
|
|
+
|
|
|
|
+ />
|
|
|
|
+ <audio
|
|
|
|
+ muted={isMusicMuted.value}
|
|
|
|
+ preload="auto"
|
|
|
|
+ ref={(el) => {
|
|
|
|
+ if (state.accompany) {
|
|
|
|
+ // audioData.backgroundEle = el as HTMLAudioElement;
|
|
|
|
+ }
|
|
|
|
+ }}
|
|
|
|
+ src={state.accompany}
|
|
|
|
+ controls
|
|
|
|
+ playsinline="false"
|
|
|
|
+ />
|
|
|
|
+ </div>
|
|
|
|
+ )}
|
|
|
|
+ </div>
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+});
|