midiPlayer.tsx 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import { defineComponent, reactive } from "vue";
  2. import state, { gotoNext, onEnded, onPlay } from "/src/state";
  3. let timer: any = null;
  4. const midiData = reactive({
  5. iframeRef: null as any,
  6. playing: false,
  7. index: 0,
  8. /** 倍数播放 */
  9. rate: 1
  10. })
  11. const playNote = () => {
  12. if (!midiData.playing) return
  13. const item = state.times[midiData.index]
  14. // 播放到最有一个音符,结束
  15. if (!item){
  16. onEnded()
  17. return
  18. }
  19. midiData.index++
  20. const duration = item.endtime - item.time
  21. midiData.iframeRef?.contentWindow?.playNote(item.realKey, duration)
  22. // gotoNext(item)
  23. timer = setTimeout(() => {
  24. playNote()
  25. }, duration / midiData.rate * 1000)
  26. }
  27. /** 停止播放 */
  28. const stopPlay = () => {
  29. midiData.playing = false
  30. }
  31. /** 初始化 */
  32. export const hanldeInitMidiData = (iframeRef: HTMLIFrameElement) => {
  33. midiData.iframeRef = iframeRef
  34. }
  35. /** 切换播放 */
  36. export const handleTogglePlayMidi = (type: "play" | "paused") => {
  37. if (type === 'play'){
  38. midiData.playing = true
  39. playNote()
  40. onPlay()
  41. } else {
  42. stopPlay()
  43. }
  44. }
  45. /** 设置倍数播放 */
  46. export const hanldeSetMidiPlaybackRate = (rate: number) => {
  47. midiData.rate = rate
  48. }
  49. /** 获取播放时间 */
  50. export const getMidiCurrentTime = () => {
  51. let index = midiData.index - 1
  52. index = index < 0 ? 0 : index
  53. return state.times[index].time
  54. }
  55. /** 获取总播放时间 */
  56. export const getMidiDuration = () => {
  57. return state.times[state.times.length - 1].endtime
  58. }
  59. /** 设置播放时间 */
  60. export const setMidiCurrentTime = (index: number) => {
  61. clearTimeout(timer)
  62. midiData.index = index
  63. playNote()
  64. }
  65. export default defineComponent({
  66. name: 'midiPlayer',
  67. setup(){
  68. return () => <div style={{display: 'none'}}></div>
  69. }
  70. })