2

目标:创建一个程序,该程序将能够根据从 MIDI 音符触发的事件来关闭和打开音乐的灯光。

大家好,我希望这不是一个太宽泛的问题。我正在做一个项目,我从 midi 文件中获取事件并将这些事件转化为时间。我从 midi 文件中记下一个注释,并将其附加到一个列表中作为放置时间

示例: https ://imgur.com/swZsrk9

我把所有这些都放在一个列表中。不要担心我是如何做到的,因为这不是我要讨论的主要目标。我刚刚在我的示例代码中用硬编码的列表替换了列表。

我现在有一个我希望灯打开或关闭的时间列表,现在我只需要设置一个无限循环,它的计时器从 0 秒开始(随着歌曲的开始)和计时器 == (列表中的下一次)它将打印出一行。这是我的代码:

import socket
import sys
import random
import time
from pygame import mixer
from mido import MidiFile

masterList = [12.37, 14.37, 15.12, 15.62,16.36, 17.61, 18.11, 19.11, 19.61, 20.35,]
mixer.init()
song = mixer.Sound('song.wav')
startTime = time.time()
endTime = startTime + song.get_length()
print(masterList)
print('Starting song.')
song.play()
print('Playing song, timer:',startTime)
while time.time() <= endTime:
    #print(round(time.clock(),1),masterList[0])
    if round(time.clock(),2) == masterList[0]:
        print(round(time.clock(),2),"<-",masterList[0],"------------------")
        del masterList[0]
    #print('playing...')
    time.sleep(.01)
mixer.quit()

这是它运行的视频:https: //www.youtube.com/watch?v= VW-eNoJH2Wo&feature=youtu.be 忽略弃用警告

它可以工作,但有时,由于编程的性质,time.clock() 并不总是 == 列表中的下一项。我知道这将是一个问题,因为您不能依赖代码执行多长时间。有时,完成一个 while 循环需要比平时多几毫秒的时间,所以当你调用 time.clock() 方法时,它 != 列表中的下一次。然后列表不会删除它的第一项,然后它永远不会等于第一项。

我尝试了 10 毫秒 (.1),但它并没有给我所需的准确性。

此外,它看起来很笨拙,有时事件会延迟几毫秒,这会使效果不那么令人愉悦。正如您从我的视频中看到的那样,打印的时间并没有完全排列在它们需要的位置,即使它们完美地放置在它们需要在 midi 文件中的位置。

问题:有没有更优雅的方法来解决这个问题?我似乎一直在寻找修补它以使其更好地工作的方法,然后它总是回到编程的本质,其中 cpu 总是不可靠的。我一直试图想出不同的方法来做到这一点,但我想不出任何办法。您的帮助将不胜感激!!

4

1 回答 1

0

由于您在演奏时会删除音符,因此您是否尝试过使用>=而不是==

例如,:

while time.time() <= endTime:
    #print(round(time.clock(),1),masterList[0])
    if round(time.clock(),2) >= masterList[0]:
        print(round(time.clock(),2),"<-",masterList[0],"------------------")
        del masterList[0]

这样,音符将在指定时间后尽快播放,并将其从队列中删除。了解实际性能的唯一方法是对其进行测试,但至少它不会跳过音符。

于 2018-12-15T05:03:58.103 回答