HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Performance of speech enhancement code for Android app

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
speechandroidappenhancementforperformancecode

Problem

I wrote a speech enhancement code for an Android App. The algorithm runs on 256 size frames of voice samples. On my PC the code runs per about 5ms per frame, while on my Nexsus 5 it more like 50ms per frame, making the speech enhancement on a 30sec long recording run for over two minutes. On my PC, enhancing the whole audio file takes under a minute. I am looking to improve run time anywhere I can. I am attaching the code that runs per frame which is where I see biggest increase in run time.

```
for(int j = 0; j < Consts.NUM_OF_CLUSTERS; j++)
{
tmp_log_h=0;
for(int k = 0; k < Consts.SIZE_OF_SEMPELS_IN_CHUNCK; k++)
{

f_X = (1/FastMath.sqrt(2FastMath.PIsigmaSqr.get(j).get(k)))FastMath.exp(-(FastMath.pow(NoisySignal[k] - mue.get(j).get(k),2))/(2sigmaSqr.get(j).get(k)));// equation (3)
F_X=(0.500 + 0.5Erf.erf((NoisySignal[k] - mue.get(j).get(k))/(FastMath.sqrt(2sigmaSqr.get(j).get(k)))));// equation (6)

if(j==0)
{
g_pdf_Y[k]=1/FastMath.sqrt(2FastMath.PINoise_sigmaSqr.get(k))FastMath.exp(-(FastMath.pow(NoisySignal[k] - Noise_mu.get(k),2))/(2Noise_sigmaSqr.get(k)));// equation (4)
G_cdf_Y[k]=(0.500 + 0.5Erf.erf((NoisySignal[k] - Noise_mu.get(k))/(FastMath.sqrt(2Noise_sigmaSqr.get(k)))));// equation (5)
}

tmp_R_samples = (f_X/F_X);// equation (12.5)

if(j==0)
{
R_noise[k]=g_pdf_Y[k]/G_cdf_Y[k]; // equation (12.5)
}

Roe[j][k] = 1/(1 + (R_noise[k]/tmp_R_samples));
X_hat[j][k] = NoisySignal[k]Roe[j][k]+ (mue.get(j).get(k))(1 - Roe[j][k]) - (sigmaSqr.get(j).get(k))((f_XR_noise[k])/(f_X + F_X*R_noise[k]));
tmp_h_first=(f_XG_cdf_Y[k] + F_Xg_pdf_Y[k]);// equation (7.5)
tmp_log_h += FastMath.log(tmp_h_first); // equation (7.5)
}

Log_h_second[j]=tmp_log_h;
Log_h_final_vecotr[j]=FastMath.log(c.get(j)) + Log_h_second[j];
}

Double maxVi = MathHelpers.findMax(Log_h_final_vecotr);

double

Solution

Performance

I cannot offer any mayor improvements, just some small things:

You should save results of a calculation or action instead of doing them over and over.

For example:

  • 2FastMath.PI: this is not dependent on the loop variables, just save it in a variable (same goes for 2sigmaSqr.get(j).get(k) which you are doing three times for every loop; and NoisySignal[k] - mue.get(j).get(k) which you are doing twice). These duplicate calculations are quite hard to catch in your code. If you write the equations on paper, it becomes easier to spot.



  • mue.get(j).get(k): you are doing this three times. I don't know what mue is, but depending on the kind of list, it may be expensive (same goes for sigmaSqr.get(j).get(k))



You could also move the calculation of X_estimate inside the previous j loop:

for(int j = 0; j < Consts.NUM_OF_CLUSTERS; j++)
{
    Log_q[j]=FastMath.log(c.get(j)) + Log_h_second[j] - Log_h_final;
    q[j]=(FastMath.exp(Log_q[j]));// equation (10)

    Double temp_X_estimate = 0.0;
    for(int k = 0; k < Consts.SIZE_OF_SEMPELS_IN_CHUNCK; k++)
    {       
        temp_X_estimate += (X_hat[j][k]*q[j]);        
    }
    X_estimate[k]=temp_X_estimate;// equation (9)
}


It will save you running through the loop once, you can profile it to see if it is worth the loss in readability.

Readability

Code Structure

I would probably pull out the j==0 case in front of the loop. Keeping it in the loop is confusing and seems unnecessary.

Function calls do cause an overhead, but I would still consider extracting some of the code to separate functions (this would make profiling the code easier).

Additional variables also cause a slight overhead, but some of your expressions are quite long and hard to grasp. You might consider adding intermediate variables with an expressive name saving a temporary state of the calculation. An alternative would be to use newlines to present the expressions in a better way.

Variable Names

I don't think that your variable names are very expressive. I'm not that deep into the topic, but I would guess that at least some of them can be improved upon.

Also, just using case to differentiate names is quite confusing (f_X vs F_X).

Comments

I'm guessing that you have some kind of documentation to which your current comments refer. But without it, they are not that useful. It might be helpful to add this documentation (or a short excerpt) to the top.

Style

Please follow general style guidelines.

  • variable names start with a lowercase letter (this lets a reader easily see that it is a variable, not a class)



  • declare variables where they are used (tmp_log_h for example is declared outside the loop, even though it is not needed there)



  • use more spaces (for example, before and after ==, =, /, *, etc)



  • in Java, camelCase is usually used instead of underscores (you do this sometimes (eg maxVi or sumExp, but mostly you use underscores)



Misc

  • get rid of unnecessary brackets (for example (X_hat[j][k]*q[j]), tmp_R_samples = (f_X/F_X), or f_X = (...); especially in the last example, the expression already has enough parentheses without the extra once :) )

Code Snippets

for(int j = 0; j < Consts.NUM_OF_CLUSTERS; j++)
{
    Log_q[j]=FastMath.log(c.get(j)) + Log_h_second[j] - Log_h_final;
    q[j]=(FastMath.exp(Log_q[j]));// equation (10)

    Double temp_X_estimate = 0.0;
    for(int k = 0; k < Consts.SIZE_OF_SEMPELS_IN_CHUNCK; k++)
    {       
        temp_X_estimate += (X_hat[j][k]*q[j]);        
    }
    X_estimate[k]=temp_X_estimate;// equation (9)
}

Context

StackExchange Code Review Q#63181, answer score: 5

Revisions (0)

No revisions yet.