Question

i have a procedure that makes samples of a frequency and returns a sample buffer in a short array, the java code is this:

private static int _AMP = 10000;
private static double _TWO_PY = 8. * Math.atan(1.);
private static double _PHASE = 0.0;
private static short[] sampleBuffer;

public static short[] buildJ(int freq, int sampleRate, int bufferSize) {        
    sampleBuffer = new short[bufferSize];   
    for(int i = 0; i < bufferSize; i++){
        sampleBuffer[i] = (short) (_AMP * Math.sin(_PHASE));
        _PHASE += _TWO_PY * freq / sampleRate;
    }               

    return sampleBuffer;
}

now i been trying to go native and do this same procedure using the ndk what I've done so far is this:

#include <jni.h>
#include <math.h>

namespace com_mytest_ndktest {

static int _AMP = 10000;
static double _TWO_PY = 8. * atan(1.0);
static double _PHASE = 0.0;

static jshortArray build(JNIEnv *env,int freq, int sampleRate, int bufferSize) {
    short sampleBuffer[bufferSize];
    for(int i = 0; i < bufferSize; i++){
        sampleBuffer[i] = (_AMP * sin(_PHASE));
        _PHASE += _TWO_PY * freq / sampleRate;
    }
    jshortArray retval = env->NewShortArray(bufferSize);
    env->SetShortArrayRegion(retval,0,bufferSize,sampleBuffer);
    return retval;
}

//JNI Wrapper
static jshortArray buildN(JNIEnv *env, jclass clazz, jint freq, jint sampleRate, jint bufferSize) {
    return build(env, freq, sampleRate, bufferSize, audioIntensity);
}

static JNINativeMethod method_table[] = {
    { "buildN", "(III)[S", (void *) buildN }
};

using namespace com_mytest_ndktest;

extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
    return -1;
} else {
    jclass clazz = env->FindClass("com/mytest/ndktest/FrequencySample");
    if (clazz) {
            env->RegisterNatives(clazz, method_table, sizeof(method_table) / sizeof(method_table[0]));
            env->DeleteLocalRef(clazz);
            return JNI_VERSION_1_6;
    } else {
            return -1;
    }
}

}

The application crashes when loading the c++ library, i believe the error is when manipulating short array in c++ i been looking arround but couldn't find how to manipulate it correctly. Would anyone tell me how should i do this?

Was it helpful?

Solution

Well finally i was able to make it work, looks like the problem was because of unused code, any ways here is the complete non auto-generated code i have for checking processing time in java an c++ that works.

in src directory: MainActivity.java

package com.mytest.ndktest;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {

TextView _tvResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        _tvResult = (TextView)findViewById(R.id.tvResult);
    } 

    public void bGo_Click(View view) {

        long time = System.currentTimeMillis();
        FrequencySample.buildJ(1000, 22050, 8192);
        time = System.currentTimeMillis() - time;
        _tvResult.append( String.format("\n(%dms)",time));

        time = System.currentTimeMillis();
        FrequencySample.buildN(1000, 22050, 8192);
        time = System.currentTimeMillis() - time;
        _tvResult.append(String.format("\n(%dms)", time));

    }
}

FrequencySample.java

package com.mytest.ndktest;

public class FrequencySample {
    private static int _AMP = 10000;
    private static double _TWO_PY = 8. * Math.atan(1.);
    private static double _PHASE = 0.0;
    private static short[] _SAMPLE_BUFFER; 

    /* Creates a frequency sample
     * Stores frequency samples in a sample buffer 
     */
    public static short[] buildJ(int freq, int sampleRate, int bufferSize) {        
        _SAMPLE_BUFFER = new short[bufferSize]; 
        for(int i = 0; i < bufferSize; i++){
            _SAMPLE_BUFFER[i] = (short) (_AMP * Math.sin(_PHASE));
            _PHASE += _TWO_PY * freq / sampleRate;
        } 
        return _SAMPLE_BUFFER;
    }

    public static native short[] buildN(int freq, int sampleRate, int bufferSize);

    static {
        System.loadLibrary("ndktest");
    }
}

in jni directory: ndktest.cpp

#include <jni.h>
#include <math.h>

namespace com_mytest_ndktest {

    static int _AMP = 10000;
    static double _TWO_PY = 8. * atan(1.0);
    static double _PHASE = 0.0;

    static jshortArray build(JNIEnv *env,int freq, int sampleRate, int bufferSize) {
        short sampleBuffer[bufferSize];
        for(int i = 0; i < bufferSize; i++){
            sampleBuffer[i] = (_AMP * sin(_PHASE));
            _PHASE += _TWO_PY * freq / sampleRate;
        }
        jshortArray retval = env->NewShortArray(bufferSize);
        env->SetShortArrayRegion(retval,0,bufferSize,sampleBuffer);
        return retval;
    }

    //JNI Wrapper
    static jshortArray buildN(JNIEnv *env, jclass clazz, jint freq, jint sampleRate, jint bufferSize) {
        return build(env, freq, sampleRate, bufferSize);
    }

    static JNINativeMethod method_table[] = {
        { "buildN", "(III)[S", (void *) buildN }
    };
}

using namespace com_mytest_ndktest;

extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    } else {
        jclass clazz = env->FindClass("com/mytest/ndktest/FrequencySample");
        if (clazz) {
                env->RegisterNatives(clazz, method_table, sizeof(method_table) / sizeof(method_table[0]));
                env->DeleteLocalRef(clazz);
                return JNI_VERSION_1_6;
        } else {
                return -1;
        }
    }
}

Application.mk

APP_ABI := all
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top