silk编解码_编解码silk - CSDN
  • Silk编解码是Skype向第三方开发人员和硬件制造商提供免版税认证(RF)的Silk宽带音频编码器。Skype已将其开源,可以访问http://developer.skype.com/silk获取最新动向。SILK Codec是一个语音和音频编解码算法, 对于...
    Silk编解码是Skype向第三方开发人员和硬件制造商提供免版税认证(RF)的Silk宽带音频编码器。Skype已将其开源,可以访问http://developer.skype.com/silk获取最新动向。SILK
     Codec是一个语音和音频编解码算法, 对于音频带宽、网络带宽和算法复杂度都具有很好的弹性。支持4种采样率:8KHz、12KHz、16KHz、24KHz;三种复杂度:低、中、高。编码码率在 6~40kbps(不同采样率具有不同的码率范围)以及还支持VAD、DTX、FEC等模块,感觉还是比较全面。最重要的一点是提供了定点C代码,非常有利于向ARM、DSP移植和优化。这一篇主要参考了pjsip中的silk实现。
    

          1、获取silk源码(http://developer.skype.com/silk

           2、创建新的android工程,并创建jni文件夹。

           3、将silk源码拷贝到jni目录

           4、在jni目录下新增Android.mk文件,编辑内容如下

       

    1. LOCAL_PATH := $(call my-dir)  
    2.    
    3. include $(CLEAR_VARS)  
    4. SILK     := silk  
    5. LOCAL_MODULE    := silkcommon  
    6. LOCAL_SRC_FILES :=  $(SILK)/src/SKP_Silk_A2NLSF.c \  
    7.     $(SILK)/src/SKP_Silk_CNG.c \  
    8.     $(SILK)/src/SKP_Silk_HP_variable_cutoff_FIX.c \  
    9.     $(SILK)/src/SKP_Silk_LBRR_reset.c \  
    10.     $(SILK)/src/SKP_Silk_LPC_inv_pred_gain.c \  
    11.     $(SILK)/src/SKP_Silk_LPC_stabilize.c \  
    12.     $(SILK)/src/SKP_Silk_LPC_synthesis_filter.c \  
    13.     $(SILK)/src/SKP_Silk_LPC_synthesis_order16.c \  
    14.     $(SILK)/src/SKP_Silk_LP_variable_cutoff.c \  
    15.     $(SILK)/src/SKP_Silk_LSF_cos_table.c \  
    16.     $(SILK)/src/SKP_Silk_LTP_analysis_filter_FIX.c \  
    17.     $(SILK)/src/SKP_Silk_LTP_scale_ctrl_FIX.c \  
    18.     $(SILK)/src/SKP_Silk_MA.c \  
    19.     $(SILK)/src/SKP_Silk_NLSF2A.c \  
    20.     $(SILK)/src/SKP_Silk_NLSF2A_stable.c \  
    21.     $(SILK)/src/SKP_Silk_NLSF_MSVQ_decode.c \  
    22.     $(SILK)/src/SKP_Silk_NLSF_MSVQ_encode_FIX.c \  
    23.     $(SILK)/src/SKP_Silk_NLSF_VQ_rate_distortion_FIX.c \  
    24.     $(SILK)/src/SKP_Silk_NLSF_VQ_sum_error_FIX.c \  
    25.     $(SILK)/src/SKP_Silk_NLSF_VQ_weights_laroia.c \  
    26.     $(SILK)/src/SKP_Silk_NLSF_stabilize.c \  
    27.     $(SILK)/src/SKP_Silk_NSQ.c \  
    28.     $(SILK)/src/SKP_Silk_NSQ_del_dec.c \  
    29.     $(SILK)/src/SKP_Silk_PLC.c \  
    30.     $(SILK)/src/SKP_Silk_VAD.c \  
    31.     $(SILK)/src/SKP_Silk_VQ_nearest_neighbor_FIX.c \  
    32.     $(SILK)/src/SKP_Silk_allpass_int.c \  
    33.     $(SILK)/src/SKP_Silk_ana_filt_bank_1.c \  
    34.     $(SILK)/src/SKP_Silk_apply_sine_window.c \  
    35.     $(SILK)/src/SKP_Silk_array_maxabs.c \  
    36.     $(SILK)/src/SKP_Silk_autocorr.c \  
    37.     $(SILK)/src/SKP_Silk_biquad.c \  
    38.     $(SILK)/src/SKP_Silk_biquad_alt.c \  
    39.     $(SILK)/src/SKP_Silk_burg_modified.c \  
    40.     $(SILK)/src/SKP_Silk_bwexpander.c \  
    41.     $(SILK)/src/SKP_Silk_bwexpander_32.c \  
    42.     $(SILK)/src/SKP_Silk_code_signs.c \  
    43.     $(SILK)/src/SKP_Silk_control_codec_FIX.c \  
    44.     $(SILK)/src/SKP_Silk_corrMatrix_FIX.c \  
    45.     $(SILK)/src/SKP_Silk_create_init_destroy.c \  
    46.     $(SILK)/src/SKP_Silk_dec_API.c \  
    47.     $(SILK)/src/SKP_Silk_decode_core.c \  
    48.     $(SILK)/src/SKP_Silk_decode_frame.c \  
    49.     $(SILK)/src/SKP_Silk_decode_indices_v4.c \  
    50.     $(SILK)/src/SKP_Silk_decode_parameters.c \  
    51.     $(SILK)/src/SKP_Silk_decode_parameters_v4.c \  
    52.     $(SILK)/src/SKP_Silk_decode_pulses.c \  
    53.     $(SILK)/src/SKP_Silk_decoder_set_fs.c \  
    54.     $(SILK)/src/SKP_Silk_detect_SWB_input.c \  
    55.     $(SILK)/src/SKP_Silk_enc_API.c \  
    56.     $(SILK)/src/SKP_Silk_encode_frame_FIX.c \  
    57.     $(SILK)/src/SKP_Silk_encode_parameters.c \  
    58.     $(SILK)/src/SKP_Silk_encode_parameters_v4.c \  
    59.     $(SILK)/src/SKP_Silk_encode_pulses.c \  
    60.     $(SILK)/src/SKP_Silk_find_LPC_FIX.c \  
    61.     $(SILK)/src/SKP_Silk_find_LTP_FIX.c \  
    62.     $(SILK)/src/SKP_Silk_find_pitch_lags_FIX.c \  
    63.     $(SILK)/src/SKP_Silk_find_pred_coefs_FIX.c \  
    64.     $(SILK)/src/SKP_Silk_gain_quant.c \  
    65.     $(SILK)/src/SKP_Silk_init_encoder_FIX.c \  
    66.     $(SILK)/src/SKP_Silk_inner_prod_aligned.c \  
    67.     $(SILK)/src/SKP_Silk_interpolate.c \  
    68.     $(SILK)/src/SKP_Silk_k2a.c \  
    69.     $(SILK)/src/SKP_Silk_k2a_Q16.c \  
    70.     $(SILK)/src/SKP_Silk_lin2log.c \  
    71.     $(SILK)/src/SKP_Silk_log2lin.c \  
    72.     $(SILK)/src/SKP_Silk_lowpass_int.c \  
    73.     $(SILK)/src/SKP_Silk_lowpass_short.c \  
    74.     $(SILK)/src/SKP_Silk_noise_shape_analysis_FIX.c \  
    75.     $(SILK)/src/SKP_Silk_pitch_analysis_core.c \  
    76.     $(SILK)/src/SKP_Silk_pitch_est_tables.c \  
    77.     $(SILK)/src/SKP_Silk_prefilter_FIX.c \  
    78.     $(SILK)/src/SKP_Silk_process_NLSFs_FIX.c \  
    79.     $(SILK)/src/SKP_Silk_process_gains_FIX.c \  
    80.     $(SILK)/src/SKP_Silk_pulses_to_bytes.c \  
    81.     $(SILK)/src/SKP_Silk_quant_LTP_gains_FIX.c \  
    82.     $(SILK)/src/SKP_Silk_range_coder.c \  
    83.     $(SILK)/src/SKP_Silk_regularize_correlations_FIX.c \  
    84.     $(SILK)/src/SKP_Silk_resample_1_2.c \  
    85.     $(SILK)/src/SKP_Silk_resample_1_2_coarse.c \  
    86.     $(SILK)/src/SKP_Silk_resample_1_2_coarsest.c \  
    87.     $(SILK)/src/SKP_Silk_resample_1_3.c \  
    88.     $(SILK)/src/SKP_Silk_resample_2_1_coarse.c \  
    89.     $(SILK)/src/SKP_Silk_resample_2_3.c \  
    90.     $(SILK)/src/SKP_Silk_resample_2_3_coarse.c \  
    91.     $(SILK)/src/SKP_Silk_resample_2_3_coarsest.c \  
    92.     $(SILK)/src/SKP_Silk_resample_2_3_rom.c \  
    93.     $(SILK)/src/SKP_Silk_resample_3_1.c \  
    94.     $(SILK)/src/SKP_Silk_resample_3_2.c \  
    95.     $(SILK)/src/SKP_Silk_resample_3_2_rom.c \  
    96.     $(SILK)/src/SKP_Silk_resample_3_4.c \  
    97.     $(SILK)/src/SKP_Silk_resample_4_3.c \  
    98.     $(SILK)/src/SKP_Silk_residual_energy16_FIX.c \  
    99.     $(SILK)/src/SKP_Silk_residual_energy_FIX.c \  
    100.     $(SILK)/src/SKP_Silk_scale_copy_vector16.c \  
    101.     $(SILK)/src/SKP_Silk_scale_vector.c \  
    102.     $(SILK)/src/SKP_Silk_schur.c \  
    103.     $(SILK)/src/SKP_Silk_schur64.c \  
    104.     $(SILK)/src/SKP_Silk_shell_coder.c \  
    105.     $(SILK)/src/SKP_Silk_sigm_Q15.c \  
    106.     $(SILK)/src/SKP_Silk_solve_LS_FIX.c \  
    107.     $(SILK)/src/SKP_Silk_sort.c \  
    108.     $(SILK)/src/SKP_Silk_sum_sqr_shift.c \  
    109.     $(SILK)/src/SKP_Silk_tables_LTP.c \  
    110.     $(SILK)/src/SKP_Silk_tables_NLSF_CB0_10.c \  
    111.     $(SILK)/src/SKP_Silk_tables_NLSF_CB0_16.c \  
    112.     $(SILK)/src/SKP_Silk_tables_NLSF_CB1_10.c \  
    113.     $(SILK)/src/SKP_Silk_tables_NLSF_CB1_16.c \  
    114.     $(SILK)/src/SKP_Silk_tables_gain.c \  
    115.     $(SILK)/src/SKP_Silk_tables_other.c \  
    116.     $(SILK)/src/SKP_Silk_tables_pitch_lag.c \  
    117.     $(SILK)/src/SKP_Silk_tables_pulses_per_block.c \  
    118.     $(SILK)/src/SKP_Silk_tables_sign.c \  
    119.     $(SILK)/src/SKP_Silk_tables_type_offset.c  
    120.       
    121. LOCAL_ARM_MODE := arm  
    122. LOCAL_CFLAGS = -O3   
    123. LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog  
    124. LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(SILK)/src $(LOCAL_PATH)/$(SILK)/interface  
    125. include $(BUILD_STATIC_LIBRARY)  
    126.   
    127.   
    128. include $(CLEAR_VARS)  
    129. LOCAL_MODULE    := silk8_jni  
    130. LOCAL_SRC_FILES := silk8_jni.cpp   
    131. LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(SILK)/src $(LOCAL_PATH)/$(SILK)/interface  
    132. LOCAL_CFLAGS = -O3   
    133. LOCAL_STATIC_LIBRARIES :=  silkcommon  
    134. LOCAL_ARM_MODE := arm  
    135. LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog  
    136. include $(BUILD_SHARED_LIBRARY)  
    137.   
    138. include $(CLEAR_VARS)  
    139. LOCAL_MODULE    := silk16_jni  
    140. LOCAL_SRC_FILES := silk16_jni.cpp   
    141. LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(SILK)/src $(LOCAL_PATH)/$(SILK)/interface  
    142. LOCAL_CFLAGS = -O3   
    143. LOCAL_STATIC_LIBRARIES :=  silkcommon  
    144. LOCAL_ARM_MODE := arm  
    145. LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog  
    146. include $(BUILD_SHARED_LIBRARY)  
    147.   
    148. include $(CLEAR_VARS)  
    149. LOCAL_MODULE    := silk24_jni  
    150. LOCAL_SRC_FILES := silk24_jni.cpp   
    151. LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(SILK)/src $(LOCAL_PATH)/$(SILK)/interface  
    152. LOCAL_CFLAGS = -O3   
    153. LOCAL_STATIC_LIBRARIES :=  silkcommon  
    154. LOCAL_ARM_MODE := arm  
    155. LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog  
    156. include $(BUILD_SHARED_LIBRARY)  


           5、创建JNI包装类silk8_jni.cpp、silk16_jni.cpp、silk24_jni.cpp,用来调用Silk中的C代码函数,编辑内容如下

          silk8_jni.cpp:

        

    1. #include <jni.h>  
    2.   
    3. #include <stdio.h>  
    4. #include <stdlib.h>  
    5. #include <string.h>  
    6. #include <math.h>  
    7.   
    8. /* Define codec specific settings */  
    9. #define MAX_BYTES_ENC_PER_FRAME     250 // Equals peak bitrate of 100 kbps   
    10. #define MAX_BYTES_DEC_PER_FRAME     1024  
    11.   
    12. #define MAX_INPUT_FRAMES        5  
    13. #define MAX_LBRR_DELAY          2  
    14. #define MAX_FRAME_LENGTH        480  
    15.   
    16. #define MAX_FRAME           160  
    17.   
    18. #include <android/log.h>   
    19.   
    20. #define LOG_TAG "silk" // text for log tag   
    21.   
    22. #include "SKP_Silk_SDK_API.h"  
    23. #include "SKP_Silk_SigProc_FIX.h"  
    24.   
    25. #undef DEBUG_SILK8  
    26.   
    27. // the header length of the RTP frame (must skip when en/decoding)  
    28. #define RTP_HDR_SIZE    12  
    29.   
    30. static int codec_open = 0;  
    31.   
    32. static JavaVM *gJavaVM;  
    33. const char *kInterfacePath = "org/sipdroid/pjlib/silk8";  
    34.   
    35. /* encoder parameters */  
    36.   
    37.     SKP_int32 encSizeBytes;  
    38.     void      *psEnc;  
    39.   
    40.     /* default settings */  
    41.     SKP_int   fs_kHz = 8;  
    42.     SKP_int   targetRate_bps = 20000;  
    43.     SKP_int   packetSize_ms = 20;  
    44.     SKP_int   frameSizeReadFromFile_ms = 20;  
    45.     SKP_int   packetLoss_perc = 0, smplsSinceLastPacket;  
    46.     SKP_int   INBandFec_enabled = 0, DTX_enabled = 0, quiet = 0;  
    47.     SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder  
    48.           
    49.   
    50. /* decoder parameters */  
    51.   
    52.     jbyte payloadToDec[    MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];  
    53.     jshort out[ ( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ], *outPtr;  
    54.     SKP_int32 decSizeBytes;  
    55.     void      *psDec;  
    56.     SKP_SILK_SDK_DecControlStruct DecControl;  
    57.   
    58. extern "C"  
    59. JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK8_open  
    60.   (JNIEnv *env, jobject obj, jint compression) {  
    61.     int ret;  
    62.   
    63.     if (codec_open++ != 0)  
    64.         return (jint)0;  
    65.   
    66.     /* Set the samplingrate that is requested for the output */  
    67.     DecControl.sampleRate = 8000;  
    68.           
    69.     /* Create decoder */  
    70.     ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );  
    71.     if( ret ) {  
    72.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    73.             "\n!!!!!!!! SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );        
    74.     }  
    75. #ifdef DEBUG_SILK8  
    76.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    77.             "### INIT Decoder decSizeBytes = %d\n", decSizeBytes);        
    78. #endif    
    79.     psDec = malloc( decSizeBytes );  
    80.   
    81.     /* Reset decoder */  
    82.     ret = SKP_Silk_SDK_InitDecoder( psDec );  
    83.     if( ret ) {  
    84.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    85.             "\n!!!!!!!! SKP_Silk_InitDecoder returned %d", ret );     
    86.     }  
    87.   
    88.   
    89.     /* Create Encoder */  
    90.     ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );  
    91.     if( ret ) {  
    92.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    93.             "\n!!!!!!!! SKP_Silk_SDK_Get_Encoder_Size returned %d", ret );    
    94.     }  
    95. #ifdef DEBUG_SILK8  
    96.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    97.             "### INIT Encoder encSizeBytes = %d\n", encSizeBytes);        
    98. #endif        
    99.     psEnc = malloc( encSizeBytes );  
    100.       
    101.     /* Reset Encoder */  
    102.     ret = SKP_Silk_SDK_InitEncoder( psEnc, &encControl );  
    103.     if( ret ) {  
    104.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    105.             "\n!!!!!!!! SKP_Silk_SDK_InitEncoder returned %d", ret );     
    106.     }  
    107.       
    108.     /* Set Encoder parameters */  
    109.     encControl.sampleRate           = fs_kHz * 1000;  
    110.     encControl.packetSize           = packetSize_ms * fs_kHz;  
    111.     encControl.packetLossPercentage = packetLoss_perc;  
    112.     encControl.useInBandFEC         = INBandFec_enabled;  
    113.     encControl.useDTX               = DTX_enabled;  
    114.     encControl.complexity           = compression;  
    115.     encControl.bitRate              = targetRate_bps;         
    116.       
    117.     return (jint)0;  
    118. }  
    119.   
    120. void Print_Decode_Error_Msg(int errcode) {  
    121.     switch (errcode) {  
    122.         case SKP_SILK_DEC_WRONG_SAMPLING_FREQUENCY:  
    123.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    124.                 "!!!!!!!!!!! Decode_Error_Message: %d\nOutput sampling frequency lower than internal decoded sampling frequency\n", errcode);  
    125.             break;  
    126.         case SKP_SILK_DEC_PAYLOAD_TOO_LARGE:  
    127.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    128.                 "!!!!!!!!!!! Decode_Error_Message: %d\nPayload size exceeded the maximum allowed 1024 bytes\n", errcode);   
    129.             break;  
    130.         case SKP_SILK_DEC_PAYLOAD_ERROR:  
    131.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    132.                 "!!!!!!!!!!! Decode_Error_Message: %d\nPayload has bit errors\n", errcode);   
    133.             break;            
    134.     }  
    135. }  
    136.   
    137. void Print_Encode_Error_Msg(int errcode) {  
    138.     switch (errcode) {  
    139.         case SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES:  
    140.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    141.                 "!!!!!!!!!!! Decode_Error_Message: %d\nInput length is not a multiplum of 10 ms, or length is longer than the packet length\n", errcode);  
    142.             break;  
    143.         case SKP_SILK_ENC_FS_NOT_SUPPORTED:  
    144.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    145.                 "!!!!!!!!!!! Decode_Error_Message: %d\nSampling frequency not 8000, 12000, 16000 or 24000 Hertz \n", errcode);   
    146.             break;  
    147.         case SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED:  
    148.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    149.                 "!!!!!!!!!!! Decode_Error_Message: %d\nPacket size not 20, 40, 60, 80 or 100 ms\n", errcode);   
    150.             break;            
    151.         case SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT:  
    152.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    153.                 "!!!!!!!!!!! Decode_Error_Message: %d\nAllocated payload buffer too short \n", errcode);  
    154.             break;  
    155.         case SKP_SILK_ENC_WRONG_LOSS_RATE:  
    156.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    157.                 "!!!!!!!!!!! Decode_Error_Message: %d\nLoss rate not between 0 and 100 percent\n", errcode);   
    158.             break;  
    159.         case SKP_SILK_ENC_WRONG_COMPLEXITY_SETTING:  
    160.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    161.                 "!!!!!!!!!!! Decode_Error_Message: %d\nComplexity setting not valid, use 0, 1 or 2\n", errcode);   
    162.             break;        
    163.         case SKP_SILK_ENC_WRONG_INBAND_FEC_SETTING:  
    164.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    165.                 "!!!!!!!!!!! Decode_Error_Message: %d\nInband FEC setting not valid, use 0 or 1\n", errcode);  
    166.             break;  
    167.         case SKP_SILK_ENC_WRONG_DTX_SETTING:  
    168.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    169.                 "!!!!!!!!!!! Decode_Error_Message: %d\nDTX setting not valid, use 0 or 1\n", errcode);   
    170.             break;  
    171.         case SKP_SILK_ENC_INTERNAL_ERROR:  
    172.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    173.                 "!!!!!!!!!!! Decode_Error_Message: %d\nInternal encoder error\n", errcode);   
    174.             break;                
    175.     }  
    176. }  
    177.   
    178. extern "C"  
    179. JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK8_encode  
    180.     (JNIEnv *env, jobject obj, jshortArray lin, jint offset, jbyteArray encoded, jint size) {  
    181.   
    182.     jbyte     enc_payload[ MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES ];  
    183.     jshort    in[ MAX_FRAME_LENGTH * MAX_INPUT_FRAMES ];      
    184.     int ret,i,frsz=MAX_FRAME;  
    185.     SKP_int16 nBytes;  
    186.     unsigned int lin_pos = 0;  
    187.       
    188.     if (!codec_open)  
    189.         return 0;  
    190.           
    191. #ifdef DEBUG_SILK8  
    192.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    193.             "encoding frame size: %d\toffset: %d\n", size, offset);           
    194. #endif  
    195.   
    196.   
    197.     for (i = 0; i < size; i+=MAX_FRAME) {  
    198. #ifdef DEBUG_SILK8  
    199.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    200.             "encoding frame size: %d\toffset: %d i: %d\n", size, offset, i);          
    201. #endif  
    202.               
    203.         env->GetShortArrayRegion(lin, offset + i,frsz, in);  
    204.         /* max payload size */  
    205.         nBytes = MAX_BYTES_ENC_PER_FRAME * MAX_INPUT_FRAMES;  
    206.   
    207.         ret = SKP_Silk_SDK_Encode( psEnc, &encControl, in, (SKP_int16)frsz, (SKP_uint8 *)enc_payload, &nBytes );  
    208.         if( ret ) {  
    209.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    210.                 "!!!!!!!! SKP_Silk_Encode returned: %d\n", ret);  
    211.             Print_Encode_Error_Msg(ret);                  
    212.             break;  
    213.         }  
    214. #ifdef DEBUG_SILK8  
    215.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    216.                 "Enocded nBytes: %d\n", nBytes);          
    217. #endif        
    218.         /* Write payload */       
    219.         env->SetByteArrayRegion(encoded, RTP_HDR_SIZE+ lin_pos, nBytes, enc_payload);  
    220.         lin_pos += nBytes;  
    221.     }  
    222. #ifdef DEBUG_SILK8  
    223.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    224.         "encoding **END** frame size: %d\toffset: %d i: %d lin_pos: %d\n", size, offset, i, lin_pos);  
    225. #endif        
    226.   
    227.     return (jint)lin_pos;  
    228. }  
    229.   
    230. extern "C"  
    231. JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK8_decode  
    232.     (JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) {  
    233.   
    234.     jbyte buffer [MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];  
    235.     jshort output_buffer[( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ];  
    236. //  SKP_int16   *outPtr;  
    237.   
    238.     int ret;  
    239.     SKP_int16 len;  
    240. //  int tot_len,frames;  
    241.   
    242.     if (!codec_open)  
    243.         return 0;  
    244.   
    245. #ifdef DEBUG_SILK8        
    246.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    247.         "##### BEGIN DECODE ********  decoding frame size: %d\n", size);      
    248. #endif  
    249.   
    250.     env->GetByteArrayRegion(encoded, RTP_HDR_SIZE, size, buffer);  
    251.   
    252. //  outPtr = output_buffer;  
    253. //    tot_len = 0;  
    254. //  frames = 0;  
    255.   
    256. //  do {  
    257.         ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0,(SKP_uint8 *) buffer, size, output_buffer,&len );  
    258.         if( ret ) {  
    259.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    260.                 "!!!!!!!! SKP_Silk_SDK_Decode returned: %d\n", ret);      
    261.             Print_Decode_Error_Msg(ret);  
    262.         }  
    263. #ifdef DEBUG_SILK8        
    264.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    265.             "##### DECODED length: %d\n\t Frame #: %d", len);     
    266. #endif  
    267. //      frames++;  
    268. //      outPtr  += len;  
    269. //      tot_len += len;       
    270.       
    271. //  } while( DecControl.moreInternalDecoderFrames );  
    272.   
    273.     env->SetShortArrayRegion(lin, 0, len,output_buffer);  
    274.     return (jint)len;  
    275. }  
    276.   
    277. extern "C"  
    278. JNIEXPORT void JNICALL Java_com_trunkbow_silk_SILK8_close  
    279.     (JNIEnv *env, jobject obj) {  
    280.   
    281.     if (--codec_open != 0)  
    282.         return;  
    283.     /* Free decoder */  
    284.     free( psDec );  
    285.     /* Free Encoder */  
    286.     free( psEnc );  
    287. }  


          silk_16.cpp:

          

    1. #include <jni.h>  
    2.   
    3. #include <stdio.h>  
    4. #include <stdlib.h>  
    5. #include <string.h>  
    6. #include <math.h>  
    7.   
    8. /* Define codec specific settings */  
    9. #define MAX_BYTES_ENC_PER_FRAME     250 // Equals peak bitrate of 100 kbps   
    10. #define MAX_BYTES_DEC_PER_FRAME     1024  
    11.   
    12. #define MAX_INPUT_FRAMES        5  
    13. #define MAX_LBRR_DELAY          2  
    14. #define MAX_FRAME_LENGTH        480  
    15.   
    16. #define MAX_FRAME           320  
    17.   
    18. #include <android/log.h>   
    19.   
    20. #define LOG_TAG "silk" // text for log tag   
    21.   
    22. #include "SKP_Silk_SDK_API.h"  
    23. #include "SKP_Silk_SigProc_FIX.h"  
    24.   
    25. #undef DEBUG_SILK16  
    26.   
    27. // the header length of the RTP frame (must skip when en/decoding)  
    28. #define RTP_HDR_SIZE    12  
    29.   
    30. static int codec_open = 0;  
    31.   
    32. static JavaVM *gJavaVM;  
    33. const char *kInterfacePath = "org/sipdroid/pjlib/silk16";  
    34.   
    35. /* encoder parameters */  
    36.   
    37.     SKP_int32 encSizeBytes;  
    38.     void      *psEnc;  
    39.   
    40.     /* default settings */  
    41.     SKP_int   fs_kHz = 16;  
    42.     SKP_int   targetRate_bps = 20000;  
    43.     SKP_int   packetSize_ms = 20;  
    44.     SKP_int   frameSizeReadFromFile_ms = 20;  
    45.     SKP_int   packetLoss_perc = 0, smplsSinceLastPacket;  
    46.     SKP_int   INBandFec_enabled = 0, DTX_enabled = 0, quiet = 0;  
    47.     SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder  
    48.           
    49.   
    50. /* decoder parameters */  
    51.   
    52.     jbyte payloadToDec[    MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];  
    53.     jshort out[ ( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ], *outPtr;  
    54.     SKP_int32 decSizeBytes;  
    55.     void      *psDec;  
    56.     SKP_SILK_SDK_DecControlStruct DecControl;  
    57.   
    58. extern "C"  
    59. JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK16_open  
    60.   (JNIEnv *env, jobject obj, jint compression) {  
    61.     int ret;  
    62.   
    63.     if (codec_open++ != 0)  
    64.         return (jint)0;  
    65.   
    66.     /* Set the samplingrate that is requested for the output */  
    67.     DecControl.sampleRate = 16000;  
    68.           
    69.     /* Create decoder */  
    70.     ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );  
    71.     if( ret ) {  
    72.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    73.             "\n!!!!!!!! SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );        
    74.     }  
    75. #ifdef DEBUG_SILK16  
    76.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    77.             "### INIT Decoder decSizeBytes = %d\n", decSizeBytes);        
    78. #endif    
    79.     psDec = malloc( decSizeBytes );  
    80.   
    81.     /* Reset decoder */  
    82.     ret = SKP_Silk_SDK_InitDecoder( psDec );  
    83.     if( ret ) {  
    84.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    85.             "\n!!!!!!!! SKP_Silk_InitDecoder returned %d", ret );     
    86.     }  
    87.   
    88.   
    89.     /* Create Encoder */  
    90.     ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );  
    91.     if( ret ) {  
    92.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    93.             "\n!!!!!!!! SKP_Silk_SDK_Get_Encoder_Size returned %d", ret );    
    94.     }  
    95. #ifdef DEBUG_SILK16  
    96.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    97.             "### INIT Encoder encSizeBytes = %d\n", encSizeBytes);        
    98. #endif        
    99.     psEnc = malloc( encSizeBytes );  
    100.       
    101.     /* Reset Encoder */  
    102.     ret = SKP_Silk_SDK_InitEncoder( psEnc, &encControl );  
    103.     if( ret ) {  
    104.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    105.             "\n!!!!!!!! SKP_Silk_SDK_InitEncoder returned %d", ret );     
    106.     }  
    107.       
    108.     /* Set Encoder parameters */  
    109.     encControl.sampleRate           = fs_kHz * 1000;  
    110.     encControl.packetSize           = packetSize_ms * fs_kHz;  
    111.     encControl.packetLossPercentage = packetLoss_perc;  
    112.     encControl.useInBandFEC         = INBandFec_enabled;  
    113.     encControl.useDTX               = DTX_enabled;  
    114.     encControl.complexity           = compression;  
    115.     encControl.bitRate              = targetRate_bps;         
    116.       
    117.     return (jint)0;  
    118. }  
    119.   
    120. void Print_Decode_Error_Msg(int errcode) {  
    121.     switch (errcode) {  
    122.         case SKP_SILK_DEC_WRONG_SAMPLING_FREQUENCY:  
    123.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    124.                 "!!!!!!!!!!! Decode_Error_Message: %d\nOutput sampling frequency lower than internal decoded sampling frequency\n", errcode);  
    125.             break;  
    126.         case SKP_SILK_DEC_PAYLOAD_TOO_LARGE:  
    127.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    128.                 "!!!!!!!!!!! Decode_Error_Message: %d\nPayload size exceeded the maximum allowed 1024 bytes\n", errcode);   
    129.             break;  
    130.         case SKP_SILK_DEC_PAYLOAD_ERROR:  
    131.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    132.                 "!!!!!!!!!!! Decode_Error_Message: %d\nPayload has bit errors\n", errcode);   
    133.             break;            
    134.     }  
    135. }  
    136.   
    137. void Print_Encode_Error_Msg(int errcode) {  
    138.     switch (errcode) {  
    139.         case SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES:  
    140.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    141.                 "!!!!!!!!!!! Decode_Error_Message: %d\nInput length is not a multiplum of 10 ms, or length is longer than the packet length\n", errcode);  
    142.             break;  
    143.         case SKP_SILK_ENC_FS_NOT_SUPPORTED:  
    144.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    145.                 "!!!!!!!!!!! Decode_Error_Message: %d\nSampling frequency not 8000, 12000, 16000 or 24000 Hertz \n", errcode);   
    146.             break;  
    147.         case SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED:  
    148.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    149.                 "!!!!!!!!!!! Decode_Error_Message: %d\nPacket size not 20, 40, 60, 80 or 100 ms\n", errcode);   
    150.             break;            
    151.         case SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT:  
    152.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    153.                 "!!!!!!!!!!! Decode_Error_Message: %d\nAllocated payload buffer too short \n", errcode);  
    154.             break;  
    155.         case SKP_SILK_ENC_WRONG_LOSS_RATE:  
    156.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    157.                 "!!!!!!!!!!! Decode_Error_Message: %d\nLoss rate not between 0 and 100 percent\n", errcode);   
    158.             break;  
    159.         case SKP_SILK_ENC_WRONG_COMPLEXITY_SETTING:  
    160.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    161.                 "!!!!!!!!!!! Decode_Error_Message: %d\nComplexity setting not valid, use 0, 1 or 2\n", errcode);   
    162.             break;        
    163.         case SKP_SILK_ENC_WRONG_INBAND_FEC_SETTING:  
    164.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    165.                 "!!!!!!!!!!! Decode_Error_Message: %d\nInband FEC setting not valid, use 0 or 1\n", errcode);  
    166.             break;  
    167.         case SKP_SILK_ENC_WRONG_DTX_SETTING:  
    168.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    169.                 "!!!!!!!!!!! Decode_Error_Message: %d\nDTX setting not valid, use 0 or 1\n", errcode);   
    170.             break;  
    171.         case SKP_SILK_ENC_INTERNAL_ERROR:  
    172.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    173.                 "!!!!!!!!!!! Decode_Error_Message: %d\nInternal encoder error\n", errcode);   
    174.             break;                
    175.     }  
    176. }  
    177.   
    178. extern "C"  
    179. JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK16_encode  
    180.     (JNIEnv *env, jobject obj, jshortArray lin, jint offset, jbyteArray encoded, jint size) {  
    181.   
    182.     jbyte     enc_payload[ MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES ];  
    183.     jshort    in[ MAX_FRAME_LENGTH * MAX_INPUT_FRAMES ];      
    184.     int ret,i,frsz=MAX_FRAME;  
    185.     SKP_int16 nBytes;  
    186.     unsigned int lin_pos = 0;  
    187.       
    188.     if (!codec_open)  
    189.         return 0;  
    190.           
    191. #ifdef DEBUG_SILK16  
    192.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    193.             "encoding frame size: %d\toffset: %d\n", size, offset);           
    194. #endif  
    195.   
    196.   
    197.     for (i = 0; i < size; i+=MAX_FRAME) {  
    198. #ifdef DEBUG_SILK16  
    199.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    200.             "encoding frame size: %d\toffset: %d i: %d\n", size, offset, i);          
    201. #endif  
    202.               
    203.         env->GetShortArrayRegion(lin, offset + i,frsz, in);  
    204.         /* max payload size */  
    205.         nBytes = MAX_BYTES_ENC_PER_FRAME * MAX_INPUT_FRAMES;  
    206.   
    207.         ret = SKP_Silk_SDK_Encode( psEnc, &encControl, in, (SKP_int16)frsz, (SKP_uint8 *)enc_payload, &nBytes );  
    208.         if( ret ) {  
    209.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    210.                 "!!!!!!!! SKP_Silk_Encode returned: %d\n", ret);  
    211.             Print_Encode_Error_Msg(ret);                      
    212.             break;  
    213.         }  
    214. #ifdef DEBUG_SILK16  
    215.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    216.                 "Enocded nBytes: %d\n", nBytes);          
    217. #endif        
    218.         /* Write payload */       
    219.         env->SetByteArrayRegion(encoded, RTP_HDR_SIZE+ lin_pos, nBytes, enc_payload);  
    220.         lin_pos += nBytes;  
    221.     }  
    222. #ifdef DEBUG_SILK16  
    223.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    224.         "encoding **END** frame size: %d\toffset: %d i: %d lin_pos: %d\n", size, offset, i, lin_pos);  
    225. #endif        
    226.   
    227.     return (jint)lin_pos;  
    228. }  
    229.   
    230. extern "C"  
    231. JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK16_decode  
    232.     (JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) {  
    233.   
    234.     jbyte buffer [MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];  
    235.     jshort output_buffer[( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ];  
    236. //  SKP_int16   *outPtr;  
    237.   
    238.     int ret;  
    239.     SKP_int16 len;  
    240. //  int tot_len,frames;  
    241.   
    242.     if (!codec_open)  
    243.         return 0;  
    244.   
    245. #ifdef DEBUG_SILK16       
    246.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    247.         "##### BEGIN DECODE ********  decoding frame size: %d\n", size);      
    248. #endif  
    249.   
    250.     env->GetByteArrayRegion(encoded, RTP_HDR_SIZE, size, buffer);  
    251.   
    252. //  outPtr = output_buffer;  
    253. //    tot_len = 0;  
    254. //  frames = 0;  
    255.   
    256. //  do {  
    257.         ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0,(SKP_uint8 *) buffer, size, output_buffer,&len );  
    258.         if( ret ) {  
    259.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    260.                 "!!!!!!!! SKP_Silk_SDK_Decode returned: %d\n", ret);      
    261.             Print_Decode_Error_Msg(ret);  
    262.         }  
    263. #ifdef DEBUG_SILK16       
    264.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    265.             "##### DECODED length: %d\n\t Frame #: %d", len);     
    266. #endif  
    267. //      frames++;  
    268. //      outPtr  += len;  
    269. //      tot_len += len;       
    270.       
    271. //  } while( DecControl.moreInternalDecoderFrames );  
    272.   
    273.     env->SetShortArrayRegion(lin, 0, len,output_buffer);  
    274.     return (jint)len;  
    275. }  
    276.   
    277. extern "C"  
    278. JNIEXPORT void JNICALL Java_com_trunkbow_silk_SILK16_close  
    279.     (JNIEnv *env, jobject obj) {  
    280.   
    281.     if (--codec_open != 0)  
    282.         return;  
    283.     /* Free decoder */  
    284.     free( psDec );  
    285.     /* Free Encoder */  
    286.     free( psEnc );  
    287. }  


             silk24_jni.cpp

            

    1. #include <jni.h>  
    2.   
    3. #include <stdio.h>  
    4. #include <stdlib.h>  
    5. #include <string.h>  
    6. #include <math.h>  
    7.   
    8. /* Define codec specific settings */  
    9. #define MAX_BYTES_ENC_PER_FRAME     250 // Equals peak bitrate of 100 kbps   
    10. #define MAX_BYTES_DEC_PER_FRAME     1024  
    11.   
    12. #define MAX_INPUT_FRAMES        5  
    13. #define MAX_LBRR_DELAY          2  
    14. #define MAX_FRAME_LENGTH        480  
    15.   
    16. #define MAX_FRAME           480  
    17.   
    18. #include <android/log.h>   
    19.   
    20. #define LOG_TAG "silk" // text for log tag   
    21.   
    22. #include "SKP_Silk_SDK_API.h"  
    23. #include "SKP_Silk_SigProc_FIX.h"  
    24.   
    25. #undef DEBUG_SILK24  
    26.   
    27. // the header length of the RTP frame (must skip when en/decoding)  
    28. #define RTP_HDR_SIZE    12  
    29.   
    30. static int codec_open = 0;  
    31.   
    32. static JavaVM *gJavaVM;  
    33. const char *kInterfacePath = "org/sipdroid/pjlib/SILK24";  
    34.   
    35. /* encoder parameters */  
    36.   
    37.     SKP_int32 encSizeBytes;  
    38.     void      *psEnc;  
    39.   
    40.     /* default settings */  
    41.     SKP_int   fs_kHz = 24;  
    42.     SKP_int   targetRate_bps = 20000;  
    43.     SKP_int   packetSize_ms = 20;  
    44.     SKP_int   frameSizeReadFromFile_ms = 20;  
    45.     SKP_int   packetLoss_perc = 0, smplsSinceLastPacket;  
    46.     SKP_int   INBandFec_enabled = 0, DTX_enabled = 0, quiet = 0;  
    47.     SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder  
    48.           
    49.   
    50. /* decoder parameters */  
    51.   
    52.     jbyte payloadToDec[    MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];  
    53.     jshort out[ ( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ], *outPtr;  
    54.     SKP_int32 decSizeBytes;  
    55.     void      *psDec;  
    56.     SKP_SILK_SDK_DecControlStruct DecControl;  
    57.   
    58. extern "C"  
    59. JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK24_open  
    60.   (JNIEnv *env, jobject obj, jint compression) {  
    61.     int ret;  
    62.   
    63.     if (codec_open++ != 0)  
    64.         return (jint)0;  
    65.   
    66.     /* Set the samplingrate that is requested for the output */  
    67.     DecControl.sampleRate = 24000;  
    68.           
    69.     /* Create decoder */  
    70.     ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );  
    71.     if( ret ) {  
    72.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    73.             "\n!!!!!!!! SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );        
    74.     }  
    75. #ifdef DEBUG_SILK24  
    76.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    77.             "### INIT Decoder decSizeBytes = %d\n", decSizeBytes);        
    78. #endif    
    79.     psDec = malloc( decSizeBytes );  
    80.   
    81.     /* Reset decoder */  
    82.     ret = SKP_Silk_SDK_InitDecoder( psDec );  
    83.     if( ret ) {  
    84.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    85.             "\n!!!!!!!! SKP_Silk_InitDecoder returned %d", ret );     
    86.     }  
    87.   
    88.   
    89.     /* Create Encoder */  
    90.     ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );  
    91.     if( ret ) {  
    92.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    93.             "\n!!!!!!!! SKP_Silk_SDK_Get_Encoder_Size returned %d", ret );    
    94.     }  
    95. #ifdef DEBUG_SILK24  
    96.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    97.             "### INIT Encoder encSizeBytes = %d\n", encSizeBytes);        
    98. #endif        
    99.     psEnc = malloc( encSizeBytes );  
    100.       
    101.     /* Reset Encoder */  
    102.     ret = SKP_Silk_SDK_InitEncoder( psEnc, &encControl );  
    103.     if( ret ) {  
    104.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    105.             "\n!!!!!!!! SKP_Silk_SDK_InitEncoder returned %d", ret );     
    106.     }  
    107.       
    108.     /* Set Encoder parameters */  
    109.     encControl.sampleRate           = fs_kHz * 1000;  
    110.     encControl.packetSize           = packetSize_ms * fs_kHz;  
    111.     encControl.packetLossPercentage = packetLoss_perc;  
    112.     encControl.useInBandFEC         = INBandFec_enabled;  
    113.     encControl.useDTX               = DTX_enabled;  
    114.     encControl.complexity           = compression;  
    115.     encControl.bitRate              = targetRate_bps;         
    116.       
    117.     return (jint)0;  
    118. }  
    119.   
    120. void Print_Decode_Error_Msg(int errcode) {  
    121.     switch (errcode) {  
    122.         case SKP_SILK_DEC_WRONG_SAMPLING_FREQUENCY:  
    123.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    124.                 "!!!!!!!!!!! Decode_Error_Message: %d\nOutput sampling frequency lower than internal decoded sampling frequency\n", errcode);  
    125.             break;  
    126.         case SKP_SILK_DEC_PAYLOAD_TOO_LARGE:  
    127.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    128.                 "!!!!!!!!!!! Decode_Error_Message: %d\nPayload size exceeded the maximum allowed 1024 bytes\n", errcode);   
    129.             break;  
    130.         case SKP_SILK_DEC_PAYLOAD_ERROR:  
    131.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    132.                 "!!!!!!!!!!! Decode_Error_Message: %d\nPayload has bit errors\n", errcode);   
    133.             break;            
    134.     }  
    135. }  
    136.   
    137. void Print_Encode_Error_Msg(int errcode) {  
    138.     switch (errcode) {  
    139.         case SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES:  
    140.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    141.                 "!!!!!!!!!!! Decode_Error_Message: %d\nInput length is not a multiplum of 10 ms, or length is longer than the packet length\n", errcode);  
    142.             break;  
    143.         case SKP_SILK_ENC_FS_NOT_SUPPORTED:  
    144.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    145.                 "!!!!!!!!!!! Decode_Error_Message: %d\nSampling frequency not 8000, 12000, 16000 or 24000 Hertz \n", errcode);   
    146.             break;  
    147.         case SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED:  
    148.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    149.                 "!!!!!!!!!!! Decode_Error_Message: %d\nPacket size not 20, 40, 60, 80 or 100 ms\n", errcode);   
    150.             break;            
    151.         case SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT:  
    152.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    153.                 "!!!!!!!!!!! Decode_Error_Message: %d\nAllocated payload buffer too short \n", errcode);  
    154.             break;  
    155.         case SKP_SILK_ENC_WRONG_LOSS_RATE:  
    156.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    157.                 "!!!!!!!!!!! Decode_Error_Message: %d\nLoss rate not between 0 and 100 percent\n", errcode);   
    158.             break;  
    159.         case SKP_SILK_ENC_WRONG_COMPLEXITY_SETTING:  
    160.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    161.                 "!!!!!!!!!!! Decode_Error_Message: %d\nComplexity setting not valid, use 0, 1 or 2\n", errcode);   
    162.             break;        
    163.         case SKP_SILK_ENC_WRONG_INBAND_FEC_SETTING:  
    164.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    165.                 "!!!!!!!!!!! Decode_Error_Message: %d\nInband FEC setting not valid, use 0 or 1\n", errcode);  
    166.             break;  
    167.         case SKP_SILK_ENC_WRONG_DTX_SETTING:  
    168.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    169.                 "!!!!!!!!!!! Decode_Error_Message: %d\nDTX setting not valid, use 0 or 1\n", errcode);   
    170.             break;  
    171.         case SKP_SILK_ENC_INTERNAL_ERROR:  
    172.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    173.                 "!!!!!!!!!!! Decode_Error_Message: %d\nInternal encoder error\n", errcode);   
    174.             break;                
    175.     }  
    176. }  
    177.   
    178. extern "C"  
    179. JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK24_encode  
    180.     (JNIEnv *env, jobject obj, jshortArray lin, jint offset, jbyteArray encoded, jint size) {  
    181.   
    182.     jbyte     enc_payload[ MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES ];  
    183.     jshort    in[ MAX_FRAME_LENGTH * MAX_INPUT_FRAMES ];      
    184.     int ret,i,frsz=MAX_FRAME;  
    185.     SKP_int16 nBytes;  
    186.     unsigned int lin_pos = 0;  
    187.       
    188.     if (!codec_open)  
    189.         return 0;  
    190.           
    191. #ifdef DEBUG_SILK24  
    192.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    193.             "encoding frame size: %d\toffset: %d\n", size, offset);           
    194. #endif  
    195.   
    196.   
    197.     for (i = 0; i < size; i+=MAX_FRAME) {  
    198. #ifdef DEBUG_SILK24  
    199.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    200.             "encoding frame size: %d\toffset: %d i: %d\n", size, offset, i);          
    201. #endif  
    202.               
    203.         env->GetShortArrayRegion(lin, offset + i,frsz, in);  
    204.         /* max payload size */  
    205.         nBytes = MAX_BYTES_ENC_PER_FRAME * MAX_INPUT_FRAMES;  
    206.   
    207.         ret = SKP_Silk_SDK_Encode( psEnc, &encControl, in, (SKP_int16)frsz, (SKP_uint8 *)enc_payload, &nBytes );  
    208.         if( ret ) {  
    209.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    210.                 "!!!!!!!! SKP_Silk_Encode returned: %d\n", ret);  
    211.             Print_Encode_Error_Msg(ret);                  
    212.             break;  
    213.         }  
    214. #ifdef DEBUG_SILK24  
    215.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    216.                 "Enocded nBytes: %d\n", nBytes);          
    217. #endif        
    218.         /* Write payload */       
    219.         env->SetByteArrayRegion(encoded, RTP_HDR_SIZE+ lin_pos, nBytes, enc_payload);  
    220.         lin_pos += nBytes;  
    221.     }  
    222. #ifdef DEBUG_SILK24  
    223.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    224.         "encoding **END** frame size: %d\toffset: %d i: %d lin_pos: %d\n", size, offset, i, lin_pos);  
    225. #endif        
    226.   
    227.     return (jint)lin_pos;  
    228. }  
    229.   
    230. extern "C"  
    231. JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK24_decode  
    232.     (JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) {  
    233.   
    234.     jbyte buffer [MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];  
    235.     jshort output_buffer[( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ];  
    236. //  SKP_int16   *outPtr;  
    237.   
    238.     int ret;  
    239.     SKP_int16 len;  
    240. //  int tot_len,frames;  
    241.   
    242.     if (!codec_open)  
    243.         return 0;  
    244.   
    245. #ifdef DEBUG_SILK24       
    246.     __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    247.         "##### BEGIN DECODE ********  decoding frame size: %d\n", size);      
    248. #endif  
    249.   
    250.     env->GetByteArrayRegion(encoded, RTP_HDR_SIZE, size, buffer);  
    251.   
    252. //  outPtr = output_buffer;  
    253. //    tot_len = 0;  
    254. //  frames = 0;  
    255.   
    256. //  do {  
    257.         ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0,(SKP_uint8 *) buffer, size, output_buffer,&len );  
    258.         if( ret ) {  
    259.             __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    260.                 "!!!!!!!! SKP_Silk_SDK_Decode returned: %d\n", ret);      
    261.             Print_Decode_Error_Msg(ret);  
    262.         }  
    263. #ifdef DEBUG_SILK24       
    264.         __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,   
    265.             "##### DECODED length: %d\n\t Frame #: %d", len);     
    266. #endif  
    267. //      frames++;  
    268. //      outPtr  += len;  
    269. //      tot_len += len;       
    270.       
    271. //  } while( DecControl.moreInternalDecoderFrames );  
    272.   
    273.     env->SetShortArrayRegion(lin, 0, len,output_buffer);  
    274.     return (jint)len;  
    275. }  
    276.   
    277. extern "C"  
    278. JNIEXPORT void JNICALL Java_com_trunkbow_silk_SILK24_close  
    279.     (JNIEnv *env, jobject obj) {  
    280.   
    281.     if (--codec_open != 0)  
    282.         return;  
    283.     /* Free decoder */  
    284.     free( psDec );  
    285.     /* Free Encoder */  
    286.     free( psEnc );  
    287. }  


        

            6、在Java层创建Speex工具类,内容如下:

               Silk8.java:

            

    1. class SILK8{     
    2.     /*  
    3.      *                 | fs (Hz) | BR (kbps) 
    4.      * ----------------+---------+--------- 
    5.      * Narrowband      | 8000    | 6 -20 
    6.      * Mediumband      | 12000   | 7 -25 
    7.      * Wideband        | 16000   | 8 -30 
    8.      * Super Wideband  | 24000   | 12 -40 
    9.      * 
    10.      * Table 1: fs specifies the audio sampling frequency in Hertz (Hz); BR 
    11.      * specifies the adaptive bit rate range in kilobits per second (kbps). 
    12.      *  
    13.      * Complexity can be scaled to optimize for CPU resources in real-time, 
    14.      * mostly in trade-off to network bit rate. 0 is least CPU demanding and 
    15.      * highest bit rate.  
    16.      */  
    17.     private static final int DEFAULT_COMPLEXITY = 0;  
    18.       
    19.     void load() {  
    20.          System.loadLibrary("silk8_jni");  
    21.     }    
    22.    
    23.     public native int open(int compression);  
    24.     public native int decode(byte encoded[], short lin[], int size);  
    25.     public native int encode(short lin[], int offset, byte encoded[], int size);  
    26.     public native void close();  
    27. }  


             Silk16.java:

    1. class SILK16 {   
    2.     /*  
    3.      *                 | fs (Hz) | BR (kbps) 
    4.      * ----------------+---------+--------- 
    5.      * Narrowband      | 8000    | 6 -20 
    6.      * Mediumband      | 12000   | 7 -25 
    7.      * Wideband        | 16000   | 8 -30 
    8.      * Super Wideband  | 24000   | 12 -40 
    9.      * 
    10.      * Table 1: fs specifies the audio sampling frequency in Hertz (Hz); BR 
    11.      * specifies the adaptive bit rate range in kilobits per second (kbps). 
    12.      *  
    13.      * Complexity can be scaled to optimize for CPU resources in real-time, 
    14.      * mostly in trade-off to network bit rate. 0 is least CPU demanding and 
    15.      * highest bit rate.  
    16.      */  
    17.     private static final int DEFAULT_COMPLEXITY = 0;  
    18.   
    19.   
    20.     void load() {  
    21.         System.loadLibrary("silk16_jni");  
    22.     }    
    23.    
    24.     public native int open(int compression);  
    25.     public native int decode(byte encoded[], short lin[], int size);  
    26.     public native int encode(short lin[], int offset, byte encoded[], int size);  
    27.     public native void close();  
    28.   
    29. }  


    Silk24.java:

    1. class SILK24  {   
    2.     /*  
    3.      *                 | fs (Hz) | BR (kbps) 
    4.      * ----------------+---------+--------- 
    5.      * Narrowband      | 8000    | 6 -20 
    6.      * Mediumband      | 12000   | 7 -25 
    7.      * Wideband        | 16000   | 8 -30 
    8.      * Super Wideband  | 24000   | 12 -40 
    9.      * 
    10.      * Table 1: fs specifies the audio sampling frequency in Hertz (Hz); BR 
    11.      * specifies the adaptive bit rate range in kilobits per second (kbps). 
    12.      *  
    13.      * Complexity can be scaled to optimize for CPU resources in real-time, 
    14.      * mostly in trade-off to network bit rate. 0 is least CPU demanding and 
    15.      * highest bit rate.  
    16.      */  
    17.     private static final int DEFAULT_COMPLEXITY = 0;  
    18.   
    19.     void load() {  
    20.         System.loadLibrary("silk24_jni");  
    21.     }    
    22.    
    23.     public native int open(int compression);  
    24.     public native int decode(byte encoded[], short lin[], int size);  
    25.     public native int encode(short lin[], int offset, byte encoded[], int size);  
    26.     public native void close();  
    27.   
    28. }  


               7、使用cygwin编译,生成so文件。       



    本文转载于 http://blog.csdn.net/xyz_lmn/article/details/8015619

    展开全文
  • Silk编解码是Skype向第三方开发人员和硬件制造商提供免版税认证(RF)的Silk宽带音频编码器。Skype已将其开源,可以访问http://developer.skype.com/silk获取最新动向。SILK Codec是一个语音和音频编解码算法, 对于...
    Silk编解码是Skype向第三方开发人员和硬件制造商提供免版税认证(RF)的Silk宽带音频编码器。Skype已将其开源,可以访问http://developer.skype.com/silk获取最新动向。SILK Codec是一个语音和音频编解码算法, 对于音频带宽、网络带宽和算法复杂度都具有很好的弹性。支持4种采样率:8KHz、12KHz、16KHz、24KHz;三种复杂度:低、中、高。编码码率在 6~40kbps(不同采样率具有不同的码率范围)以及还支持VAD、DTX、FEC等模块,感觉还是比较全面。最重要的一点是提供了定点C代码,非常有利于向ARM、DSP移植和优化。这一篇主要参考了pjsip中的silk实现。

          1、获取silk源码(http://developer.skype.com/silk

           2、创建新的android工程,并创建jni文件夹。

           3、将silk源码拷贝到jni目录

           4、在jni目录下新增Android.mk文件,编辑内容如下

       

    LOCAL_PATH := $(call my-dir)
     
    include $(CLEAR_VARS)
    SILK     := silk
    LOCAL_MODULE    := silkcommon
    LOCAL_SRC_FILES :=  $(SILK)/src/SKP_Silk_A2NLSF.c \
    	$(SILK)/src/SKP_Silk_CNG.c \
    	$(SILK)/src/SKP_Silk_HP_variable_cutoff_FIX.c \
    	$(SILK)/src/SKP_Silk_LBRR_reset.c \
    	$(SILK)/src/SKP_Silk_LPC_inv_pred_gain.c \
    	$(SILK)/src/SKP_Silk_LPC_stabilize.c \
    	$(SILK)/src/SKP_Silk_LPC_synthesis_filter.c \
    	$(SILK)/src/SKP_Silk_LPC_synthesis_order16.c \
    	$(SILK)/src/SKP_Silk_LP_variable_cutoff.c \
    	$(SILK)/src/SKP_Silk_LSF_cos_table.c \
    	$(SILK)/src/SKP_Silk_LTP_analysis_filter_FIX.c \
    	$(SILK)/src/SKP_Silk_LTP_scale_ctrl_FIX.c \
    	$(SILK)/src/SKP_Silk_MA.c \
    	$(SILK)/src/SKP_Silk_NLSF2A.c \
    	$(SILK)/src/SKP_Silk_NLSF2A_stable.c \
    	$(SILK)/src/SKP_Silk_NLSF_MSVQ_decode.c \
    	$(SILK)/src/SKP_Silk_NLSF_MSVQ_encode_FIX.c \
    	$(SILK)/src/SKP_Silk_NLSF_VQ_rate_distortion_FIX.c \
    	$(SILK)/src/SKP_Silk_NLSF_VQ_sum_error_FIX.c \
    	$(SILK)/src/SKP_Silk_NLSF_VQ_weights_laroia.c \
    	$(SILK)/src/SKP_Silk_NLSF_stabilize.c \
    	$(SILK)/src/SKP_Silk_NSQ.c \
    	$(SILK)/src/SKP_Silk_NSQ_del_dec.c \
    	$(SILK)/src/SKP_Silk_PLC.c \
    	$(SILK)/src/SKP_Silk_VAD.c \
    	$(SILK)/src/SKP_Silk_VQ_nearest_neighbor_FIX.c \
    	$(SILK)/src/SKP_Silk_allpass_int.c \
    	$(SILK)/src/SKP_Silk_ana_filt_bank_1.c \
    	$(SILK)/src/SKP_Silk_apply_sine_window.c \
    	$(SILK)/src/SKP_Silk_array_maxabs.c \
    	$(SILK)/src/SKP_Silk_autocorr.c \
    	$(SILK)/src/SKP_Silk_biquad.c \
    	$(SILK)/src/SKP_Silk_biquad_alt.c \
    	$(SILK)/src/SKP_Silk_burg_modified.c \
    	$(SILK)/src/SKP_Silk_bwexpander.c \
    	$(SILK)/src/SKP_Silk_bwexpander_32.c \
    	$(SILK)/src/SKP_Silk_code_signs.c \
    	$(SILK)/src/SKP_Silk_control_codec_FIX.c \
    	$(SILK)/src/SKP_Silk_corrMatrix_FIX.c \
    	$(SILK)/src/SKP_Silk_create_init_destroy.c \
    	$(SILK)/src/SKP_Silk_dec_API.c \
    	$(SILK)/src/SKP_Silk_decode_core.c \
    	$(SILK)/src/SKP_Silk_decode_frame.c \
    	$(SILK)/src/SKP_Silk_decode_indices_v4.c \
    	$(SILK)/src/SKP_Silk_decode_parameters.c \
    	$(SILK)/src/SKP_Silk_decode_parameters_v4.c \
    	$(SILK)/src/SKP_Silk_decode_pulses.c \
    	$(SILK)/src/SKP_Silk_decoder_set_fs.c \
    	$(SILK)/src/SKP_Silk_detect_SWB_input.c \
    	$(SILK)/src/SKP_Silk_enc_API.c \
    	$(SILK)/src/SKP_Silk_encode_frame_FIX.c \
    	$(SILK)/src/SKP_Silk_encode_parameters.c \
    	$(SILK)/src/SKP_Silk_encode_parameters_v4.c \
    	$(SILK)/src/SKP_Silk_encode_pulses.c \
    	$(SILK)/src/SKP_Silk_find_LPC_FIX.c \
    	$(SILK)/src/SKP_Silk_find_LTP_FIX.c \
    	$(SILK)/src/SKP_Silk_find_pitch_lags_FIX.c \
    	$(SILK)/src/SKP_Silk_find_pred_coefs_FIX.c \
    	$(SILK)/src/SKP_Silk_gain_quant.c \
    	$(SILK)/src/SKP_Silk_init_encoder_FIX.c \
    	$(SILK)/src/SKP_Silk_inner_prod_aligned.c \
    	$(SILK)/src/SKP_Silk_interpolate.c \
    	$(SILK)/src/SKP_Silk_k2a.c \
    	$(SILK)/src/SKP_Silk_k2a_Q16.c \
    	$(SILK)/src/SKP_Silk_lin2log.c \
    	$(SILK)/src/SKP_Silk_log2lin.c \
    	$(SILK)/src/SKP_Silk_lowpass_int.c \
    	$(SILK)/src/SKP_Silk_lowpass_short.c \
    	$(SILK)/src/SKP_Silk_noise_shape_analysis_FIX.c \
    	$(SILK)/src/SKP_Silk_pitch_analysis_core.c \
    	$(SILK)/src/SKP_Silk_pitch_est_tables.c \
    	$(SILK)/src/SKP_Silk_prefilter_FIX.c \
    	$(SILK)/src/SKP_Silk_process_NLSFs_FIX.c \
    	$(SILK)/src/SKP_Silk_process_gains_FIX.c \
    	$(SILK)/src/SKP_Silk_pulses_to_bytes.c \
    	$(SILK)/src/SKP_Silk_quant_LTP_gains_FIX.c \
    	$(SILK)/src/SKP_Silk_range_coder.c \
    	$(SILK)/src/SKP_Silk_regularize_correlations_FIX.c \
    	$(SILK)/src/SKP_Silk_resample_1_2.c \
    	$(SILK)/src/SKP_Silk_resample_1_2_coarse.c \
    	$(SILK)/src/SKP_Silk_resample_1_2_coarsest.c \
    	$(SILK)/src/SKP_Silk_resample_1_3.c \
    	$(SILK)/src/SKP_Silk_resample_2_1_coarse.c \
    	$(SILK)/src/SKP_Silk_resample_2_3.c \
    	$(SILK)/src/SKP_Silk_resample_2_3_coarse.c \
    	$(SILK)/src/SKP_Silk_resample_2_3_coarsest.c \
    	$(SILK)/src/SKP_Silk_resample_2_3_rom.c \
    	$(SILK)/src/SKP_Silk_resample_3_1.c \
    	$(SILK)/src/SKP_Silk_resample_3_2.c \
    	$(SILK)/src/SKP_Silk_resample_3_2_rom.c \
    	$(SILK)/src/SKP_Silk_resample_3_4.c \
    	$(SILK)/src/SKP_Silk_resample_4_3.c \
    	$(SILK)/src/SKP_Silk_residual_energy16_FIX.c \
    	$(SILK)/src/SKP_Silk_residual_energy_FIX.c \
    	$(SILK)/src/SKP_Silk_scale_copy_vector16.c \
    	$(SILK)/src/SKP_Silk_scale_vector.c \
    	$(SILK)/src/SKP_Silk_schur.c \
    	$(SILK)/src/SKP_Silk_schur64.c \
    	$(SILK)/src/SKP_Silk_shell_coder.c \
    	$(SILK)/src/SKP_Silk_sigm_Q15.c \
    	$(SILK)/src/SKP_Silk_solve_LS_FIX.c \
    	$(SILK)/src/SKP_Silk_sort.c \
    	$(SILK)/src/SKP_Silk_sum_sqr_shift.c \
    	$(SILK)/src/SKP_Silk_tables_LTP.c \
    	$(SILK)/src/SKP_Silk_tables_NLSF_CB0_10.c \
    	$(SILK)/src/SKP_Silk_tables_NLSF_CB0_16.c \
    	$(SILK)/src/SKP_Silk_tables_NLSF_CB1_10.c \
    	$(SILK)/src/SKP_Silk_tables_NLSF_CB1_16.c \
    	$(SILK)/src/SKP_Silk_tables_gain.c \
    	$(SILK)/src/SKP_Silk_tables_other.c \
    	$(SILK)/src/SKP_Silk_tables_pitch_lag.c \
    	$(SILK)/src/SKP_Silk_tables_pulses_per_block.c \
    	$(SILK)/src/SKP_Silk_tables_sign.c \
    	$(SILK)/src/SKP_Silk_tables_type_offset.c
    	
    LOCAL_ARM_MODE := arm
    LOCAL_CFLAGS = -O3 
    LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
    LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(SILK)/src $(LOCAL_PATH)/$(SILK)/interface
    include $(BUILD_STATIC_LIBRARY)
    
    
    include $(CLEAR_VARS)
    LOCAL_MODULE    := silk8_jni
    LOCAL_SRC_FILES := silk8_jni.cpp 
    LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(SILK)/src $(LOCAL_PATH)/$(SILK)/interface
    LOCAL_CFLAGS = -O3 
    LOCAL_STATIC_LIBRARIES :=  silkcommon
    LOCAL_ARM_MODE := arm
    LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
    include $(BUILD_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE    := silk16_jni
    LOCAL_SRC_FILES := silk16_jni.cpp 
    LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(SILK)/src $(LOCAL_PATH)/$(SILK)/interface
    LOCAL_CFLAGS = -O3 
    LOCAL_STATIC_LIBRARIES :=  silkcommon
    LOCAL_ARM_MODE := arm
    LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
    include $(BUILD_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE    := silk24_jni
    LOCAL_SRC_FILES := silk24_jni.cpp 
    LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(SILK)/src $(LOCAL_PATH)/$(SILK)/interface
    LOCAL_CFLAGS = -O3 
    LOCAL_STATIC_LIBRARIES :=  silkcommon
    LOCAL_ARM_MODE := arm
    LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
    include $(BUILD_SHARED_LIBRARY)


           5、创建JNI包装类silk8_jni.cpp、silk16_jni.cpp、silk24_jni.cpp,用来调用Silk中的C代码函数,编辑内容如下

          silk8_jni.cpp:

        

    #include <jni.h>
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    
    /* Define codec specific settings */
    #define MAX_BYTES_ENC_PER_FRAME     250 // Equals peak bitrate of 100 kbps 
    #define MAX_BYTES_DEC_PER_FRAME     1024
    
    #define MAX_INPUT_FRAMES        5
    #define MAX_LBRR_DELAY          2
    #define MAX_FRAME_LENGTH        480
    
    #define	MAX_FRAME			160
    
    #include <android/log.h> 
    
    #define LOG_TAG "silk" // text for log tag 
    
    #include "SKP_Silk_SDK_API.h"
    #include "SKP_Silk_SigProc_FIX.h"
    
    #undef DEBUG_SILK8
    
    // the header length of the RTP frame (must skip when en/decoding)
    #define	RTP_HDR_SIZE	12
    
    static int codec_open = 0;
    
    static JavaVM *gJavaVM;
    const char *kInterfacePath = "org/sipdroid/pjlib/silk8";
    
    /* encoder parameters */
    
        SKP_int32 encSizeBytes;
        void      *psEnc;
    
        /* default settings */
        SKP_int   fs_kHz = 8;
        SKP_int   targetRate_bps = 20000;
        SKP_int   packetSize_ms = 20;
        SKP_int   frameSizeReadFromFile_ms = 20;
        SKP_int   packetLoss_perc = 0, smplsSinceLastPacket;
        SKP_int   INBandFec_enabled = 0, DTX_enabled = 0, quiet = 0;
        SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder
            
    
    /* decoder parameters */
    
        jbyte payloadToDec[    MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
        jshort out[ ( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ], *outPtr;
        SKP_int32 decSizeBytes;
        void      *psDec;
        SKP_SILK_SDK_DecControlStruct DecControl;
    
    extern "C"
    JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK8_open
      (JNIEnv *env, jobject obj, jint compression) {
    	int ret;
    
    	if (codec_open++ != 0)
    		return (jint)0;
    
    	/* Set the samplingrate that is requested for the output */
        DecControl.sampleRate = 8000;
    		
        /* Create decoder */
        ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );		
        }
    #ifdef DEBUG_SILK8
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "### INIT Decoder decSizeBytes = %d\n", decSizeBytes); 		
    #endif	
        psDec = malloc( decSizeBytes );
    
        /* Reset decoder */
        ret = SKP_Silk_SDK_InitDecoder( psDec );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_InitDecoder returned %d", ret );	
        }
    
    
        /* Create Encoder */
        ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_SDK_Get_Encoder_Size returned %d", ret );	
        }
    #ifdef DEBUG_SILK8
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "### INIT Encoder encSizeBytes = %d\n", encSizeBytes); 		
    #endif		
        psEnc = malloc( encSizeBytes );
        
        /* Reset Encoder */
        ret = SKP_Silk_SDK_InitEncoder( psEnc, &encControl );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_SDK_InitEncoder returned %d", ret );	
    	}
        
        /* Set Encoder parameters */
        encControl.sampleRate           = fs_kHz * 1000;
        encControl.packetSize           = packetSize_ms * fs_kHz;
        encControl.packetLossPercentage = packetLoss_perc;
        encControl.useInBandFEC         = INBandFec_enabled;
        encControl.useDTX               = DTX_enabled;
        encControl.complexity           = compression;
        encControl.bitRate              = targetRate_bps;		
    	
    	return (jint)0;
    }
    
    void Print_Decode_Error_Msg(int errcode) {
    	switch (errcode) {
    		case SKP_SILK_DEC_WRONG_SAMPLING_FREQUENCY:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nOutput sampling frequency lower than internal decoded sampling frequency\n", errcode);
    			break;
    		case SKP_SILK_DEC_PAYLOAD_TOO_LARGE:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nPayload size exceeded the maximum allowed 1024 bytes\n", errcode); 
    			break;
    		case SKP_SILK_DEC_PAYLOAD_ERROR:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nPayload has bit errors\n", errcode); 
    			break;			
    	}
    }
    
    void Print_Encode_Error_Msg(int errcode) {
    	switch (errcode) {
    		case SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nInput length is not a multiplum of 10 ms, or length is longer than the packet length\n", errcode);
    			break;
    		case SKP_SILK_ENC_FS_NOT_SUPPORTED:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nSampling frequency not 8000, 12000, 16000 or 24000 Hertz \n", errcode); 
    			break;
    		case SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nPacket size not 20, 40, 60, 80 or 100 ms\n", errcode); 
    			break;			
    		case SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nAllocated payload buffer too short \n", errcode);
    			break;
    		case SKP_SILK_ENC_WRONG_LOSS_RATE:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nLoss rate not between 0 and 100 percent\n", errcode); 
    			break;
    		case SKP_SILK_ENC_WRONG_COMPLEXITY_SETTING:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nComplexity setting not valid, use 0, 1 or 2\n", errcode); 
    			break;		
    		case SKP_SILK_ENC_WRONG_INBAND_FEC_SETTING:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nInband FEC setting not valid, use 0 or 1\n", errcode);
    			break;
    		case SKP_SILK_ENC_WRONG_DTX_SETTING:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nDTX setting not valid, use 0 or 1\n", errcode); 
    			break;
    		case SKP_SILK_ENC_INTERNAL_ERROR:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nInternal encoder error\n", errcode); 
    			break;				
    	}
    }
    
    extern "C"
    JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK8_encode
        (JNIEnv *env, jobject obj, jshortArray lin, jint offset, jbyteArray encoded, jint size) {
    
        jbyte	  enc_payload[ MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES ];
        jshort    in[ MAX_FRAME_LENGTH * MAX_INPUT_FRAMES ];	
    	int ret,i,frsz=MAX_FRAME;
    	SKP_int16 nBytes;
    	unsigned int lin_pos = 0;
    	
    	if (!codec_open)
    		return 0;
    		
    #ifdef DEBUG_SILK8
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "encoding frame size: %d\toffset: %d\n", size, offset); 		
    #endif
    
    
    	for (i = 0; i < size; i+=MAX_FRAME) {
    #ifdef DEBUG_SILK8
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "encoding frame size: %d\toffset: %d i: %d\n", size, offset, i); 		
    #endif
    			
    		env->GetShortArrayRegion(lin, offset + i,frsz, in);
            /* max payload size */
            nBytes = MAX_BYTES_ENC_PER_FRAME * MAX_INPUT_FRAMES;
    
            ret = SKP_Silk_SDK_Encode( psEnc, &encControl, in, (SKP_int16)frsz, (SKP_uint8 *)enc_payload, &nBytes );
            if( ret ) {
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!! SKP_Silk_Encode returned: %d\n", ret);
    			Print_Encode_Error_Msg(ret);				
                break;
            }
    #ifdef DEBUG_SILK8
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"Enocded nBytes: %d\n", nBytes); 		
    #endif		
            /* Write payload */		
    		env->SetByteArrayRegion(encoded, RTP_HDR_SIZE+ lin_pos, nBytes, enc_payload);
    		lin_pos += nBytes;
    	}
    #ifdef DEBUG_SILK8
    	__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
            "encoding **END** frame size: %d\toffset: %d i: %d lin_pos: %d\n", size, offset, i, lin_pos);
    #endif		
    
        return (jint)lin_pos;
    }
    
    extern "C"
    JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK8_decode
        (JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) {
    
        jbyte buffer [MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
        jshort output_buffer[( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ];
    //	SKP_int16	*outPtr;
    
    	int ret;
    	SKP_int16 len;
    //	int	tot_len,frames;
    
    	if (!codec_open)
    		return 0;
    
    #ifdef DEBUG_SILK8		
    	__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
            "##### BEGIN DECODE ********  decoding frame size: %d\n", size); 	
    #endif
    
    	env->GetByteArrayRegion(encoded, RTP_HDR_SIZE, size, buffer);
    
    //	outPtr = output_buffer;
    //    tot_len = 0;
    //	frames = 0;
    
    //	do {
    		ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0,(SKP_uint8 *) buffer, size, output_buffer,&len );
    		if( ret ) {
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!! SKP_Silk_SDK_Decode returned: %d\n", ret); 	
    			Print_Decode_Error_Msg(ret);
    		}
    #ifdef DEBUG_SILK8		
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    			"##### DECODED length: %d\n\t Frame #: %d", len); 	
    #endif
    //		frames++;
    //		outPtr  += len;
    //		tot_len += len;		
    	
    //	} while( DecControl.moreInternalDecoderFrames );
    
    	env->SetShortArrayRegion(lin, 0, len,output_buffer);
    	return (jint)len;
    }
    
    extern "C"
    JNIEXPORT void JNICALL Java_com_trunkbow_silk_SILK8_close
        (JNIEnv *env, jobject obj) {
    
    	if (--codec_open != 0)
    		return;
        /* Free decoder */
        free( psDec );
        /* Free Encoder */
        free( psEnc );
    }


          silk_16.cpp:

          

    #include <jni.h>
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    
    /* Define codec specific settings */
    #define MAX_BYTES_ENC_PER_FRAME     250 // Equals peak bitrate of 100 kbps 
    #define MAX_BYTES_DEC_PER_FRAME     1024
    
    #define MAX_INPUT_FRAMES        5
    #define MAX_LBRR_DELAY          2
    #define MAX_FRAME_LENGTH        480
    
    #define	MAX_FRAME			320
    
    #include <android/log.h> 
    
    #define LOG_TAG "silk" // text for log tag 
    
    #include "SKP_Silk_SDK_API.h"
    #include "SKP_Silk_SigProc_FIX.h"
    
    #undef DEBUG_SILK16
    
    // the header length of the RTP frame (must skip when en/decoding)
    #define	RTP_HDR_SIZE	12
    
    static int codec_open = 0;
    
    static JavaVM *gJavaVM;
    const char *kInterfacePath = "org/sipdroid/pjlib/silk16";
    
    /* encoder parameters */
    
        SKP_int32 encSizeBytes;
        void      *psEnc;
    
        /* default settings */
        SKP_int   fs_kHz = 16;
        SKP_int   targetRate_bps = 20000;
        SKP_int   packetSize_ms = 20;
        SKP_int   frameSizeReadFromFile_ms = 20;
        SKP_int   packetLoss_perc = 0, smplsSinceLastPacket;
        SKP_int   INBandFec_enabled = 0, DTX_enabled = 0, quiet = 0;
        SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder
            
    
    /* decoder parameters */
    
        jbyte payloadToDec[    MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
        jshort out[ ( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ], *outPtr;
        SKP_int32 decSizeBytes;
        void      *psDec;
        SKP_SILK_SDK_DecControlStruct DecControl;
    
    extern "C"
    JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK16_open
      (JNIEnv *env, jobject obj, jint compression) {
    	int ret;
    
    	if (codec_open++ != 0)
    		return (jint)0;
    
    	/* Set the samplingrate that is requested for the output */
        DecControl.sampleRate = 16000;
    		
        /* Create decoder */
        ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );		
        }
    #ifdef DEBUG_SILK16
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "### INIT Decoder decSizeBytes = %d\n", decSizeBytes); 		
    #endif	
        psDec = malloc( decSizeBytes );
    
        /* Reset decoder */
        ret = SKP_Silk_SDK_InitDecoder( psDec );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_InitDecoder returned %d", ret );	
        }
    
    
        /* Create Encoder */
        ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_SDK_Get_Encoder_Size returned %d", ret );	
        }
    #ifdef DEBUG_SILK16
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "### INIT Encoder encSizeBytes = %d\n", encSizeBytes); 		
    #endif		
        psEnc = malloc( encSizeBytes );
        
        /* Reset Encoder */
        ret = SKP_Silk_SDK_InitEncoder( psEnc, &encControl );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_SDK_InitEncoder returned %d", ret );	
    	}
        
        /* Set Encoder parameters */
        encControl.sampleRate           = fs_kHz * 1000;
        encControl.packetSize           = packetSize_ms * fs_kHz;
        encControl.packetLossPercentage = packetLoss_perc;
        encControl.useInBandFEC         = INBandFec_enabled;
        encControl.useDTX               = DTX_enabled;
        encControl.complexity           = compression;
        encControl.bitRate              = targetRate_bps;		
    	
    	return (jint)0;
    }
    
    void Print_Decode_Error_Msg(int errcode) {
    	switch (errcode) {
    		case SKP_SILK_DEC_WRONG_SAMPLING_FREQUENCY:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nOutput sampling frequency lower than internal decoded sampling frequency\n", errcode);
    			break;
    		case SKP_SILK_DEC_PAYLOAD_TOO_LARGE:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nPayload size exceeded the maximum allowed 1024 bytes\n", errcode); 
    			break;
    		case SKP_SILK_DEC_PAYLOAD_ERROR:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nPayload has bit errors\n", errcode); 
    			break;			
    	}
    }
    
    void Print_Encode_Error_Msg(int errcode) {
    	switch (errcode) {
    		case SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nInput length is not a multiplum of 10 ms, or length is longer than the packet length\n", errcode);
    			break;
    		case SKP_SILK_ENC_FS_NOT_SUPPORTED:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nSampling frequency not 8000, 12000, 16000 or 24000 Hertz \n", errcode); 
    			break;
    		case SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nPacket size not 20, 40, 60, 80 or 100 ms\n", errcode); 
    			break;			
    		case SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nAllocated payload buffer too short \n", errcode);
    			break;
    		case SKP_SILK_ENC_WRONG_LOSS_RATE:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nLoss rate not between 0 and 100 percent\n", errcode); 
    			break;
    		case SKP_SILK_ENC_WRONG_COMPLEXITY_SETTING:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nComplexity setting not valid, use 0, 1 or 2\n", errcode); 
    			break;		
    		case SKP_SILK_ENC_WRONG_INBAND_FEC_SETTING:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nInband FEC setting not valid, use 0 or 1\n", errcode);
    			break;
    		case SKP_SILK_ENC_WRONG_DTX_SETTING:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nDTX setting not valid, use 0 or 1\n", errcode); 
    			break;
    		case SKP_SILK_ENC_INTERNAL_ERROR:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nInternal encoder error\n", errcode); 
    			break;				
    	}
    }
    
    extern "C"
    JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK16_encode
        (JNIEnv *env, jobject obj, jshortArray lin, jint offset, jbyteArray encoded, jint size) {
    
        jbyte	  enc_payload[ MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES ];
        jshort    in[ MAX_FRAME_LENGTH * MAX_INPUT_FRAMES ];	
    	int ret,i,frsz=MAX_FRAME;
    	SKP_int16 nBytes;
    	unsigned int lin_pos = 0;
    	
    	if (!codec_open)
    		return 0;
    		
    #ifdef DEBUG_SILK16
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "encoding frame size: %d\toffset: %d\n", size, offset); 		
    #endif
    
    
    	for (i = 0; i < size; i+=MAX_FRAME) {
    #ifdef DEBUG_SILK16
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "encoding frame size: %d\toffset: %d i: %d\n", size, offset, i); 		
    #endif
    			
    		env->GetShortArrayRegion(lin, offset + i,frsz, in);
            /* max payload size */
            nBytes = MAX_BYTES_ENC_PER_FRAME * MAX_INPUT_FRAMES;
    
            ret = SKP_Silk_SDK_Encode( psEnc, &encControl, in, (SKP_int16)frsz, (SKP_uint8 *)enc_payload, &nBytes );
            if( ret ) {
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!! SKP_Silk_Encode returned: %d\n", ret);
    			Print_Encode_Error_Msg(ret);					
                break;
            }
    #ifdef DEBUG_SILK16
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"Enocded nBytes: %d\n", nBytes); 		
    #endif		
            /* Write payload */		
    		env->SetByteArrayRegion(encoded, RTP_HDR_SIZE+ lin_pos, nBytes, enc_payload);
    		lin_pos += nBytes;
    	}
    #ifdef DEBUG_SILK16
    	__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
            "encoding **END** frame size: %d\toffset: %d i: %d lin_pos: %d\n", size, offset, i, lin_pos);
    #endif		
    
        return (jint)lin_pos;
    }
    
    extern "C"
    JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK16_decode
        (JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) {
    
        jbyte buffer [MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
        jshort output_buffer[( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ];
    //	SKP_int16	*outPtr;
    
    	int ret;
    	SKP_int16 len;
    //	int	tot_len,frames;
    
    	if (!codec_open)
    		return 0;
    
    #ifdef DEBUG_SILK16		
    	__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
            "##### BEGIN DECODE ********  decoding frame size: %d\n", size); 	
    #endif
    
    	env->GetByteArrayRegion(encoded, RTP_HDR_SIZE, size, buffer);
    
    //	outPtr = output_buffer;
    //    tot_len = 0;
    //	frames = 0;
    
    //	do {
    		ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0,(SKP_uint8 *) buffer, size, output_buffer,&len );
    		if( ret ) {
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!! SKP_Silk_SDK_Decode returned: %d\n", ret); 	
    			Print_Decode_Error_Msg(ret);
    		}
    #ifdef DEBUG_SILK16		
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    			"##### DECODED length: %d\n\t Frame #: %d", len); 	
    #endif
    //		frames++;
    //		outPtr  += len;
    //		tot_len += len;		
    	
    //	} while( DecControl.moreInternalDecoderFrames );
    
    	env->SetShortArrayRegion(lin, 0, len,output_buffer);
    	return (jint)len;
    }
    
    extern "C"
    JNIEXPORT void JNICALL Java_com_trunkbow_silk_SILK16_close
        (JNIEnv *env, jobject obj) {
    
    	if (--codec_open != 0)
    		return;
        /* Free decoder */
        free( psDec );
        /* Free Encoder */
        free( psEnc );
    }
    


             silk24_jni.cpp

            

    #include <jni.h>
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    
    /* Define codec specific settings */
    #define MAX_BYTES_ENC_PER_FRAME     250 // Equals peak bitrate of 100 kbps 
    #define MAX_BYTES_DEC_PER_FRAME     1024
    
    #define MAX_INPUT_FRAMES        5
    #define MAX_LBRR_DELAY          2
    #define MAX_FRAME_LENGTH        480
    
    #define	MAX_FRAME			480
    
    #include <android/log.h> 
    
    #define LOG_TAG "silk" // text for log tag 
    
    #include "SKP_Silk_SDK_API.h"
    #include "SKP_Silk_SigProc_FIX.h"
    
    #undef DEBUG_SILK24
    
    // the header length of the RTP frame (must skip when en/decoding)
    #define	RTP_HDR_SIZE	12
    
    static int codec_open = 0;
    
    static JavaVM *gJavaVM;
    const char *kInterfacePath = "org/sipdroid/pjlib/SILK24";
    
    /* encoder parameters */
    
        SKP_int32 encSizeBytes;
        void      *psEnc;
    
        /* default settings */
        SKP_int   fs_kHz = 24;
        SKP_int   targetRate_bps = 20000;
        SKP_int   packetSize_ms = 20;
        SKP_int   frameSizeReadFromFile_ms = 20;
        SKP_int   packetLoss_perc = 0, smplsSinceLastPacket;
        SKP_int   INBandFec_enabled = 0, DTX_enabled = 0, quiet = 0;
        SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder
            
    
    /* decoder parameters */
    
        jbyte payloadToDec[    MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
        jshort out[ ( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ], *outPtr;
        SKP_int32 decSizeBytes;
        void      *psDec;
        SKP_SILK_SDK_DecControlStruct DecControl;
    
    extern "C"
    JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK24_open
      (JNIEnv *env, jobject obj, jint compression) {
    	int ret;
    
    	if (codec_open++ != 0)
    		return (jint)0;
    
    	/* Set the samplingrate that is requested for the output */
        DecControl.sampleRate = 24000;
    		
        /* Create decoder */
        ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );		
        }
    #ifdef DEBUG_SILK24
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "### INIT Decoder decSizeBytes = %d\n", decSizeBytes); 		
    #endif	
        psDec = malloc( decSizeBytes );
    
        /* Reset decoder */
        ret = SKP_Silk_SDK_InitDecoder( psDec );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_InitDecoder returned %d", ret );	
        }
    
    
        /* Create Encoder */
        ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_SDK_Get_Encoder_Size returned %d", ret );	
        }
    #ifdef DEBUG_SILK24
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "### INIT Encoder encSizeBytes = %d\n", encSizeBytes); 		
    #endif		
        psEnc = malloc( encSizeBytes );
        
        /* Reset Encoder */
        ret = SKP_Silk_SDK_InitEncoder( psEnc, &encControl );
        if( ret ) {
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "\n!!!!!!!! SKP_Silk_SDK_InitEncoder returned %d", ret );	
    	}
        
        /* Set Encoder parameters */
        encControl.sampleRate           = fs_kHz * 1000;
        encControl.packetSize           = packetSize_ms * fs_kHz;
        encControl.packetLossPercentage = packetLoss_perc;
        encControl.useInBandFEC         = INBandFec_enabled;
        encControl.useDTX               = DTX_enabled;
        encControl.complexity           = compression;
        encControl.bitRate              = targetRate_bps;		
    	
    	return (jint)0;
    }
    
    void Print_Decode_Error_Msg(int errcode) {
    	switch (errcode) {
    		case SKP_SILK_DEC_WRONG_SAMPLING_FREQUENCY:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nOutput sampling frequency lower than internal decoded sampling frequency\n", errcode);
    			break;
    		case SKP_SILK_DEC_PAYLOAD_TOO_LARGE:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nPayload size exceeded the maximum allowed 1024 bytes\n", errcode); 
    			break;
    		case SKP_SILK_DEC_PAYLOAD_ERROR:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nPayload has bit errors\n", errcode); 
    			break;			
    	}
    }
    
    void Print_Encode_Error_Msg(int errcode) {
    	switch (errcode) {
    		case SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nInput length is not a multiplum of 10 ms, or length is longer than the packet length\n", errcode);
    			break;
    		case SKP_SILK_ENC_FS_NOT_SUPPORTED:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nSampling frequency not 8000, 12000, 16000 or 24000 Hertz \n", errcode); 
    			break;
    		case SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nPacket size not 20, 40, 60, 80 or 100 ms\n", errcode); 
    			break;			
    		case SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nAllocated payload buffer too short \n", errcode);
    			break;
    		case SKP_SILK_ENC_WRONG_LOSS_RATE:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nLoss rate not between 0 and 100 percent\n", errcode); 
    			break;
    		case SKP_SILK_ENC_WRONG_COMPLEXITY_SETTING:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nComplexity setting not valid, use 0, 1 or 2\n", errcode); 
    			break;		
    		case SKP_SILK_ENC_WRONG_INBAND_FEC_SETTING:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nInband FEC setting not valid, use 0 or 1\n", errcode);
    			break;
    		case SKP_SILK_ENC_WRONG_DTX_SETTING:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nDTX setting not valid, use 0 or 1\n", errcode); 
    			break;
    		case SKP_SILK_ENC_INTERNAL_ERROR:
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!!!!! Decode_Error_Message: %d\nInternal encoder error\n", errcode); 
    			break;				
    	}
    }
    
    extern "C"
    JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK24_encode
        (JNIEnv *env, jobject obj, jshortArray lin, jint offset, jbyteArray encoded, jint size) {
    
        jbyte	  enc_payload[ MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES ];
        jshort    in[ MAX_FRAME_LENGTH * MAX_INPUT_FRAMES ];	
    	int ret,i,frsz=MAX_FRAME;
    	SKP_int16 nBytes;
    	unsigned int lin_pos = 0;
    	
    	if (!codec_open)
    		return 0;
    		
    #ifdef DEBUG_SILK24
        __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "encoding frame size: %d\toffset: %d\n", size, offset); 		
    #endif
    
    
    	for (i = 0; i < size; i+=MAX_FRAME) {
    #ifdef DEBUG_SILK24
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
                "encoding frame size: %d\toffset: %d i: %d\n", size, offset, i); 		
    #endif
    			
    		env->GetShortArrayRegion(lin, offset + i,frsz, in);
            /* max payload size */
            nBytes = MAX_BYTES_ENC_PER_FRAME * MAX_INPUT_FRAMES;
    
            ret = SKP_Silk_SDK_Encode( psEnc, &encControl, in, (SKP_int16)frsz, (SKP_uint8 *)enc_payload, &nBytes );
            if( ret ) {
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!! SKP_Silk_Encode returned: %d\n", ret);
    			Print_Encode_Error_Msg(ret);				
                break;
            }
    #ifdef DEBUG_SILK24
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"Enocded nBytes: %d\n", nBytes); 		
    #endif		
            /* Write payload */		
    		env->SetByteArrayRegion(encoded, RTP_HDR_SIZE+ lin_pos, nBytes, enc_payload);
    		lin_pos += nBytes;
    	}
    #ifdef DEBUG_SILK24
    	__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
            "encoding **END** frame size: %d\toffset: %d i: %d lin_pos: %d\n", size, offset, i, lin_pos);
    #endif		
    
        return (jint)lin_pos;
    }
    
    extern "C"
    JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK24_decode
        (JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) {
    
        jbyte buffer [MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
        jshort output_buffer[( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ];
    //	SKP_int16	*outPtr;
    
    	int ret;
    	SKP_int16 len;
    //	int	tot_len,frames;
    
    	if (!codec_open)
    		return 0;
    
    #ifdef DEBUG_SILK24		
    	__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
            "##### BEGIN DECODE ********  decoding frame size: %d\n", size); 	
    #endif
    
    	env->GetByteArrayRegion(encoded, RTP_HDR_SIZE, size, buffer);
    
    //	outPtr = output_buffer;
    //    tot_len = 0;
    //	frames = 0;
    
    //	do {
    		ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0,(SKP_uint8 *) buffer, size, output_buffer,&len );
    		if( ret ) {
    			__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    				"!!!!!!!! SKP_Silk_SDK_Decode returned: %d\n", ret); 	
    			Print_Decode_Error_Msg(ret);
    		}
    #ifdef DEBUG_SILK24		
    		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, 
    			"##### DECODED length: %d\n\t Frame #: %d", len); 	
    #endif
    //		frames++;
    //		outPtr  += len;
    //		tot_len += len;		
    	
    //	} while( DecControl.moreInternalDecoderFrames );
    
    	env->SetShortArrayRegion(lin, 0, len,output_buffer);
    	return (jint)len;
    }
    
    extern "C"
    JNIEXPORT void JNICALL Java_com_trunkbow_silk_SILK24_close
        (JNIEnv *env, jobject obj) {
    
    	if (--codec_open != 0)
    		return;
        /* Free decoder */
        free( psDec );
        /* Free Encoder */
        free( psEnc );
    }
    


        

            6、在Java层创建Speex工具类,内容如下:

               Silk8.java:

            

    class SILK8{   
    	/* 
    	 *                 | fs (Hz) | BR (kbps)
    	 * ----------------+---------+---------
    	 * Narrowband	   | 8000    | 6 -20
    	 * Mediumband      | 12000   | 7 -25
    	 * Wideband        | 16000   | 8 -30
    	 * Super Wideband  | 24000   | 12 -40
    	 *
    	 * Table 1: fs specifies the audio sampling frequency in Hertz (Hz); BR
    	 * specifies the adaptive bit rate range in kilobits per second (kbps).
    	 * 
    	 * Complexity can be scaled to optimize for CPU resources in real-time,
    	 * mostly in trade-off to network bit rate. 0 is least CPU demanding and
    	 * highest bit rate. 
    	 */
    	private static final int DEFAULT_COMPLEXITY = 0;
    	
    	void load() {
    		 System.loadLibrary("silk8_jni");
    	}  
     
    	public native int open(int compression);
    	public native int decode(byte encoded[], short lin[], int size);
    	public native int encode(short lin[], int offset, byte encoded[], int size);
    	public native void close();
    }
    


             Silk16.java:

    class SILK16 { 
    	/* 
    	 *                 | fs (Hz) | BR (kbps)
    	 * ----------------+---------+---------
    	 * Narrowband	   | 8000    | 6 -20
    	 * Mediumband      | 12000   | 7 -25
    	 * Wideband        | 16000   | 8 -30
    	 * Super Wideband  | 24000   | 12 -40
    	 *
    	 * Table 1: fs specifies the audio sampling frequency in Hertz (Hz); BR
    	 * specifies the adaptive bit rate range in kilobits per second (kbps).
    	 * 
    	 * Complexity can be scaled to optimize for CPU resources in real-time,
    	 * mostly in trade-off to network bit rate. 0 is least CPU demanding and
    	 * highest bit rate. 
    	 */
    	private static final int DEFAULT_COMPLEXITY = 0;
    
    
    	void load() {
    		System.loadLibrary("silk16_jni");
    	}  
     
    	public native int open(int compression);
    	public native int decode(byte encoded[], short lin[], int size);
    	public native int encode(short lin[], int offset, byte encoded[], int size);
    	public native void close();
    
    }
    


    Silk24.java:

    class SILK24  { 
    	/* 
    	 *                 | fs (Hz) | BR (kbps)
    	 * ----------------+---------+---------
    	 * Narrowband	   | 8000    | 6 -20
    	 * Mediumband      | 12000   | 7 -25
    	 * Wideband        | 16000   | 8 -30
    	 * Super Wideband  | 24000   | 12 -40
    	 *
    	 * Table 1: fs specifies the audio sampling frequency in Hertz (Hz); BR
    	 * specifies the adaptive bit rate range in kilobits per second (kbps).
    	 * 
    	 * Complexity can be scaled to optimize for CPU resources in real-time,
    	 * mostly in trade-off to network bit rate. 0 is least CPU demanding and
    	 * highest bit rate. 
    	 */
    	private static final int DEFAULT_COMPLEXITY = 0;
    
    	void load() {
    		System.loadLibrary("silk24_jni");
    	}  
     
    	public native int open(int compression);
    	public native int decode(byte encoded[], short lin[], int size);
    	public native int encode(short lin[], int offset, byte encoded[], int size);
    	public native void close();
    
    }
    


               7、使用cygwin编译,生成so文件。       


      ***********************************************************************

      * 转载务必在明显处注明:http://blog.csdn.net/xyz_lmn    *

      * 作者:张兴业                                                                                           *

      * 邮箱:xy-zhang@163.com                                                                   *

      ***********************************************************************


    参考:http://developer.skype.com/silk

    http://blog.csdn.net/wanggp_2007/article/details/5540686    Skype SILK vs. iLBC vs. Speex


    /**
    * @author 张兴业
    *  iOS入门群:83702688
    *  android开发进阶群:241395671
    *  我的新浪微博:@张兴业TBOW
    */

          

      ***********************************************************************

      * 转载务必在明显处注明:http://blog.csdn.net/xyz_lmn    *

      * 作者:张兴业                                                                                           *

      * 邮箱:xy-zhang#163.com                                                                   *

      ***********************************************************************

    展开全文
  • SILK SPYPE 语音编解码

    2020-07-15 23:34:45
    SILK SPYPE 语音编解码 源码
  • OPUS是由Silk和CELT两个编码器组成的,用来处理全频带的语音和音乐信号,OPUS在集成Silk的时候,对Silk的一些细节做了改动,这里简单整理一下OPUS中的Silk模块和纯的Silk编解码器的不同之处。一、预测部分:计算逻辑...
        

    OPUS是由Silk和CELT两个编码器组成的,用来处理全频带的语音和音乐信号,OPUS在集成Silk的时候,对Silk的一些细节做了改动,这里简单整理一下OPUS中的Silk模块和纯的Silk编解码器的不同之处。
    一、预测部分:计算逻辑上来看,二者是相同的。不同之处有:
    1、OPUS的整体计算精度更高一些,由Silk里的Q10转换成了Q14后进行判断,包括LPC、LTP和excition部分。
    2、在做Delaydecision的时候,OPUS中对判断算法进行了重写,增加了一个quantoffset,重新规划了量化的范围,这里和Silk比较,带来的MOS分增益我自己测的是大约在0.05左右,不一定准确。
    3、OPUS是使用SHIFT_ROUND将Q10转化成了Q0传入到编码模块,Silk使用的是SHIFT方法,两者的不同之处在于,SHIFT_ROUND会将[-512,512]的值都转化为0,而SHIFT的置零区间为[0,1024],这里使用不同的SHIFT算法会影响到后续编码激励时分配的码率。
    4、OPUS的Delaydecision默认是计算40个采样点的总误差,Silk是32个,这两个我试了一下对MOS分的影响基本没有。
    5、OPUS通过调整计算步骤,加新的参数(如delayedgain和diff等)等方法,减少了少量计算量。
    二、编码部分:
    1、OPUS中的编码模块由依赖Silk中的概率密度函数转成了逆概率密度函数,我这里也不清楚做这种改动的原因,从结果上来看,使用CDF和iCDF的编码效率是差不多的。
    2、OPUS将编码index和excition的函数区分开了,但函数的实现及各个参数的编码顺序是相同的。Silk的编码函数都在了一起显得有点拥挤,也不太方便后续自己开发。
    三、其余部分:
    1、增益计算部分,OPUS在较多函数里使用的是Q7,Silk使用的是Q0,从代码上来看OPUS对增益的控制能稍微准一些
    2、OPUS的码率控制算法进行了重写,但总体逻辑是一样的,我个人感觉OPUS的码率控制更为激进一点
    3、OPUS的抖动算法中Seed的判断方法也改变了,OPUS中通过判断Seed是否小于0进行符号的转换,Silk通过把Seed右移31位后做异或后自减进行判断,其实这两种方法的结果是一样的,只是表现方法不一样。
    先写到这里吧,以后有想起来的再补充。

    展开全文
  • silk与opencore-amr编码对比 ...silk编解码后 最新测试结果 两个编码器在PCM声音源比较清晰的情况下,压缩率比较高。 最终测试结果是SILK的压缩率高于AMR 两个编码器在数据压缩之后传输都低于 ...

    silk与opencore-amr编码对比

    在采样率8000 单声道 16位采样精度情况下

    silk的压缩率为 1/15 opencore-amr 1/17

    对比图

    原始的音频编码

    638421-20161105221225643-746731258.png

    opencore-amr编解码后

    638421-20161105221302658-1551284931.png

    silk编解码后

    638421-20161105221325533-1884032124.png

    最新测试结果

    两个编码器在PCM声音源比较清晰的情况下,压缩率比较高。

    最终测试结果是SILK的压缩率高于AMR

    两个编码器在数据压缩之后传输都低于 1k/s

    转载于:https://www.cnblogs.com/QUSIR/p/6034221.html

    展开全文
  • Android JNI 调用 Silk 音频编解码包,采用现在Skepe官网上最新的1.09版修改为成,可以使用Cygwin编译即可产生.so文件,供大家使用
  • 谈起 Opus,对于编解码器有所了解的同学也许会知道,Opus 是由两个编解码器——Silk 和 Celt 融合而成。为什么来自两个组织的编解码器会合二为一,Opus 的性能又如何,本文将简述一下 Opus 的前世今生和部分技术分析...
    作者:赵晓涵,声网 Agora 音频算法工程师。原文首发于 RTC 开发者社区

    谈起 Opus,对于编解码器有所了解的同学也许会知道,Opus 是由两个编解码器——Silk 和 Celt 融合而成。为什么来自两个组织的编解码器会合二为一,Opus 的性能又如何,本文将简述一下 Opus 的前世今生和部分技术分析。

    提到 Opus,就不得不提到它的主要作者,Jean Marc Valin,他从学生时代就开始致力于高音质编解码算法的实现,著名的编解码器 Speex 也是他的作品之一。时间回到2007年,Jean Marc Valin 在博士后期间,完成了 Speex 的开发。在当时,业内编解码器主要分为两个流派:高延时的音乐编解码器(如 MP3、AAC 和 Vorbis)和低延时的语音编解码器(AMR、Speex、G.729)。而工业界对低延时音乐编解码器的需求越来越高,于是 Celt 的开发也被提上了日程。Celt 的早期目标是实现 4-8ms 的编码延时,相比当时 MP3 和 AAC 编码的 100ms+ 延时,优势是非常巨大的。

    在研发过程中,Jean Marc Valin 和其他开发者始终围绕着 Vorbis 作者 Christopher “Monty” Montgomery 的意见“尽量保持信号能量谱的低失真”进行开发,这也是 Celt(Constrained Energy Lapped Transform)名字的由来。第一版 Celt 的研发持续了两年,但因为需要保证低延时的原因,Celt 的表现并没有超过 MP3 和 AAC。但在经过了持续六个月的改进后(使用了部分 MP3 的技术),Celt 的表现第一次超过了 MP3。也就是在那个时候,Celt 逐渐走出实验室,迎来了它在工业界的第一批使用者–部分用户因为低延时的强需求不得不选择了 Celt。也就是这一批最早期的用户给了 Celt 的开发者们宝贵的反馈,使其不断改进 Celt。

    在开发 Celt 的同时,另一批来自 Skype,以 Koen Vos 为首的开发者开发了业内领先的语音编解码器 Silk,并将其提交至 IETF,作为一款免版税的开源编解码器。Celt 也紧随 Silk 的步伐进行了提交。但 Silk 和 Celt 都遭遇了很大的阻力,这个阻力的来源更多的不是技术因素,而是『政治』因素:此前有大量投资者投资了带版税的编解码器,这些投资者在业内的权威也很大。正是这些阻力促使 Silk 和 Celt 结合到一起,诞生了 Opus。在 Opus 里,Silk 主要负责处理 16khz 及 8khz 的信号,而 Celt 则能处理 8khz 以上的信号。实际上,关于 Opus 里 Silk 和 Celt 的工作模式并不仅仅这么简单,Opus 里共有 32 种模式用来处理不同种类的信号。Opus编解码器架构如下。

    编码器:


    解码器:


    为了和 Silk 结合,Celt 做出了一定的改动。之前 Celt 为了极低延时,把帧长设置的比较短,但 Silk 需要 20ms 的帧长,于是 Celt 牺牲了部分延时和 Silk 的帧长对齐,但仍能把整体延时控制在 10ms。Opus 诞生后又经过了很多改进,关键的改进来自于 Broadcom 提供的一种滤波器,这个滤波器在编码端和解码端各有一个。在编码端,前置滤波器可以保留音乐信号的低频部分,减弱高频部分,这样就可以更高效的去编码;在解码端,后置滤波器可以近乎无损的把被减弱的高频恢复出来。这种前置-后置滤波器结合上述拉长到 20ms 的帧长,Opus 第一次在音乐音质和压缩率上超过了 HE-AAC。这对于 Opus 来说是一个非常重要的节点,因为这代表着 Opus 在语音、音乐、复杂度和延时上有了全面超越其他编解码器的能力。

    而融合进 Opus 的 Silk 模块改动则不是很大,主要的改动点都是非常小的细节,我简单整理了一些,如下所示:

    一、线性预测部分:二者的计算逻辑是相同的。不同之处有:

    1. OPUS 的整体计算精度更高一些,由 Silk 里的 Q10 转换成了 Q14 后进行判断,包括短时预测、长时预测和激励部分。
    2. 在做 Delaydecision(一种延时选择算法,可以令标量量化拥有近似矢量量化的效率)的时候,OPUS 中对判断算法进行了重写,增加了一个 quantoffset 参数并重新规划了量化的范围,这里和 Silk 比较,带来的 MOS 分增益,我自己测的是大约在 0.05 左右(少量样本测试,不一定准确,仅供参考)。
    3. OPUS 的 Delaydecision 模块默认是计算 40 个采样点的总误差,Silk 是 32 个,选择的采样点越多,误差越小,但延时会越大,这两个我试了一下对 MOS 分的影响基本没有,。
    4. 在编码时,OPUS 使用 SHIFT_ROUND 将 Q10 转化成了 Q0 传入到编码模块,Silk 使用的是 SHIFT 方法,两者的不同之处在于,SHIFT_ROUND 会将 [-512,512] 的值都转化为 0,而 SHIFT 的置零区间为 [0,1024],这里使用不同的 SHIFT 算法会影响到后续编码激励时分配的码率。
    5. OPUS 通过调整计算步骤,增加新参数(如 delayedgain 和 diff 等)等方法,减少了少量计算量。

    二、编码部分:

    1. OPUS 中的编码模块由依赖Silk中的概率密度函数 CDF 转成了逆概率密度函数 iCDF,尚不清楚做这种改动的原因,从结果上来看,使用 CDF 和 iCDF 的编码效率是差不多的。
    2. OPUS 将编码 index 和 excition 的函数区分开了,但函数的实现及各个参数的编码顺序和 Silk 是相同的,总的来说,这是一个关于模块化的改进。

    三、其余部分:

    1. 增益计算部分,OPUS 在较多函数里使用的是 Q7,Silk 使用的是 Q0,因此 OPUS 对增益的控制能稍微准一些。
    2. OPUS 对码率控制算法进行了重写,但总体逻辑和 Silk 是相同的,个人认为 OPUS 的码率控制更为激进一点,压得狠,放的快。
    3. OPUS 的抖动算法中 Seed 的判断方法也改变了,OPUS 中通过判断 Seed 是否小于 0 进行符号的转换,Silk 通过把 Seed 右移 31 位后做异或后自减进行判断,其实这两种方法的结果是完全一样的,只是方式一的计算量更小。

    Silk 和 Celt 整合到一起后,经过各方努力,Opus 在 2012 年作为免版税的开源编解码器成为了 IETF 的标准。也就是在差不多那个时候,WebRTC 也成为了 IETF 在 Web 通信上的标准,而 Opus 凭借其卓越的性能成为了 WebRTC 的内置编解码器。一直到今天,Opus 仍在不断发布版本,就在前不久,Opus 发布了 Opus 1.3.1。从发版趋势可以看出,Opus 也在拥抱 AI 化。

    目前 Opus 里和 AI 相关的技术有两个:基于 RNN 的语音音乐分类器和一个附加的基于 RNN 的降噪模块(这个降噪模块目前并不在 Opus 本身的代码里,但不排除以后会和 Speex 一样,把信号处理模块耦合进编解码器)。

    从 Opus 的诞生和发展历程可以看出,任何产品做到极致都需要付出不懈的努力和漫长的打磨时间,尤其是在创新领域,其路漫漫,道阻且长,各位同学一起加油吧。

    展开全文
  • 各种音视频编解码学习详解  编解码学习笔记(一):基本概念   媒体业务是网络的主要业务之间。尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析、...
  • 最近在研究音视频编解码这一块儿,看到@bitbit大神写的【各种音视频编解码学习详解】这篇文章,非常感谢,佩服的五体投地。奈何大神这边文章太长,在这里我把它分解很多小的篇幅,方便阅读。大神博客传送门:...
  • 编解码学习笔记二codec类型编解码学习笔记三Mpeg系列Mpeg 1和Mpeg 2编解码学习笔记四Mpeg系列Mpeg 4编解码学习笔记五Mpeg系列AAC音频编解码学习笔记六H26x系列编解码学习笔记七微软Windows Media系列编解码学习笔记...
  • 视频编解码概述

    2017-05-31 21:24:40
     编解码器(codec)指的是一个能够对一个信号或者一个数据流进行变换的设备或者程序。这里指的变换既包括将信号或者数据流进行编码(通常是为了传输、存储或者加密)或者提取得到一个编码流的操作,也包括为了观察...
  • 一) sipdroid1)架构sip协议栈使用JAVA实现,音频Codec使用skype的silk(Silk编解码是Skype向第三方开发人员和硬件制造商提供免版税认证(RF)的Silk宽带音频编码器)实现。NAT传输支持stun server.2)优缺点:NAT方面...
1 2 3 4 5 ... 20
收藏数 491
精华内容 196
热门标签
关键字:

silk编解码