Android JNI中的双数组

Android JNI中的双数组,android,android-ndk,java-native-interface,Android,Android Ndk,Java Native Interface,我尝试在Android上使用JNI实现两个音频文件的直接卷积。。到目前为止,我已经做到了: JNIEXPORT jint JNICALL Java_com_example_directconv_MainActivity_convolve (JNIEnv * env, jobject obj, jdoubleArray signal1, jdoubleArray signal2, jdoubleArray output) { jdouble *sig1, *sig2, *out; // j

我尝试在Android上使用JNI实现两个音频文件的直接卷积。。到目前为止,我已经做到了:

JNIEXPORT jint JNICALL Java_com_example_directconv_MainActivity_convolve (JNIEnv * env, jobject obj, jdoubleArray signal1, jdoubleArray signal2, jdoubleArray output)

{

jdouble *sig1, *sig2, *out;

//  jboolean     isCopy1, isCopy2, isCopy3;
int i,j;
jsize n,m;

sig1=(*env)->NewDoubleArray(env,n);
sig2=(*env)->NewDoubleArray(env,m);
out=(*env)->NewDoubleArray(env,m);


n=(*env)->GetArrayLength(env, sig1);
m=(*env)->GetArrayLength(env,sig2);

sig1=(*env)->GetDoubleArrayElements(env, signal1,NULL);
sig2=(*env)->GetDoubleArrayElements(env, signal2,NULL);
out=(*env)->GetDoubleArrayElements(env, output, NULL);

if (sig1 != NULL || sig2!=NULL) {

    memcpy(signal1,sig1,n);
    memcpy(signal2,sig2,m);

    (*env)->ReleaseDoubleArrayElements(env,signal1,sig1,JNI_ABORT);
    (*env)->ReleaseDoubleArrayElements(env,signal2,sig2,JNI_ABORT);
}


for(i=0; i<n;i++)
{
    out[i]=0;
    for(j=0;j<m;j++)
    {
        out[i]+=sig1[i-j]*sig2[j];
    }
}

(*env)->ReleaseDoubleArrayElements(env,output,out,0);


return 1;}
JNIEXPORT jint JNICALL Java_com_示例_directconv_main activity_convolve(JNIEnv*env、jobject obj、jdoubleArray信号1、jdoubleArray信号2、jdoubleArray输出)
{
jdouble*sig1,*sig2,*out;
//jboolean isCopy1、isCopy2、isCopy3;
int i,j;
jsn,m;
sig1=(*env)->NewDoubleArray(env,n);
sig2=(*env)->NewDoubleArray(env,m);
out=(*env)->NewDoubleArray(env,m);
n=(*env)->GetArrayLength(env,sig1);
m=(*env)->GetArrayLength(env,sig2);
sig1=(*env)->GetDoubleArrayElements(env,signal1,NULL);
sig2=(*env)->GetDoubleArrayElements(env,signal2,NULL);
out=(*env)->GetDoubleArrayElements(env,output,NULL);
if(sig1!=NULL | | sig2!=NULL){
memcpy(signal1,sig1,n);
memcpy(信号2,信号2,m);
(*env)->释放双阵列元素(env、信号1、sig1、JNI_中止);
(*env)->释放双阵列元素(env、信号2、信号2、JNI_中止);
}

对于(i=0;i来说,您对JNI数组的处理是完全错误的。首先,您没有理由在这里创建任何新数组。您的输入和输出是向下传递的,您要做的是将输入转换为C数组,在纯C中处理它们,然后将输出数组转换为Java数组

其次,您不需要memcpys。调用getDoubleArrayElements可以帮您完成这一任务

第三,您需要通过setDoubleArrayRegion将输入输出值放回输出

第四,你需要清理你的内存使用情况。如果你不这样做,你将导致内存泄漏,最终死亡,因为有256个(或者是512个?我忘了太久了)Java对象被固定到C

您的代码应该更像:

JNIEXPORT jint JNICALL Java_com_example_directconv_MainActivity_convolve (JNIEnv * env, jobject obj, jdoubleArray signal1, jdoubleArray signal2, jdoubleArray output)

{

double *sig1, *sig2, *out;

int i,j;
jsize n,m;


n=(*env)->GetArrayLength(env, sig1);
m=(*env)->GetArrayLength(env,sig2);

sig1=(*env)->GetDoubleArrayElements(env, signal1,NULL);
sig2=(*env)->GetDoubleArrayElements(env, signal2,NULL);

for(i=0; i<n;i++)
{
    out[i]=0;
    for(j=0;j<m;j++)
    {
        out[i]+=sig1[i-j]*sig2[j];
    }
}

(*env)->SetDoubleArrayRegion(env, output, 0, n, out);

(*env)->ReleaseDoubleArrayElements(env,signal1,sig1,JNI_ABORT);
(*env)->ReleaseDoubleArrayElements(env,signal2,sig2,JNI_ABORT);

return 1;}
JNIEXPORT jint JNICALL Java_com_示例_directconv_main activity_convolve(JNIEnv*env、jobject obj、jdoubleArray信号1、jdoubleArray信号2、jdoubleArray输出)
{
双精度*sig1,*sig2,*out;
int i,j;
jsn,m;
n=(*env)->GetArrayLength(env,sig1);
m=(*env)->GetArrayLength(env,sig2);
sig1=(*env)->GetDoubleArrayElements(env,signal1,NULL);
sig2=(*env)->GetDoubleArrayElements(env,signal2,NULL);
对于(i=0;iReleasedoublerayElements)(环境、信号1、信号1、JNI_中止);
(*env)->释放双阵列元素(env、信号2、信号2、JNI_中止);
返回1;}

我要假设你的卷积数学是正确的,现在开始记住这些东西已经太晚了:)

您对JNI数组的处理完全是错误的。首先,您没有理由在这里创建任何新数组。您的输入和输出是传递的,您要做的是将输入转换为C数组,在纯C中处理它们,然后将输出数组转换为Java数组

其次,您不需要memcpys。调用getDoubleArrayElements可以帮您完成这一任务

第三,您需要通过setDoubleArrayRegion将输入输出值放回输出

第四,你需要清理你的内存使用情况。如果你不这样做,你将导致内存泄漏,最终死亡,因为有256个(或者是512个?我忘了太久了)Java对象被固定到C

您的代码应该更像:

JNIEXPORT jint JNICALL Java_com_example_directconv_MainActivity_convolve (JNIEnv * env, jobject obj, jdoubleArray signal1, jdoubleArray signal2, jdoubleArray output)

{

double *sig1, *sig2, *out;

int i,j;
jsize n,m;


n=(*env)->GetArrayLength(env, sig1);
m=(*env)->GetArrayLength(env,sig2);

sig1=(*env)->GetDoubleArrayElements(env, signal1,NULL);
sig2=(*env)->GetDoubleArrayElements(env, signal2,NULL);

for(i=0; i<n;i++)
{
    out[i]=0;
    for(j=0;j<m;j++)
    {
        out[i]+=sig1[i-j]*sig2[j];
    }
}

(*env)->SetDoubleArrayRegion(env, output, 0, n, out);

(*env)->ReleaseDoubleArrayElements(env,signal1,sig1,JNI_ABORT);
(*env)->ReleaseDoubleArrayElements(env,signal2,sig2,JNI_ABORT);

return 1;}
JNIEXPORT jint JNICALL Java_com_示例_directconv_main activity_convolve(JNIEnv*env、jobject obj、jdoubleArray信号1、jdoubleArray信号2、jdoubleArray输出)
{
双精度*sig1,*sig2,*out;
int i,j;
jsn,m;
n=(*env)->GetArrayLength(env,sig1);
m=(*env)->GetArrayLength(env,sig2);
sig1=(*env)->GetDoubleArrayElements(env,signal1,NULL);
sig2=(*env)->GetDoubleArrayElements(env,signal2,NULL);
对于(i=0;iReleasedoublerayElements)(环境、信号1、信号1、JNI_中止);
(*env)->释放双阵列元素(env、信号2、信号2、JNI_中止);
返回1;}

我假设你的卷积数学是正确的,现在开始记住这些东西已经太晚了:)

我解决了这个问题。我添加了文件大小作为参数,如下所示:

JNIEXPORT jint JNICALL Java_com_example_directconv_MainActivity_convolve (JNIEnv * env, jobject obj, jdoubleArray signal1, jdoubleArray signal2, jdoubleArray output, jint size1, jint size2)
{
jdouble *sig1, *sig2, *out;
int i,j,k;
jint n,m;

n=size1;
m=size2;

sig1=(*env)->GetDoubleArrayElements(env, signal1,NULL);
sig2=(*env)->GetDoubleArrayElements(env, signal2,NULL);
out=(*env)->GetDoubleArrayElements(env,output,NULL);


for(i=0; i<n;i++)
{
    out[i]=0;

    for(j=0;j<m;j++)
    {
        if(i-j>=0)

        out[i]+=sig1[i-j]*sig2[j];
    }
}

(*env)->SetDoubleArrayRegion(env, output, 0, n, out);
(*env)->ReleaseDoubleArrayElements(env,signal1,sig1,JNI_ABORT);
(*env)->ReleaseDoubleArrayElements(env,signal2,sig2,JNI_ABORT);

return 1;
}
JNIEXPORT jint JNICALL Java_com_示例_directconv_main activity_convolve(JNIEnv*env、jobject obj、jdoubleArray signal 1、jdoubleArray signal 2、jdoubleArray输出、jint size1、jint size2)
{
jdouble*sig1,*sig2,*out;
int i,j,k;
金特n,m;
n=尺寸1;
m=尺寸2;
sig1=(*env)->GetDoubleArrayElements(env,signal1,NULL);
sig2=(*env)->GetDoubleArrayElements(env,signal2,NULL);
out=(*env)->GetDoubleArrayElements(env,output,NULL);
for(i=0;iSetDoubleArrayRegion(环境,输出,0,n,输出);
(*env)->释放双阵列元素(env、信号1、sig1、JNI_中止);
(*env)->释放双阵列元素(env、信号2、信号2、JNI_中止);
返回1;
}

我解决了问题。我添加了文件大小作为参数,如下所示:

JNIEXPORT jint JNICALL Java_com_example_directconv_MainActivity_convolve (JNIEnv * env, jobject obj, jdoubleArray signal1, jdoubleArray signal2, jdoubleArray output, jint size1, jint size2)
{
jdouble *sig1, *sig2, *out;
int i,j,k;
jint n,m;

n=size1;
m=size2;

sig1=(*env)->GetDoubleArrayElements(env, signal1,NULL);
sig2=(*env)->GetDoubleArrayElements(env, signal2,NULL);
out=(*env)->GetDoubleArrayElements(env,output,NULL);


for(i=0; i<n;i++)
{
    out[i]=0;

    for(j=0;j<m;j++)
    {
        if(i-j>=0)

        out[i]+=sig1[i-j]*sig2[j];
    }
}

(*env)->SetDoubleArrayRegion(env, output, 0, n, out);
(*env)->ReleaseDoubleArrayElements(env,signal1,sig1,JNI_ABORT);
(*env)->ReleaseDoubleArrayElements(env,signal2,sig2,JNI_ABORT);

return 1;
}
JNIEXPORT jint JNICALL Java_com_示例_directconv_main activity_convolve(JNIEnv*env、jobject obj、jdoubleArray signal 1、jdoubleArray signal 2、jdoubleArray输出、jint size1、jint size2)
{
jdouble*sig1,*sig2,*out;
int i,j,k;
金特n,m;
n=尺寸1;
m=尺寸2;
sig1=(*env)->GetDoubleArrayElements(env,signal1,NULL);
sig2=(*env)->GetDoubleArrayElements(env,signal2,NULL);
out=(*env)->GetDoubleArrayElements(env,output,NULL);
for(i=0;iSetDoubleArrayRegion(环境,输出,0,n,输出);
(*env)->释放双阵列元素(env、信号1、sig1、JNI_中止);
(*env)->释放双阵列元素(env、信号2、信号2、JNI_中止);
返回1;
}

您修改了错误的数组。您将值赋给了
out
,但我想您应该使用
output
,这不是他的问题。output是一个java数组,out是一个C数组。他确实忘了将C数组转换回java,所以我应该修改什么?键入它,给我一分钟。Gabe的回答几乎是正确的rect.我已经两年没有在jni上工作了,但是在调用
GetArrayLength
之前,您可能想调用
sig1=env->GetDoubleArrayElements
sig2=env->GetDoubleArrayElements
。在访问它之前,您需要为
*out
分配空间,否则您将得到正在修改的sigsev错误的数组。您正在将值分配给
out
,但我想您应该使用