blob: a9cbbd0e54ffe7ebf4e42bdc520224717c104fe4 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.cts.verifier.audio.wavelib;
import android.util.Log;
public class DspBufferMath {
private static final String TAG = "DspBufferMath";
public static final int OPERANDS_TYPE_UNKNOWN = -1;
public static final int OPERANDS_TYPE_REAL = 0;
public static final int OPERANDS_TYPE_COMPLEX = 1;
public static final int OPERANDS_TYPE_MIXED = 2;
public static final int MATH_RESULT_UNDEFINED = -1;
public static final int MATH_RESULT_SUCCESS = 0;
public static final int MATH_RESULT_ERROR = 1;
static private<T extends DspBufferBase> int estimateOperandsType(T a, T b) {
if (a instanceof DspBufferComplex) {
if (b instanceof DspBufferComplex) {
return OPERANDS_TYPE_COMPLEX;
} else if (b instanceof DspBufferDouble) {
return OPERANDS_TYPE_MIXED;
}
} else if (a instanceof DspBufferDouble) {
if (b instanceof DspBufferComplex) {
return OPERANDS_TYPE_MIXED;
} else if (b instanceof DspBufferDouble) {
return OPERANDS_TYPE_REAL;
}
}
return OPERANDS_TYPE_UNKNOWN;
}
/**
* adds r = a + b; element by element
*
* If the result is double vector, the imaginary part of complex operations is ignored.
*/
static public <T extends DspBufferBase> int add(T r, T a, T b) {
int size = Math.min(a.getSize(), b.getSize());
r.setSize(size);
T x = a;
T y = b;
int opType = estimateOperandsType(a, b);
if (opType == OPERANDS_TYPE_MIXED) {
if (a instanceof DspBufferDouble) {
x = b; //Complex first
y = a;
}
}
if (opType == OPERANDS_TYPE_UNKNOWN) {
return MATH_RESULT_UNDEFINED;
}
if (r instanceof DspBufferComplex) {
switch (opType) {
case OPERANDS_TYPE_REAL:
for (int i = 0; i < size; i++) {
((DspBufferComplex) r).mReal[i] =
((DspBufferDouble) x).mData[i] + ((DspBufferDouble) y).mData[i];
((DspBufferComplex) r).mImag[i] = 0;
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_COMPLEX:
for (int i = 0; i < size; i++) {
((DspBufferComplex) r).mReal[i] =
((DspBufferComplex) x).mReal[i] + ((DspBufferComplex) y).mReal[i];
((DspBufferComplex) r).mImag[i] =
((DspBufferComplex) x).mImag[i] + ((DspBufferComplex) y).mImag[i];
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_MIXED:
for (int i = 0; i < size; i++) {
((DspBufferComplex) r).mReal[i] =
((DspBufferComplex) x).mReal[i] + ((DspBufferDouble) y).mData[i];
((DspBufferComplex) r).mImag[i] = ((DspBufferComplex) x).mImag[i];
}
return MATH_RESULT_SUCCESS;
}
} else if (r instanceof DspBufferDouble) {
switch (opType) {
case OPERANDS_TYPE_REAL:
for (int i = 0; i < size; i++) {
((DspBufferDouble) r).mData[i] =
((DspBufferDouble) x).mData[i] + ((DspBufferDouble) y).mData[i];
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_COMPLEX:
for (int i = 0; i < size; i++) {
((DspBufferDouble) r).mData[i] =
((DspBufferComplex) x).mReal[i] + ((DspBufferComplex) y).mReal[i];
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_MIXED:
for (int i = 0; i < size; i++) {
((DspBufferDouble) r).mData[i] =
((DspBufferComplex) x).mReal[i] + ((DspBufferDouble) y).mData[i];
}
return MATH_RESULT_SUCCESS;
}
}
return MATH_RESULT_ERROR;
}
/**
* mult r = a * b; element by element
*/
static public <T extends DspBufferBase> int mult(T r, T a, T b) {
int size = Math.min(a.getSize(), b.getSize());
r.setSize(size);
T x = a;
T y = b;
int opType = estimateOperandsType(a, b);
if (opType == OPERANDS_TYPE_MIXED) {
if (a instanceof DspBufferDouble) {
x = b; //Complex first
y = a;
}
}
if (opType == OPERANDS_TYPE_UNKNOWN) {
return MATH_RESULT_UNDEFINED;
}
if (r instanceof DspBufferComplex) {
switch (opType) {
case OPERANDS_TYPE_REAL:
for (int i = 0; i < size; i++) {
((DspBufferComplex) r).mReal[i] =
((DspBufferDouble) x).mData[i] * ((DspBufferDouble) y).mData[i];
((DspBufferComplex) r).mImag[i] = 0;
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_COMPLEX:
for (int i = 0; i < size; i++) {
double A = ((DspBufferComplex) x).mReal[i];
double B = ((DspBufferComplex) x).mImag[i];
double C = ((DspBufferComplex) y).mReal[i];
double D = ((DspBufferComplex) y).mImag[i];
((DspBufferComplex) r).mReal[i] = (C * A) - (B * D);
((DspBufferComplex) r).mImag[i] = (C * B) + (A * D);
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_MIXED:
for (int i = 0; i < size; i++) {
double A = ((DspBufferComplex) x).mReal[i];
double B = ((DspBufferComplex) x).mImag[i];
double C = ((DspBufferDouble) y).mData[i];
//double D = 0;
((DspBufferComplex) r).mReal[i] = C * A;
((DspBufferComplex) r).mImag[i] = C * B;
}
return MATH_RESULT_SUCCESS;
}
} else if (r instanceof DspBufferDouble) {
switch (opType) {
case OPERANDS_TYPE_REAL:
for (int i = 0; i < size; i++) {
((DspBufferDouble) r).mData[i] =
((DspBufferDouble) x).mData[i] * ((DspBufferDouble) y).mData[i];
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_COMPLEX:
for (int i = 0; i < size; i++) {
double A = ((DspBufferComplex) x).mReal[i];
double B = ((DspBufferComplex) x).mImag[i];
double C = ((DspBufferComplex) y).mReal[i];
double D = ((DspBufferComplex) y).mImag[i];
((DspBufferDouble) r).mData[i] = (C * A) - (B * D);
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_MIXED:
for (int i = 0; i < size; i++) {
double A = ((DspBufferComplex) x).mReal[i];
double B = ((DspBufferComplex) x).mImag[i];
double C = ((DspBufferDouble) y).mData[i];
//double D = 0;
((DspBufferDouble) r).mData[i] = C * A;
}
return MATH_RESULT_SUCCESS;
}
}
return MATH_RESULT_ERROR;
}
/**
* mult r = a * v; element by element
*/
static public <T extends DspBufferBase> int mult(T r, T a, double v) {
int size = a.getSize();
r.setSize(size);
T x = a;
int opType = estimateOperandsType(r, a);
if (opType == OPERANDS_TYPE_UNKNOWN) {
return MATH_RESULT_UNDEFINED;
}
if (r instanceof DspBufferComplex) {
switch (opType) {
case OPERANDS_TYPE_MIXED:
for (int i = 0; i < size; i++) {
((DspBufferComplex) r).mReal[i] = ((DspBufferDouble) x).mData[i] * v;
((DspBufferComplex) r).mImag[i] = 0;
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_COMPLEX:
for (int i = 0; i < size; i++) {
((DspBufferComplex) r).mReal[i] = ((DspBufferComplex) x).mReal[i] * v;
((DspBufferComplex) r).mImag[i] = ((DspBufferComplex) x).mImag[i] * v;
}
return MATH_RESULT_SUCCESS;
}
} else if (r instanceof DspBufferDouble) {
switch (opType) {
case OPERANDS_TYPE_REAL:
for (int i = 0; i < size; i++) {
((DspBufferDouble) r).mData[i] = ((DspBufferDouble) x).mData[i] * v;
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_MIXED:
for (int i = 0; i < size; i++) {
((DspBufferDouble) r).mData[i] = ((DspBufferComplex) x).mReal[i] * v;
}
return MATH_RESULT_SUCCESS;
}
}
return MATH_RESULT_ERROR;
}
/**
* set r = a ; element by element
*/
static public <T extends DspBufferBase> int set(T r, T a) {
int size = a.getSize();
r.setSize(size);
T x = a;
int opType = estimateOperandsType(r, a);
if (opType == OPERANDS_TYPE_UNKNOWN) {
return MATH_RESULT_UNDEFINED;
}
if (r instanceof DspBufferComplex) {
switch (opType) {
case OPERANDS_TYPE_MIXED:
for (int i = 0; i < size; i++) {
((DspBufferComplex) r).mReal[i] = ((DspBufferDouble) x).mData[i];
((DspBufferComplex) r).mImag[i] = 0;
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_COMPLEX:
for (int i = 0; i < size; i++) {
((DspBufferComplex) r).mReal[i] = ((DspBufferComplex) x).mReal[i];
((DspBufferComplex) r).mImag[i] = ((DspBufferComplex) x).mImag[i];
}
return MATH_RESULT_SUCCESS;
}
} else if (r instanceof DspBufferDouble) {
switch(opType) {
case OPERANDS_TYPE_REAL:
for (int i = 0; i < size; i++) {
((DspBufferDouble) r).mData[i] = ((DspBufferDouble) x).mData[i];
}
return MATH_RESULT_SUCCESS;
case OPERANDS_TYPE_MIXED:
for (int i = 0; i < size; i++) {
((DspBufferDouble) r).mData[i] = ((DspBufferComplex) x).mReal[i];
}
return MATH_RESULT_SUCCESS;
}
}
return MATH_RESULT_ERROR;
}
/**
* set r = v ; all elements the same
* It keeps the size of the return vector
*/
static public <T extends DspBufferBase> int set(T r, double ...values) {
int size = r.getSize();
double a = 0;
double b = 0;
if (values.length > 0) {
a = values[0];
}
if (values.length > 1) {
b = values[1];
}
if (r instanceof DspBufferComplex) {
for (int i = 0; i < size; i++) {
((DspBufferComplex) r).mReal[i] = a;
((DspBufferComplex) r).mImag[i] = b;
}
return MATH_RESULT_SUCCESS;
} else if (r instanceof DspBufferDouble) {
for (int i = 0; i < size; i++) {
((DspBufferDouble) r).mData[i] = a;
}
return MATH_RESULT_SUCCESS;
}
return MATH_RESULT_ERROR;
}
}