поддержка Speex в Android - PullRequest
       50

поддержка Speex в Android

13 голосов
/ 01 февраля 2012

Может ли кто-нибудь помочь мне по , как использовать speex или jspeex в Android?

Я много искал, но нигде не смог найти. Есть много проблем по этому поводу в code.google.com / android , но никто не ответил на него.Здесь также этот вопрос не получил хорошего ответа, так как мой другой вопрос относительно этого - Декодирование speex закодированного байтового массива в Android .Поэтому, если вы что-то знаете об этом, пожалуйста, предоставьте мне информацию об этом.

Мне нужно кодировать и декодировать байтовый массив аудиофайлов с использованием этого кодека.

Я пробовал Android-ndkи кодирование завершено, , но возникла проблема при декодировании массива байтов. Есть ли другая альтернатива для достижения этой цели?

EDIT

Мои функции кодирования в собственном файле c следующие:

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

Теперь для декодирования я отправляю преобразованный короткий массив в функцию декодирования следующим образом:

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

мои функции кодирования работают нормально, пример приведен в блоге Оболочка JNI для Speex на Android

Еще одна попытка декодирования путем передачи массива char и возврата короткого массивавыглядит следующим образом:

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

результат

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)

Ответы [ 3 ]

3 голосов
/ 15 февраля 2012

speex_bits_reset выполняет в своем теле следующее:

bits->nbBits=0;

и speex_bits_nbytes возвращает ((биты-> nbBits + 7) >> 3);Поэтому, если вы вызываете speex_bits_nbytes сразу после speex_bits_reset, вы всегда получаете 0. Поэтому вы должны вызвать speex_bits_read_from до выделения массива:

/*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;
1 голос
/ 10 февраля 2012

Не знаю конкретно о коде, но есть несколько Android-приложений с открытым исходным кодом, которые включают поддержку speex, которую вы можете использовать в качестве справки:

0 голосов
/ 01 марта 2012

Фатальный сигнал 11 (SIGSEGV) при 0x00000018 (код = 1). Ошибка возникает, когда у вас нет повторной инициализации декодера

decod_state = speex_decoder_init(&speex_wb_mode);

и попытка использовать данные кадра декодирования, ..

не забудьте сначала вызвать ваш initDecode() метод из Java, а затем декодировать кадр

...