The compression weapon in language chat Speex
Recently, the project team started developing an IM project, instant chat app. So when engineers are building a backend server, I have to address some of the front-end and back-end interaction data, such as protocols, heartbeat packets, and so on. The difficulty of voice chat is the compression and encryption of voice.
After referring to the following articles, the decision is to use Speex this open source tool to compress the voice bar.
http://code.csdn.net/news/313194
Google has the following Speex, many of the demo information is 13 12 years, so I decided to go to their Speex official website to download a new down to re-compiled into the NDK. So library.
Configuration Speex, reference: http://www.phonesdevelopers.com/1787731/
Unzip the downloaded compressed package, I downloaded: speex-1.2rc1.tar.gz, the files in the include and Libspeex folders copied to the project JNI.
1.
Create a new Speex.java class in the project and use the Javah command to generate the header file.
PackageCom.park.speex; Public class Speex { /* Quality * 1:4kbps (very noticeable artifacts, usually intelligible) * 2:6kbps (very noticeable artifact S, good intelligibility) * 4:8kbps (noticeable artifacts sometimes) * 6:11KPBS (artifacts usually only noticea ble with headphones) * 8:15kbps (artifacts not usually noticeable) */ Private Static Final intDefault_compression =8; Public Speex() { } Public void Init() {load (); Open (default_compression); }Private void Load() {Try{System.loadlibrary ("Speex"); }Catch(Throwable e) {E.printstacktrace (); } } Public native int Open(intcompression); Public native int getframesize(); Public native int Decode(byteEncoded[], ShortLin[],intsize); Public native int encode( ShortLin[],intOffsetbyteEncoded[],intsize); Public native void Close();}
After Javah generated the com_park_speex_speex.h header file, and then write Speex.cpp file to really achieve compression decompression.
#include <jni.h>#include <string.h>#include <unistd.h>#include <speex/speex.h>Static intCodec_open =0;Static intDec_frame_size;Static intEnc_frame_size;StaticSpeexbits Ebits, Dbits;void*enc_state;void*dec_state;StaticJAVAVM *GJAVAVM;extern "C"Jniexport jint jnicall java_com_park_speex_speex_open (jnienv *env, jobject obj, jint compression) {inttmpif(codec_open++! =0)return(Jint)0; Speex_bits_init (&ebits); Speex_bits_init (&dbits); Enc_state = Speex_encoder_init (&speex_nb_mode); Dec_state = Speex_decoder_init (&speex_nb_mode); TMP = compression; Speex_encoder_ctl (Enc_state, speex_set_quality, &tmp); Speex_encoder_ctl (Enc_state, Speex_get_frame_size, &enc_frame_size); Speex_decoder_ctl (Dec_state, Speex_get_frame_size, &dec_frame_size);return(Jint)0;}extern "C"Jniexport jint Java_com_park_speex_speex_encode (jnienv *env, Jobject obj, Jshortarray Lin, jint offset, Jbytearray enc Oded, Jint size) {Jshort buffer[enc_frame_size]; Jbyte Output_buffer[enc_frame_size];intNsamples = (size-1)/enc_frame_size +1;intI, tot_bytes =0;if(!codec_open)return 0; Speex_bits_reset (&ebits); for(i =0; i < nsamples; i++) {env->getshortarrayregion (Lin, offset + i*enc_frame_size, enc_frame_size, buffer); Speex_encode_int (enc_state, buffer, &ebits); }//env->getshortarrayregion (Lin, offset, enc_frame_size, buffer); //speex_encode_int (enc_state, buffer, &ebits);Tot_bytes = Speex_bits_write (&ebits, (Char*) Output_buffer, enc_frame_size); Env->setbytearrayregion (encoded,0, Tot_bytes, Output_buffer);return(Jint) Tot_bytes;}extern "C"Jniexport jint jnicall Java_com_park_speex_speex_decode (jnienv *env, Jobject obj, Jbytearray encoded, JshortArray Lin, Jint size) {jbyte buffer[dec_frame_size]; Jshort Output_buffer[dec_frame_size]; Jsize encoded_length = size;if(!codec_open)return 0; Env->getbytearrayregion (encoded,0, encoded_length, buffer); Speex_bits_read_from (&dbits, (Char*) buffer, encoded_length); Speex_decode_int (Dec_state, &dbits, Output_buffer); Env->setshortarrayregion (Lin,0, Dec_frame_size, Output_buffer);return(Jint) Dec_frame_size;}extern "C"Jniexport jint jnicall java_com_park_speex_speex_getframesize (jnienv *env, Jobject obj) {if(!codec_open)return 0;return(Jint) Enc_frame_size;}extern "C"JniexportvoidJnicall Java_com_park_speex_speex_close (jnienv *env, Jobject obj) {if(--codec_open! =0)return; Speex_bits_destroy (&ebits); Speex_bits_destroy (&dbits); Speex_decoder_destroy (dec_state); Speex_encoder_destroy (enc_state);}
Note: The method in the CPP file must match the method name in the header file
In other projects, copy the ANDROID.MK and application.mk to the Jni folder.
Android.mk as follows:
# Copyright (C) The Android Open Source Project## Licensed under the Apache License, Version 2.0 (the "License");# You are not a use of this file except in compliance with the License.# Obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## unless required by applicable or agreed to writing, software# Distributed under the License is distributed on a "as is" BASIS,# without warranties or CONDITIONS of any KIND, either express or implied.# See the License for the specific language governing permissions and# Limitations under the License.#Local_path:= $(PagerMY-DIR) include $ (clear_vars) Local_module: = Speexlocal_cflags =-dfixed_point-duse_kiss_fft-dexport=""-uhave_config_h local_c_includes: = $ (Local_path)/include local_src_files: =./speex_jni. cpp./libspeex/buffer. C./libspeex/bits. C./libspeex/cb_search. C./libspeex/exc_10_16_table. C./libspeex/exc_10_32_table. C./libspeex/exc_20_32_table. C./libspeex/exc_5_256_table. C./libspeex/exc_5_64_table. C./libspeex/exc_8_128_table. C./libspeex/fftwrap. C./libspeex/filterbank. C./libspeex/filters. C./libspeex/gain_table. C./libspeex/gain_table_lbr. C./libspeex/hexc_10_32_table. C./libspeex/hexc_table. C./libspeex/high_lsp_tables. C./libspeex/jitter. C./libspeex/kiss_fft. C./libspeex/kiss_fftr. C./LIBSPEEX/LPC. C./libspeex/lsp. C./libspeex/lsp_tables_nb. C./LIBSPEEX/LTP. C./libspeex/mdf. C./libspeex/modes. C./LIBSPEEX/MODES_WB. C./libspeex/nb_celp. C./libspeex/preprocess. C./libspeex/quant_lsp. C./libspeex/resample. C./libspeex/sb_celp. C./libspeex/scal. C./libspeex/smallft. C./libspeex/speex. C./libspeex/speex_callbacks. C./libspeex/speex_header. C./libspeex/stereo. C./LIBSPEEX/VBR. C./libspeex/vq. C./libspeex/window. CInclude $ (build_shared_library)
Note: The file name "\" After Local_src_files is not followed by a space, as follows:
This will happen "JNI/ANDROID.MK:26: * missing separator. Stop. " Compilation error, this error indicates that there are spaces after "\" in line 25.
Almost, can be compiled, the use of cygdrive ndk-build command for JNI compilation, but found an error:
Jni/include/speex/speex_types.h:122:40:fatal error:speex/speex_config_types.h:no such file or directory
No files were found for speex_config_types.h.
So go to Include\speex and see that there is only one file named: speex_config_types.h.in. At this time my heart Anxi a bit, this all to me find, this time should be able to compile successfully. I copied this. in file directly named: Speex_config_types.h, then NDK, and then error, I xxxxxxxx.
The error message is: jni/include/speex/speex.h:325:35:error: ' spx_int16_t ' have not been declared
It means that the "spx_int16_t" in this file has not yet been declared. Open this speex_config_types.h.in file a look, sure enough there is a called "typedef @[email protected] spx_int16_t;" Things, then how to change it? Referring to the above article, I directly copied their speex_config_types.h file content come over, as follows:
#ifndef __SPEEX_TYPES_H__#define __SPEEX_TYPES_H__/* these are filled in by configure */typedefshort spx_int16_t;typedefunsignedshort spx_uint16_t;typedefint spx_int32_t;typedefunsignedint spx_uint32_t;#endif
Then the NDK compiled, and finally successfully generated the libspeex.so file.
If want to understand this C write Speex can this article to re-write compression and decompression algorithm, there is a note description.
"Tech-speex" Language chat in the compression of the sharp weapon Speex "1"