Tuesday, 1 March 2011

First Post

I'm completely new to blogging so please bear with me while I figure out layout and design.

This blog is a place for me to document technical challenges and solutions in the world of computing. I tend to code for small games or create visual assets such as models, textures etc. Currently I'm in my final year of a computer animation degree, so for a while this blog is going to focus mainly on my major project: an audio visualization node for Autodesk Maya.

The node is written in Python and will take a user defined wav file as input. The node will provide outputs for amplitudes, frequency data and beat detection. This will allow users to plug these values into other attributes (such as the scale of a polyCube, rotation of a joint, intensity of a light, etc) and create works of art that blur the line between sound and vision.

* * *

Python makes wav processing extremely easy: the most challenging part is converting the samples from hex to signed integers. Currently I am trying to feed the amplitude of a wav into the Maya node. This involves using a moving average to find the amplitude of a single Maya frame's worth of audio.

Today's problem:
To get a single frame's worth of audio samples I need to know how many seconds there are per frame in Maya. There is no straightforward way of doing this.

Today's solution:
Maya offers commands to fetch the current time and the current time units. Units would be ideal for calculating seconds-per-frame, unfortunately it typically returns strings such as "hour", "pal", "20fps", etc.

Google provided the following solution in the form of a MEL script:

The script works perfectly on a one-off basis. HOWEVER, when run during animation the repeated modification of animation settings causes the node to evaluate incorrectly.

I decided to just give in and write the following trivial function (I'll research syntax highlighting sometime):

#get seconds per frame
def getSpf():

    #[hour | min | sec | millisec | game | film | pal | ntsc | show | palf | ntscf]
    #values are followed by "fps"
    unit = cmds.currentUnit( query = True, time = True )
    if unit == "hour": return 360
    if unit == "min": return 60
    if unit == "sec": return 1
    if unit == "millisec": return 1.0/1000.0
    if unit == "game": return 1.0/15.0
    if unit == "film": return 1.0/24.0
    if unit == "pal": return 1.0/25.0
    if unit == "ntsc": return 1.0/30.0
    if unit == "show": return 1.0/48.0
    if unit == "palf": return 1.0/50.0
    if unit == "ntscf": return 1.0/60.0
    unit = unit.replace("fps", "")
    return 1.0/unit

So there you go, nothing complicated at all. I haven't even bothered to set up a dictionary to avoid the number of IF statements. Hopefully this function will save someone a few minutes of mindless typing.

Soon I'll hopefully be able to post a playblast of the amplitude output in use.

No comments:

Post a Comment