Sean,
The code snapshot I'm attaching is extremely similar to that posted by
altenbach. There are just a few comments I'd like to make that may help you get more speed, some at the expense of accuracy and others at the expense of "purity" (not using an actual decibel measurement).
1. You'll want to avoid division in an inner loop. So rewrite your equation as the equivalent 20*LOG10(x(i,j)) - 20*LOG10(MAX(x))
The entire first term, including the multiplication, can be stored as the lookup value. The second term is calculated just once after find the MAX value. The innermost loop will then just perform a lookup operation and a single subtraction.
2. How important is the actual MAX value? Can you ignore it altogther? If not, here are a couple ways that may help you speed up a MAX search at the expense of some accuracy.
2A. Make your own MAX function that terminates as soon as you find a value "close enough" to 255, the max possible U8 value.
2B. You may be able to take a small random sampling of your ~200k of frame data and use the MAX of the sample as an estimate of MAX for the frame. Combined with 2A, you may often get good results with just hundreds of elements rather than the entire 200k. You'd probably need to predefine the random numbers as another lookup table though since you wouldn't want to calculate them live.
3. A log is a log is a log. Your original equation measures an amplitude ratio and expresses it in decibels. If you can switch to a different base for your LOG function and use another multiplier, you can get more resolution in your lookup table (assuming the table is a set of U8's or other integer values).
The method to make the table is to perform the LOG calculation and multiplication in floating point first, then convert to U8. With decibels, your LOG10 values will range from 0 to 2.4 After multiplying by 20 and converting to U8, they'll range from 0 to 48.
But why not use more of the available bits to define your LOG lookup table? For example, if you perform LOG2 you can get values from 0 to 7.994 If you then multiply by 32 and convert to U8 you'll use the entire range 0 to 255. Using base 2 and powers of 2 may be advantageous if you can write the routine in C or assembly. In my sample, I stuck with base 10 but multiplied by 100 rather than 20 to make better use of the possible U8 range.
4. As
altenbach mentioned, your ratio is always <=1 so the LOG of it will always be <=0. This may actually work out ok for you. Under U8 subtraction, a result that "wants" to be -1 will be represented as 255. Intensity values that are close to max would "want" to be small negative values, but would actually turn out as values close to 255.
WARNING: If you use my idea 2A or 2B, you may end up with individual elements that are actually
larger than your approx or estimated MAX. Even if you don't, there are still some elements that will be equal to MAX. These subtractions will be small numbers >= 0, which makes them appear more like elements with very low intensity. You would need to deal with this issue carefully. In my sample, I found the actual MAX and simply incremented the value for LOG(MAX(x)) so it would always be larger than any actual value in the frame.
ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.