代码之家  ›  专栏  ›  技术社区  ›  Community wiki

android中的speex支持

  •  13
  • Community wiki  · 技术社区  · 1 年前

    有人能帮我吗 如何在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数组并返回short数组进行解码的另一种尝试如下:

    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 回复  |  直到 8 年前
        1
  •  4
  •   Andrey Starodubtsev    13 年前

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

    bits->nbBits=0;
    

    并且specex_ bits_>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;
    
        2
  •  2
  •   Stobor    13 年前

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

        3
  •  0
  •   Hiren Morzariya    13 年前

    0x00000018处的致命信号11(SIGSEGV)(代码=1)当你没有重新初始化解码器时,错误出现

    decod_state = speex_decoder_init(&speex_wb_mode);
    

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

    别忘了打电话给你的 initDecode() 先从java中提取方法,然后对帧进行解码