Skip to content

Instantly share code, notes, and snippets.

@HK-SHAO
Created April 25, 2022 08:53
Show Gist options
  • Save HK-SHAO/431f21d9c4a763c14cfe1f6d9a1fabb9 to your computer and use it in GitHub Desktop.
Save HK-SHAO/431f21d9c4a763c14cfe1f6d9a1fabb9 to your computer and use it in GitHub Desktop.
manim music visualization demo 2
from manimlib import *
import wave
import numpy as np
import queue
def my_coord(x, y):
return RIGHT * x + UP * y
def new_my_point(scale=1):
point = Dot()
point.scale(scale)
point.set_fill(WHITE, opacity=0.5)
point.set_stroke(WHITE, width=0)
return point
def my_curve(t, k1, k2, k3, k4, k5, k6, omega):
rou = (abs(t/k1 + k2))**k5 / k3 + k4
theta = t / k6
return my_coord(rou * np.cos(theta + omega), rou * np.sin(theta + omega))
class MWave():
def __init__(self):
self.nframes = 0
self.framerate = 0
self.frames = []
self.npmin = 0
self.npmax = 0
self.points = []
self.k_values = []
self.num_points = 0
self.vsum = 0
self.vsum_qq = None
self.omega = 0
self.k1 = 400
self.k2 = 0
self.k3 = 2
self.k4 = -1
self.k5 = 0.4
def open(self, path: str):
with wave.open(path) as f:
nframes = f.getnframes()
self.framerate = f.getframerate()
m_frames = f.readframes(nframes)
frames = np.frombuffer(m_frames, dtype='short')
self.nframes = len(frames)
# part = nframes//4
self.frames = frames
self.npmin = np.min(frames)
self.npmax = np.max(frames)
return self
def create(self, scene, scale):
distance = 200
# 创建点集
for i in range(distance):
rate = int(i**0.8)
for j in range(0, rate):
k = i + j / rate
point = new_my_point(scale)
scene.add(point)
self.points.append(point)
self.k_values.append(k)
self.num_points = len(self.points)
self.vsum_qq = queue.Queue(self.num_points)
def init(self, color_func, opacity_func, k1, k2, k3, k4, k5, k6, k7):
self.k1 = k1
self.k2 = k2
self.k3 = k3
self.k4 = k4
self.k5 = k5
self.k6 = k6
self.k7 = k7
self.color_func = color_func
self.opacity_func = opacity_func
def update(self, i):
index = i % self.num_points
value = 1000*(int(self.frames[i]) - int(self.npmin) /
1000) / (int(self.npmax) - int(self.npmin))
value = min(max(value, 0), 1)
v2 = index / self.num_points
pos = my_curve(self.k_values[index], self.k1,
self.k2, self.k3, self.k4, self.k5, self.k6, self.omega)
self.points[index].move_to(pos)
self.points[index].set_fill(rgb_to_color(
self.color_func(value, v2)), opacity=self.opacity_func(value, v2))
self.vsum_qq.put(self.frames[i])
self.vsum += self.frames[i]
if self.vsum_qq.qsize() >= self.num_points:
self.vsum -= self.vsum_qq.get()
rou = self.vsum / self.num_points
time = i / self.framerate
self.k2 = abs(rou)
self.omega = time / self.k7
wave1 = MWave().open('assets/wav/qt-no.wav')
wave2 = MWave().open('assets/wav/qt-vocal.wav')
print(wave1.nframes, wave2.nframes)
class MusicVisualizeMain1(Scene):
def wait1frame(self):
self.wait(1/self.camera.frame_rate)
def construct(self):
wave1.create(self, 2)
wave2.create(self, 1)
nframes = wave2.nframes
wave1.init(color_func=lambda value, v2: [value, v2, 1 - value / 2],
opacity_func=lambda value, v2: value/4,
k1=400, k2=0, k3=4, k4=2, k5=0.3, k6=2, k7=10)
wave2.init(color_func=lambda value, v2: [1 - value / 2, v2, 0.2+0.8*value],
opacity_func=lambda value, v2: 0.2+value/2,
k1=400, k2=0, k3=3, k4=0, k5=0.5, k6=4, k7=10)
for i in range(nframes):
wave1.update(i)
wave2.update(i)
if i % wave2.num_points == 0:
self.wait1frame()
# manimgl wave-anim.py --uhd --frame_rate 30 -w
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment