【问题标题】:speex support in androidandroid中的speex支持
【发布时间】:2012-02-23 22:22:04
【问题描述】:

谁能帮助我如何在 android 中使用 speex 或 jspeex?

我搜索了很多,但无法找到任何地方。code.google.com/android 中有很多关于此的问题,但没有人回答。在这里,这个问题也没有得到很好的回应,因为我的另一个问题是Decoding speex encoded byte array in Android。因此,如果您对此有所了解,请提供相关信息。

我需要使用此编解码器对音频文件的字节数组进行编码和解码。

我尝试过Android-ndk and got encoding done,,但在解码字节数组时遇到了问题。还有其他方法可以实现这一点吗?

编辑

我在原生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;
}

我的编码功能运行良好,博客A JNI Wrapper for Speex on 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)

【问题讨论】:

  • 你遇到了什么问题?
  • 我有一个编码函数返回一个字节数组,所以我必须将字节数组传递给解码函数,但 speex_bits_read_from 函数在其参数中采用 char 数组。
  • @nos 我已经添加了本机代码的代码。请看这个。
  • 一个愚蠢的问题,答案可能很明显,JSpeex 可以移植到 Android 上吗? jspeex.sourceforge.net
  • @Cliff thanx 回复我已经引用了该链接,但我没有任何博客或文章在 android 上实现了此功能。如果有人提出建议,那将是一个很大的帮助。

标签: java android android-ndk speex jspeex


【解决方案1】:

致命信号 11 (SIGSEGV) at 0x00000018 (code=1) 错误来了,当你没有重新初始化解码器时

decod_state = speex_decoder_init(&speex_wb_mode);

并尝试使用解码帧数据,..

别忘了先从 java 调用你的 initDecode() 方法,然后再解码帧

【讨论】:

    【解决方案2】:

    speex_bits_reset 在其正文中执行以下操作:

    bits->nbBits=0;
    

    并且 speex_bits_nbytes 返回 ((bits->nbBits+7)>>3); 所以如果你在 speex_bits_reset 之后立即调用 speex_bits_nbytes,你总是收到 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;
    

    【讨论】:

      【解决方案3】:

      不知道具体的代码,但有一些开源的 Android 应用程序包括 speex 支持,您可以将其用作参考:

      【讨论】:

        猜你喜欢
        • 2014-05-21
        • 2011-04-22
        • 1970-01-01
        • 2011-02-24
        • 1970-01-01
        • 2018-02-06
        • 2011-04-26
        • 2020-10-07
        • 1970-01-01
        相关资源
        最近更新 更多