7
\$\begingroup\$

This is part of the code from a spectral subtraction algorithm. I'm trying to optimize it for Android.

Matlab code:

function Seg=segment(signal,W,SP,Window)

% SEGMENT chops a signal to overlapping windowed segments
% A= SEGMENT(X,W,SP,WIN) returns a matrix which its columns are segmented
% and windowed frames of the input one dimentional signal, X. W is the
% number of samples per window, default value W=256. SP is the shift
% percentage, default value SP=0.4. WIN is the window that is multiplied by
% each segment and its length should be W. the default window is hamming
% window.
% 06-Sep-04
% Esfandiar Zavarehei

if nargin<3
    SP=.4;
end
if nargin<2
    W=256;
end
if nargin<4
    Window=hamming(W);
end
Window=Window(:); %make it a column vector

L=length(signal);
SP=fix(W.*SP);
N=fix((L-W)/SP +1); %number of segments

Index=(repmat(1:W,N,1)+repmat((0:(N-1))'*SP,1,W))';
hw=repmat(Window,1,N);
Seg=signal(Index).*hw;

Java code:

public class MatrixAndSegments 
{
    public int numberOfSegments;
    public double[][] res;

    public MatrixAndSegments(int numberOfSegments,double[][] res)
    {
        this.numberOfSegments = numberOfSegments;
        this.res = res;
    }
}



public MatrixAndSegments segment (double[] signal_in,int samplesPerWindow, double        shiftPercentage, double[] window)
{
    //default shiftPercentage = 0.4
    //default samplesPerWindow = 256  //W
    //default window = hanning 


    int L = signal_in.length;
    shiftPercentage = fix(samplesPerWindow * shiftPercentage); //SP
    int numberOfSegments = fix ( (L - samplesPerWindow)/ shiftPercentage + 1); //N

    double[][] reprowMatrix =  reprowtrans(samplesPerWindow,numberOfSegments);
    double[][] repcolMatrix = repcoltrans(numberOfSegments, shiftPercentage,samplesPerWindow );

    //Index=(repmat(1:W,N,1)+repmat((0:(N-1))'*SP,1,W))';
    double[][] index = new double[samplesPerWindow+1][numberOfSegments+1];

    for (int x = 1;  x < samplesPerWindow+1; x++ )
    {
        for (int y = 1 ; y < numberOfSegments + 1; y++) //numberOfSegments was 3
        {
             index[x][y] = reprowMatrix[x][y] + repcolMatrix[x][y];
        }
    }

    //hamming window
    double[] hammingWindow = this.HammingWindow(samplesPerWindow);
    double[][] HW = repvector(hammingWindow, numberOfSegments);

    double[][] seg = new double[samplesPerWindow][numberOfSegments];
    for (int y = 1 ; y < numberOfSegments + 1; y++)
    {
        for (int x = 1; x < samplesPerWindow+1; x++)
        {
            seg[x-1][y-1] = signal_in[ (int)index[x][y]-1 ] * HW[x-1][y-1]; 
        }
    }
    MatrixAndSegments Matrixseg = new MatrixAndSegments(numberOfSegments,seg);
    return Matrixseg;

}


public int fix(double val) {
    if (val < 0) {
        return (int) Math.ceil(val);
    }
    return (int) Math.floor(val);
}

public double[][] repvector(double[] vec, int replications)
{
    double[][] result = new double[vec.length][replications];

    for (int x = 0; x < vec.length; x++) {
        for (int y = 0; y < replications; y++) {
            result[x][y] = vec[x];
        }
    }

    return result;
}

public double[][] reprowtrans(int end, int replications)
{
    double[][] result = new double[end +1][replications+1];

    for (int x = 1; x <= end; x++) {
        for (int y = 1; y <= replications; y++) {
            result[x][y] = x ;
        }
    }

    return result;
}

 public double[][] repcoltrans(int end, double multiplier, int replications)
{
    double[][] result = new double[replications+1][end+1];

    for (int x = 1; x <= replications; x++) {
        for (int y = 1; y <= end ; y++) {
            result[x][y] = (y-1)*multiplier;
        }
    }

    return result;
}

 public double[] HammingWindow(int size)
{
    double[] window = new double[size];
    for (int i = 0; i < size; i++)
    {

        window[i] =  0.54-0.46 * (Math.cos(2.0 * Math.PI * i / (size-1)));
    }
    return window;
}
\$\endgroup\$
  • \$\begingroup\$ you could start by flattening your double[][] to double[]. If every little bit counts, there's some RAM and speed you can gain by it. \$\endgroup\$ – Arne Aug 24 '12 at 13:09
  • \$\begingroup\$ does it need optimization for android? have you profiled the code? \$\endgroup\$ – Denis Tulskiy Aug 25 '12 at 13:25
5
\$\begingroup\$

I don't have a clue about spectral subtraction, so just some minor, general notes about code:

  1. public int fix(double val) {
        if (val < 0) {
            return (int) Math.ceil(val);
        }
        return (int) Math.floor(val);
    }
    

    It should be called truncate.

  2. A few variables could be renamed to follow the Java code conventions.

    • Variables, parameters:
      • signal_in to inputSignal or signal
      • HW to hw
      • seg maybe to segments or segment (?)
      • Matrixseg to matrixSeg
    • Methods:
      • HammingWindow to calculateHammingWindow

    (Effective Java, 2nd edition, Item 56: Adhere to generally accepted naming conventions and The Java Language Specification, Java SE 7 Edition, 6.1 Declarations).

  3. This comments looks unnecessary:

    // hamming window
    double[] hammingWindow = this.HammingWindow(samplesPerWindow);
    

    (Clean Code by Robert C. Martin: Chapter 4: Comments, Noise Comments)

    The this. prefix also unnecessary.

\$\endgroup\$
  • 1
    \$\begingroup\$ hw could have a better name. I don't know why he have hammingWindows and then HW, when it's looks like the same thing but does not represent the same data (double[] vs double[][]). Maybe switch the two name so that the one who is used more often would have a complete name ? \$\endgroup\$ – Marc-Andre Mar 10 '14 at 14:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.