我一直在尝试使用C库在Android下对两个wav文件进行卷积。 我总是得到空的输出。我试图追查问题,我注意到数组没有正确分配。 这是代码:
int transform(double real[], double imag[], size_t n) {
if (n == 0)
return 1;
else // More complicated algorithm for arbitrary sizes
{
return transform_bluestein(real, imag, n);
__android_log_print(ANDROID_LOG_VERBOSE, "log", "inside transform ", 1);
}
}
int inverse_transform(double real[], double imag[], size_t n) {
__android_log_print(ANDROID_LOG_VERBOSE, "log", "inside ifft ", 1);
return transform(imag, real, n);
}
int transform_bluestein(double real[], double imag[], size_t n) {
// Variables
int status = 0;
double *cos_table, *sin_table;
double *areal, *aimag;
double *breal, *bimag;
double *creal, *cimag;
size_t m;
size_t size_n, size_m;
size_t i;
JNIEnv *env;
jobject obj;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "start bluestein ", 1);
// Find a power-of-2 convolution length m such that m >= n * 2 + 1
{
size_t target;
if (n > (SIZE_MAX - 1) / 2)
{
__android_log_print(ANDROID_LOG_VERBOSE, "log", "return zero ", 1);
return 0;
}
target = n * 2 + 1;
for (m = 1; m < target; m *= 2) {
if (SIZE_MAX / 2 < m)
{
__android_log_print(ANDROID_LOG_VERBOSE, "log", "return 0", 1);
return 0;
}
}
}
// Allocate memory
if (SIZE_MAX / sizeof(double) < n || SIZE_MAX / sizeof(double) < m)
return 0;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "allocate ", 1);
size_n = n * sizeof(double);
size_m = m * sizeof(double);
cos_table = malloc(size_n);
sin_table = malloc(size_n);
__android_log_print(ANDROID_LOG_VERBOSE, "log", "inside allocate ", 1);
areal = calloc(m, sizeof(double));
aimag = calloc(m, sizeof(double));
breal = calloc(m, sizeof(double));
bimag = calloc(m, sizeof(double));
creal = malloc(size_m);
cimag = malloc(size_m);
if (cos_table == NULL || sin_table == NULL
|| areal == NULL || aimag == NULL
|| breal == NULL || bimag == NULL
|| creal == NULL || cimag == NULL)
goto cleanup;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "finished allocation", 1);
// Trignometric tables
for (i = 0; i < n; i++) {
double temp = M_PI * (size_t)((unsigned long long)i * i % ((unsigned long long)n * 2)) / n;
// Less accurate version if long long is unavailable: double temp = M_PI * i * i / n;
cos_table[i] = cos(temp);
sin_table[i] = sin(temp);
// __android_log_print(ANDROID_LOG_VERBOSE, "log", "inside for %d ", i);
}
// Temporary vectors and preprocessing
for (i = 0; i < n; i++) {
areal[i] = real[i] * cos_table[i] + imag[i] * sin_table[i];
aimag[i] = -real[i] * sin_table[i] + imag[i] * cos_table[i];
// __android_log_print(ANDROID_LOG_VERBOSE, "log", "inside for %d ", i);
}
breal[0] = cos_table[0];
bimag[0] = sin_table[0];
for (i = 1; i < n; i++) {
breal[i] = breal[m - i] = cos_table[i];
bimag[i] = bimag[m - i] = sin_table[i];
// __android_log_print(ANDROID_LOG_VERBOSE, "log", "inside for %d ", i);
}
__android_log_print(ANDROID_LOG_VERBOSE, "log", "before postprocessing ", i);
// // Convolution
// if (!Java_com_example_convolution_MainActivity_convolution(env, obj, areal, aimag, breal, bimag, creal, cimag, m))
// goto cleanup;
// Postprocessing
for (i = 0; i < n; i++) {
real[i] = creal[i] * cos_table[i] + cimag[i] * sin_table[i];//------------------- (problem starts here)
imag[i] = -creal[i] * sin_table[i] + cimag[i] * cos_table[i];
// __android_log_print(ANDROID_LOG_VERBOSE, "log", "inside for %d ", i);
}
status = 1;
// Deallocation
cleanup:
free(cimag);
free(creal);
free(bimag);
free(breal);
free(aimag);
free(areal);
free(sin_table);
free(cos_table);
return status;
}
JNIEXPORT jint JNICALL Java_com_example_convolution_MainActivity_convolution (JNIEnv *env, jobject obj, jdoubleArray xreal, jdoubleArray ximag, jdoubleArray yreal, jdoubleArray yimag, jdoubleArray outreal, jdoubleArray outimag, jsize n)
{
jint status = 0;
size_t size;
size_t i;
jdouble *xr, *xi, *yr, *yi;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "start of convolution ", 1);
if (SIZE_MAX / sizeof(double) < n)
return 0;
size = n * sizeof(double);
xr = (*env)->GetDoubleArrayElements(env, xreal, 0);
xi = (*env)->GetDoubleArrayElements(env, ximag, 0);
yr = (*env)->GetDoubleArrayElements(env, yreal, 0);
yi = (*env)->GetDoubleArrayElements(env, yimag, 0);
if (xr == NULL || xi == NULL || yr == NULL || yi == NULL)
{
goto cleanup;
}
__android_log_print(ANDROID_LOG_VERBOSE, "log", "after allocation ", 1);
transform(xr,xi,n);
transform(yr,yi,n);
if (!transform(xr, xi, n))
{
goto cleanup;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "transform(xr,xi,n) not performed ", 1);
}
if (!transform(yr, yi, n))
{
goto cleanup;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "transform(yr,yi,n) not performed ", 1);
}
__android_log_print(ANDROID_LOG_VERBOSE, "log", "after fft ", 1);//------------------------not showing
for (i = 0; i < n; i++) {
double temp = xr[i] * yr[i] - xi[i] * yi[i];
xi[i] = xi[i] * yr[i] + xr[i] * yi[i];
xr[i] = temp;
//__android_log_print(ANDROID_LOG_VERBOSE, "log", "inside for convolution", 1);//---------------------not showing
}
inverse_transform(xr,xi,n);
if (!inverse_transform(xr, xi, n))
{
goto cleanup;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "inverse_transform(xr,xi,n) not performed ", 1);
}
// for (i = 0; i < n; i++) { // Scaling (because this FFT implementation omits it)
// outreal[i] = xr[i] / n;
// outimag[i] = xi[i] / n;
// }
status = 1;
cleanup:
//free(yi);
(*env)->ReleaseDoubleArrayElements(env, yimag, yi, 0);
//free(yr);
(*env)->ReleaseDoubleArrayElements(env, yreal, yr, 0);
//free(xi);
(*env)->ReleaseDoubleArrayElements(env, ximag, xi, 0);
//free(xr);
(*env)->ReleaseDoubleArrayElements(env, xreal, xr, 0);
return status;
}
任何人都可以帮我这个吗?
修改 这是日志:
03-04 11:16:25.705: I/imag1(15736): imag1 5442
03-04 11:16:25.705: I/imag2(15736): imag2 5442
03-04 11:16:25.705: I/raw2(15736): raw2 5442
03-04 11:16:25.705: V/log(15736): start of convolution
03-04 11:16:25.705: V/log(15736): after allocation
03-04 11:16:25.705: V/log(15736): start bluestein
03-04 11:16:25.705: V/log(15736): allocate
03-04 11:16:25.705: V/log(15736): inside allocate
03-04 11:16:25.705: V/log(15736): finished allocation
03-04 11:16:25.720: V/log(15736): before postprocessing
03-04 11:16:25.720: V/log(15736): start bluestein
03-04 11:16:25.720: V/log(15736): allocate
03-04 11:16:25.720: V/log(15736): inside allocate
03-04 11:16:25.720: V/log(15736): finished allocation
03-04 11:16:25.735: V/log(15736): before postprocessing
03-04 11:16:25.740: V/log(15736): start bluestein
03-04 11:16:25.740: V/log(15736): allocate
03-04 11:16:25.740: V/log(15736): inside allocate
03-04 11:16:25.740: V/log(15736): finished allocation
03-04 11:16:25.750: V/log(15736): before postprocessing
03-04 11:16:25.755: V/log(15736): start bluestein
03-04 11:16:25.755: V/log(15736): allocate
03-04 11:16:25.755: V/log(15736): inside allocate
03-04 11:16:25.755: V/log(15736): finished allocation
03-04 11:16:25.770: V/log(15736): before postprocessing
03-04 11:16:25.770: V/log(15736): after fft
03-04 11:16:25.775: V/log(15736): inside ifft
03-04 11:16:25.775: V/log(15736): start bluestein
03-04 11:16:25.775: V/log(15736): allocate
03-04 11:16:25.775: V/log(15736): inside allocate
03-04 11:16:25.775: V/log(15736): finished allocation
03-04 11:16:25.785: V/log(15736): before postprocessing
03-04 11:16:25.790: V/log(15736): inside ifft
03-04 11:16:25.790: V/log(15736): start bluestein
03-04 11:16:25.790: V/log(15736): allocate
03-04 11:16:25.790: V/log(15736): inside allocate
03-04 11:16:25.790: V/log(15736): finished allocation
03-04 11:16:25.805: V/log(15736): before postprocessing
03-04 11:16:25.805: I/result(15736): result1
答案 0 :(得分:0)
您永远不会访问outreal
函数中的outimag
和Java_com_example_convolution_MainActivity_convolution
参数。
你评论了它。没有任何输出是正常的。
<强>更新强>
您必须首先获得outreal
和outimag
上的指针,就像输入图像一样。
jdouble *xr, *xi, *yr, *yi;
jdouble *or, *oi; // <-- add this declaration
...
xr = (*env)->GetDoubleArrayElements(env, xreal, 0);
xi = (*env)->GetDoubleArrayElements(env, ximag, 0);
// add the two lines below
or = (*env)->GetDoubleArrayElements(env, outreal, 0);
oi = (*env)->GetDoubleArrayElements(env, outimag, 0);
...
// for (i = 0; i < n; i++) { // Scaling (because this FFT implementation omits it)
// outreal[i] = xr[i] / n;
// outimag[i] = xi[i] / n;
// }
// This now copies the result in or and oi
for (i = 0; i < n; i++) { // Scaling (because this FFT implementation omits it)
or[i] = xr[i] / n;
oi[i] = xi[i] / n;
}
...
//free(xi);
(*env)->ReleaseDoubleArrayElements(env, ximag, xi, 0);
//free(xr);
(*env)->ReleaseDoubleArrayElements(env, xreal, xr, 0);
// Add the two lines below
//free(oi);
(*env)->ReleaseDoubleArrayElements(env, outimag, oi, 0);
//free(or);
(*env)->ReleaseDoubleArrayElements(env, outreal, or, 0);
答案 1 :(得分:0)
JNIEXPORT jint JNICALL Java_com_example_convolution_MainActivity_convolution (JNIEnv *env, jobject obj, jdoubleArray xreal, jdoubleArray ximag, jdoubleArray yreal, jdoubleArray yimag, jdoubleArray outreal, jdoubleArray outimag, jsize n)
{
jint status = 0;
size_t size;
size_t i;
jdouble *xr, *xi, *yr, *yi, *or, *oi;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "start of convolution ", 1);
if (SIZE_MAX / sizeof(double) < n)
return 0;
size = n * sizeof(double);
xr = (*env)->GetDoubleArrayElements(env, xreal, 0);
xi = (*env)->GetDoubleArrayElements(env, ximag, 0);
yr = (*env)->GetDoubleArrayElements(env, yreal, 0);
yi = (*env)->GetDoubleArrayElements(env, yimag, 0);
or = (*env)->GetDoubleArrayElements(env, outreal, 0);
oi = (*env)->GetDoubleArrayElements(env, outimag, 0);
if (!xr || !xi || !yr || !yi || !or || !oi)
goto cleanup;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "after allocation ", 1);
// These are two duplicate transforms to get rid of
// transform(xr,xi,n);
// transform(yr,yi,n);
if (!transform(xr, xi, n)) // <- this performs the transform on x
{
goto cleanup;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "transform(xr,xi,n) not performed ", 1);
}
if (!transform(yr, yi, n)) // <- this performs the transform on y
{
goto cleanup;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "transform(yr,yi,n) not performed ", 1);
}
__android_log_print(ANDROID_LOG_VERBOSE, "log", "after fft ", 1);//------------------------not showing
for (i = 0; i < n; i++)
{
double temp = xr[i] * yr[i] - xi[i] * yi[i];
xi[i] = xi[i] * yr[i] + xr[i] * yi[i];
xr[i] = temp;
//__android_log_print(ANDROID_LOG_VERBOSE, "log", "inside for convolution", 1);//---------------------not showing
}
// This inverse transform is also a duplicate
// inverse_transform(xr,xi,n);
if (!inverse_transform(xr, xi, n)) // <-- this performs the inverse transform
{
goto cleanup;
__android_log_print(ANDROID_LOG_VERBOSE, "log", "inverse_transform(xr,xi,n) not performed ", 1);
}
// This now copies the result in or and oi
for (i = 0; i < n; i++) { // Scaling (because this FFT implementation omits it)
or[i] = xr[i] / n;
oi[i] = xi[i] / n;
}
status = 1;
cleanup:
(*env)->ReleaseDoubleArrayElements(env, yimag, yi, 0);
(*env)->ReleaseDoubleArrayElements(env, yreal, yr, 0);
(*env)->ReleaseDoubleArrayElements(env, ximag, xi, 0);
(*env)->ReleaseDoubleArrayElements(env, xreal, xr, 0);
(*env)->ReleaseDoubleArrayElements(env, outimag, oi, 0);
(*env)->ReleaseDoubleArrayElements(env, outreal, or, 0);
return status;
}