index.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import { computed, defineComponent, onMounted, reactive, ref, watch } from "vue";
  2. import styles from "./index.module.less";
  3. import {
  4. getMidiCurrentTime,
  5. getMidiDuration,
  6. handleTogglePlayMidi,
  7. hanldeInitMidiData,
  8. hanldeSetMidiPlaybackRate,
  9. setMidiCurrentTime,
  10. } from "./midiPlayer";
  11. import state, { IPlayState, onEnded, onPlay } from "/src/state";
  12. import { api_playProgress, api_cloudTimeUpdae } from "/src/helpers/communication";
  13. import { evaluatingData } from "/src/view/evaluating";
  14. import { cloudToggleState } from "/src/helpers/midiPlay"
  15. export const audioData = reactive({
  16. songEle: null as unknown as HTMLAudioElement,
  17. backgroundEle: null as unknown as HTMLAudioElement,
  18. midiRender: false,
  19. progress: 0,
  20. duration: 0
  21. });
  22. const midiRef = ref();
  23. /** 播放或暂停 */
  24. export const audioListStart = (type: "play" | "paused") => {
  25. // 开始播放之前, 先设置倍数
  26. if (type === "play" && state.originSpeed !== 0) {
  27. setAudioPlaybackRate(state.speed / state.originSpeed);
  28. }
  29. console.log('api','midi状态1',type,audioData.midiRender)
  30. // 如果是midi播放
  31. if (audioData.midiRender) {
  32. // handleTogglePlayMidi(type);
  33. cloudToggleState(type);
  34. return;
  35. }
  36. if (type === "play") {
  37. audioData.songEle?.play();
  38. audioData.backgroundEle?.play();
  39. } else if (type === "paused") {
  40. audioData.songEle?.pause();
  41. audioData.backgroundEle?.pause();
  42. }
  43. };
  44. /** 设置倍数播放 */
  45. export const setAudioPlaybackRate = (rate: number) => {
  46. // 如果是midi播放
  47. if (audioData.midiRender) {
  48. hanldeSetMidiPlaybackRate(rate);
  49. return;
  50. }
  51. audioData.songEle && (audioData.songEle.playbackRate = rate);
  52. audioData.backgroundEle && (audioData.backgroundEle.playbackRate = rate);
  53. };
  54. /** 获取当前播放的时间 */
  55. export const getAudioCurrentTime = () => {
  56. // 如果是midi播放
  57. if (audioData.midiRender) {
  58. // const c = getMidiCurrentTime();
  59. return audioData.progress;
  60. }
  61. // console.log('返回的时间',state.playSource, audioData.songEle?.currentTime,audioData.progress)
  62. if (state.playSource === "music") return audioData.songEle?.currentTime || audioData.progress;
  63. if (state.playSource === "background") return audioData.backgroundEle?.currentTime || audioData.progress;
  64. return audioData.songEle?.currentTime || audioData.progress;
  65. };
  66. /** 获取曲谱的总时间 */
  67. export const getAudioDuration = () => {
  68. // 如果是midi播放
  69. if (audioData.midiRender) {
  70. // const d = getMidiDuration();
  71. const songEndTime = state.times[state.times.length - 1 || 0]?.endtime || 0
  72. return audioData.duration || songEndTime;
  73. }
  74. return audioData.songEle?.duration || audioData.backgroundEle?.duration || audioData.duration;
  75. };
  76. /** 设置播放的开始时间 */
  77. export const setAudioCurrentTime = (time: number, index = 0) => {
  78. // console.log('开始时间12345',time)
  79. // 如果是midi播放
  80. if (audioData.midiRender) {
  81. setMidiCurrentTime(index);
  82. return;
  83. }
  84. audioData.songEle && (audioData.songEle.currentTime = time);
  85. audioData.backgroundEle && (audioData.backgroundEle.currentTime = time);
  86. audioData.progress = time;
  87. };
  88. /** 设置当前没有播放的音频静音 */
  89. export const toggleMutePlayAudio = (source: IPlayState, muted: boolean) => {
  90. if (source === "music") {
  91. if (audioData.songEle) {
  92. audioData.songEle.muted = muted;
  93. }
  94. } else if (source === "background") {
  95. if (audioData.backgroundEle) {
  96. audioData.backgroundEle.muted = muted;
  97. }
  98. }
  99. };
  100. /** 检测音源数量 */
  101. export const detectTheNumberOfSoundSources = () => {
  102. let total = 0;
  103. if (audioData.songEle) total += 1;
  104. if (audioData.backgroundEle) total += 1;
  105. return total;
  106. };
  107. export default defineComponent({
  108. name: "audio-list",
  109. setup() {
  110. /** iframe 加载完成后, 加载midiURL */
  111. const handleLoad = () => {
  112. midiRef.value.contentWindow.handleRendered = () => {
  113. audioData.midiRender = true;
  114. };
  115. hanldeInitMidiData(midiRef.value);
  116. };
  117. watch(
  118. () => state.playSource,
  119. () => {
  120. if (state.modeType === "evaluating" && !state.setting.enableAccompaniment) {
  121. console.log("评测模式设置了关闭伴奏,不切换原音伴奏");
  122. return;
  123. }
  124. if (state.playSource === "music") {
  125. audioData.songEle && (audioData.songEle.muted = false);
  126. audioData.backgroundEle && (audioData.backgroundEle.muted = true);
  127. } else {
  128. audioData.songEle && (audioData.songEle.muted = true);
  129. audioData.backgroundEle && (audioData.backgroundEle.muted = false);
  130. }
  131. }
  132. );
  133. const createAudio = (src: string): Promise<HTMLAudioElement | null> => {
  134. return new Promise((resolve) => {
  135. const a = new Audio(src + '?v=' + Date.now());
  136. a.load();
  137. a.onloadedmetadata = () => {
  138. resolve(a);
  139. };
  140. a.onerror = () => {
  141. resolve(null);
  142. };
  143. });
  144. };
  145. // 监听评测曲谱音频播放进度,返回
  146. const progress = (res: any) => {
  147. const currentTime = res?.currentTime || res?.content?.currentTime;
  148. const total = res?.totalDuration || res?.content?.totalDuration;
  149. const time = currentTime / 1000;
  150. audioData.progress = time;
  151. audioData.songEle && (audioData.songEle.currentTime = time);
  152. audioData.backgroundEle && (audioData.backgroundEle.currentTime = time);
  153. audioData.duration = total / 1000;
  154. if (
  155. res?.content?.totalDuration > 1000 &&
  156. currentTime >= total
  157. ) {
  158. if (evaluatingData.isAudioPlayEnd) return
  159. evaluatingData.isAudioPlayEnd = true
  160. onEnded();
  161. }
  162. };
  163. // midi播放进度回调
  164. const midiProgress = (res: any) => {
  165. // console.log('api',res)
  166. const currentTime = res?.currentTime || res?.content?.currentTime;
  167. const total = res?.totalDuration || res?.content?.totalDuration;
  168. const time = currentTime / 1000;
  169. audioData.progress = time;
  170. audioData.duration = total / 1000;
  171. if (
  172. res?.content?.totalDuration > 1000 &&
  173. currentTime >= total
  174. ) {
  175. onEnded();
  176. }
  177. }
  178. onMounted(() => {
  179. if (state.playMode !== "MIDI") {
  180. Promise.all([createAudio(state.music), createAudio(state.accompany)]).then(
  181. ([music, accompany]) => {
  182. // console.log(music, accompany);
  183. if (music) {
  184. audioData.songEle = music;
  185. }
  186. if (accompany) {
  187. audioData.backgroundEle = accompany;
  188. }
  189. if (audioData.songEle) {
  190. audioData.songEle.addEventListener("play", onPlay);
  191. audioData.songEle.addEventListener("ended", onEnded);
  192. accompany && (accompany.muted = true);
  193. } else if (audioData.backgroundEle) {
  194. audioData.backgroundEle.addEventListener("play", onPlay);
  195. audioData.backgroundEle.addEventListener("ended", onEnded);
  196. }
  197. }
  198. );
  199. api_playProgress(progress);
  200. }
  201. // 监听midi播放进度
  202. api_cloudTimeUpdae(midiProgress);
  203. });
  204. // console.log(state.playMode, state.midiUrl);
  205. return () => (
  206. <div class={styles.audioList}>
  207. {state.playMode === "MIDI" && state.speed != 0 && (
  208. <iframe
  209. style={{ display: "none" }}
  210. ref={midiRef}
  211. src={`/midi/index.html`}
  212. onLoad={handleLoad}
  213. />
  214. )}
  215. </div>
  216. );
  217. },
  218. });