JNI Android中的分配和释放问题

时间:2015-03-04 10:04:55

标签: android c java-native-interface

我一直在尝试使用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

2 个答案:

答案 0 :(得分:0)

您永远不会访问outreal函数中的outimagJava_com_example_convolution_MainActivity_convolution参数。

你评论了它。没有任何输出是正常的。

<强>更新

您必须首先获得outrealoutimag上的指针,就像输入图像一样。

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