Activity › Forums › Adobe After Effects Expressions › Faster / Less calculation heavy expression needed
-
Faster / Less calculation heavy expression needed
Posted by Ole Peters on December 3, 2015 at 8:26 pmHello,
I’ve got this beautiful expression from Dan Ebberts MotionScript website.
z = time*5;
spd = comp("Music").layer("Audio Amplitude").effect("Both Channels")("Slider");
mult = 1;
n = spd.numKeys;
if (n > 0 && spd.key(1).time < time){
accum = spd.key(1).value*(spd.key(1).time - inPoint);
for (i = 2; i <= n; i++){
if (spd.key(i).time > time) break;
k1 = spd.key(i-1);
k2 = spd.key(i);
accum += (k1.value + k2.value)*(k2.time - k1.time)/2;
}
accum += (spd.value + spd.key(i-1).value)*(time - spd.key(i-1).time)/2;
}else{
accum = spd.value*(time - inPoint);
}
value + z+accum*multHowever, it’s really calculation heavy and isnt too good for rendering over and over again.
I would like to know if theres a faster expression to achieve that effect (Moving faster on a beat). Or somethig that adds up only positive values from an audio amplitude.Cheers!
OleOle Peters replied 10 years, 9 months ago 3 Members · 8 Replies -
8 Replies
-
Kalleheikki Kannisto
December 4, 2015 at 1:01 pmNot through an expression, an expression needs to check all preceding frames to do something like this.
Two options come to mind:
1) Convert expressions to keyframes. Then you don’t have to calculate each frame every time you render.
2) Use Trapcode Soundkeys to do this, it will bake the values into keyframes, and has an option to do cumulative.
-
Ole Peters
December 4, 2015 at 1:34 pmSo, theres absolutely no other way of adding up values with an expression?
Hm.My After Effects crashes when I try to convert the expression to keyframes and I don’t really want to use soundkeys because I would have to change the whole file.
-
Dan Ebberts
December 4, 2015 at 10:26 pmYou can probably do it with a script. Here’s a rough version (without all the bells and whistles like making sure the active item is a comp, the Audio Amplitude layer and Both Channels slider exist, making sure the new slider hasn’t already been added, etc.):
var myComp = app.project.activeItem;var newSliderControl = myComp.layer("Audio Amplitude").property("Effects").addProperty("ADBE Slider Control");
newSliderControl.name = "Accum";
var mySlider = newSliderControl.property("Slider");
var spdSlider = myComp.layer("Audio Amplitude").property("Effects").property("Both Channels").property("Slider");var accum = 0;
mySlider.setValueAtTime(spdSlider.keyTime(1),accum);
for (var i = 2; i <= spdSlider.numKeys; i++){
accum += (spdSlider.keyValue(i) + spdSlider.keyValue(i-1))/2;
mySlider.setValueAtTime(i*myComp.frameDuration,accum);
}
It adds a slider named Accum with the accumulated audio value to the Audio Amplitude layer. You’ll probably need to scale the value in whatever expression you use.
Dan
-
Ole Peters
December 5, 2015 at 2:01 pmWorks perfectly! Thank you, Dan!
One last question, how do I check if the Accum slider is already on a layer?
I’ve thought about something like this:tabB.onClick = function () {
function main(){
var myComp = app.project.activeItem;var newSliderControl = myComp.layer("Audio Amplitude").property("Effects").addProperty("ADBE Slider Control");
newSliderControl.name = "Accum";
var mySlider = newSliderControl.property("Slider");
var spdSlider = myComp.layer("Audio Amplitude").property("Effects").property("Both Channels").property("Slider");var accum = 0;
mySlider.setValueAtTime(spdSlider.keyTime(1),accum);
for (var i = 2; i <= spdSlider.numKeys; i++){
accum += (spdSlider.keyValue(i) + spdSlider.keyValue(i-1))/2;
mySlider.setValueAtTime(i*myComp.frameDuration,accum);}
}
var selLayer = app.project.activeItem;
if (selLayer.selectedLayers.length == 0){
alert ("No layer selected.");
return;}
var dCheck = selLayer.property("Effects").property("Accum").property("Slider");
if (dCheck == selLayer.property("Effects")){
alert("Accum is already applied.");
}main();
}Everything works until I add the part with the dCheck to tell me that Accum is already applied.
Any ideas?Ole
-
Dan Ebberts
December 5, 2015 at 7:02 pmI think I’d do it with a function that looks for an existing slider named “Accum”. If it doesn’t exist, it creates one and returns the “Slider” property. If it does exist, it removes any existing keyframes and returns the “Slider” property:
function addAccum(theLayer){
var theSlider = theLayer.property("Effects").property("Accum");
if (theSlider != null){
var theProp = theSlider.property("Slider");
for (var i = theProp.numKeys; i > 0; i--){
theProp.removeKey(i);
}
return theProp;
}else{
theSlider = theLayer.property("Effects").addProperty("ADBE Slider Control");
theSlider.name = "Accum";
return theSlider.property("Slider");
}
}
Dan
-
Ole Peters
December 5, 2015 at 8:07 pmHow do I implement that into the script so I get the alarm?
The whole thing looks like that right now:
function AtA(thisObj)
{//==================
var version = '1';
//==================var palette = (thisObj instanceof Panel) ? thisObj : new Window('palette','AtA',undefined, {resizeable:true});
palette.orientation = 'stack';
palette.alignChildren = ['fill','fill'];function addHGroup(container){
var groupe = palette.add('group');
groupe.alignChildren = ['fill','fill'];
groupe.orientation = 'row';
groupe.spacing = 10;
groupe.margins = 3;
return groupe;
}
var bottomGroup = addHGroup('mainGroup');
bottomGroup.alignment = ['fill','bottom'];{
var trimCompURL = bottomGroup.add ('statictext',undefined,'Custom');
trimCompURL.alignment = ['right','bottom'];
}var guiP = palette.add('group');
guiP.orientation = 'column';
guiP.alignChildren = ['fill', 'fill'];
var tcB = guiP.add('tabbedpanel', undefined, '');
var tabContent1 = tcB.add('tab', undefined, 'Convert');
var tabB = tabContent1.add('button', undefined, 'Convert dat shit!');
tabB.size = [100,50];
tabB.alignment = ['center', 'center'];
var tabContent2 = tcB.add('tab', undefined, 'Version & Credits');
tabContent2.add('statictext', undefined, ' -- ' + 'AtA v' + (version) + ' -- ' + '\n\n' , {multiline:true});tabB.onClick = function () {
function main(){
var myComp = app.project.activeItem;var newSliderControl = myComp.layer("Audio Amplitude").property("Effects").addProperty("ADBE Slider Control");
newSliderControl.name = "Accum";
var mySlider = newSliderControl.property("Slider");
var spdSlider = myComp.layer("Audio Amplitude").property("Effects").property("Both Channels").property("Slider");var accum = 0;
mySlider.setValueAtTime(spdSlider.keyTime(1),accum);
for (var i = 2; i <= spdSlider.numKeys; i++){
accum += (spdSlider.keyValue(i) + spdSlider.keyValue(i-1))/2;
mySlider.setValueAtTime(i*myComp.frameDuration,accum);}
}
var selLayer = app.project.activeItem;
if (selLayer.selectedLayers.length == 0){
alert ("No layer selected.");
return;}
main();
}guiP.hide();
function loadAtA() {
guiP.show();
}
loadAtA();palette.layout.layout(true);
palette.layout.resize();
palette.onResizing = palette.onResize = function () { this.layout.resize(); }
if (!(thisObj instanceof Panel)) palette.show();return palette;
}
AtA(this);
If I try to put it in there it still adds the Accum Slider but you can still add another one and another one, I have to get into scripts more..Ole
-
Dan Ebberts
December 5, 2015 at 8:31 pmI wouldn’t worry about the alarm since the script can take care of it. I’d add the addAccum() function, then replace these three lines:
var newSliderControl = myComp.layer(“Audio Amplitude”).property(“Effects”).addProperty(“ADBE Slider Control”);
newSliderControl.name = “Accum”;
var mySlider = newSliderControl.property(“Slider”);with this:
var mySlider = addAccum(myComp.layer(“Audio Amplitude”));
Dan
Reply to this Discussion! Login or Sign Up