Silk编解码在android实现
2015-12-30 13:36
701 查看
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文件,编辑内容如下:
[plain]
view plaincopyprint?
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:
[cpp]
view plaincopyprint?
#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:
[cpp]
view plaincopyprint?
#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
[cpp]
view plaincopyprint?
#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:
[java]
view plaincopyprint?
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:
[java]
view plaincopyprint?
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:
[java]
view plaincopyprint?
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
/article/7859830.html
Skype SILK vs. iLBC vs. Speex
/**
* @author 张兴业
* http://blog.csdn.net/xyz_lmn
* iOS入门群:83702688
* android开发进阶群:241395671
* 我的新浪微博:@张兴业TBOW
*/
***********************************************************************
* 转载务必在明显处注明:http://blog.csdn.net/xyz_lmn *
* 作者:张兴业 *
* 邮箱:xy-zhang#163.com *
***********************************************************************
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文件,编辑内容如下:
[plain]
view plaincopyprint?
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)
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:
[cpp]
view plaincopyprint?
#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 );
}
#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:
[cpp]
view plaincopyprint?
#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 );
}
#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
[cpp]
view plaincopyprint?
#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 );
}
#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:
[java]
view plaincopyprint?
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();
}
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:
[java]
view plaincopyprint?
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();
}
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:
[java]
view plaincopyprint?
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();
}
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
/article/7859830.html
Skype SILK vs. iLBC vs. Speex
/**
* @author 张兴业
* http://blog.csdn.net/xyz_lmn
* iOS入门群:83702688
* android开发进阶群:241395671
* 我的新浪微博:@张兴业TBOW
*/
***********************************************************************
* 转载务必在明显处注明:http://blog.csdn.net/xyz_lmn *
* 作者:张兴业 *
* 邮箱:xy-zhang#163.com *
***********************************************************************
相关文章推荐
- Android 5.1 Lollipop Phone工作流程浅析(十三)__InCallActivity启动Performance浅析
- speex编解码在android上实现
- ilbc编解码在android实现
- android 状态栏、标题栏、屏幕高度
- android限制edittext不能输入表情
- Android 拍照与从相册选取图片时,图片不显示的问题
- Android:ContentProvider、URI、UriMatcher、ContentUris、ContentResolver、ContentObserver
- Android中的线程池简介
- Android 媒体 I-媒体播放
- MPAndroidChart 教程:MarkerView(十一)
- Android Studio快捷键
- Android:ListView
- Android性能优化
- android AsyncTask介绍 AsyncTask和Handler对比
- Android 4.4 实现透明状态栏Translucent system bar(Status bar)
- Android:嵌入式关系型SQLite数据库、SQLiteOpenHelper、SQLiteDatabase、事务
- Android实现夜间模式方式
- AndroidStudio proguard-rules.pro混淆 gson
- android-sharing files with NFC
- Android:SharedPreferences