将信号窗口代码从Matlab移植到Java

时间:2012-08-18 11:44:32

标签: matlab voice optimization

这是来自谱减法算法的代码的一部分,我正在尝试为android.please帮助我优化它。

这是matlab代码:

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代码:

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;
}

1 个答案:

答案 0 :(得分:5)

将语句的Matlab代码语句“移植”到Java是一种不好的方法。

Matlab中很少使用循环和寻址单个元素来处理数据(因为Matlab解释器/ VM相当慢),而是通过调用块处理函数(已经仔细编写和优化)。这导致了一种非常特殊的编程风格,其中repmatreshapefind,花式索引等。用于执行通过Java循环更自然地表达的操作。

例如,要将矩阵A的每一列乘以向量v,您将用matlab编写:

A = diag(v) * A

A = repmat(v', 1, size(A, 2)) .* A

此解决方案:

for i = 1:size(A, 2),
  A(:, i) = A(:, i) .* v';
end;

效率低下。

但尝试在Java中执行相同的操作并调用矩阵产品或使用重复的v副本构建矩阵将是非常愚蠢的。相反,只需执行:

for (int i = 0; i < rows; i++) {
  for (int j = 0; j < columns; j++) {
    a[i][j] *= v[i]
  }
}

我建议你尝试理解这个matlab函数实际正在做的 ,而不是专注于 它正在做什么,并在Java中从头开始重新实现它,忘记了所有matlab实现,除了注释中给出的规范。你写的一半代码确实没用。实际上,在我看来,根本不需要这个功能,它可以有效地集成到调用者的代码中。