这是科学问题和编程问题。
我使用pyaudio来创建20-20000 Hz的拍频。但现在我想想象这些频率。不是在一条线上,而是在一个圆圈中,甚至是一个更好的球体。有在线工具可以做前者,但不是后者。我对动态渲染而不是静态图像很感兴趣,我希望看到单个频率F1到Fn以及由此产生的拍频在屏幕上随时间和空间移动。
但是什么库可以做到这一点? matplotlib是静态的(根据下面的评论,它不是静态的。显然,我现在不知道我写的问题,你可以使用matplotlib制作动画。),那么可以使用什么库以及如何使用?或者Blender可以更轻松地做到这一点?
在matplotlib中我可以创建浮出水面的形状,但还没有想到根据拍频现象的物理属性使它们像高尔夫球一样颠簸。在matplotlib中我认为它会像X1,Y1 = F1和X2,Y2 = F2 :: X,Y = Fbeat但是还没弄明白该怎么做。
用于编写阅读文本的大脑的决策树。
1问题是否完全理解?是的,不是吗?
如果否: 写下答案让DrillBit更好地解释。
如果是:
2可以在matplotlib -how中完成吗?
如果是:
向DrillBit解释如果我知道它是如何在matplotlib中完成的。 否则停顿65小时然后喝咖啡。
如果否:
3可以在其他Python库或Blender中完成吗?
如果是:
4请向DrillBit解释如何完成或提示RTFM。拍拍自拍,与猫视频一起庆祝。
答案 0 :(得分:0)
为了把我的帽子扔进戒指,我建议使用PyOpenGL
(创建你的圆圈/球体并做甜蜜的实时2D / 3D图形)和PyQt
的组合(来创建)一个OpenGL上下文,用于存放您的可视化以及为输入提供用户界面)。 请注意,如果您选择这条路线,虽然这将非常灵活,但请准备从头开始编写大量内容。您可能还可以查看这两个库的现有组合在@Jeronimo PyQtGraph
的评论中提出,这可能更直截了当。
让我们从可视化技术退一步,并在数学上思考 我们将在屏幕上绘制它。从您的问题来看,您的目标似乎如下:
我希望在屏幕上看到单个频率F1到Fn以及产生的拍频在时间和空间中移动。
这有点模糊,你应该在你的问题中清除你期望绘制的内容。为了我自己的理智,让我们看一下具有可变半径的圆的“更简单”情况。设圆圈的radius r
可以根据幅度+/- a
而变化。这种变化可以向我们展示波形。从0到2 * pi弧度开始并逆时针绕圆圈的周长,我们可以模拟沿圆周的t0
到t1
的时间范围。然后,我们可以实时增加t0
(和t1
)的值,从而改变我们的模拟值范围。
玩this demo一个问题,我看到只是“包裹”你的线并创建一个完美的ouroboros是在包装点会有不连续 ,除非你改变周长,以便它可以完全被你的拍频周期整除。
此外,我得到的结果(见下面的代码)看起来相当令人失望。为什么?增加时间会使圆圈旋转(将其视为我们的波只是沿着圆的表面传播)。无论如何,这是(凌乱)代码的样子;希望它能提供一些关于如何从头开始创建自己的可视化的想法:
from OpenGL.GL import *
from OpenGL.GLU import *
from PyQt4 import QtGui
from PyQt4.QtCore import QTimer
from PyQt4.QtGui import QColor, QStatusBar, QSizePolicy
from PyQt4.QtOpenGL import *
import math
import numpy as np
import sys
import time
class Waveform(object):
"""
Defines a class Waveform where waves are of the form: y = sin(2*pi*f*t).
"""
def __init__(self, frequency):
self.f = frequency
def calc_points(self, t0, t1, n):
"""
Samples at n points from [t0, t1] and calculates the appropriate amplitude "a" value.
Returns the data as a list of tuples.
"""
data = []
for i in range(n):
frac = (t1 - t0)/(n - 1)
t = i * frac + t0
a = math.sin(2 * math.pi * self.f * t)
data.append((i, t, a))
return data
class MainWindow(QtGui.QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.widget = GLWidget(self)
layout = QtGui.QVBoxLayout()
layout.addWidget(self.widget)
layout.setContentsMargins(5, 5, 5, 5)
self.setLayout(layout)
class GLWidget(QGLWidget):
def __init__(self, parent):
QGLWidget.__init__(self, parent)
self.setMinimumSize(800, 600)
self.start_time = time.time()
self.timer = QTimer()
self.timer.timeout.connect(self.update)
self.timer.start(1000/60)#so-called "60 fps"
def initializeGL(self):
glClearColor(0, 0, 0, 1)
glClearDepth(1.0)
glEnable(GL_DEPTH_TEST)
def resizeGL(self, width, height):
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0, width, 0, height, -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
def paintGL(self):#Important part of the code (circle drawing stuff) here!
curr_time = time.time()
delta = (curr_time - self.start_time)
t0, t1 = 0 + delta, 0.05 + delta
f1 = 500
f2 = 490
num_slices = 1001
radius = 200
amplitude = 5
a = Waveform(f1)
b = Waveform(f2)
data1 = a.calc_points(t0, t1, num_slices)
data2 = b.calc_points(t0, t1, num_slices)
w, h = self.width(), self.height()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glBegin(GL_TRIANGLE_FAN)
glColor(1.0, 0.0, 0.0, 1.0)
glVertex3f(w/2.0, h/2.0, 0)
for point in range(len(data1)):
i1, p1, a1 = data1[point]
i2, p2, a2 = data2[point]
t = p1
a = a1 + a2#adding the waveforms together
frac = (t - t0)/(t1 - t0)
angle = 2 * math.pi * frac
r = radius + amplitude * a
x = r * math.cos(angle) + (w/2)
y = r * math.sin(angle) + (h/2)
glVertex3f(x, y, 0)
glEnd()
def update(self):
self.updateGL()#seems odd, but calling this causes a paintGL() call behind the scenes
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.setWindowTitle("Beat Frequency App")
window.show()
app.exec_()