免责声明:不确定标题是否合适,这是我的第一篇文章,所以我正在学习如何组织这个
代码背景:
我使用 Apophysis7x 创建分形火焰(迭代图像)并在 Fractal Fr0st 中打开 .flame 文件(此文件未渲染,它只是保存要在另一个编辑器中打开的信息),我可以在其中自动化例如不断旋转的迭代从而创建动画。Fractal Fr0st 使用 python 进行此类自动化,但它们是不变的。我制作音乐并希望有一天能完成下面的代码,以根据我的歌曲的 BPM 进行轮换。在编辑与程序关联的实际 python 文件之前,我开始自己编写代码以生成滴答声序列(该代码现在并不完全重要,但在最后发布)
到目前为止有关问题的信息:
我马上就知道 Python 不是最快的语言,但我不能 100% 确定我的代码是否不够高效,无法跟上我想要输出的内容。请查看我的代码和评论,因为我试图尽可能彻底地解释发生了什么。
计时器.py:
import time
#Feel free to test as you'd like
#Suppose we have a song at 140 Beat Per Minute (BPM) -> There is approximately 2.33 Beats Per Second (BPS)
#So it takes approximately 0.43 (s) per beat
#So if freq = 0.43, leng = *length of song*
#This program should alternate printing "tick" "tock" (or some action that I hope to code in the future)
#The Tick Tock output should come out every (in this case) .43 seconds
class timer(object):
"takes in a frequency and duration of loop in seconds"
def __init__(self,freq,leng):
"input a frequency and duration in seconds"
#rounded to 2 decimal places
self.freq= round (freq,2)
self.leng= round (leng,2)
def ticker (self):
"Starts the time and loop to be broken when max time is reached"
counter = 0 #recorded out of curiosity to check just how many loops were made overall
ticker = 0 #alternates the "tick" "tock"
initTime = time.time() #records the initial upon starting the loop
rnded = 0 #initial rounded time set at 0 *see the first if statement below*
while True:
stop = time.time() #The time recorded during the loop *stopwatch so-to-speak*
passed = stop - initTime #The time passed from initial launch to time during the loop
if rnded == self.leng:
"When the time that has passed reaches time limit print stats and break"
return print("Loops:".ljust(10).rjust(14) + "Initial Time:".ljust(17).rjust(21) + "Time Stopped:".ljust(17).rjust(21)+ "Passed:".ljust(11).rjust(15) + "Total Ticks:".ljust(16).rjust(20) + "\n" + (str (counter) ).ljust(10).rjust(14) +(str (initTime) ).ljust(17).rjust(21)+ (str (stop) ).ljust(17).rjust(21)+(str (rnded) ).ljust(11).rjust(15) + (str (ticker) ).ljust(11).rjust(15) )
elif round(passed,2) == rnded:
"Prevents duplicates, ie: previous stopped at .9999 (1.0) and current loop sopped at 1.001 (1.0) skip"
#If your current value happened to be rounded to the previous value don't continue
#uncomment bellow for debugging
#print ("*TEST* \t Initiated: ", initTime, "\t Time stopped: ",stop, "\nTime passed: ", rnded, "\t Tick Counter: ", ticker, "\n ---")
pass
else:
"Tick tock code"
rnded = round(passed,2) #now set current time differnce value after being checked for duplicates
if rnded % self.freq == 0 and rnded != 0:
"if the time passed mod the frequency is 0 continue to execute tick tock"
if ticker % 2 == 0:
#gives stats for debugging purposes, delete, after "tick" / "tock" if desired
#prints in the meantime in the future I would like an action to be done with music in another program as precise as possible
print ("Tick \t Initiated: ", initTime, "\t Time stopped: ",stop, "\nTime passed: ", rnded, "\t Tick Counter: ", ticker, "\n ---")
elif ticker % 2 == 1:
print ("Tock \t Initiated: ", initTime, "\t Time stopped: ",stop, "\nTime passed: ", rnded, "\t Tick Counter: ", ticker, "\n ---")
ticker +=1 #only increases if tick/tock was processed
counter += 1 #counts how many times loop was accessed, use this as you'd like
def chngFreq(self, freq):
'Changes current frequency'
self.freq = round (freq,2)
def chngLeng(self,leng):
'Changes current duration'
self.leng = round(leng,2)
示例 1:
随着频率变快,输出会跳过多个“滴答”/“滴答”(我只是在测试,例如,当频率为 0.01(s)且总时间为 4(s)时,总共应该有 399 个滴答声但它只达到了 5 个滴答声。我的理论是,由于它确实需要时间来完成循环(但是时间非常短),它可能会跳过一个滴答声,因为在从 . 01 到 .02 在四舍五入之前可能是一个勾号,但代码处理速度不够快。我四舍五入到最后尽可能准确,并制作了“elif”部分以防止重复(请参阅上面的代码)
输出:
>>>s = timer(.01,4)
>>>s.ticker()
Tick Initiated: 1502409793.6775877 Time stopped: 1502409793.6937597
Time passed: 0.02 Tick Counter: 0
---
Tock Initiated: 1502409793.6775877 Time stopped: 1502409793.7562232
Time passed: 0.08 Tick Counter: 1
---
Tick Initiated: 1502409793.6775877 Time stopped: 1502409793.8409605
Time passed: 0.16 Tick Counter: 2
---
Tock Initiated: 1502409793.6775877 Time stopped: 1502409793.9940765
Time passed: 0.32 Tick Counter: 3
---
Tick Initiated: 1502409793.6775877 Time stopped: 1502409794.9579115
Time passed: 1.28 Tick Counter: 4
---
Loops: Initial Time: Time Stopped: Passed: Total Ticks:
5473896 1502409793.6775877 1502409797.680171 4.0 5
请注意,有时只计算 2^x 的刻度,即: .01、.02、.04、.08、.16、.32... 而不是: .01、.02、.03、.04、 .05, .06...
我知道这不是我在代码中给出的示例,但是每当我尝试使用更近似的频率(例如 0.23 或 .01)时都是如此,但是无论精度如何,频率越大,即:4.29 它更可能准确返回“刻度”4.29、8.58、12.87 等...
示例 2
在以下示例中,您可以说它工作得非常好,因为它在刻度之间有更长的时间来处理
>>>s = timer(1,4)
>>>s.ticker()
Tick Initiated: 1502411198.8088021 Time stopped: 1502411199.8091898
Time passed: 1.0 Tick Counter: 0
---
Tock Initiated: 1502411198.8088021 Time stopped: 1502411200.8089292
Time passed: 2.0 Tick Counter: 1
---
Tick Initiated: 1502411198.8088021 Time stopped: 1502411201.81057
Time passed: 3.0 Tick Counter: 2
---
Tock Initiated: 1502411198.8088021 Time stopped: 1502411202.8121786
Time passed: 4.0 Tick Counter: 3
---
Loops: Initial Time: Time Stopped: Passed: Total Ticks:
5586557 1502411198.8088021 1502411202.8328226 4.0 4
如果有任何代码不清楚,请告诉我,但请务必先阅读每条评论,并在需要时运行代码/修改。
一旦我之前的问题得到解决,我希望修改 Fractal Fr0st 中使用的以下代码的“if x.animate:”部分。
默认.py:
update_flame = False
while True:
for x in flame.xform:
if x.animate:
x.rotate(-3)
preview()
最后感谢一百万我知道这真的很长,但我真的想了解 python 发生了什么/它是如何运作的,不管我的最终目标是什么。
此外,如果任何其他方法更快/更有效,请告诉我。谢谢!!!