Created
April 29, 2016 21:03
-
-
Save ericjang/af35a0a814044075cd6cbdd9721ef05d to your computer and use it in GitHub Desktop.
audio-driven keyframes in Maya
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Author: Eric Jang | |
# 2013-Jul-17 | |
# The problem with using audioWave + time nodes + audioWave bonus tool in Maya | |
# to drive animation is that we can't really do spectral analysis (high pass/low pass filters) | |
# short of implementing it using hypershade nodes, so we can't get really fine-tuned animation | |
# ... but Python is good for this! | |
# caveat: this was coded up in one night so it may be unstable. Use with caution. | |
# future work: instead of just the simple amplitude, we can perform FFT/spectral analysis to extract | |
# more interesting information, tweak the audio driving keys | |
# audio track: arbitrary wav file. currently uses the "World Engine" noise from Man of Steel. | |
import maya.cmds as cmds | |
import numpy as np | |
import random | |
from scipy.io import wavfile | |
# settings | |
l_sph = 12 # num copies of the sphere along each dimension | |
xy_s = 3 # x or y distance of each sphere from each other | |
afile = "/home/cello/pythonfun/wubwub/zod.wav" | |
width = 3 | |
maxR = 10 | |
### | |
rate, a = wavfile.read(afile) | |
a = np.average(a, 1) # merge audio channels into mono | |
nf = int((float(len(a)) / rate * 24) / width) #number of frames we will animate | |
spf = int(rate/24 * width) # audio samples per animation frame (1837). Increase width to smooth animation out | |
# normalized sine "bump" + some array comprehension | |
# see the heatmap_sample to get an idea of what it looks like | |
dz_s = [ [np.sin(i*np.pi/l_sph)*np.sin(j*np.pi/l_sph)*5.0 for j in range(l_sph)] for i in range(l_sph)] | |
orig = cmds.ls("JuliaSphere")[0] # we don't animate this one | |
for i in range(l_sph): | |
for j in range(l_sph): | |
print(str(i*l_sph+j)) | |
cp = cmds.duplicate(orig) | |
pos = [i*xy_s, j*xy_s, 0.0] | |
cmds.makeIdentity(cp, apply=True, t=1, r=1, s=1, n=0, pn=1) #freeze transforms | |
for frame in range(1,nf+1): | |
s = (frame -1 ) * spf #start of audio sampling frame | |
amp = np.average(np.abs(a[s:s+spf]))/1000 - 4 | |
z = amp * dz_s[i][j] + random.uniform(0, 1) # a bit of jitter | |
dr = [random.uniform(0.01, maxR) * amp for k in range(3)] | |
if z < 0.0: | |
z *= 0.3 | |
cmds.move(0, 0, z, cp, rpr=True) | |
cmds.xform(cp, ws=True, ro=dr) #translate it, rotate it | |
for key in ["translateZ", "rotateX", "rotateY", "rotateZ"]: | |
cmds.setKeyframe(cp, at=key, t=frame * width)# set keyframe | |
cmds.move(pos[0], pos[1], 0, cp, rpr=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment