Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/206.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JNI-Android中的分配和释放问题_Android_C_Java Native Interface - Fatal编程技术网

JNI-Android中的分配和释放问题

JNI-Android中的分配和释放问题,android,c,java-native-interface,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 trans

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

Java\u com\u example\u convolution\u main activity\u convolution
函数中,您从不访问
outreal
outimag
参数

你把它注释掉了。没有任何输出是正常的

更新:

您必须首先获得
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);
jdouble*xr,*xi,*yr,*yi;
jdouble*或,*oi;//GetDoubleArrayElements(环境、xreal、0);
席=(*Env)-> GeDouthRayRayes(Env,Ximag,0);
//添加下面的两行
或者=(*env)->GetDoubleArrayElements(env,outreal,0);
oi=(*env)->GetDoubleArrayElements(env,outimag,0);
...
//对于(i=0;i释放的脲分子(Env,XimAg,席,0);
//免费(xr);
(*env)->释放双数组元素(env、xreal、xr、0);
//添加下面的两行
//免费(oi);
(*env)->发布双数组元素(env、outimag、oi,0);
//免费(或免费);
(*env)->ReleaseDoubleArrayElements(env、outreal或0);
JNIEXPORT jint JNICALL Java\u com\u示例\u卷积\u主要活动\u卷积(JNIEnv*env、jobject obj、jdoubleArray xreal、jdoubleArray ximag、jdoubleArray yreal、jdoubleArray yimag、jdoubleArray outreal、jdoubleArray outimag、jsizen)
{
jint状态=0;
大小;
尺寸i;
jdouble*xr,*xi,*yr,*yi,*或,*oi;
__安卓日志打印(安卓日志详细,“日志”,“卷积开始”,1);
如果(最大尺寸/尺寸(双)GetDoubleArrayElements(env,xreal,0);
席=(*Env)-> GeDouthRayRayes(Env,Ximag,0);
yr=(*env)->GetDoubleArrayElements(env,yreal,0);
yi=(*env)->GetDoubleArrayElements(env,yimag,0);
或者=(*env)->GetDoubleArrayElements(env,outreal,0);
oi=(*env)->GetDoubleArrayElements(env,outimag,0);
如果(XR)!席!!!!!!!
去清理;
__安卓日志打印(安卓日志详细,“日志”,“分配后”,1);
//这是要消除的两个重复变换
//变换(XR,席,N);
//变换(yr,yi,n);
如果(…变换(XR,席席,N))/ /释放的UBB(Env,Ximag,Xi,0);
(*env)->释放双数组元素(env、xreal、xr、0);
(*env)->发布双数组元素(env、outimag、oi,0);
(*env)->ReleaseDoubleArrayElements(env、outreal或0);
返回状态;
}

您的意思是输出用零填充?也许这是因为XR和席是N。您是否尝试在or和oi中写入常量值以测试写入是否有效?你肯定需要我给你的代码,这是你的代码中缺少的。从Java调用函数时,还必须传递两个输出缓冲区。另一个问题是,每个转换调用两次。这将取消转换!所以你不需要计算数据的卷积。我将更新我的答案,向您展示如何解决这个问题。请注意,优化代码是可能的。在
transform\u bluestein
中,您计算存储在分配块中的数据,这些数据对于所有三种变换都是相同的。你可以计算它们一次,然后在每次转换中重复使用。这很奇怪。。我完全照你说的做了我还是得到零。你的意思是我应该去掉副本,改用数组吗?上面的代码现在应该可以了。首先尝试注释掉卷积,看看是否在输出中返回x。这将允许您测试分配和转换是否按预期工作。
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);
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;
}