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實現。
一、獲取silk源碼(http://developer.skype.com/silk) java
二、建立新的android工程,並建立jni文件夾。 android
三、將silk源碼拷貝到jni目錄 算法
四、在jni目錄下新增Android.mk文件,編輯內容以下: shell
五、建立JNI包裝類silk8_jni.cpp、silk16_jni.cpp、silk24_jni.cpp,用來調用Silk中的C代碼函數,編輯內容以下 網絡
silk8_jni.cpp: app
- #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: ide
- #include <jni.h>
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
-
- /* Define codec specific settings */
- #define MAX_BYTES_ENC_PER_FRAME 250 // Equals peak bitrate of 100 kbps
- #define MAX_BYTES_DEC_PER_FRAME 1024
-
- #define MAX_INPUT_FRAMES 5
- #define MAX_LBRR_DELAY 2
- #define MAX_FRAME_LENGTH 480
-
- #define MAX_FRAME 320
-
- #include <android/log.h>
-
- #define LOG_TAG "silk" // text for log tag
-
- #include "SKP_Silk_SDK_API.h"
- #include "SKP_Silk_SigProc_FIX.h"
-
- #undef DEBUG_SILK16
-
- // the header length of the RTP frame (must skip when en/decoding)
- #define RTP_HDR_SIZE 12
-
- static int codec_open = 0;
-
- static JavaVM *gJavaVM;
- const char *kInterfacePath = "org/sipdroid/pjlib/silk16";
-
- /* encoder parameters */
-
- SKP_int32 encSizeBytes;
- void *psEnc;
-
- /* default settings */
- SKP_int fs_kHz = 16;
- SKP_int targetRate_bps = 20000;
- SKP_int packetSize_ms = 20;
- SKP_int frameSizeReadFromFile_ms = 20;
- SKP_int packetLoss_perc = 0, smplsSinceLastPacket;
- SKP_int INBandFec_enabled = 0, DTX_enabled = 0, quiet = 0;
- SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder
-
-
- /* decoder parameters */
-
- jbyte payloadToDec[ MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
- jshort out[ ( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ], *outPtr;
- SKP_int32 decSizeBytes;
- void *psDec;
- SKP_SILK_SDK_DecControlStruct DecControl;
-
- extern "C"
- JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK16_open
- (JNIEnv *env, jobject obj, jint compression) {
- int ret;
-
- if (codec_open++ != 0)
- return (jint)0;
-
- /* Set the samplingrate that is requested for the output */
- DecControl.sampleRate = 16000;
-
- /* Create decoder */
- ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "\n!!!!!!!! SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );
- }
- #ifdef DEBUG_SILK16
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "### INIT Decoder decSizeBytes = %d\n", decSizeBytes);
- #endif
- psDec = malloc( decSizeBytes );
-
- /* Reset decoder */
- ret = SKP_Silk_SDK_InitDecoder( psDec );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "\n!!!!!!!! SKP_Silk_InitDecoder returned %d", ret );
- }
-
-
- /* Create Encoder */
- ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "\n!!!!!!!! SKP_Silk_SDK_Get_Encoder_Size returned %d", ret );
- }
- #ifdef DEBUG_SILK16
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "### INIT Encoder encSizeBytes = %d\n", encSizeBytes);
- #endif
- psEnc = malloc( encSizeBytes );
-
- /* Reset Encoder */
- ret = SKP_Silk_SDK_InitEncoder( psEnc, &encControl );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "\n!!!!!!!! SKP_Silk_SDK_InitEncoder returned %d", ret );
- }
-
- /* Set Encoder parameters */
- encControl.sampleRate = fs_kHz * 1000;
- encControl.packetSize = packetSize_ms * fs_kHz;
- encControl.packetLossPercentage = packetLoss_perc;
- encControl.useInBandFEC = INBandFec_enabled;
- encControl.useDTX = DTX_enabled;
- encControl.complexity = compression;
- encControl.bitRate = targetRate_bps;
-
- return (jint)0;
- }
-
- void Print_Decode_Error_Msg(int errcode) {
- switch (errcode) {
- case SKP_SILK_DEC_WRONG_SAMPLING_FREQUENCY:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nOutput sampling frequency lower than internal decoded sampling frequency\n", errcode);
- break;
- case SKP_SILK_DEC_PAYLOAD_TOO_LARGE:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nPayload size exceeded the maximum allowed 1024 bytes\n", errcode);
- break;
- case SKP_SILK_DEC_PAYLOAD_ERROR:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nPayload has bit errors\n", errcode);
- break;
- }
- }
-
- void Print_Encode_Error_Msg(int errcode) {
- switch (errcode) {
- case SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nInput length is not a multiplum of 10 ms, or length is longer than the packet length\n", errcode);
- break;
- case SKP_SILK_ENC_FS_NOT_SUPPORTED:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nSampling frequency not 8000, 12000, 16000 or 24000 Hertz \n", errcode);
- break;
- case SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nPacket size not 20, 40, 60, 80 or 100 ms\n", errcode);
- break;
- case SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nAllocated payload buffer too short \n", errcode);
- break;
- case SKP_SILK_ENC_WRONG_LOSS_RATE:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nLoss rate not between 0 and 100 percent\n", errcode);
- break;
- case SKP_SILK_ENC_WRONG_COMPLEXITY_SETTING:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nComplexity setting not valid, use 0, 1 or 2\n", errcode);
- break;
- case SKP_SILK_ENC_WRONG_INBAND_FEC_SETTING:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nInband FEC setting not valid, use 0 or 1\n", errcode);
- break;
- case SKP_SILK_ENC_WRONG_DTX_SETTING:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nDTX setting not valid, use 0 or 1\n", errcode);
- break;
- case SKP_SILK_ENC_INTERNAL_ERROR:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nInternal encoder error\n", errcode);
- break;
- }
- }
-
- extern "C"
- JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK16_encode
- (JNIEnv *env, jobject obj, jshortArray lin, jint offset, jbyteArray encoded, jint size) {
-
- jbyte enc_payload[ MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES ];
- jshort in[ MAX_FRAME_LENGTH * MAX_INPUT_FRAMES ];
- int ret,i,frsz=MAX_FRAME;
- SKP_int16 nBytes;
- unsigned int lin_pos = 0;
-
- if (!codec_open)
- return 0;
-
- #ifdef DEBUG_SILK16
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "encoding frame size: %d\toffset: %d\n", size, offset);
- #endif
-
-
- for (i = 0; i < size; i+=MAX_FRAME) {
- #ifdef DEBUG_SILK16
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "encoding frame size: %d\toffset: %d i: %d\n", size, offset, i);
- #endif
-
- env->GetShortArrayRegion(lin, offset + i,frsz, in);
- /* max payload size */
- nBytes = MAX_BYTES_ENC_PER_FRAME * MAX_INPUT_FRAMES;
-
- ret = SKP_Silk_SDK_Encode( psEnc, &encControl, in, (SKP_int16)frsz, (SKP_uint8 *)enc_payload, &nBytes );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!! SKP_Silk_Encode returned: %d\n", ret);
- Print_Encode_Error_Msg(ret);
- break;
- }
- #ifdef DEBUG_SILK16
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "Enocded nBytes: %d\n", nBytes);
- #endif
- /* Write payload */
- env->SetByteArrayRegion(encoded, RTP_HDR_SIZE+ lin_pos, nBytes, enc_payload);
- lin_pos += nBytes;
- }
- #ifdef DEBUG_SILK16
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "encoding **END** frame size: %d\toffset: %d i: %d lin_pos: %d\n", size, offset, i, lin_pos);
- #endif
-
- return (jint)lin_pos;
- }
-
- extern "C"
- JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK16_decode
- (JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) {
-
- jbyte buffer [MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
- jshort output_buffer[( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ];
- // SKP_int16 *outPtr;
-
- int ret;
- SKP_int16 len;
- // int tot_len,frames;
-
- if (!codec_open)
- return 0;
-
- #ifdef DEBUG_SILK16
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "##### BEGIN DECODE ******** decoding frame size: %d\n", size);
- #endif
-
- env->GetByteArrayRegion(encoded, RTP_HDR_SIZE, size, buffer);
-
- // outPtr = output_buffer;
- // tot_len = 0;
- // frames = 0;
-
- // do {
- ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0,(SKP_uint8 *) buffer, size, output_buffer,&len );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!! SKP_Silk_SDK_Decode returned: %d\n", ret);
- Print_Decode_Error_Msg(ret);
- }
- #ifdef DEBUG_SILK16
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "##### DECODED length: %d\n\t Frame #: %d", len);
- #endif
- // frames++;
- // outPtr += len;
- // tot_len += len;
-
- // } while( DecControl.moreInternalDecoderFrames );
-
- env->SetShortArrayRegion(lin, 0, len,output_buffer);
- return (jint)len;
- }
-
- extern "C"
- JNIEXPORT void JNICALL Java_com_trunkbow_silk_SILK16_close
- (JNIEnv *env, jobject obj) {
-
- if (--codec_open != 0)
- return;
- /* Free decoder */
- free( psDec );
- /* Free Encoder */
- free( psEnc );
- }
silk24_jni.cpp 函數
- #include <jni.h>
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
-
- /* Define codec specific settings */
- #define MAX_BYTES_ENC_PER_FRAME 250 // Equals peak bitrate of 100 kbps
- #define MAX_BYTES_DEC_PER_FRAME 1024
-
- #define MAX_INPUT_FRAMES 5
- #define MAX_LBRR_DELAY 2
- #define MAX_FRAME_LENGTH 480
-
- #define MAX_FRAME 480
-
- #include <android/log.h>
-
- #define LOG_TAG "silk" // text for log tag
-
- #include "SKP_Silk_SDK_API.h"
- #include "SKP_Silk_SigProc_FIX.h"
-
- #undef DEBUG_SILK24
-
- // the header length of the RTP frame (must skip when en/decoding)
- #define RTP_HDR_SIZE 12
-
- static int codec_open = 0;
-
- static JavaVM *gJavaVM;
- const char *kInterfacePath = "org/sipdroid/pjlib/SILK24";
-
- /* encoder parameters */
-
- SKP_int32 encSizeBytes;
- void *psEnc;
-
- /* default settings */
- SKP_int fs_kHz = 24;
- SKP_int targetRate_bps = 20000;
- SKP_int packetSize_ms = 20;
- SKP_int frameSizeReadFromFile_ms = 20;
- SKP_int packetLoss_perc = 0, smplsSinceLastPacket;
- SKP_int INBandFec_enabled = 0, DTX_enabled = 0, quiet = 0;
- SKP_SILK_SDK_EncControlStruct encControl; // Struct for input to encoder
-
-
- /* decoder parameters */
-
- jbyte payloadToDec[ MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
- jshort out[ ( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ], *outPtr;
- SKP_int32 decSizeBytes;
- void *psDec;
- SKP_SILK_SDK_DecControlStruct DecControl;
-
- extern "C"
- JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK24_open
- (JNIEnv *env, jobject obj, jint compression) {
- int ret;
-
- if (codec_open++ != 0)
- return (jint)0;
-
- /* Set the samplingrate that is requested for the output */
- DecControl.sampleRate = 24000;
-
- /* Create decoder */
- ret = SKP_Silk_SDK_Get_Decoder_Size( &decSizeBytes );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "\n!!!!!!!! SKP_Silk_SDK_Get_Decoder_Size returned %d", ret );
- }
- #ifdef DEBUG_SILK24
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "### INIT Decoder decSizeBytes = %d\n", decSizeBytes);
- #endif
- psDec = malloc( decSizeBytes );
-
- /* Reset decoder */
- ret = SKP_Silk_SDK_InitDecoder( psDec );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "\n!!!!!!!! SKP_Silk_InitDecoder returned %d", ret );
- }
-
-
- /* Create Encoder */
- ret = SKP_Silk_SDK_Get_Encoder_Size( &encSizeBytes );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "\n!!!!!!!! SKP_Silk_SDK_Get_Encoder_Size returned %d", ret );
- }
- #ifdef DEBUG_SILK24
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "### INIT Encoder encSizeBytes = %d\n", encSizeBytes);
- #endif
- psEnc = malloc( encSizeBytes );
-
- /* Reset Encoder */
- ret = SKP_Silk_SDK_InitEncoder( psEnc, &encControl );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "\n!!!!!!!! SKP_Silk_SDK_InitEncoder returned %d", ret );
- }
-
- /* Set Encoder parameters */
- encControl.sampleRate = fs_kHz * 1000;
- encControl.packetSize = packetSize_ms * fs_kHz;
- encControl.packetLossPercentage = packetLoss_perc;
- encControl.useInBandFEC = INBandFec_enabled;
- encControl.useDTX = DTX_enabled;
- encControl.complexity = compression;
- encControl.bitRate = targetRate_bps;
-
- return (jint)0;
- }
-
- void Print_Decode_Error_Msg(int errcode) {
- switch (errcode) {
- case SKP_SILK_DEC_WRONG_SAMPLING_FREQUENCY:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nOutput sampling frequency lower than internal decoded sampling frequency\n", errcode);
- break;
- case SKP_SILK_DEC_PAYLOAD_TOO_LARGE:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nPayload size exceeded the maximum allowed 1024 bytes\n", errcode);
- break;
- case SKP_SILK_DEC_PAYLOAD_ERROR:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nPayload has bit errors\n", errcode);
- break;
- }
- }
-
- void Print_Encode_Error_Msg(int errcode) {
- switch (errcode) {
- case SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nInput length is not a multiplum of 10 ms, or length is longer than the packet length\n", errcode);
- break;
- case SKP_SILK_ENC_FS_NOT_SUPPORTED:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nSampling frequency not 8000, 12000, 16000 or 24000 Hertz \n", errcode);
- break;
- case SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nPacket size not 20, 40, 60, 80 or 100 ms\n", errcode);
- break;
- case SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nAllocated payload buffer too short \n", errcode);
- break;
- case SKP_SILK_ENC_WRONG_LOSS_RATE:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nLoss rate not between 0 and 100 percent\n", errcode);
- break;
- case SKP_SILK_ENC_WRONG_COMPLEXITY_SETTING:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nComplexity setting not valid, use 0, 1 or 2\n", errcode);
- break;
- case SKP_SILK_ENC_WRONG_INBAND_FEC_SETTING:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nInband FEC setting not valid, use 0 or 1\n", errcode);
- break;
- case SKP_SILK_ENC_WRONG_DTX_SETTING:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nDTX setting not valid, use 0 or 1\n", errcode);
- break;
- case SKP_SILK_ENC_INTERNAL_ERROR:
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!!!!! Decode_Error_Message: %d\nInternal encoder error\n", errcode);
- break;
- }
- }
-
- extern "C"
- JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK24_encode
- (JNIEnv *env, jobject obj, jshortArray lin, jint offset, jbyteArray encoded, jint size) {
-
- jbyte enc_payload[ MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES ];
- jshort in[ MAX_FRAME_LENGTH * MAX_INPUT_FRAMES ];
- int ret,i,frsz=MAX_FRAME;
- SKP_int16 nBytes;
- unsigned int lin_pos = 0;
-
- if (!codec_open)
- return 0;
-
- #ifdef DEBUG_SILK24
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "encoding frame size: %d\toffset: %d\n", size, offset);
- #endif
-
-
- for (i = 0; i < size; i+=MAX_FRAME) {
- #ifdef DEBUG_SILK24
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "encoding frame size: %d\toffset: %d i: %d\n", size, offset, i);
- #endif
-
- env->GetShortArrayRegion(lin, offset + i,frsz, in);
- /* max payload size */
- nBytes = MAX_BYTES_ENC_PER_FRAME * MAX_INPUT_FRAMES;
-
- ret = SKP_Silk_SDK_Encode( psEnc, &encControl, in, (SKP_int16)frsz, (SKP_uint8 *)enc_payload, &nBytes );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!! SKP_Silk_Encode returned: %d\n", ret);
- Print_Encode_Error_Msg(ret);
- break;
- }
- #ifdef DEBUG_SILK24
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "Enocded nBytes: %d\n", nBytes);
- #endif
- /* Write payload */
- env->SetByteArrayRegion(encoded, RTP_HDR_SIZE+ lin_pos, nBytes, enc_payload);
- lin_pos += nBytes;
- }
- #ifdef DEBUG_SILK24
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "encoding **END** frame size: %d\toffset: %d i: %d lin_pos: %d\n", size, offset, i, lin_pos);
- #endif
-
- return (jint)lin_pos;
- }
-
- extern "C"
- JNIEXPORT jint JNICALL Java_com_trunkbow_silk_SILK24_decode
- (JNIEnv *env, jobject obj, jbyteArray encoded, jshortArray lin, jint size) {
-
- jbyte buffer [MAX_BYTES_DEC_PER_FRAME * MAX_INPUT_FRAMES * ( MAX_LBRR_DELAY + 1 ) ];
- jshort output_buffer[( MAX_FRAME_LENGTH << 1 ) * MAX_INPUT_FRAMES ];
- // SKP_int16 *outPtr;
-
- int ret;
- SKP_int16 len;
- // int tot_len,frames;
-
- if (!codec_open)
- return 0;
-
- #ifdef DEBUG_SILK24
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "##### BEGIN DECODE ******** decoding frame size: %d\n", size);
- #endif
-
- env->GetByteArrayRegion(encoded, RTP_HDR_SIZE, size, buffer);
-
- // outPtr = output_buffer;
- // tot_len = 0;
- // frames = 0;
-
- // do {
- ret = SKP_Silk_SDK_Decode( psDec, &DecControl, 0,(SKP_uint8 *) buffer, size, output_buffer,&len );
- if( ret ) {
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "!!!!!!!! SKP_Silk_SDK_Decode returned: %d\n", ret);
- Print_Decode_Error_Msg(ret);
- }
- #ifdef DEBUG_SILK24
- __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG,
- "##### DECODED length: %d\n\t Frame #: %d", len);
- #endif
- // frames++;
- // outPtr += len;
- // tot_len += len;
-
- // } while( DecControl.moreInternalDecoderFrames );
-
- env->SetShortArrayRegion(lin, 0, len,output_buffer);
- return (jint)len;
- }
-
- extern "C"
- JNIEXPORT void JNICALL Java_com_trunkbow_silk_SILK24_close
- (JNIEnv *env, jobject obj) {
-
- if (--codec_open != 0)
- return;
- /* Free decoder */
- free( psDec );
- /* Free Encoder */
- free( psEnc );
- }
六、在Java層建立Speex工具類,內容以下: 工具
Silk8.java: 優化
- class SILK8{
- /*
- * | fs (Hz) | BR (kbps)
- * ----------------+---------+---------
- * Narrowband | 8000 | 6 -20
- * Mediumband | 12000 | 7 -25
- * Wideband | 16000 | 8 -30
- * Super Wideband | 24000 | 12 -40
- *
- * Table 1: fs specifies the audio sampling frequency in Hertz (Hz); BR
- * specifies the adaptive bit rate range in kilobits per second (kbps).
- *
- * Complexity can be scaled to optimize for CPU resources in real-time,
- * mostly in trade-off to network bit rate. 0 is least CPU demanding and
- * highest bit rate.
- */
- private static final int DEFAULT_COMPLEXITY = 0;
-
- void load() {
- System.loadLibrary("silk8_jni");
- }
-
- public native int open(int compression);
- public native int decode(byte encoded[], short lin[], int size);
- public native int encode(short lin[], int offset, byte encoded[], int size);
- public native void close();
- }
Silk16.java:
- class SILK16 {
- /*
- * | fs (Hz) | BR (kbps)
- * ----------------+---------+---------
- * Narrowband | 8000 | 6 -20
- * Mediumband | 12000 | 7 -25
- * Wideband | 16000 | 8 -30
- * Super Wideband | 24000 | 12 -40
- *
- * Table 1: fs specifies the audio sampling frequency in Hertz (Hz); BR
- * specifies the adaptive bit rate range in kilobits per second (kbps).
- *
- * Complexity can be scaled to optimize for CPU resources in real-time,
- * mostly in trade-off to network bit rate. 0 is least CPU demanding and
- * highest bit rate.
- */
- private static final int DEFAULT_COMPLEXITY = 0;
-
-
- void load() {
- System.loadLibrary("silk16_jni");
- }
-
- public native int open(int compression);
- public native int decode(byte encoded[], short lin[], int size);
- public native int encode(short lin[], int offset, byte encoded[], int size);
- public native void close();
-
- }
Silk24.java:
- class SILK24 {
- /*
- * | fs (Hz) | BR (kbps)
- * ----------------+---------+---------
- * Narrowband | 8000 | 6 -20
- * Mediumband | 12000 | 7 -25
- * Wideband | 16000 | 8 -30
- * Super Wideband | 24000 | 12 -40
- *
- * Table 1: fs specifies the audio sampling frequency in Hertz (Hz); BR
- * specifies the adaptive bit rate range in kilobits per second (kbps).
- *
- * Complexity can be scaled to optimize for CPU resources in real-time,
- * mostly in trade-off to network bit rate. 0 is least CPU demanding and
- * highest bit rate.
- */
- private static final int DEFAULT_COMPLEXITY = 0;
-
- void load() {
- System.loadLibrary("silk24_jni");
- }
-
- public native int open(int compression);
- public native int decode(byte encoded[], short lin[], int size);
- public native int encode(short lin[], int offset, byte encoded[], int size);
- public native void close();
-
- }
七、使用cygwin編譯,生成so文件。
***********************************************************************
* 轉載務必在明顯處註明:http://blog.csdn.net/xyz_lmn *
* 做者:張興業 *
* 郵箱:xy-zhang@163.com *
***********************************************************************
參考:http://developer.skype.com/silk
http://blog.csdn.net/wanggp_2007/article/details/5540686 Skype SILK vs. iLBC vs. Speex
***********************************************************************
* 轉載務必在明顯處註明:http://blog.csdn.net/xyz_lmn *
* 做者:張興業 *
* 郵箱:xy-zhang@163.com *
***********************************************************************