speex support in android

13

Can anybody help me on how to use speex or jspeex in android?

I have searched a lot but could not able to find anywhere.There are many issues regarding this in code.google.com/android but none have answered it. Here also this question did not got a good response as my another question regarding this is Decoding speex encoded byte array in Android. So If you know something about this then Please provide me information regarding this.

I need to encode and decode bytearray of audio file using this codec.

I have tried Android-ndk and got encoding done, but getting a problem in decoding the byte array. Is there any other alternative to achieve this?

EDIT

my encoding Functions in native c file are as follow:

#include <jni.h>
#include "speex/speex.h"

#define FRAME_SIZE 320

int nbBytes;
/*Holds the state of the encoder*/
void *state;
void *decod_state;


/*Holds bits so they can be read and written to by the Speex routines*/

SpeexBits decod_bits;
SpeexBits bits;
int i, tmp;

void Java_com_mycom_speex_SpeexEncodingActivity_init(JNIEnv * env, jobject jobj) {
   /*Create a new encoder state in narrowband mode*/
   state = speex_encoder_init(&speex_wb_mode);

   /*Set the quality to 8*/
   tmp=8;
   speex_encoder_ctl(state, SPEEX_SET_QUALITY, &tmp);

   /*Initialization of the structure that holds the bits*/
   speex_bits_init(&bits);
}

jbyteArray Java_com_mycom_speex_SpeexEncodingActivity_encode(JNIEnv * env, jobject jobj, jshortArray inputData) {
        jbyteArray ret;

        jshort * inputArrayElements = (*env)->GetShortArrayElements(env, inputData, 0);

        /*Flush all the bits in the struct so we can encode a new frame*/
        speex_bits_reset(&bits);

        /*Encode the frame*/
        speex_encode_int(state, inputArrayElements, &bits);
        /*Copy the bits to an array of char that can be written*/
        nbBytes = speex_bits_nbytes(&bits);

        ret = (jbyteArray) ((*env)->NewByteArray(env, nbBytes));
        jbyte * arrayElements = (*env)->GetByteArrayElements(env, ret, 0);

        speex_bits_write(&bits, arrayElements, nbBytes);

        (*env)->ReleaseShortArrayElements(env, inputData, inputArrayElements, JNI_ABORT);
        (*env)->ReleaseByteArrayElements(env, ret, arrayElements, 0);
        return ret;
}

now for decoding i am sending the converted short array to decode function as follow:

void Java_com_mycom_speex_SpeexEncodingActivity_initDecode(JNIEnv * env,
        jobject jobj) {

    decod_state = speex_decoder_init(&speex_wb_mode);

    tmp = 1;
    speex_decoder_ctl(decod_state, SPEEX_SET_ENH, &tmp);

    /*Initialization of the structure that holds the bits*/
    speex_bits_init(&decod_bits);
}

jshortArray Java_com_mycom_speex_SpeexEncodingActivity_decode(JNIEnv * env,
        jobject jobj, jshortArray inputData) {



    jshort * inputArrayElements = (*env)->GetShortArrayElements(env, inputData,
            0);

    /*Flush all the bits in the struct so we can decode a new frame*/
    speex_bits_reset(&decod_bits);
    /*Copy the bits to an array of char that can be written*/
    nbBytes = speex_bits_nbytes(&decod_bits);
    speex_bits_read_from(&decod_bits,inputArrayElements, nbBytes); // here it requires char * in second argument
    /*Decode the frame*/
    speex_decode_int(decod_state, &decod_bits, inputArrayElements);
    (*env)->ReleaseShortArrayElements(env, encodedData, inputArrayElements,
            JNI_ABORT);
    return inputArrayElements;
}

my Encoding functions are working fine the example is provided on the blog A JNI Wrapper for Speex on Android

Another attempt to decoding by passing char array and returning short array is as follow:

jshortArray Java_com_mycom_speex_SpeexEncodingActivity_decode(JNIEnv * env,
        jobject jobj, jcharArray inputCharData) {

    jshortArray ret;
    jchar * inputArrayElements = (*env)->GetCharArrayElements(env,
            inputCharData, 0);
    /*Flush all the bits in the struct so we can decode a new frame*/
    speex_bits_reset(&decod_bits);
    /*Copy the bits to an array of char that can be written*/
    nbBytes = speex_bits_nbytes(&decod_bits);
    ret = (jshortArray)((*env)->NewShortArray(env, nbBytes));
    jshort * arrayElements = (*env)->GetShortArrayElements(env, ret, 0);

    speex_bits_read_from(&decod_bits,(char *) inputArrayElements, nbBytes);
    /*Decode the frame*/
    speex_decode_int(decod_state, &decod_bits, arrayElements);

    (*env)->ReleaseCharArrayElements(env, inputCharData, inputArrayElements,
            JNI_ABORT);
    (*env)->ReleaseShortArrayElements(env, ret, arrayElements, 0);
    return ret;
}

the result is

Returned empty array of short if i return ret and if i return arrayElements it 
gives an error Fatal signal 11 (SIGSEGV) at 0x00000018 (code=1)
java
android
android-ndk
speex
jspeex
asked on Stack Overflow Feb 1, 2012 by Hemant Metalia • edited May 23, 2017 by Community

3 Answers

4

speex_bits_reset do following in its body:

bits->nbBits=0;

and speex_bits_nbytes returns ((bits->nbBits+7)>>3); So if you call speex_bits_nbytes right after speex_bits_reset, you always receive 0. So you must call speex_bits_read_from before array allocation:

/*Flush all the bits in the struct so we can decode a new frame*/
speex_bits_reset(&decod_bits);

/*Read bits in decod_bits struct from java array*/
speex_bits_read_from(&decod_bits,(char *) inputArrayElements, nbBytes);

/*Copy the bits to an array of char that can be written*/
nbBytes = speex_bits_nbytes(&decod_bits);
ret = (jshortArray)((*env)->NewShortArray(env, nbBytes));
jshort * arrayElements = (*env)->GetShortArrayElements(env, ret, 0);

/*Decode the frame*/
speex_decode_int(decod_state, &decod_bits, arrayElements);

(*env)->ReleaseCharArrayElements(env, inputCharData, inputArrayElements,
        JNI_ABORT);
(*env)->ReleaseShortArrayElements(env, ret, arrayElements, 0);
return ret;
answered on Stack Overflow Feb 15, 2012 by Andrey Starodubtsev
2

Don't know about the code specifically, but there are a few open-source Android applications out there which include speex support, which you could use as a reference:

answered on Stack Overflow Feb 10, 2012 by Stobor
0

Fatal signal 11 (SIGSEGV) at 0x00000018 (code=1) Error comes,when u have not reinitialize decoder

decod_state = speex_decoder_init(&speex_wb_mode);

and try to use decode frame data,..

don't forget to call your initDecode() method from java first and then decode frame

answered on Stack Overflow Mar 1, 2012 by Hiren Morzariya

User contributions licensed under CC BY-SA 3.0