【问题标题】:Python visualize beat frequency in circles or spheresPython可视化圆或球体中的拍频
【发布时间】:2018-03-09 21:23:19
【问题描述】:

这是科学问题和编程问题。

我希望发生的事情的图片

我使用 pyaudio 创建拍频,20-20000 Hz。但现在我想可视化这些频率。不是在一条线上,而是在一个圆圈中,甚至更好的是一个球体。有在线工具可以做前者,但不是后者。我对动态渲染感兴趣,而不是静态图像,即我想看到各个频率 F1 到 Fn 以及由此产生的拍频在屏幕上的时间和空间上移动。

但是什么库可以做到这一点? matplotlib 是静态的(根据下面的评论,它不是静态的。显然,目前我不知道我写了你可以用 matplotlib 制作动画的问题。),那么可以使用什么库以及如何使用?或者 Blender 可以做得更简单?

在 matplotlib 中,我可以创建表面形状,但还没有想出根据拍频现象的物理属性使它们像高尔夫球一样凹凸不平。在 matplotlib 中,我认为它类似于 X1, Y1 = F1 和 X2, Y2 = F2 :: X, Y = Fbeat 但还没有弄清楚如何去做。

用于对阅读文本的大脑进行编程的决策树。

1 问题是否完全理解?是,不是?

如果否: 写出答案让DrillBit解释得更好。

如果是:

2 可以在 matplotlib 中完成吗?

如果是:

如果我知道它是如何在 matplotlib 中完成的,请向 DrillBit 解释。 否则暂停 65 小时,然后喝咖啡。

如果没有:

3 可以在其他 Python 库或 Blender 中完成吗?

如果是:

4 请向DrillBit解释如何完成或提示RTFM。拍拍自己的肩膀,用猫咪视频庆祝一下。

我创建了一个平坦的表面,没有“频率”引起的颠簸

【问题讨论】:

  • 从没想过我会在 SO 上看到 Björk。不知道她有一个新的音乐视频,太棒了!我完全不明白你在这里试图摆脱什么。您的 2D 图片甚至显示了什么?例如here 是一些二维板模式。请注意,即使板是 2D 的,模式也是 3D 可视化的。如果你想用球体来可视化它,你没有另一个维度来使球体变形,所以你唯一的选择就是只有一个球体并给它上色(但这会很无聊)。
  • 你只是想取一维频率并将其环绕成一个圆圈吗?顺便说一句,这对于本网站来说不是一个很好的问题格式,它更多地用于编程问题,并且就问题寻求一般性建议被认为是题外话。不过,这是一个有趣的问题。
  • @AlexanderReynolds 是的,最初我只想直接包裹成圆形,就像一条蛇咬它的尾巴或从静止中心创建一个圆形或球体的幅度差异的函数。您提到的板模型仍然是平坦的,而不是从中心向外。我将编辑这个问题,所以它不是一般性的。
  • pyqtgraph.org 非常擅长这种高速渲染任务。不如 matplotlib 强大,但要快得多。
  • 也许 stackoverflow 通常的工作方式在这里并不清楚。遵循决策树:(1)阅读How to Ask 和minimal reproducible example。 (2) 尝试在 matplotlib 中绘制正弦波 (3) 在圆坐标或极坐标图上绘制一条线 (4) 在圆坐标或极坐标图上绘制正弦波 (5) 尝试对正弦波进行动画处理 ( 6)尝试在循环中为正弦波设置动画。协调。或极坐标图。这些步骤有很多例子;如果任何步骤有问题,请提出问题。如果没有,第 (6) 步将解决您的问题。

标签: python-3.x matplotlib pyaudio pyopengl


【解决方案1】:

如果想把我的帽子扔进擂台,我建议结合使用PyOpenGL(创建你的圆圈/球体并制作精美的实时 2D/3D 图形)和PyQt(创建一个 OpenGL 上下文容纳您的可视化,并提供输入用户界面)。 请注意,如果您选择走这条路,虽然这将非常灵活,但请准备好从头开始编写大量的东西。您可能还可以看看这两个库的现有组合: @Jeronimo 在 cmets 中建议,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_()

【讨论】:

  • academo 工具正是我所想的。衔尾蛇问题是物理学开始的地方。如果半径和波长一致,你就有一个完美的“球体”,但如果不是,你就有差异。是通过光子发射还是激发来解决?我会在使用更大的计算机时立即尝试您的解决方案。
猜你喜欢
  • 1970-01-01
  • 2021-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
  • 2013-05-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多