August 12, 2008

CLAM 1.3.0, the ?shooting flying plugins? release


The CLAM team enraptured to announce the 1.3.0 release of CLAM, the C++ framework for audio and music,
code name The Shooting of the Flying Plugins release.

Highlights of this release are:

  • NetworkEditor automatically generates and compiles a LADSPA plugin containing the network you are editing. CLAM also provides a new simple API to code that by hand yourself.
  • More FAUST integration into network editor: edit faust code, compile, reload, view the svg diagrams (Natanael Olaiz GSoC)
  • Lots of usability enhancements on the NetworkEditor: cut&paste, context menus to connect ports, keyboard shortcuts, default double click actions, and a processing tree filter (Natanael Olaiz GSoC)
  • Annotator has also enhanced its functionality (Wang Jun GSoC):
    • You can build a project that aggregates content from several extractors
    • Extractors may have a config file
    • Extractors can write back data (useful if the extractor is a database of webservice and needs to upload modifications)
  • New ProgressControl widget and paired AudioFileMemoryLoader processing to support seeking (Pawel Bartkiewicz GSoC)
  • A bunch of new 3D spatialization processings from CI Barcelona Media audio research group.
  • Scripts and graphical front-end to generate a native CLAM plugin project from scratch.
  • Experimental Python bindings (still just-for-hackers install procedure)
  • TickExtractor example is compiling again (many thanks to Amaury Hazan from MTG-UPF)
  • Development deployment for Windows native compilation using MinGW (Wang Jun GSoC)

And a lot of small nice features and fixes you will appreciate for sure.
Source and binary packages for different platforms are available at the CLAM download page.

See also: development screenshots, the CHANGELOG, and the version migration guide.

We are very excited on what next releases promise us. Some ongoing work:

  • Generating other types of network based plugins and programs (LV2, JACK, VST…),
  • Subnetworks (Natanael Olaiz GSoC)
  • Improved OSC support, 3D scene descriptors parametrization receivers processings and Blender exporter to the spatialization processing choreographer. (Natanael Olaiz GSoC - related blogging)
  • Typed controls (Francisco Tufro GSoC)
  • A new musician-oriented standalone chord extraction application (Pawel Bartkiewicz GSoC)

Blender Scene

Diagram of a testing Blender scene used to export to CLAM.
Three audio sources(simple spheres), one condenser mic and two omni mic linked to visual camera positions, plus a lamp.



As the objects are grouped, could be easily exported.
(will be continued...)

August 07, 2008

Agile Research

The 3 main features of any agile methodology are:
  • Iterative development
  • Focus on executable software
  • Adaptation to change
  • Focus on individuals
But what does all this have to do with Scientific research? My hypothesis, which I presented in a talk recently, is that research is inherently agile. Research teams can and should indeed apply many of the agile principles in their day to day work.

If we take a look at the traditional Scientific Method process (see figure below) we can see that it shares many features with agile methodologies. Above all, the scientific method is inherently iterative. In every iteration we set a hypothesis, test it, and analyze the results.


In this sense, it resembles most of Agile process definitions such as Scrum or XP: the first part of the process deals with setting up the general questions. This is similar to Scrum's sprint 0 in order to define the product backlog or to XP's Planning Game. Then we start doing iterations, or sprints, in which we ask smaller questions or decide which of the original hypothesis we are going to test.

Finally, it is interesting to note that the whole process is hypothesis-driven. This is very similar to the Test-driven development practice promoted by XP'ers. And there are many other practices (such as Peer programming or Simple Design, equivalent to Occam's Razor) that have a direct mapping between agile software development and Scientific Research.

Based on this I propose an agile scientific method in which:

  • Use an Iteration 0 (or XP planning game or Scrum Sprint 0) to build up general hypothesis and list those "stories" that you would like to have in your final article (optionally writing the article stub already).
  • Every 1-2 weeks come up with a list o prioritized taks
    • List all possible tasks (ideally 1-2 day workload)
    • Measure interest of task towards final goal
    • Measure cost in terms of predicted hours of work
    • List them in order of priority value (= interest - cost)
    • In the iteration planning re-evaluate general hypothesis.
  • Plan stories as an "executable hypothesis": if I can prove hypothesis H then it should happen that tests t1 and t2 should pass.
  • Maintain collection of tests as a record of experimetns.
  • Use the red-green-refactor cycle of Test-driven development to refine model while still complying with experimental data.
If you are interested you can read the full presentation that Gemma Hornos and I did at a recent seminar where she also presented some agile initiatives in Telefonica.

August 04, 2008

Modifying a FAuSt compiled LADSPA plugin within CLAM

Is not a good "video", but shows how to edit a faust module, recompile and reload in CLAM without have to quit the program. By now, you have to delete and reinsert the processing from the tree...

The changed line:
  • smooth(c) = *(1-c) : +~*(c);
to:
  • smooth(c,p) = *(1-c) : +~*(c*p);
I.e., two audio inputs instead one, and the new one modulating in amplitude a part of the original process (TODO: put here the diagrams -and learn the Faust syntax- ;-)).



Interactive CLAM programming

Recently I been playing with python bindings for the CLAM library. Here is a demo demonstrating how to interactively build a network and play a file using the IPython shell:


 
Related scripts: playfile.py fft_example.py

July 27, 2008

It's so hard to blog...

when you get used to twitting!

I have around 6 unfinished posts and I find it really hard to get the time to polish them to a bloggable level. Investing that time in finishing a blog post is hard when you know that in the same time you could probably send 10 interesting microposts in twitter.

In any case, it's not that I like twitter that much. I like the idea of microblogging but now twitter is turning into everything else: post board, public mailing list... It is really hard to find interesting twitters and most of them are more and more using it as a social post board instead (I cannot exclude myself from this category either).

In any case, I hope to get a couple of this blog posts finished soon.

July 22, 2008

Exterminating signals and slots

I recently posted at the clam devel wiki some advices, conventions, traps and tips on programing with Qt within CLAM addressed to the GSoC students. The most painful trap is the one of gratuitous signals and slots usage. Signals and slots is a very powerful way of designing independent components that comunicate each other with low coupling. Is that powerful that it is very tempting for novices to use them everywhere and this can turn very harmful for you.

If a connected slot doesn't exist, you just get an error console on run-time, checks on slots are that soft, and this is bad. Also the signal slot resolution is more expensive than just a method call. But the main reason to avoid them is that they make the code very hard to follow. When you see a signal 'emit' you have to find where such signal is connected in order to find which are the objects and slots that will be called. Multiply this process by nearly 200 signal emisions that were done at the vmqt library Annotator is using and you'll understand why such components although very smartly designed in structure, they are very hard to maintain and use.

You should emit signals just when you don't know which is the receiver of an event. If you can guess the receiver, there is no use for signals. On the other side, if you cannot access the emitter code, or you don't want to couple it, then there is room for a 'connect'.

A bad smell for noticing that you are over using sigslots is having in a class you are writting a connection like this:
connect(this, signal, knownWidget, slot)

and later, maybe in a different method:
emit signal()

When that known, and later forgotten, object is the only one you are connecting to the slot you might want to just keep a reference to it and just call the slot instead of emitting the signal.
knownWidget->slot()

which is faster, compile time checked and much more traceable.

Given that bad smell locator at hand i decided to do a fast review of vmqt module. vmqt is the successor of the many Visualization Modules we had in CLAM, just annother definitive VM rewrite. I tried to use it several times, but it is very hard to have a global view of what it does because all the program flow is driven by signal connections. No joke: 180 signal emissions and a similar number of 'connect's in 30 classes.

After a first review, 110 signals emisions have been avoided just by having a pointer to the Plot2D at the Renderers (the objects that represent drawing layers of the plot such as the lines, the playhead, the grid...). Having a pointer to it, Renderers can do a direct call to the Plot2D slots (now regular functions) instead of emitting a signal whose only receiver is the plot.

70 'emit's are still wandering around. Some of them communicate the plot with the wplot (a widget containing the plot and other elements such as the sliders, the rulers...) so they are used to syncronize. Those are likely to be removed in a similar way than for renderers.

The rest are specific renderer signals that are connected and propagated by the specific wplot. Those are harder to remove and indeed they are very convenient to keep.

As the extermination goes on, one can better see how to really take profit of the nice vmqt module structure and which aspects can be enhanced.

July 12, 2008

Por qué me gusta GNU/Linux - Why I like GNU/Linux

Andá a hacer esto en Windows!!!! / Do this on Windows!!!!

July 11, 2008

---why do I get the danceablity upside down ?

 Why do I get the danceablity upside down ?

 reversedDance   reversedDance    reversedDance 

Weeks ago I implemented the detrended fluctuation analysis exponent (dfaExponent) to scale the danceablity. The dfaExponent is introduced in [1] by Streich and Herrera. However, today I happened to notice that, compared with the observation of the reference, the dfaExponent I've obtained is the hell upside down.

30s-length segmentations of 107 dance tracks and 103 classical tracks are processed, which are half less long than those of the reference. On the left is the result of dfaExponent shown in the  reference, and on the right is the funny one who stands on its hands:

Dance              DFAComponent_OnsetPeak

As the clam annotator now is taking random danceability data as one of the high-level annotations, is anybody interested in filling this fast implementation in?

July 07, 2008

CLAM processing generator script (example of use)

This script is about a basic code generation of a CLAM plugin. In some point I think this is some kind of meta-programming or perhaps the term “automatic programming” fits better. The basic idea is to specify some basic features of the planned new processing in a plain text and then, generate some code with the script, saving in this way many of the often repetitive and mechanical work needed to set-up a new processing from scratch. Main intention is to allow concentrate in the Do() function or plugin details quickly.

As an example, I will reproduce here how I worked with me some time ago:
 
One day, in the irc #clam channel:
“[11:51] <groton> Consul, do you know if there is any trigger-like processing unit, list when the volume gets louder than a threshold or something like that”

I’m not Consul in the irc (I’m hordia), but next day at my console…

cd CLAM/scripts/TemplatedPluginsGenerator
vi ThresholdTrigger.template

Name:ThresholdTriggerTemplate
BaseClass:Processing
i:AudioInPort,Audio Input
ic:0,1,Threshold
oc:0,1,Trigger

In words, this means a Processing template named “ThresholdTriggerTemplate” using “Processing” as a base class and with one input of “AudioInPort” type named “Audio Input”, with one in control in the 0..1 range named “Threshold” and one out control named “Trigger”. Of course, you can add as many inputs/outputs of ports or controls as you want.
 

This script creates the template:

./TemplateGenerator.py ThresholdTrigger.template

 
And this one the processing plugin:

./TemplatedPluginsGenerator.py ThresholdTrigger ThresholdTriggerTemplate "Hernán Ordiales" GPL 2008

Again in words, this means create a new processing called “ThresholdTrigger” based on the “ThresholdTriggerTemplate” filling the copyright with my name plus the current year and the license with the GPL text.

 
A final edit just typing the required code for the Do() function:

cd CLAM/plugins/ThresholdTrigger
vi ThresholdTrigger.hxx

#include <cmath>
 
bool Do()
{
       bool result = Do( mAudioInput.GetAudio() );
       mAudioInput.Consume();
       return result;
}
 
bool Do(const Audio& in)
{
       int size = in.GetSize();
       const DataArray& inb = in.GetBuffer();
       TData threshold = mThreshold.GetLastValue();
       bool trigger = 0;
       for (int i=0;i<size ;i++)
       {
               if (std::fabs(inb[i])>threshold)
                       trigger = 1;
       }
       mTrigger.SendControl(trigger);
       return true;
}
</size></cmath>

At this point, just remains add the basic SConstruct file for a CLAM plugin, compile it with the corresponding clam_prefix and install it:

scons install clam_prefix=$CLAM_PATH
NetworkEditor

And ready to use…

This example it’s very simple and has a poor implementation but was just to show the idea of how those scripts can save a lot of work.

Update: I made a frontend for these scripts: ProcessingCodeGenerator

July 06, 2008

Linking scripts to objects in blender

The previous python-blender script was called on FrameChanged event, and it iterates over all objects to print its information.
How to access specific object information when you assign(link) the script to, let's say, ObjectUpdate? How to know which object is calling the script? Using the variables of the Blender module.

Here I made a new script and linked the same to:
  • an object (Audio_Omni_Source2), on ObjectUpdate event
  • a scene, on FrameChanged event
  • a world, on FrameChanged event


When the animation is running, the script says on console:

July 04, 2008

Receiving OSC from the CLAM Network

CLAM supports OSC as a plugin. You can compile CLAM/plugins/osc just as the other clam modules ("scons [options]").

That, for now, compiles a simply server processing (LibloSource) using the high level API of liblo.

On NetworkEditor (click to see animation):


As you can see on the animation, it have 2 options: osc port number and osc path.
LibloSource print whatever osc pakage it receives on that port in the console[1], and if the package have the config path and contain just 3 floats, the values are sent to the three control outputs[2].

If you configure the processing to get port 7000, you will see in the console:
LibloSource::ConcreteConfigure: STARTING the server. port 7000
So, just run the blender animation and back to the clam console, it will show something like:


That's it! You have three floats from every blender object osc position package! So, you could configure your LibloSource server to receive an object position subpath[3]:





[1] catched with
lo_server_thread_add_method(st, NULL, NULL, generic_handler, this);

[2] catched with
lo_server_thread_add_method(st, _config.GetOscPath().c_str(), "fff", controls_handler, this);
(the tree "f"s are the three typespec: floats...)

[3] at the moment just once at the time, because it create a new thread server on each processing, which make the port slot be busy and clam crash. This is an IMPORTANT todo task, when see how to deal with several osc paths/objects... Another bugs in actual implementation: if you duplicate a object with the same parameters it crashes... and if you change the options there is no reload (you actually need to quit and open the file again).
I expect to strike these bugs soon, but that need to define some things: what we want to use? a processing as server with different linked (sub)processings as paths? (this could be implemented using some kind of list control messages to deal with paths) Or just a big but configurable processing to receive all paths from an osc sender (for instance, blender)?

Exploring the scene (part 2)

Let's review the previous scene with an alternative access method.
Using the Blender module:

dir (Blender)
['Armature', 'BGL', 'BezTriple', 'Camera', 'Constraint', 'CountPackedFiles', 'CurNurb', 'Curve', 'Draw', 'Effect', 'FALSE', 'Geometry', 'Get', 'GetPaths', 'Group', 'Image', 'Ipo', 'IpoCurve', 'Key', 'Lamp', 'Lattice', 'Library', 'Load', 'Material', 'Mathutils', 'Mesh', 'Metaball', 'Modifier', 'NMesh', 'Node', 'Noise', 'Object', 'PackAll', 'Particle', 'Quit', 'Redraw', 'Registry', 'Run', 'Save', 'SaveUndoState', 'Scene', 'Set', 'ShowHelp', 'Sound', 'SpaceHandlers', 'SurfNurb', 'TRUE', 'Text', 'Text3d', 'Texture', 'Types', 'UnpackAll', 'UnpackModes', 'UpdateMenus', 'Window', 'World', '__doc__', '__name__', 'bylink', 'event', 'link', 'mode', 'sys']

dir(Blender.Scene)
['Get', 'GetCurrent', 'New', 'Radio', 'Render', 'Sequence', 'TimeLine', 'Unlink', '__doc__', '__name__', 'get', 'getCurrent', 'unlink']

scene1=Blender.Scene.GetCurrent()
scene1
[Scene "Scene"]

list (scene1.objects)
[[Object "mic_condenser"], [Object "Omni_mic_mono_side"], [Object "Audio_Omni_Source3"], [Object "Audio_Omni_Source2"], [Object "Audio_Omni_Source1"], [Object "Lamp"], [Object "Omni_mic_mono_zenit"]]


We can use the following script, for instance, to get all the objects from a scene, prints their names and positions and then send it to a local Open Sound Control server (we need to have OSC.py on ~/src/osc):
#!BPY
"""

Name: 'OSCSender'
Blender: 244
"""

# use bpy module of Blender:
from bpy import data

from sys import path
from os import getenv
home=getenv("HOME")
path.append(home+"/src/liblo")

# use OSC client module for python - by Stefan Kersten
from OSC import Message

def main():
scene=data.scenes.active
for object in scene.objects:
name=object.name
location=object.getLocation()
print name
print location
Message("/blender/"+scene.name+"/"+name,location).sendlocal(7000)

# This lets you can import the script without running it
if __name__ == '__main__':
main()

We can link the previous script to the active scene (scene.addScriptLink), on FrameChanged event:


The console output, when is playing:

July 03, 2008

Exploring the scene (part 1)

How to access blender data?

I created a test scene, with some spheres (named as sound sources) some which have trajectories:


In Blender you have an internal Python console. Buggy, but still useful to test the access:


So, let's see some logs of the python console:
Using bpy module:
dir(bpy)
['__doc__', '__name__', 'config', 'data', 'libraries']

dir(bpy.data)
['__doc__', '__name__', 'actions', 'armatures', 'cameras', 'curves', 'fonts', 'groups', 'images', 'ipos', 'lamps', 'lattices', 'materials', 'meshes', 'metaballs', 'objects', 'scenes', 'sounds', 'texts', 'textures', 'worlds']

dir(bpy.data.scenes)
['__class__', '__cmp__', '__delattr__', '__doc__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__len__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'active', 'new', 'next', 'tag', 'unlink']

scene1=bpy.data.scenes.active

scene1
[Scene "Scene"]

dir(scene1)
['Layers', '__class__', '__cmp__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'addScriptLink', 'clearScriptLinks', 'copy', 'cursor', 'fakeUser', 'getActiveObject', 'getChildren', 'getCurrentCamera', 'getLayers', 'getName', 'getRadiosityContext', 'getRenderingContext', 'getScriptLinks', 'getTimeLine', 'layers', 'lib', 'link', 'makeCurrent', 'name', 'objects', 'play', 'properties', 'radiosity', 'render', 'sequence', 'setCurrentCamera', 'setLayers', 'setName', 'tag', 'timeline', 'unlink', 'update', 'users', 'world']

list(scene1.objects)
[[Object "mic_condenser"], [Object "Omni_mic_mono_side"], [Object "Audio_Omni_Source3"], [Object "Audio_Omni_Source2"], [Object "Audio_Omni_Source1"], [Object "Lamp"], [Object "Omni_mic_mono_zenit"]]

for object in scene1.objects:
if object.name.lower().find('mic')!=-1:
print 'Object: '+object.name + '; '+str(dir(object))
Object: mic_condenser; ['DupEnd', 'DupGroup', 'DupObjects', 'DupOff', 'DupOn', 'DupSta', 'Layer', 'Layers', 'LocX', 'LocY', 'LocZ', 'RotX', 'RotY', 'RotZ', 'SizeX', 'SizeY', 'SizeZ', '__class__', '__cmp__', '__copy__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'action', 'actionStrips', 'activeMaterial', 'activeShape', 'addProperty', 'addScriptLink', 'addVertexGroupsFromArmature', 'axis', 'boundingBox', 'buildParts', 'clearIpo', 'clearScriptLinks', 'clearTrack', 'clrParent', 'colbits', 'constraints', 'convertActionToStrip', 'copy', 'copyAllPropertiesTo', 'copyNLA', 'dLocX', 'dLocY', 'dLocZ', 'dRotX', 'dRotY', 'dRotZ', 'dSizeX', 'dSizeY', 'dSizeZ', 'data', 'dloc', 'drawMode', 'drawSize', 'drawType', 'drot', 'dsize', 'dupFacesScaleFac', 'effects', 'enableDupFaces', 'enableDupFacesScale', 'enableDupFrames', 'enableDupGroup', 'enableDupNoSpeed', 'enableDupRot', 'enableDupVerts', 'enableNLAOverride', 'evaluatePose', 'fakeUser', 'game_properties', 'getAction', 'getAllProperties', 'getBoundBox', 'getData', 'getDeltaLocation', 'getDrawMode', 'getDrawType', 'getEuler', 'getInverseMatrix', 'getIpo', 'getLocation', 'getMaterials', 'getMatrix', 'getName', 'getPIDeflection', 'getPIFalloff', 'getPIMaxDist', 'getPIPerm', 'getPIRandomDamp', 'getPIStrength', 'getPISurfaceDamp', 'getPIType', 'getPIUseMaxDist', 'getParent', 'getParentBoneName', 'getParticleSystems', 'getPose', 'getProperty', 'getSBDefaultGoal', 'getSBErrorLimit', 'getSBFriction', 'getSBGoalFriction', 'getSBGoalSpring', 'getSBGravity', 'getSBInnerSpring', 'getSBInnerSpringFriction', 'getSBMass', 'getSBMaxGoal', 'getSBMinGoal', 'getSBStiffQuads', 'getSBUseEdges', 'getSBUseGoal', 'getScriptLinks', 'getSize', 'getTimeOffset', 'getTracked', 'getType', 'insertCurrentPoseKey', 'insertIpoKey', 'insertPoseKey', 'insertShapeKey', 'ipo', 'isSB', 'isSelected', 'isSoftBody', 'join', 'layers', 'lib', 'link', 'loc', 'makeDisplayList', 'makeParent', 'makeParentBone', 'makeParentDeform', 'makeParentVertex', 'makeTrack', 'mat', 'materialUsage', 'matrix', 'matrixLocal', 'matrixOldWorld', 'matrixParentInverse', 'matrixWorld', 'modifiers', 'name', 'nameMode', 'newParticleSystem', 'parent', 'parentType', 'parentVertexIndex', 'parentbonename', 'passIndex', 'piDeflection', 'piFalloff', 'piMaxDist', 'piPermeability', 'piRandomDamp', 'piSoftbodyDamp', 'piSoftbodyIThick', 'piSoftbodyOThick', 'piStrength', 'piSurfaceDamp', 'piType', 'piUseMaxDist', 'pinShape', 'properties', 'protectFlags', 'rbFlags', 'rbHalfExtents', 'rbMass', 'rbRadius', 'rbShapeBoundType', 'removeAllProperties', 'removeProperty', 'restrictDisplay', 'restrictRender', 'restrictSelect', 'rot', 'sbDefaultGoal', 'sbErrorLimit', 'sbFriction', 'sbGoalFriction', 'sbGoalSpring', 'sbGrav', 'sbInnerSpring', 'sbInnerSpringFrict', 'sbMass', 'sbMaxGoal', 'sbMinGoal', 'sbSpeed', 'sbStiffQuads', 'sbUseEdges', 'sbUseGoal', 'sel', 'select', 'setConstraintInfluenceForBone', 'setDeltaLocation', 'setDrawMode', 'setDrawType', 'setEuler', 'setIpo', 'setLocation', 'setMaterials', 'setMatrix', 'setName', 'setPIDeflection', 'setPIFalloff', 'setPIMaxDist', 'setPIPerm', 'setPIRandomDamp', 'setPIStrength', 'setPISurfaceDamp', 'setPIType', 'setPIUseMaxDist', 'setSBDefaultGoal', 'setSBErrorLimit', 'setSBFriction', 'setSBGoalFriction', 'setSBGoalSpring', 'setSBGravity', 'setSBInnerSpring', 'setSBInnerSpringFriction', 'setSBMass', 'setSBMaxGoal', 'setSBMinGoal', 'setSBStiffQuads', 'setSBUseEdges', 'setSBUseGoal', 'setSize', 'setTimeOffset', 'shareFrom', 'size', 'tag', 'texSpace', 'timeOffset', 'track', 'trackAxis', 'transp', 'type', 'upAxis', 'users', 'wireMode', 'xRay']
Object: Omni_mic_mono_side; ['DupEnd', 'DupGroup', 'DupObjects', 'DupOff', 'DupOn', 'DupSta', 'Layer', 'Layers', 'LocX', 'LocY', 'LocZ', 'RotX', 'RotY', 'RotZ', 'SizeX', 'SizeY', 'SizeZ', '__class__', '__cmp__', '__copy__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'action', 'actionStrips', 'activeMaterial', 'activeShape', 'addProperty', 'addScriptLink', 'addVertexGroupsFromArmature', 'axis', 'boundingBox', 'buildParts', 'clearIpo', 'clearScriptLinks', 'clearTrack', 'clrParent', 'colbits', 'constraints', 'convertActionToStrip', 'copy', 'copyAllPropertiesTo', 'copyNLA', 'dLocX', 'dLocY', 'dLocZ', 'dRotX', 'dRotY', 'dRotZ', 'dSizeX', 'dSizeY', 'dSizeZ', 'data', 'dloc', 'drawMode', 'drawSize', 'drawType', 'drot', 'dsize', 'dupFacesScaleFac', 'effects', 'enableDupFaces', 'enableDupFacesScale', 'enableDupFrames', 'enableDupGroup', 'enableDupNoSpeed', 'enableDupRot', 'enableDupVerts', 'enableNLAOverride', 'evaluatePose', 'fakeUser', 'game_properties', 'getAction', 'getAllProperties', 'getBoundBox', 'getData', 'getDeltaLocation', 'getDrawMode', 'getDrawType', 'getEuler', 'getInverseMatrix', 'getIpo', 'getLocation', 'getMaterials', 'getMatrix', 'getName', 'getPIDeflection', 'getPIFalloff', 'getPIMaxDist', 'getPIPerm', 'getPIRandomDamp', 'getPIStrength', 'getPISurfaceDamp', 'getPIType', 'getPIUseMaxDist', 'getParent', 'getParentBoneName', 'getParticleSystems', 'getPose', 'getProperty', 'getSBDefaultGoal', 'getSBErrorLimit', 'getSBFriction', 'getSBGoalFriction', 'getSBGoalSpring', 'getSBGravity', 'getSBInnerSpring', 'getSBInnerSpringFriction', 'getSBMass', 'getSBMaxGoal', 'getSBMinGoal', 'getSBStiffQuads', 'getSBUseEdges', 'getSBUseGoal', 'getScriptLinks', 'getSize', 'getTimeOffset', 'getTracked', 'getType', 'insertCurrentPoseKey', 'insertIpoKey', 'insertPoseKey', 'insertShapeKey', 'ipo', 'isSB', 'isSelected', 'isSoftBody', 'join', 'layers', 'lib', 'link', 'loc', 'makeDisplayList', 'makeParent', 'makeParentBone', 'makeParentDeform', 'makeParentVertex', 'makeTrack', 'mat', 'materialUsage', 'matrix', 'matrixLocal', 'matrixOldWorld', 'matrixParentInverse', 'matrixWorld', 'modifiers', 'name', 'nameMode', 'newParticleSystem', 'parent', 'parentType', 'parentVertexIndex', 'parentbonename', 'passIndex', 'piDeflection', 'piFalloff', 'piMaxDist', 'piPermeability', 'piRandomDamp', 'piSoftbodyDamp', 'piSoftbodyIThick', 'piSoftbodyOThick', 'piStrength', 'piSurfaceDamp', 'piType', 'piUseMaxDist', 'pinShape', 'properties', 'protectFlags', 'rbFlags', 'rbHalfExtents', 'rbMass', 'rbRadius', 'rbShapeBoundType', 'removeAllProperties', 'removeProperty', 'restrictDisplay', 'restrictRender', 'restrictSelect', 'rot', 'sbDefaultGoal', 'sbErrorLimit', 'sbFriction', 'sbGoalFriction', 'sbGoalSpring', 'sbGrav', 'sbInnerSpring', 'sbInnerSpringFrict', 'sbMass', 'sbMaxGoal', 'sbMinGoal', 'sbSpeed', 'sbStiffQuads', 'sbUseEdges', 'sbUseGoal', 'sel', 'select', 'setConstraintInfluenceForBone', 'setDeltaLocation', 'setDrawMode', 'setDrawType', 'setEuler', 'setIpo', 'setLocation', 'setMaterials', 'setMatrix', 'setName', 'setPIDeflection', 'setPIFalloff', 'setPIMaxDist', 'setPIPerm', 'setPIRandomDamp', 'setPIStrength', 'setPISurfaceDamp', 'setPIType', 'setPIUseMaxDist', 'setSBDefaultGoal', 'setSBErrorLimit', 'setSBFriction', 'setSBGoalFriction', 'setSBGoalSpring', 'setSBGravity', 'setSBInnerSpring', 'setSBInnerSpringFriction', 'setSBMass', 'setSBMaxGoal', 'setSBMinGoal', 'setSBStiffQuads', 'setSBUseEdges', 'setSBUseGoal', 'setSize', 'setTimeOffset', 'shareFrom', 'size', 'tag', 'texSpace', 'timeOffset', 'track', 'trackAxis', 'transp', 'type', 'upAxis', 'users', 'wireMode', 'xRay']
Object: Omni_mic_mono_zenit; ['DupEnd', 'DupGroup', 'DupObjects', 'DupOff', 'DupOn', 'DupSta', 'Layer', 'Layers', 'LocX', 'LocY', 'LocZ', 'RotX', 'RotY', 'RotZ', 'SizeX', 'SizeY', 'SizeZ', '__class__', '__cmp__', '__copy__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'action', 'actionStrips', 'activeMaterial', 'activeShape', 'addProperty', 'addScriptLink', 'addVertexGroupsFromArmature', 'axis', 'boundingBox', 'buildParts', 'clearIpo', 'clearScriptLinks', 'clearTrack', 'clrParent', 'colbits', 'constraints', 'convertActionToStrip', 'copy', 'copyAllPropertiesTo', 'copyNLA', 'dLocX', 'dLocY', 'dLocZ', 'dRotX', 'dRotY', 'dRotZ', 'dSizeX', 'dSizeY', 'dSizeZ', 'data', 'dloc', 'drawMode', 'drawSize', 'drawType', 'drot', 'dsize', 'dupFacesScaleFac', 'effects', 'enableDupFaces', 'enableDupFacesScale', 'enableDupFrames', 'enableDupGroup', 'enableDupNoSpeed', 'enableDupRot', 'enableDupVerts', 'enableNLAOverride', 'evaluatePose', 'fakeUser', 'game_properties', 'getAction', 'getAllProperties', 'getBoundBox', 'getData', 'getDeltaLocation', 'getDrawMode', 'getDrawType', 'getEuler', 'getInverseMatrix', 'getIpo', 'getLocation', 'getMaterials', 'getMatrix', 'getName', 'getPIDeflection', 'getPIFalloff', 'getPIMaxDist', 'getPIPerm', 'getPIRandomDamp', 'getPIStrength', 'getPISurfaceDamp', 'getPIType', 'getPIUseMaxDist', 'getParent', 'getParentBoneName', 'getParticleSystems', 'getPose', 'getProperty', 'getSBDefaultGoal', 'getSBErrorLimit', 'getSBFriction', 'getSBGoalFriction', 'getSBGoalSpring', 'getSBGravity', 'getSBInnerSpring', 'getSBInnerSpringFriction', 'getSBMass', 'getSBMaxGoal', 'getSBMinGoal', 'getSBStiffQuads', 'getSBUseEdges', 'getSBUseGoal', 'getScriptLinks', 'getSize', 'getTimeOffset', 'getTracked', 'getType', 'insertCurrentPoseKey', 'insertIpoKey', 'insertPoseKey', 'insertShapeKey', 'ipo', 'isSB', 'isSelected', 'isSoftBody', 'join', 'layers', 'lib', 'link', 'loc', 'makeDisplayList', 'makeParent', 'makeParentBone', 'makeParentDeform', 'makeParentVertex', 'makeTrack', 'mat', 'materialUsage', 'matrix', 'matrixLocal', 'matrixOldWorld', 'matrixParentInverse', 'matrixWorld', 'modifiers', 'name', 'nameMode', 'newParticleSystem', 'parent', 'parentType', 'parentVertexIndex', 'parentbonename', 'passIndex', 'piDeflection', 'piFalloff', 'piMaxDist', 'piPermeability', 'piRandomDamp', 'piSoftbodyDamp', 'piSoftbodyIThick', 'piSoftbodyOThick', 'piStrength', 'piSurfaceDamp', 'piType', 'piUseMaxDist', 'pinShape', 'properties', 'protectFlags', 'rbFlags', 'rbHalfExtents', 'rbMass', 'rbRadius', 'rbShapeBoundType', 'removeAllProperties', 'removeProperty', 'restrictDisplay', 'restrictRender', 'restrictSelect', 'rot', 'sbDefaultGoal', 'sbErrorLimit', 'sbFriction', 'sbGoalFriction', 'sbGoalSpring', 'sbGrav', 'sbInnerSpring', 'sbInnerSpringFrict', 'sbMass', 'sbMaxGoal', 'sbMinGoal', 'sbSpeed', 'sbStiffQuads', 'sbUseEdges', 'sbUseGoal', 'sel', 'select', 'setConstraintInfluenceForBone', 'setDeltaLocation', 'setDrawMode', 'setDrawType', 'setEuler', 'setIpo', 'setLocation', 'setMaterials', 'setMatrix', 'setName', 'setPIDeflection', 'setPIFalloff', 'setPIMaxDist', 'setPIPerm', 'setPIRandomDamp', 'setPIStrength', 'setPISurfaceDamp', 'setPIType', 'setPIUseMaxDist', 'setSBDefaultGoal', 'setSBErrorLimit', 'setSBFriction', 'setSBGoalFriction', 'setSBGoalSpring', 'setSBGravity', 'setSBInnerSpring', 'setSBInnerSpringFriction', 'setSBMass', 'setSBMaxGoal', 'setSBMinGoal', 'setSBStiffQuads', 'setSBUseEdges', 'setSBUseGoal', 'setSize', 'setTimeOffset', 'shareFrom', 'size', 'tag', 'texSpace', 'timeOffset', 'track', 'trackAxis', 'transp', 'type', 'upAxis', 'users', 'wireMode', 'xRay']

list(bpy.data.ipos)
[Ipo "fast_pass" (Object)], [Ipo "Orbit1" (Object)]]

trajectory1=bpy.data.ipos['fast_pass']

dir(trajectory1)
['EvaluateCurveOn', '__class__', '__cmp__', '__contains__', '__copy__', '__delattr__', '__delitem__', '__doc__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__len__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__str__', 'addCurve', 'blocktype', 'channel', 'copy', 'curveConsts', 'curves', 'delBezPoint', 'delCurve', 'fakeUser', 'getBlocktype', 'getCurve', 'getCurveBP', 'getCurveBeztriple', 'getCurveCurval', 'getCurves', 'getNBezPoints', 'getName', 'getNcurves', 'getRctf', 'lib', 'name', 'next', 'properties', 'rctf', 'setBlocktype', 'setCurveBeztriple', 'setName', 'setRctf', 'tag', 'users']

for i in range(10):
for o in trajectory1.curves:
frame=i*20
tempPos=o.evaluate(frame)
tempName=o.name
print 'on frame '+str(frame)+', curve '+tempName+' has interpolated pos: '+str(tempPos)
on frame 0, curve LocX has interpolated pos: -12.0658063889
on frame 0, curve LocY has interpolated pos: 15.4735555649
on frame 20, curve LocX has interpolated pos: -7.77819442749
on frame 20, curve LocY has interpolated pos: 10.7129554749
on frame 40, curve LocX has interpolated pos: -3.2807290554
on frame 40, curve LocY has interpolated pos: 5.92898416519
on frame 60, curve LocX has interpolated pos: 1.36230826378
on frame 60, curve LocY has interpolated pos: 1.14720904827
on frame 80, curve LocX has interpolated pos: 6.08232021332
on frame 80, curve LocY has interpolated pos: -3.60687565804
on frame 100, curve LocX has interpolated pos: 10.8083820343
on frame 100, curve LocY has interpolated pos: -8.30803489685
on frame 120, curve LocX has interpolated pos: 15.469367981
on frame 120, curve LocY has interpolated pos: -12.931634903
on frame 140, curve LocX has interpolated pos: 19.9961471558
on frame 140, curve LocY has interpolated pos: -17.4538326263
on frame 160, curve LocX has interpolated pos: 24.3235778809
on frame 160, curve LocY has interpolated pos: -21.851858139
on frame 180, curve LocX has interpolated pos: 28.3921985626
on frame 180, curve LocY has interpolated pos: -26.1042022705

for object in bpy.data.objects:
if object.name.lower().find('source')!=-1:
print object.name
print object.getIpo().name
Audio_Omni_Source1
fast_pass
Audio_Omni_Source2
Orbit1
Audio_Omni_Source3
fast_pass

(it will be continued...)

June 24, 2008

Too much?



I like it. :-)


ACTUALIZATION:
I had some troubles with LADSPA/FAUST support on my usual customized UbuntuStudio Feisty... I though that the problem was because some old jack/alsa packages, so I rebooted on Hardy to test it. Not only all the problems dissapeared, but also I noted this impressive graphics difference. A network like the previous is showed here:


Isn't it beautiful? :-D

June 22, 2008

NetworkEditor Copy & Paste

One of the NE improvements which I worked on is the copy & paste processings boxes selections functionality.

You select the processings, copy (or cut) them from the processings context menu (or CTRL-C/X) and then paste it from the canvas context menu (or CTRL-V).

A graphical demonstration:



BTW, David added very nice icons to the menu items, so actually it look like this:

June 15, 2008

What do users essentially want?

DSCN1482I attended Google Developer day 2008. How colorful the day is~

One of the most impressive speech is given by Xiaosheng Tan, CTO of MySpace.cn. This guy is so funny, hehehe, that the last thing on earth I'll do is to write his joke down on my blog.??

MySpace.cn is an OpenSocial website, where users can embed all sorts of gadgets in their web pages. There is a gadget code competition on MySpace.cn. A lot of nice works are received and two of them are extraordinary.
One is "a clock that can stretch". One guy developed it in an afternoon when he got bored of his daily work and just wanna have fun for a while.
The other is "E-Album" by MagicBox, which is developed by a team of molihe.com, and is very versatile, powerful, and with profound technics of photoshop, 3D effects, etc.
It turns out the winner is "a clock that can stretch", whose user-setup amount achieves 10683 till now, far beyond the number of 8577 of "E-Album".

          StretchingClock2               E_Album_MagicBox                       
Why does the little pink lazy clock beat the brilliant magic E-Album down? Mr.Tan gave us a vivid illustration about what do users essentially want:

  • If users are the mass, simpleness and intuitive are especially crutial.
  • The tool must appear as CUTE as possible, always!
  • Fancy& design> Technic.
As to the myspace.cn users, one big bonus of the clock is-- "Emm, it apears cool!".

June 14, 2008

Getting Blender positions in CLAM via OSC

A very first attempt to access Blender parameters within CLAM, via Open Sound Control. A sphere traveling around the origin of coordinates in Blender, and CLAM printing the values. Nothing new, but... IT WORKS! :-)

Just a screenshot. It would be better to capture a video, but I don't know how to do it.

June 09, 2008

Network Scalability

Let's start describing a little of my CLAM GSoC first main area: the Network Scalability.

To be honest, one of the things that I dislike about visual object oriented DSP designers like Network Editor, Pd, etc, is the (visual) complexity that a network/patch sometimes can reach with a simple design that uses so many objects and correspondent "cables" connections, when the same design in a text code language could be a lot simpler to write, read and understand. That is the main reason to had choosen the network scalability proposed idea, because I think is one of the best ways to solve that issue. Beyond it seems to be a good solution because its logic, several years of similar implementations on both Max/MSP and Pd can prove that it really is. And that is the reason because my ideas about the implementation are closer to the Pd models. [1]

Subnetworks will allows the users to encapsulate networks onto new single processings. Once they finish a functional block, they can simplify it onto new "black boxes", improving the networks in a modular way.

To do that, I think to use network's level audio and control "sinks" and "sources" processings boxes, which will be appear as inlets and outlets on the newer encapsulated network-processings. [2]
A first approach could be making some "wireless" processings boxes, which can interconnect distant processings (at first) on the same network, using a key name as identifier, like a "variable". [3]

Those improvements are close related with the networks flow task of the proposed idea on the wiki. Once done that, and defined the infrastructure to use for recursive networks [4], I'll need to search a way to finish the integration of composite objects-subnetworks within the Network Editor.

As an intermediate task I though to allow some kind of grouping management on a same-level network. For now, the user can only selects objects in NE canvas to move, delete and copy/cut to clipboard. So, managing the processings as groups could be extended then to layers and later to subnetworks.

Well, this is an overview of the scalability area. Insofar as I involve further on developing these ideas I'll found more issues. For now, I'd been dedicated to make NE canvas interface improvements, so I think those related tasks don't be difficult. Let's see about the CLAM specific flow management...

[1] But of course, any suggestion against, or improving these models are welcome.
[2] Like "inlet" and "outlet" Pd objects.
[3] Like "send" and "receive" Pd objects.
[4] Writing this, I realize that my previous question on the devel-list has no much sense, because we are not talking about a defined limited levels, but recursion...

June 08, 2008

Standards for 3D Scene Description

What can you do if you want to describe a 3D scene including audio and graphics using some kind of standard? This is the result of a quick survey we did for CLAM, feedback is welcomed!

There are several standards and open languages to describe 3D graphics, but what if you want to add 3D audio description into the scene? Well, that limits your choices but there are still some possibilities.

First, you can take a look at MPEG4's BIFS and AudioBIFS. BIFS is in fact an extension of VRML. MPEG4's SAOL (Structured Audio Orchestra Language) can also be included inside AudioBIFS. Unfortunately I don't know of any Open Source reference implementation of this, although parts of it have been implemented, for instance, in Ross Bencina's Audio Mulch.

X3D is a W3 standard that is also a sucessor of VRML (with the advantage of using an new XML format), in which the sound is integrated too. There are no complete implementations of X3D available and all of them are written in Java. X3D shares a lot with BIFS. As a matter of fact the MPEG standard already includes a link to X3D.

Another possibility is using VML from the Verse project. This project is very much related to Blender. Using VML can tie you into their data model. However Verse is released with a BSD license.

Finally, SpatDIF, is an extension of the SDIF format for sound interchange. It uses OSC for real-time communication and SDIF as the intermediate file format. There are no available implementations yet and it is unclear whether it can be easily extended to include 3D graphics. However, SDIF can be transcoded into SAOL and, as already mentioned, SAOL can be included inside MPEG4's BIFS.

So, in summary, it looks as there are several competing and complementary efforts but none is sufficiently mature yet. Again, any feedback on related experiences will be appreciated.