Is there a way to simplify this expression? It would help this script I’m working on go faster if so. It can be written cleanly in at least these two fashions:
Is there a way to simplify this expression? It would help this script I’m working on go faster if so. It can be written cleanly in at least these two fashions:
1/2 * log_2(x) is the same as log_2(x) - 1 as 1/2 * log_2(x) represent 1/2 * 2^y ?= x which is the same as 2^(y-1) ?= x
Further simplication isn’t possible and 10^x just is 10^x, there is no way to simplify that. Log is the worst possible operation you can have (which is why it is still used for encryption protocols although much more robust solutions exist).
The only thing you could do there is just drop maths altogether, not sure if it is faster thought so you would have to test.
10^x is the same as
string result = "1";
for( i = 0; i < x; i++ )
result += "0";
and then casting that to number
when working with those operations, ensure that you define the variables as int if possible. Int log is faster than float log
You’re a smart cookie! :o
Here’s what I’m doing. I’d love to hear any suggestion to improve it.
hmm not that much of a smart cookie sadly. Just too much beeing exposed to ETH Zurich maths courses I guess ^^
Most important to change there: Introduce a state that tells you if you need to update the volume at all ie “only calc if you have to calc”
But other than that, the only way to reduce it is what mentioned above.
So the final would look similar to this one (written out of head)
var loudnessChanged : boolean = false;
var loudness : float = 1;
// I would not leave this in Update() for a release.
// Put it wherever you need it, to change the volume in-game.
function Update ()
{
if( loudnessChanged ) {
audio.volume = Mathf.Pow(10, Mathf.Log(loudness, 2)-1);
loudnessChanged = false;
}
}
function SetLoudness( newLoudness : float ){
// this is not a too clean solution as floats rarely win the == game
// mainly wanted to have this in place to show the optimization point
if( newLoudness == loudness )
return;
loudness = newLoudness;
loudnessChanged = true;
}
Your reasoning is why I put my original comments in. I would leave the loudness evaluation in Update, when initially prototyping, so that you could drag/alter the value in the inspector and have immediate results, and then switch it out later, to wherever it was needed in the game code. Is there perhaps a better way, given whatever new editor features 2.5 brings?
True, but given that the calculation uses a binary log there are fast algorithms to approximate it using bitwise operations. The binary log of a number (as an unsigned int, at least) is always going to be less than the number of significant bits and greater than the number of significant bits - 1. For example Log_2(19) would be:
x = Log_2(19) = Log_2(00010011) = 5 > x > 4
I’ll have to brush up on my bitwise operators before I can make a code example out of that, but for something like a volume controller an approximate value like that should be good enough that you can fudge the values in between (just interpolate linearly between each 10dB step).
Nice that someone is caring about the sfx aspect of Unity.
Btw i know it’s somehow a complete waste of time and there exist hundreds of VSTIs already but it’s just so much plain fun that from time to time i’m enjoying working on my own softsynth, all wip.
Sadly can’t provide it in the webplayer but a shortrecorded ogg in here with some weird and to some ears maybe disgusting düdeldideldü. :O9
dawvee: nice cutdown for ints
Sadly this one here is a float [0,1]
I’m no expert on audio, but it seems that unless you particularly want to calibrate the sound volume in decibels, you don’t need to bother with the log at all.
Loudness, as I understand it, roughly obeys a power law (Wikipedia article) a bit like colour gamma. The Wikipedia article gives the exponent as 0.67, so
perceivedLoudness = soundPower ^ 0.67
In your code, I think you just need a line like
audio.volume = Mathf.Pow(loudness, 1f / 0.67f)
…to get the result you want (1 / 0.67 is actually 1.493, by the way). This will also ensure that the volume is zero when the loudness is zero and one when the loudness is one. Pow is still a processor-hungry function, unfortunately.
Thanks, andeeee. I’ve definitely found a way to eliminate the necessity for the logarithm, but only because I stumbled across the following interesting property experimentally. Can someone give me a link to proof of this, so I can update the “Why this works” section on the wiki? I haven’t come across it yet elsewhere, but it definitely works for all the numbers I’ve thrown at it, and it’s exactly what I need to make the algorithm execute faster. Unfortunately, I’m just a guy who is interested in sound, not a mathematician.
a^log(b) = b^log(a)
First, given the definition of a logarithm you can define a as:
a = b^logb(a)
and b is likewise:
b = a^loga(b)
So taking one side of your equation and substituting the above identity for b, we get:
a^log10(b) = a^log10(a^loga(b))
The exponent inside the log can be brought outside to give us:
a^loga(b)*log10(a)
And since x^a*b = (x^a)^b, we can do this:
(a^loga(b))^log10(a)
and finally, substitute the part in parentheses with the identity of b again to give us this:
b^log10(a)
and we have equality!
That’s fantastic. May I include your proof in the wiki explanation? Is there some way you would like me to credit you?
Of course you’re free to include it, mathematical concepts aren’t copyrighted, after all. :lol:
If you want to credit me though, that’s cool too. Screen name or real name (David Huntrods), however you see fit. Just glad I could help - gave me a chance to dust off a few neurons, too.
Thanks again, guys. Here are the fruits of my labor, as of late. Please let me know if you have any suggestions for improvement.
Great work, Jessy! Should come in very handy for more audio-intensive work!