├── .gitattributes ├── .gitignore ├── README.md ├── audio ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── dev │ │ └── mars │ │ └── audio │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── dev │ │ │ └── mars │ │ │ └── audio │ │ │ ├── AudioFrame.java │ │ │ ├── AudioUtils.java │ │ │ ├── Common.java │ │ │ ├── LogUtils.java │ │ │ ├── NativeLib.java │ │ │ └── SpeexUtils.java │ ├── jni │ │ ├── CMakeLists.txt │ │ ├── log.h │ │ ├── native.cpp │ │ ├── opensl_io.c │ │ └── opensl_io.h │ ├── jnilibs │ │ ├── arm64-v8a │ │ │ ├── libspeex.so │ │ │ └── libspeexdsp.so │ │ ├── armeabi │ │ │ ├── libspeex.so │ │ │ └── libspeexdsp.so │ │ ├── speex_include │ │ │ ├── speex.h │ │ │ ├── speex_bits.h │ │ │ ├── speex_buffer.h │ │ │ ├── speex_callbacks.h │ │ │ ├── speex_config_types.h │ │ │ ├── speex_echo.h │ │ │ ├── speex_header.h │ │ │ ├── speex_jitter.h │ │ │ ├── speex_preprocess.h │ │ │ ├── speex_resampler.h │ │ │ ├── speex_stereo.h │ │ │ ├── speex_types.h │ │ │ ├── speexdsp_config_types.h │ │ │ └── speexdsp_types.h │ │ └── x86 │ │ │ ├── libspeex.so │ │ │ └── libspeexdsp.so │ └── res │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── dev │ └── mars │ └── audio │ └── ExampleUnitTest.java ├── build.gradle ├── callme ├── .gitignore ├── build.gradle ├── libs │ ├── mina-core-2.0.16.jar │ └── slf4j-api-1.7.21.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── dev │ │ └── mars │ │ └── callme │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── dev │ │ │ └── mars │ │ │ └── callme │ │ │ ├── CallingActivity.java │ │ │ ├── CommunicatingActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── OnCallActivity.java │ │ │ ├── base │ │ │ ├── BaseActivity.java │ │ │ └── BaseApplication.java │ │ │ ├── bean │ │ │ ├── KeepAliveMessage.java │ │ │ ├── SocketMessage.java │ │ │ └── UDPMessage.java │ │ │ ├── common │ │ │ └── Constants.java │ │ │ ├── event │ │ │ ├── CallingEvent.java │ │ │ ├── OnCallEvent.java │ │ │ ├── SessionClosedEvent.java │ │ │ └── StartCommunicatingEvent.java │ │ │ ├── remote │ │ │ ├── UDPUtils.java │ │ │ └── mina │ │ │ │ ├── BaseCodecFactory.java │ │ │ │ ├── BaseDecoder.java │ │ │ │ ├── BaseEncoder.java │ │ │ │ ├── ISendListener.java │ │ │ │ ├── KeepAliveFilter.java │ │ │ │ ├── client │ │ │ │ ├── ClientSessionState.java │ │ │ │ ├── ClientSessionStatus.java │ │ │ │ ├── ClosedSessionState.java │ │ │ │ ├── ConnectedSessionState.java │ │ │ │ ├── ConnectingSessionState.java │ │ │ │ └── MinaSocketClient.java │ │ │ │ └── server │ │ │ │ └── MinaSocketServer.java │ │ │ ├── service │ │ │ └── CommunicateService.java │ │ │ └── utils │ │ │ ├── BasicTypeConvertUtils.java │ │ │ ├── IPUtils.java │ │ │ ├── LogUtils.java │ │ │ ├── RingtonePlayer.java │ │ │ └── WifiUtils.java │ └── res │ │ ├── layout │ │ ├── activity_calling.xml │ │ ├── activity_communicating.xml │ │ ├── activity_main.xml │ │ └── activity_on_call.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── dev │ └── mars │ └── callme │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── video ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── mars │ └── dev │ └── video │ └── ExampleInstrumentedTest.java ├── main ├── AndroidManifest.xml ├── java │ └── mars │ │ └── dev │ │ └── video │ │ ├── BaseActivity.java │ │ ├── LogUtils.java │ │ ├── MainActivity.java │ │ └── VideoActivity.java └── res │ ├── layout │ ├── activity_main.xml │ └── activity_video.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml └── test └── java └── mars └── dev └── video └── ExampleUnitTest.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | /.idea 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CallMe 2 | 局域网内语音通话研究,已完成基础部分,回声消除效果差,待优化 3 | -------------------------------------------------------------------------------- /audio/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /audio/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "25.0.2" 6 | defaultConfig { 7 | minSdkVersion 14 8 | targetSdkVersion 24 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | ndk { 13 | abiFilters 'armeabi','arm64-v8a', 'x86' 14 | } 15 | externalNativeBuild { 16 | cmake { 17 | arguments '-DANDROID_TOOLCHAIN=clang','-DANDROID_STL=gnustl_static' 18 | } 19 | } 20 | //, 'arm64-v8a', 'x86', 'x86_64' 21 | } 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | externalNativeBuild { 29 | cmake { 30 | path "src/main/jni/CMakeLists.txt" 31 | } 32 | } 33 | } 34 | 35 | dependencies { 36 | compile fileTree(dir: 'libs', include: ['*.jar']) 37 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 38 | exclude group: 'com.android.support', module: 'support-annotations' 39 | }) 40 | compile 'com.android.support:appcompat-v7:24.2.1' 41 | testCompile 'junit:junit:4.12' 42 | } 43 | -------------------------------------------------------------------------------- /audio/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in F:\IDE\AndroidSDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /audio/src/androidTest/java/dev/mars/audio/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package dev.mars.audio; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("dev.mars.openslesdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /audio/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /audio/src/main/java/dev/mars/audio/AudioFrame.java: -------------------------------------------------------------------------------- 1 | package dev.mars.audio; 2 | 3 | /** 4 | * Created by ma.xuanwei on 2017/3/31. 5 | */ 6 | 7 | public class AudioFrame { 8 | public byte[] data; 9 | } 10 | -------------------------------------------------------------------------------- /audio/src/main/java/dev/mars/audio/AudioUtils.java: -------------------------------------------------------------------------------- 1 | package dev.mars.audio; 2 | 3 | import android.provider.SyncStateContract; 4 | 5 | import java.util.concurrent.BlockingQueue; 6 | import java.util.concurrent.ExecutorService; 7 | import java.util.concurrent.Executors; 8 | import java.util.concurrent.atomic.AtomicBoolean; 9 | 10 | /** 11 | * Created by mars_ma on 2017/3/1audio6. 12 | */ 13 | 14 | public class AudioUtils { 15 | private ExecutorService executor = Executors.newCachedThreadPool(); 16 | private NativeLib nativeBridge; 17 | 18 | public AudioUtils(){ 19 | nativeBridge = new NativeLib(); 20 | } 21 | 22 | public void setNoiseClear(boolean enable){ 23 | nativeBridge.setNoiseClear(enable); 24 | } 25 | 26 | public void setEchoClearEnable(boolean enable){ 27 | nativeBridge.setEchoClear(enable); 28 | } 29 | 30 | public boolean recordAndPlayPCM(final boolean enable1, final boolean enable2){ 31 | if(!nativeBridge.isRecordingAndPlaying()) { 32 | executor.execute(new Runnable() { 33 | @Override 34 | public void run() { 35 | nativeBridge.recordAndPlayPCM(enable1,enable2); 36 | } 37 | }); 38 | return true; 39 | }else{ 40 | return false; 41 | } 42 | } 43 | 44 | public boolean stopRecordAndPlay(){ 45 | if(!nativeBridge.isRecordingAndPlaying()) { 46 | return false; 47 | }else{ 48 | nativeBridge.stopRecordingAndPlaying(); 49 | return true; 50 | } 51 | } 52 | 53 | public void startPlay(final BlockingQueue queue){ 54 | if(isPlaying()) 55 | return; 56 | executor.execute(new Runnable() { 57 | @Override 58 | public void run() { 59 | nativeBridge.startPlay2(queue); 60 | } 61 | }); 62 | } 63 | 64 | 65 | public void stopRecord(){ 66 | nativeBridge.stopRecording(); 67 | } 68 | 69 | public void startRecord(final OnRecordListener onRecordListener){ 70 | if(nativeBridge.isRecording()){ 71 | return; 72 | } 73 | executor.execute(new Runnable() { 74 | @Override 75 | public void run() { 76 | nativeBridge.setOnRecordListener(new NativeLib.OnRecordListener() { 77 | @Override 78 | public void onRecord(byte[] datas) { 79 | onRecordListener.onRecord(datas); 80 | } 81 | 82 | @Override 83 | public void onStart() { 84 | onRecordListener.onStart(); 85 | } 86 | }); 87 | nativeBridge.startRecording2(Common.SAMPLERATE,Common.PERIOD_TIME,Common.CHANNELS); 88 | } 89 | }); 90 | } 91 | 92 | public void stopPlay() { 93 | nativeBridge.stopPlaying(); 94 | LogUtils.DEBUG("stopPlay"); 95 | } 96 | 97 | public interface OnRecordListener{ 98 | void onRecord(byte[] datas); 99 | void onStart(); 100 | } 101 | 102 | public boolean isPlaying(){ 103 | return nativeBridge.isPlaying(); 104 | } 105 | 106 | public boolean isRecording(){ 107 | return nativeBridge.isRecording(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /audio/src/main/java/dev/mars/audio/Common.java: -------------------------------------------------------------------------------- 1 | package dev.mars.audio; 2 | 3 | import android.os.Environment; 4 | 5 | /** 6 | * Created by 37550 on 2017/3/8. 7 | */ 8 | 9 | public class Common { 10 | public static final int SAMPLERATE = 8000; //bit/s 11 | public static final int CHANNELS = 2; //1:单/2:双声道 12 | public static final int PERIOD_TIME = 20; //ms 13 | public static final String DEFAULT_PCM_FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/test_pcm.pcm"; 14 | public static final String DEFAULT_PCM_OUTPUT_FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/output_pcm.pcm"; 15 | public static final String DEFAULT_SPEEX_FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/test_speex.raw"; 16 | } 17 | -------------------------------------------------------------------------------- /audio/src/main/java/dev/mars/audio/LogUtils.java: -------------------------------------------------------------------------------- 1 | package dev.mars.audio; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * Created by ma.xuanwei on 2017/3/7. 7 | */ 8 | 9 | public class LogUtils { 10 | public static void DEBUG(String msg){ 11 | android.util.Log.d("dev_mars",msg); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /audio/src/main/java/dev/mars/audio/NativeLib.java: -------------------------------------------------------------------------------- 1 | package dev.mars.audio; 2 | 3 | import java.util.concurrent.BlockingQueue; 4 | import java.util.concurrent.atomic.AtomicBoolean; 5 | import java.util.concurrent.locks.ReentrantLock; 6 | 7 | /** 8 | * Created by ma.xuanwei on 2017/3/7. 9 | */ 10 | 11 | public class NativeLib { 12 | 13 | private AtomicBoolean isRecording = new AtomicBoolean(false); 14 | private AtomicBoolean isPlaying = new AtomicBoolean(false); 15 | private AtomicBoolean isRecordAndPlay = new AtomicBoolean(false); 16 | 17 | private AudioFrame echoAudioFrame = new AudioFrame(); 18 | private static ReentrantLock reentrantLock = new ReentrantLock(true); 19 | 20 | public void setEchoAudioFrame(byte[] bytes){ 21 | reentrantLock.lock(); 22 | echoAudioFrame.data = bytes; 23 | reentrantLock.unlock(); 24 | } 25 | 26 | public byte[] getEchoAudioFrame(){ 27 | reentrantLock.lock(); 28 | byte[] bytes = echoAudioFrame.data; 29 | reentrantLock.unlock(); 30 | return bytes; 31 | } 32 | 33 | static { 34 | System.loadLibrary("native"); 35 | } 36 | 37 | public void setIsRecording(boolean v) { 38 | isRecording.set(v); 39 | LogUtils.DEBUG("setIsRecording " + v); 40 | } 41 | 42 | public void setIsRecordingAndPlaying(boolean v) { 43 | isRecordAndPlay.set(v); 44 | LogUtils.DEBUG("setIsRecordingAndPlaying " + v); 45 | } 46 | 47 | public boolean isRecording() { 48 | return isRecording.get(); 49 | } 50 | 51 | public void setIsPlaying(boolean b) { 52 | isPlaying.set(b); 53 | LogUtils.DEBUG("setIsPlaying " + b); 54 | } 55 | 56 | public boolean isPlaying() { 57 | return isPlaying.get(); 58 | } 59 | 60 | public boolean isRecordingAndPlaying() { 61 | return isRecordAndPlay.get(); 62 | } 63 | 64 | 65 | public native void stopRecording(); 66 | 67 | 68 | public native void stopPlaying(); 69 | 70 | public native int encode(String pcm, String speex); 71 | 72 | public native int decode(String speex, String pcm); 73 | 74 | public native int recordAndPlayPCM(boolean enableProcess, boolean enableEchoCancel); 75 | 76 | public native int stopRecordingAndPlaying(); 77 | 78 | BlockingQueue audioFrames; 79 | 80 | public void startPlay2(BlockingQueue audioFrames) { 81 | this.audioFrames = audioFrames; 82 | playRecording2(Common.SAMPLERATE,Common.PERIOD_TIME,Common.CHANNELS); 83 | } 84 | 85 | public native void startRecording2(int sampleRate, int period, int channels); 86 | 87 | public native void playRecording2(int sampleRate, int period, int channels); 88 | 89 | public byte[] getOneFrame() { 90 | 91 | //AudioFrame audioFrame = audioFrames.take(); 92 | AudioFrame audioFrame = audioFrames.poll(); //非阻塞 93 | if (audioFrame == null) { 94 | return null; 95 | } 96 | LogUtils.DEBUG("JNI 从 JAVA层取走byte[]数据"); 97 | return audioFrame.data; 98 | } 99 | 100 | public void onRecord(byte[] bytes) { 101 | LogUtils.DEBUG("收到native传来的bytes,长度 = " + (bytes == null ? 0 : bytes.length)); 102 | if (onRecordListener != null) { 103 | onRecordListener.onRecord(bytes); 104 | } 105 | } 106 | 107 | public void onRecordStart() { 108 | if (onRecordListener != null) 109 | onRecordListener.onStart(); 110 | } 111 | 112 | OnRecordListener onRecordListener; 113 | 114 | public void setOnRecordListener(OnRecordListener l) { 115 | onRecordListener = l; 116 | } 117 | 118 | public interface OnRecordListener { 119 | void onRecord(byte[] datas); 120 | 121 | void onStart(); 122 | } 123 | 124 | public native void setNoiseClear(boolean enable); 125 | 126 | public native void setEchoClear(boolean enable); 127 | } 128 | -------------------------------------------------------------------------------- /audio/src/main/java/dev/mars/audio/SpeexUtils.java: -------------------------------------------------------------------------------- 1 | package dev.mars.audio; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | 7 | /** 8 | * Created by ma.xuanwei on 2017/3/16. 9 | */ 10 | 11 | public class SpeexUtils { 12 | private ExecutorService executor = Executors.newSingleThreadExecutor(); 13 | private NativeLib nativeBridge; 14 | 15 | public SpeexUtils() { 16 | nativeBridge = new NativeLib(); 17 | } 18 | 19 | public void encode(final String pcm, final String speex) { 20 | executor.execute(new Runnable() { 21 | @Override 22 | public void run() { 23 | nativeBridge.encode(pcm,speex); 24 | } 25 | }); 26 | } 27 | 28 | public void decode(final String defaultSpeexFilePath, final String defaultPcmOutputFilePath) { 29 | executor.execute(new Runnable() { 30 | @Override 31 | public void run() { 32 | nativeBridge.decode(defaultSpeexFilePath, defaultPcmOutputFilePath); 33 | } 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /audio/src/main/jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | set(JNI_LIBS ${CMAKE_SOURCE_DIR}/../jnilibs) 4 | 5 | add_library(speex-lib SHARED IMPORTED) 6 | set_target_properties(speex-lib PROPERTIES IMPORTED_LOCATION ${JNI_LIBS}/${ANDROID_ABI}/libspeex.so) 7 | 8 | 9 | add_library(speexdsp-lib SHARED IMPORTED) 10 | set_target_properties(speexdsp-lib PROPERTIES IMPORTED_LOCATION ${JNI_LIBS}/${ANDROID_ABI}/libspeexdsp.so) 11 | 12 | include_directories( ${JNI_LIBS}/speex_include ) 13 | 14 | add_library(native SHARED 15 | native.cpp 16 | opensl_io.c 17 | opensl_io.h 18 | log.h) 19 | 20 | target_link_libraries( 21 | native 22 | log 23 | OpenSLES 24 | speex-lib 25 | speexdsp-lib 26 | ) 27 | -------------------------------------------------------------------------------- /audio/src/main/jni/log.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef ANDROID_OPENSLES_DEMO_LOG_H 4 | #define ANDROID_OPENSLES_DEMO_LOG_H 5 | 6 | #endif //ANDROID_OPENSLES_DEMO_LOG_H 7 | #define LOG_OPEN 1 8 | #if(LOG_OPEN==1) 9 | #define LOG(...) __android_log_print(ANDROID_LOG_DEBUG,"dev_mars",__VA_ARGS__) 10 | #else 11 | #define LOG(...) NULL 12 | #endif 13 | -------------------------------------------------------------------------------- /audio/src/main/jni/opensl_io.h: -------------------------------------------------------------------------------- 1 | /* opensl_io.c: 2 | Android OpenSL input/output module header 3 | Copyright (c) 2012, Victor Lazzarini All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef OPENSL_IO 29 | #define OPENSL_IO 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #define RECORD_MODE 0 37 | #define PLAY_MODE 1 38 | 39 | typedef struct threadLock_ { 40 | pthread_mutex_t m; 41 | pthread_cond_t c; 42 | unsigned char s; 43 | } threadLock; 44 | 45 | #ifdef __cplusplus 46 | extern "C" { 47 | #endif 48 | 49 | typedef struct opensl_stream { 50 | 51 | // engine interfaces 52 | SLObjectItf engineObject; 53 | SLEngineItf engineEngine; 54 | 55 | // output mix interfaces 56 | SLObjectItf outputMixObject; 57 | 58 | // buffer queue player interfaces 59 | SLObjectItf bqPlayerObject; 60 | SLPlayItf bqPlayerPlay; 61 | SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue; 62 | SLEffectSendItf bqPlayerEffectSend; 63 | 64 | // recorder interfaces 65 | SLObjectItf recorderObject; 66 | SLRecordItf recorderRecord; 67 | SLAndroidSimpleBufferQueueItf recorderBufferQueue; 68 | 69 | // buffer indexes 70 | uint32_t currentInputIndex; 71 | uint32_t currentOutputIndex; 72 | 73 | // current buffer half (0, 1) 74 | uint8_t currentOutputBuffer; 75 | uint8_t currentInputBuffer; 76 | 77 | // buffers 78 | uint16_t *outputBuffer[2]; 79 | uint16_t *inputBuffer[2]; 80 | 81 | // size of buffers 82 | uint32_t outBufSamples; //播放缓冲数组的大小 83 | uint32_t inBufSamples; //录入缓冲数组的大小 84 | 85 | // locks 86 | void* inlock; //录入同步锁 87 | void* outlock; //播放同步锁 88 | 89 | double time; 90 | uint32_t inchannels; //输入的声道数量 91 | uint32_t outchannels; //输出的声道数量 92 | uint32_t sampleRate; //采样率 93 | 94 | } OPENSL_STREAM; 95 | 96 | /* 97 | Open the audio device with a given sampling rate (sr), input and output channels and IO buffer size 98 | in frames. Returns a handle to the OpenSL stream 99 | */ 100 | OPENSL_STREAM* android_OpenAudioDevice(uint32_t sr, uint32_t inchannels, uint32_t outchannels, uint32_t bufferframes , uint32_t mode); 101 | 102 | /* 103 | Close the audio device 104 | */ 105 | void android_CloseAudioDevice(OPENSL_STREAM *p); 106 | 107 | /* 108 | Read a buffer from the OpenSL stream *p, of size samples. Returns the number of samples read. 109 | */ 110 | uint32_t android_AudioIn(OPENSL_STREAM *p, uint16_t *buffer,uint32_t size); 111 | 112 | /* 113 | Write a buffer to the OpenSL stream *p, of size samples. Returns the number of samples written. 114 | */ 115 | uint32_t android_AudioOut(OPENSL_STREAM *p, uint16_t *buffer,uint32_t size); 116 | 117 | /* 118 | Get the current IO block time in seconds 119 | */ 120 | double android_GetTimestamp(OPENSL_STREAM *p); 121 | 122 | #ifdef __cplusplus 123 | }; 124 | #endif 125 | 126 | #endif // #ifndef OPENSL_IO 127 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/arm64-v8a/libspeex.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/audio/src/main/jnilibs/arm64-v8a/libspeex.so -------------------------------------------------------------------------------- /audio/src/main/jnilibs/arm64-v8a/libspeexdsp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/audio/src/main/jnilibs/arm64-v8a/libspeexdsp.so -------------------------------------------------------------------------------- /audio/src/main/jnilibs/armeabi/libspeex.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/audio/src/main/jnilibs/armeabi/libspeex.so -------------------------------------------------------------------------------- /audio/src/main/jnilibs/armeabi/libspeexdsp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/audio/src/main/jnilibs/armeabi/libspeexdsp.so -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speex.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002-2006 Jean-Marc Valin*/ 2 | /** 3 | @file speex.h 4 | @brief Describes the different modes of the codec 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | - Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | - Neither the name of the Xiph.org Foundation nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | */ 35 | 36 | #ifndef SPEEX_H 37 | #define SPEEX_H 38 | /** @defgroup Codec Speex encoder and decoder 39 | * This is the Speex codec itself. 40 | * @{ 41 | */ 42 | 43 | #include "speex_types.h" 44 | #include "speex_bits.h" 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | /* Values allowed for *ctl() requests */ 51 | 52 | /** Set enhancement on/off (decoder only) */ 53 | #define SPEEX_SET_ENH 0 54 | /** Get enhancement state (decoder only) */ 55 | #define SPEEX_GET_ENH 1 56 | 57 | /*Would be SPEEX_SET_FRAME_SIZE, but it's (currently) invalid*/ 58 | /** Obtain frame size used by encoder/decoder */ 59 | #define SPEEX_GET_FRAME_SIZE 3 60 | 61 | /** Set quality value */ 62 | #define SPEEX_SET_QUALITY 4 63 | /** Get current quality setting */ 64 | /* #define SPEEX_GET_QUALITY 5 -- Doesn't make much sense, does it? */ 65 | 66 | /** Set sub-mode to use */ 67 | #define SPEEX_SET_MODE 6 68 | /** Get current sub-mode in use */ 69 | #define SPEEX_GET_MODE 7 70 | 71 | /** Set low-band sub-mode to use (wideband only)*/ 72 | #define SPEEX_SET_LOW_MODE 8 73 | /** Get current low-band mode in use (wideband only)*/ 74 | #define SPEEX_GET_LOW_MODE 9 75 | 76 | /** Set high-band sub-mode to use (wideband only)*/ 77 | #define SPEEX_SET_HIGH_MODE 10 78 | /** Get current high-band mode in use (wideband only)*/ 79 | #define SPEEX_GET_HIGH_MODE 11 80 | 81 | /** Set VBR on (1) or off (0) */ 82 | #define SPEEX_SET_VBR 12 83 | /** Get VBR status (1 for on, 0 for off) */ 84 | #define SPEEX_GET_VBR 13 85 | 86 | /** Set quality value for VBR encoding (0-10) */ 87 | #define SPEEX_SET_VBR_QUALITY 14 88 | /** Get current quality value for VBR encoding (0-10) */ 89 | #define SPEEX_GET_VBR_QUALITY 15 90 | 91 | /** Set complexity of the encoder (0-10) */ 92 | #define SPEEX_SET_COMPLEXITY 16 93 | /** Get current complexity of the encoder (0-10) */ 94 | #define SPEEX_GET_COMPLEXITY 17 95 | 96 | /** Set bit-rate used by the encoder (or lower) */ 97 | #define SPEEX_SET_BITRATE 18 98 | /** Get current bit-rate used by the encoder or decoder */ 99 | #define SPEEX_GET_BITRATE 19 100 | 101 | /** Define a handler function for in-band Speex request*/ 102 | #define SPEEX_SET_HANDLER 20 103 | 104 | /** Define a handler function for in-band user-defined request*/ 105 | #define SPEEX_SET_USER_HANDLER 22 106 | 107 | /** Set sampling rate used in bit-rate computation */ 108 | #define SPEEX_SET_SAMPLING_RATE 24 109 | /** Get sampling rate used in bit-rate computation */ 110 | #define SPEEX_GET_SAMPLING_RATE 25 111 | 112 | /** Reset the encoder/decoder memories to zero*/ 113 | #define SPEEX_RESET_STATE 26 114 | 115 | /** Get VBR info (mostly used internally) */ 116 | #define SPEEX_GET_RELATIVE_QUALITY 29 117 | 118 | /** Set VAD status (1 for on, 0 for off) */ 119 | #define SPEEX_SET_VAD 30 120 | 121 | /** Get VAD status (1 for on, 0 for off) */ 122 | #define SPEEX_GET_VAD 31 123 | 124 | /** Set Average Bit-Rate (ABR) to n bits per seconds */ 125 | #define SPEEX_SET_ABR 32 126 | /** Get Average Bit-Rate (ABR) setting (in bps) */ 127 | #define SPEEX_GET_ABR 33 128 | 129 | /** Set DTX status (1 for on, 0 for off) */ 130 | #define SPEEX_SET_DTX 34 131 | /** Get DTX status (1 for on, 0 for off) */ 132 | #define SPEEX_GET_DTX 35 133 | 134 | /** Set submode encoding in each frame (1 for yes, 0 for no, setting to no breaks the standard) */ 135 | #define SPEEX_SET_SUBMODE_ENCODING 36 136 | /** Get submode encoding in each frame */ 137 | #define SPEEX_GET_SUBMODE_ENCODING 37 138 | 139 | /*#define SPEEX_SET_LOOKAHEAD 38*/ 140 | /** Returns the lookahead used by Speex separately for an encoder and a decoder. 141 | * Sum encoder and decoder lookahead values to get the total codec lookahead. */ 142 | #define SPEEX_GET_LOOKAHEAD 39 143 | 144 | /** Sets tuning for packet-loss concealment (expected loss rate) */ 145 | #define SPEEX_SET_PLC_TUNING 40 146 | /** Gets tuning for PLC */ 147 | #define SPEEX_GET_PLC_TUNING 41 148 | 149 | /** Sets the max bit-rate allowed in VBR mode */ 150 | #define SPEEX_SET_VBR_MAX_BITRATE 42 151 | /** Gets the max bit-rate allowed in VBR mode */ 152 | #define SPEEX_GET_VBR_MAX_BITRATE 43 153 | 154 | /** Turn on/off input/output high-pass filtering */ 155 | #define SPEEX_SET_HIGHPASS 44 156 | /** Get status of input/output high-pass filtering */ 157 | #define SPEEX_GET_HIGHPASS 45 158 | 159 | /** Get "activity level" of the last decoded frame, i.e. 160 | how much damage we cause if we remove the frame */ 161 | #define SPEEX_GET_ACTIVITY 47 162 | 163 | 164 | /* Preserving compatibility:*/ 165 | /** Equivalent to SPEEX_SET_ENH */ 166 | #define SPEEX_SET_PF 0 167 | /** Equivalent to SPEEX_GET_ENH */ 168 | #define SPEEX_GET_PF 1 169 | 170 | 171 | 172 | 173 | /* Values allowed for mode queries */ 174 | /** Query the frame size of a mode */ 175 | #define SPEEX_MODE_FRAME_SIZE 0 176 | 177 | /** Query the size of an encoded frame for a particular sub-mode */ 178 | #define SPEEX_SUBMODE_BITS_PER_FRAME 1 179 | 180 | 181 | 182 | /** Get major Speex version */ 183 | #define SPEEX_LIB_GET_MAJOR_VERSION 1 184 | /** Get minor Speex version */ 185 | #define SPEEX_LIB_GET_MINOR_VERSION 3 186 | /** Get micro Speex version */ 187 | #define SPEEX_LIB_GET_MICRO_VERSION 5 188 | /** Get extra Speex version */ 189 | #define SPEEX_LIB_GET_EXTRA_VERSION 7 190 | /** Get Speex version string */ 191 | #define SPEEX_LIB_GET_VERSION_STRING 9 192 | 193 | /*#define SPEEX_LIB_SET_ALLOC_FUNC 10 194 | #define SPEEX_LIB_GET_ALLOC_FUNC 11 195 | #define SPEEX_LIB_SET_FREE_FUNC 12 196 | #define SPEEX_LIB_GET_FREE_FUNC 13 197 | 198 | #define SPEEX_LIB_SET_WARNING_FUNC 14 199 | #define SPEEX_LIB_GET_WARNING_FUNC 15 200 | #define SPEEX_LIB_SET_ERROR_FUNC 16 201 | #define SPEEX_LIB_GET_ERROR_FUNC 17 202 | */ 203 | 204 | /** Number of defined modes in Speex */ 205 | #define SPEEX_NB_MODES 3 206 | 207 | /** modeID for the defined narrowband mode */ 208 | #define SPEEX_MODEID_NB 0 209 | 210 | /** modeID for the defined wideband mode */ 211 | #define SPEEX_MODEID_WB 1 212 | 213 | /** modeID for the defined ultra-wideband mode */ 214 | #define SPEEX_MODEID_UWB 2 215 | 216 | struct SpeexMode; 217 | 218 | 219 | /* Prototypes for mode function pointers */ 220 | 221 | /** Encoder state initialization function */ 222 | typedef void *(*encoder_init_func)(const struct SpeexMode *mode); 223 | 224 | /** Encoder state destruction function */ 225 | typedef void (*encoder_destroy_func)(void *st); 226 | 227 | /** Main encoding function */ 228 | typedef int (*encode_func)(void *state, void *in, SpeexBits *bits); 229 | 230 | /** Function for controlling the encoder options */ 231 | typedef int (*encoder_ctl_func)(void *state, int request, void *ptr); 232 | 233 | /** Decoder state initialization function */ 234 | typedef void *(*decoder_init_func)(const struct SpeexMode *mode); 235 | 236 | /** Decoder state destruction function */ 237 | typedef void (*decoder_destroy_func)(void *st); 238 | 239 | /** Main decoding function */ 240 | typedef int (*decode_func)(void *state, SpeexBits *bits, void *out); 241 | 242 | /** Function for controlling the decoder options */ 243 | typedef int (*decoder_ctl_func)(void *state, int request, void *ptr); 244 | 245 | 246 | /** Query function for a mode */ 247 | typedef int (*mode_query_func)(const void *mode, int request, void *ptr); 248 | 249 | /** Struct defining a Speex mode */ 250 | typedef struct SpeexMode { 251 | /** Pointer to the low-level mode data */ 252 | const void *mode; 253 | 254 | /** Pointer to the mode query function */ 255 | mode_query_func query; 256 | 257 | /** The name of the mode (you should not rely on this to identify the mode)*/ 258 | const char *modeName; 259 | 260 | /**ID of the mode*/ 261 | int modeID; 262 | 263 | /**Version number of the bitstream (incremented every time we break 264 | bitstream compatibility*/ 265 | int bitstream_version; 266 | 267 | /** Pointer to encoder initialization function */ 268 | encoder_init_func enc_init; 269 | 270 | /** Pointer to encoder destruction function */ 271 | encoder_destroy_func enc_destroy; 272 | 273 | /** Pointer to frame encoding function */ 274 | encode_func enc; 275 | 276 | /** Pointer to decoder initialization function */ 277 | decoder_init_func dec_init; 278 | 279 | /** Pointer to decoder destruction function */ 280 | decoder_destroy_func dec_destroy; 281 | 282 | /** Pointer to frame decoding function */ 283 | decode_func dec; 284 | 285 | /** ioctl-like requests for encoder */ 286 | encoder_ctl_func enc_ctl; 287 | 288 | /** ioctl-like requests for decoder */ 289 | decoder_ctl_func dec_ctl; 290 | 291 | } SpeexMode; 292 | 293 | /** 294 | * Returns a handle to a newly created Speex encoder state structure. For now, 295 | * the "mode" argument can be &nb_mode or &wb_mode . In the future, more modes 296 | * may be added. Note that for now if you have more than one channels to 297 | * encode, you need one state per channel. 298 | * 299 | * @param mode The mode to use (either speex_nb_mode or speex_wb.mode) 300 | * @return A newly created encoder state or NULL if state allocation fails 301 | */ 302 | void *speex_encoder_init(const SpeexMode *mode); 303 | 304 | /** Frees all resources associated to an existing Speex encoder state. 305 | * @param state Encoder state to be destroyed */ 306 | void speex_encoder_destroy(void *state); 307 | 308 | /** Uses an existing encoder state to encode one frame of speech pointed to by 309 | "in". The encoded bit-stream is saved in "bits". 310 | @param state Encoder state 311 | @param in Frame that will be encoded with a +-2^15 range. This data MAY be 312 | overwritten by the encoder and should be considered uninitialised 313 | after the call. 314 | @param bits Bit-stream where the data will be written 315 | @return 0 if frame needs not be transmitted (DTX only), 1 otherwise 316 | */ 317 | int speex_encode(void *state, float *in, SpeexBits *bits); 318 | 319 | /** Uses an existing encoder state to encode one frame of speech pointed to by 320 | "in". The encoded bit-stream is saved in "bits". 321 | @param state Encoder state 322 | @param in Frame that will be encoded with a +-2^15 range 323 | @param bits Bit-stream where the data will be written 324 | @return 0 if frame needs not be transmitted (DTX only), 1 otherwise 325 | */ 326 | int speex_encode_int(void *state, spx_int16_t *in, SpeexBits *bits); 327 | 328 | /** Used like the ioctl function to control the encoder parameters 329 | * 330 | * @param state Encoder state 331 | * @param request ioctl-type request (one of the SPEEX_* macros) 332 | * @param ptr Data exchanged to-from function 333 | * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter 334 | */ 335 | int speex_encoder_ctl(void *state, int request, void *ptr); 336 | 337 | 338 | /** Returns a handle to a newly created decoder state structure. For now, 339 | * the mode argument can be &nb_mode or &wb_mode . In the future, more modes 340 | * may be added. Note that for now if you have more than one channels to 341 | * decode, you need one state per channel. 342 | * 343 | * @param mode Speex mode (one of speex_nb_mode or speex_wb_mode) 344 | * @return A newly created decoder state or NULL if state allocation fails 345 | */ 346 | void *speex_decoder_init(const SpeexMode *mode); 347 | 348 | /** Frees all resources associated to an existing decoder state. 349 | * 350 | * @param state State to be destroyed 351 | */ 352 | void speex_decoder_destroy(void *state); 353 | 354 | /** Uses an existing decoder state to decode one frame of speech from 355 | * bit-stream bits. The output speech is saved written to out. 356 | * 357 | * @param state Decoder state 358 | * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost) 359 | * @param out Where to write the decoded frame 360 | * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream) 361 | */ 362 | int speex_decode(void *state, SpeexBits *bits, float *out); 363 | 364 | /** Uses an existing decoder state to decode one frame of speech from 365 | * bit-stream bits. The output speech is saved written to out. 366 | * 367 | * @param state Decoder state 368 | * @param bits Bit-stream from which to decode the frame (NULL if the packet was lost) 369 | * @param out Where to write the decoded frame 370 | * @return return status (0 for no error, -1 for end of stream, -2 corrupt stream) 371 | */ 372 | int speex_decode_int(void *state, SpeexBits *bits, spx_int16_t *out); 373 | 374 | /** Used like the ioctl function to control the encoder parameters 375 | * 376 | * @param state Decoder state 377 | * @param request ioctl-type request (one of the SPEEX_* macros) 378 | * @param ptr Data exchanged to-from function 379 | * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter 380 | */ 381 | int speex_decoder_ctl(void *state, int request, void *ptr); 382 | 383 | 384 | /** Query function for mode information 385 | * 386 | * @param mode Speex mode 387 | * @param request ioctl-type request (one of the SPEEX_* macros) 388 | * @param ptr Data exchanged to-from function 389 | * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter 390 | */ 391 | int speex_mode_query(const SpeexMode *mode, int request, void *ptr); 392 | 393 | /** Functions for controlling the behavior of libspeex 394 | * @param request ioctl-type request (one of the SPEEX_LIB_* macros) 395 | * @param ptr Data exchanged to-from function 396 | * @return 0 if no error, -1 if request in unknown, -2 for invalid parameter 397 | */ 398 | int speex_lib_ctl(int request, void *ptr); 399 | 400 | /** Default narrowband mode */ 401 | extern const SpeexMode speex_nb_mode; 402 | 403 | /** Default wideband mode */ 404 | extern const SpeexMode speex_wb_mode; 405 | 406 | /** Default "ultra-wideband" mode */ 407 | extern const SpeexMode speex_uwb_mode; 408 | 409 | /** List of all modes available */ 410 | extern const SpeexMode * const speex_mode_list[SPEEX_NB_MODES]; 411 | 412 | /** Obtain one of the modes available */ 413 | const SpeexMode * speex_lib_get_mode (int mode); 414 | 415 | #ifndef WIN32 416 | /* We actually override the function in the narrowband case so that we can avoid linking in the wideband stuff */ 417 | #define speex_lib_get_mode(mode) ((mode)==SPEEX_MODEID_NB ? &speex_nb_mode : speex_lib_get_mode (mode)) 418 | #endif 419 | 420 | #ifdef __cplusplus 421 | } 422 | #endif 423 | 424 | /** @}*/ 425 | #endif 426 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speex_bits.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002 Jean-Marc Valin */ 2 | /** 3 | @file speex_bits.h 4 | @brief Handles bit packing/unpacking 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | - Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | - Neither the name of the Xiph.org Foundation nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | */ 35 | 36 | #ifndef BITS_H 37 | #define BITS_H 38 | /** @defgroup SpeexBits SpeexBits: Bit-stream manipulations 39 | * This is the structure that holds the bit-stream when encoding or decoding 40 | * with Speex. It allows some manipulations as well. 41 | * @{ 42 | */ 43 | 44 | #ifdef __cplusplus 45 | extern "C" { 46 | #endif 47 | 48 | /** Bit-packing data structure representing (part of) a bit-stream. */ 49 | typedef struct SpeexBits { 50 | char *chars; /**< "raw" data */ 51 | int nbBits; /**< Total number of bits stored in the stream*/ 52 | int charPtr; /**< Position of the byte "cursor" */ 53 | int bitPtr; /**< Position of the bit "cursor" within the current char */ 54 | int owner; /**< Does the struct "own" the "raw" buffer (member "chars") */ 55 | int overflow;/**< Set to one if we try to read past the valid data */ 56 | int buf_size;/**< Allocated size for buffer */ 57 | int reserved1; /**< Reserved for future use */ 58 | void *reserved2; /**< Reserved for future use */ 59 | } SpeexBits; 60 | 61 | /** Initializes and allocates resources for a SpeexBits struct */ 62 | void speex_bits_init(SpeexBits *bits); 63 | 64 | /** Initializes SpeexBits struct using a pre-allocated buffer*/ 65 | void speex_bits_init_buffer(SpeexBits *bits, void *buff, int buf_size); 66 | 67 | /** Sets the bits in a SpeexBits struct to use data from an existing buffer (for decoding without copying data) */ 68 | void speex_bits_set_bit_buffer(SpeexBits *bits, void *buff, int buf_size); 69 | 70 | /** Frees all resources associated to a SpeexBits struct. Right now this does nothing since no resources are allocated, but this could change in the future.*/ 71 | void speex_bits_destroy(SpeexBits *bits); 72 | 73 | /** Resets bits to initial value (just after initialization, erasing content)*/ 74 | void speex_bits_reset(SpeexBits *bits); 75 | 76 | /** Rewind the bit-stream to the beginning (ready for read) without erasing the content */ 77 | void speex_bits_rewind(SpeexBits *bits); 78 | 79 | /** Initializes the bit-stream from the data in an area of memory */ 80 | void speex_bits_read_from(SpeexBits *bits, const char *bytes, int len); 81 | 82 | /** Append bytes to the bit-stream 83 | * 84 | * @param bits Bit-stream to operate on 85 | * @param bytes pointer to the bytes what will be appended 86 | * @param len Number of bytes of append 87 | */ 88 | void speex_bits_read_whole_bytes(SpeexBits *bits, const char *bytes, int len); 89 | 90 | /** Write the content of a bit-stream to an area of memory 91 | * 92 | * @param bits Bit-stream to operate on 93 | * @param bytes Memory location where to write the bits 94 | * @param max_len Maximum number of bytes to write (i.e. size of the "bytes" buffer) 95 | * @return Number of bytes written to the "bytes" buffer 96 | */ 97 | int speex_bits_write(SpeexBits *bits, char *bytes, int max_len); 98 | 99 | /** Like speex_bits_write, but writes only the complete bytes in the stream. Also removes the written bytes from the stream */ 100 | int speex_bits_write_whole_bytes(SpeexBits *bits, char *bytes, int max_len); 101 | 102 | /** Append bits to the bit-stream 103 | * @param bits Bit-stream to operate on 104 | * @param data Value to append as integer 105 | * @param nbBits number of bits to consider in "data" 106 | */ 107 | void speex_bits_pack(SpeexBits *bits, int data, int nbBits); 108 | 109 | /** Interpret the next bits in the bit-stream as a signed integer 110 | * 111 | * @param bits Bit-stream to operate on 112 | * @param nbBits Number of bits to interpret 113 | * @return A signed integer represented by the bits read 114 | */ 115 | int speex_bits_unpack_signed(SpeexBits *bits, int nbBits); 116 | 117 | /** Interpret the next bits in the bit-stream as an unsigned integer 118 | * 119 | * @param bits Bit-stream to operate on 120 | * @param nbBits Number of bits to interpret 121 | * @return An unsigned integer represented by the bits read 122 | */ 123 | unsigned int speex_bits_unpack_unsigned(SpeexBits *bits, int nbBits); 124 | 125 | /** Returns the number of bytes in the bit-stream, including the last one even if it is not "full" 126 | * 127 | * @param bits Bit-stream to operate on 128 | * @return Number of bytes in the stream 129 | */ 130 | int speex_bits_nbytes(SpeexBits *bits); 131 | 132 | /** Same as speex_bits_unpack_unsigned, but without modifying the cursor position 133 | * 134 | * @param bits Bit-stream to operate on 135 | * @param nbBits Number of bits to look for 136 | * @return Value of the bits peeked, interpreted as unsigned 137 | */ 138 | unsigned int speex_bits_peek_unsigned(SpeexBits *bits, int nbBits); 139 | 140 | /** Get the value of the next bit in the stream, without modifying the 141 | * "cursor" position 142 | * 143 | * @param bits Bit-stream to operate on 144 | * @return Value of the bit peeked (one bit only) 145 | */ 146 | int speex_bits_peek(SpeexBits *bits); 147 | 148 | /** Advances the position of the "bit cursor" in the stream 149 | * 150 | * @param bits Bit-stream to operate on 151 | * @param n Number of bits to advance 152 | */ 153 | void speex_bits_advance(SpeexBits *bits, int n); 154 | 155 | /** Returns the number of bits remaining to be read in a stream 156 | * 157 | * @param bits Bit-stream to operate on 158 | * @return Number of bits that can still be read from the stream 159 | */ 160 | int speex_bits_remaining(SpeexBits *bits); 161 | 162 | /** Insert a terminator so that the data can be sent as a packet while auto-detecting 163 | * the number of frames in each packet 164 | * 165 | * @param bits Bit-stream to operate on 166 | */ 167 | void speex_bits_insert_terminator(SpeexBits *bits); 168 | 169 | #ifdef __cplusplus 170 | } 171 | #endif 172 | 173 | /* @} */ 174 | #endif 175 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speex_buffer.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2007 Jean-Marc Valin 2 | 3 | File: speex_buffer.h 4 | This is a very simple ring buffer implementation. It is not thread-safe 5 | so you need to do your own locking. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are 9 | met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | 14 | 2. Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | 3. The name of the author may not be used to endorse or promote products 19 | derived from this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef SPEEX_BUFFER_H 35 | #define SPEEX_BUFFER_H 36 | 37 | #include "speexdsp_types.h" 38 | 39 | #ifdef __cplusplus 40 | extern "C" { 41 | #endif 42 | 43 | struct SpeexBuffer_; 44 | typedef struct SpeexBuffer_ SpeexBuffer; 45 | 46 | SpeexBuffer *speex_buffer_init(int size); 47 | 48 | void speex_buffer_destroy(SpeexBuffer *st); 49 | 50 | int speex_buffer_write(SpeexBuffer *st, void *data, int len); 51 | 52 | int speex_buffer_writezeros(SpeexBuffer *st, int len); 53 | 54 | int speex_buffer_read(SpeexBuffer *st, void *data, int len); 55 | 56 | int speex_buffer_get_available(SpeexBuffer *st); 57 | 58 | int speex_buffer_resize(SpeexBuffer *st, int len); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speex_callbacks.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002 Jean-Marc Valin*/ 2 | /** 3 | @file speex_callbacks.h 4 | @brief Describes callback handling and in-band signalling 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | - Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | - Neither the name of the Xiph.org Foundation nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | */ 35 | 36 | #ifndef SPEEX_CALLBACKS_H 37 | #define SPEEX_CALLBACKS_H 38 | /** @defgroup SpeexCallbacks Various definitions for Speex callbacks supported by the decoder. 39 | * @{ 40 | */ 41 | 42 | #include "speex.h" 43 | 44 | #ifdef __cplusplus 45 | extern "C" { 46 | #endif 47 | 48 | /** Total number of callbacks */ 49 | #define SPEEX_MAX_CALLBACKS 16 50 | 51 | /* Describes all the in-band requests */ 52 | 53 | /*These are 1-bit requests*/ 54 | /** Request for perceptual enhancement (1 for on, 0 for off) */ 55 | #define SPEEX_INBAND_ENH_REQUEST 0 56 | /** Reserved */ 57 | #define SPEEX_INBAND_RESERVED1 1 58 | 59 | /*These are 4-bit requests*/ 60 | /** Request for a mode change */ 61 | #define SPEEX_INBAND_MODE_REQUEST 2 62 | /** Request for a low mode change */ 63 | #define SPEEX_INBAND_LOW_MODE_REQUEST 3 64 | /** Request for a high mode change */ 65 | #define SPEEX_INBAND_HIGH_MODE_REQUEST 4 66 | /** Request for VBR (1 on, 0 off) */ 67 | #define SPEEX_INBAND_VBR_QUALITY_REQUEST 5 68 | /** Request to be sent acknowledge */ 69 | #define SPEEX_INBAND_ACKNOWLEDGE_REQUEST 6 70 | /** Request for VBR (1 for on, 0 for off) */ 71 | #define SPEEX_INBAND_VBR_REQUEST 7 72 | 73 | /*These are 8-bit requests*/ 74 | /** Send a character in-band */ 75 | #define SPEEX_INBAND_CHAR 8 76 | /** Intensity stereo information */ 77 | #define SPEEX_INBAND_STEREO 9 78 | 79 | /*These are 16-bit requests*/ 80 | /** Transmit max bit-rate allowed */ 81 | #define SPEEX_INBAND_MAX_BITRATE 10 82 | 83 | /*These are 32-bit requests*/ 84 | /** Acknowledge packet reception */ 85 | #define SPEEX_INBAND_ACKNOWLEDGE 12 86 | 87 | /** Callback function type */ 88 | typedef int (*speex_callback_func)(SpeexBits *bits, void *state, void *data); 89 | 90 | /** Callback information */ 91 | typedef struct SpeexCallback { 92 | int callback_id; /**< ID associated to the callback */ 93 | speex_callback_func func; /**< Callback handler function */ 94 | void *data; /**< Data that will be sent to the handler */ 95 | void *reserved1; /**< Reserved for future use */ 96 | int reserved2; /**< Reserved for future use */ 97 | } SpeexCallback; 98 | 99 | /** Handle in-band request */ 100 | int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state); 101 | 102 | /** Standard handler for mode request (change mode, no questions asked) */ 103 | int speex_std_mode_request_handler(SpeexBits *bits, void *state, void *data); 104 | 105 | /** Standard handler for high mode request (change high mode, no questions asked) */ 106 | int speex_std_high_mode_request_handler(SpeexBits *bits, void *state, void *data); 107 | 108 | /** Standard handler for in-band characters (write to stderr) */ 109 | int speex_std_char_handler(SpeexBits *bits, void *state, void *data); 110 | 111 | /** Default handler for user-defined requests: in this case, just ignore */ 112 | int speex_default_user_handler(SpeexBits *bits, void *state, void *data); 113 | 114 | 115 | 116 | /** Standard handler for low mode request (change low mode, no questions asked) */ 117 | int speex_std_low_mode_request_handler(SpeexBits *bits, void *state, void *data); 118 | 119 | /** Standard handler for VBR request (Set VBR, no questions asked) */ 120 | int speex_std_vbr_request_handler(SpeexBits *bits, void *state, void *data); 121 | 122 | /** Standard handler for enhancer request (Turn enhancer on/off, no questions asked) */ 123 | int speex_std_enh_request_handler(SpeexBits *bits, void *state, void *data); 124 | 125 | /** Standard handler for VBR quality request (Set VBR quality, no questions asked) */ 126 | int speex_std_vbr_quality_request_handler(SpeexBits *bits, void *state, void *data); 127 | 128 | 129 | #ifdef __cplusplus 130 | } 131 | #endif 132 | 133 | /** @} */ 134 | #endif 135 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speex_config_types.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPEEX_TYPES_H__ 2 | #define __SPEEX_TYPES_H__ 3 | typedef short spx_int16_t; 4 | typedef unsigned short spx_uint16_t; 5 | typedef int spx_int32_t; 6 | typedef unsigned int spx_uint32_t; 7 | #endif 8 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speex_echo.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) Jean-Marc Valin */ 2 | /** 3 | @file speex_echo.h 4 | @brief Echo cancellation 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are 9 | met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | 14 | 2. Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | 3. The name of the author may not be used to endorse or promote products 19 | derived from this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef SPEEX_ECHO_H 35 | #define SPEEX_ECHO_H 36 | /** @defgroup SpeexEchoState SpeexEchoState: Acoustic echo canceller 37 | * This is the acoustic echo canceller module. 38 | * @{ 39 | */ 40 | #include "speexdsp_types.h" 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | /** Obtain frame size used by the AEC */ 47 | #define SPEEX_ECHO_GET_FRAME_SIZE 3 48 | 49 | /** Set sampling rate */ 50 | #define SPEEX_ECHO_SET_SAMPLING_RATE 24 51 | /** Get sampling rate */ 52 | #define SPEEX_ECHO_GET_SAMPLING_RATE 25 53 | 54 | /* Can't set window sizes */ 55 | /** Get size of impulse response (int32) */ 56 | #define SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE 27 57 | 58 | /* Can't set window content */ 59 | /** Get impulse response (int32[]) */ 60 | #define SPEEX_ECHO_GET_IMPULSE_RESPONSE 29 61 | 62 | /** Internal echo canceller state. Should never be accessed directly. */ 63 | struct SpeexEchoState_; 64 | 65 | /** @class SpeexEchoState 66 | * This holds the state of the echo canceller. You need one per channel. 67 | */ 68 | 69 | /** Internal echo canceller state. Should never be accessed directly. */ 70 | typedef struct SpeexEchoState_ SpeexEchoState; 71 | 72 | /** Creates a new echo canceller state 73 | * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms) 74 | * @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms) 75 | * @return Newly-created echo canceller state 76 | */ 77 | SpeexEchoState *speex_echo_state_init(int frame_size, int filter_length); 78 | 79 | /** Creates a new multi-channel echo canceller state 80 | * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms) 81 | * @param filter_length Number of samples of echo to cancel (should generally correspond to 100-500 ms) 82 | * @param nb_mic Number of microphone channels 83 | * @param nb_speakers Number of speaker channels 84 | * @return Newly-created echo canceller state 85 | */ 86 | SpeexEchoState *speex_echo_state_init_mc(int frame_size, int filter_length, int nb_mic, int nb_speakers); 87 | 88 | /** Destroys an echo canceller state 89 | * @param st Echo canceller state 90 | */ 91 | void speex_echo_state_destroy(SpeexEchoState *st); 92 | 93 | /** Performs echo cancellation a frame, based on the audio sent to the speaker (no delay is added 94 | * to playback in this form) 95 | * 96 | * @param st Echo canceller state 97 | * @param rec Signal from the microphone (near end + far end echo) 98 | * @param play Signal played to the speaker (received from far end) 99 | * @param out Returns near-end signal with echo removed 100 | */ 101 | void speex_echo_cancellation(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out); 102 | 103 | /** Performs echo cancellation a frame (deprecated) */ 104 | void speex_echo_cancel(SpeexEchoState *st, const spx_int16_t *rec, const spx_int16_t *play, spx_int16_t *out, spx_int32_t *Yout); 105 | 106 | /** Perform echo cancellation using internal playback buffer, which is delayed by two frames 107 | * to account for the delay introduced by most soundcards (but it could be off!) 108 | * @param st Echo canceller state 109 | * @param rec Signal from the microphone (near end + far end echo) 110 | * @param out Returns near-end signal with echo removed 111 | */ 112 | void speex_echo_capture(SpeexEchoState *st, const spx_int16_t *rec, spx_int16_t *out); 113 | 114 | /** Let the echo canceller know that a frame was just queued to the soundcard 115 | * @param st Echo canceller state 116 | * @param play Signal played to the speaker (received from far end) 117 | */ 118 | void speex_echo_playback(SpeexEchoState *st, const spx_int16_t *play); 119 | 120 | /** Reset the echo canceller to its original state 121 | * @param st Echo canceller state 122 | */ 123 | void speex_echo_state_reset(SpeexEchoState *st); 124 | 125 | /** Used like the ioctl function to control the echo canceller parameters 126 | * 127 | * @param st Echo canceller state 128 | * @param request ioctl-type request (one of the SPEEX_ECHO_* macros) 129 | * @param ptr Data exchanged to-from function 130 | * @return 0 if no error, -1 if request in unknown 131 | */ 132 | int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr); 133 | 134 | 135 | 136 | struct SpeexDecorrState_; 137 | 138 | typedef struct SpeexDecorrState_ SpeexDecorrState; 139 | 140 | 141 | /** Create a state for the channel decorrelation algorithm 142 | This is useful for multi-channel echo cancellation only 143 | * @param rate Sampling rate 144 | * @param channels Number of channels (it's a bit pointless if you don't have at least 2) 145 | * @param frame_size Size of the frame to process at ones (counting samples *per* channel) 146 | */ 147 | SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size); 148 | 149 | /** Remove correlation between the channels by modifying the phase and possibly 150 | adding noise in a way that is not (or little) perceptible. 151 | * @param st Decorrelator state 152 | * @param in Input audio in interleaved format 153 | * @param out Result of the decorrelation (out *may* alias in) 154 | * @param strength How much alteration of the audio to apply from 0 to 100. 155 | */ 156 | void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength); 157 | 158 | /** Destroy a Decorrelation state 159 | * @param st State to destroy 160 | */ 161 | void speex_decorrelate_destroy(SpeexDecorrState *st); 162 | 163 | 164 | #ifdef __cplusplus 165 | } 166 | #endif 167 | 168 | 169 | /** @}*/ 170 | #endif 171 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speex_header.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002 Jean-Marc Valin */ 2 | /** 3 | @file speex_header.h 4 | @brief Describes the Speex header 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | - Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | - Neither the name of the Xiph.org Foundation nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | */ 35 | 36 | 37 | #ifndef SPEEX_HEADER_H 38 | #define SPEEX_HEADER_H 39 | /** @defgroup SpeexHeader SpeexHeader: Makes it easy to write/parse an Ogg/Speex header 40 | * This is the Speex header for the Ogg encapsulation. You don't need that if you just use RTP. 41 | * @{ 42 | */ 43 | 44 | #include "speex_types.h" 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | struct SpeexMode; 51 | 52 | /** Length of the Speex header identifier */ 53 | #define SPEEX_HEADER_STRING_LENGTH 8 54 | 55 | /** Maximum number of characters for encoding the Speex version number in the header */ 56 | #define SPEEX_HEADER_VERSION_LENGTH 20 57 | 58 | /** Speex header info for file-based formats */ 59 | typedef struct SpeexHeader { 60 | char speex_string[SPEEX_HEADER_STRING_LENGTH]; /**< Identifies a Speex bit-stream, always set to "Speex " */ 61 | char speex_version[SPEEX_HEADER_VERSION_LENGTH]; /**< Speex version */ 62 | spx_int32_t speex_version_id; /**< Version for Speex (for checking compatibility) */ 63 | spx_int32_t header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */ 64 | spx_int32_t rate; /**< Sampling rate used */ 65 | spx_int32_t mode; /**< Mode used (0 for narrowband, 1 for wideband) */ 66 | spx_int32_t mode_bitstream_version; /**< Version ID of the bit-stream */ 67 | spx_int32_t nb_channels; /**< Number of channels encoded */ 68 | spx_int32_t bitrate; /**< Bit-rate used */ 69 | spx_int32_t frame_size; /**< Size of frames */ 70 | spx_int32_t vbr; /**< 1 for a VBR encoding, 0 otherwise */ 71 | spx_int32_t frames_per_packet; /**< Number of frames stored per Ogg packet */ 72 | spx_int32_t extra_headers; /**< Number of additional headers after the comments */ 73 | spx_int32_t reserved1; /**< Reserved for future use, must be zero */ 74 | spx_int32_t reserved2; /**< Reserved for future use, must be zero */ 75 | } SpeexHeader; 76 | 77 | /** Initializes a SpeexHeader using basic information */ 78 | void speex_init_header(SpeexHeader *header, int rate, int nb_channels, const struct SpeexMode *m); 79 | 80 | /** Creates the header packet from the header itself (mostly involves endianness conversion) */ 81 | char *speex_header_to_packet(SpeexHeader *header, int *size); 82 | 83 | /** Creates a SpeexHeader from a packet */ 84 | SpeexHeader *speex_packet_to_header(char *packet, int size); 85 | 86 | /** Frees the memory allocated by either speex_header_to_packet() or speex_packet_to_header() */ 87 | void speex_header_free(void *ptr); 88 | 89 | #ifdef __cplusplus 90 | } 91 | #endif 92 | 93 | /** @} */ 94 | #endif 95 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speex_jitter.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002 Jean-Marc Valin */ 2 | /** 3 | @file speex_jitter.h 4 | @brief Adaptive jitter buffer for Speex 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | - Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | - Neither the name of the Xiph.org Foundation nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | 34 | */ 35 | 36 | #ifndef SPEEX_JITTER_H 37 | #define SPEEX_JITTER_H 38 | /** @defgroup JitterBuffer JitterBuffer: Adaptive jitter buffer 39 | * This is the jitter buffer that reorders UDP/RTP packets and adjusts the buffer size 40 | * to maintain good quality and low latency. 41 | * @{ 42 | */ 43 | 44 | #include "speexdsp_types.h" 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | /** Generic adaptive jitter buffer state */ 51 | struct JitterBuffer_; 52 | 53 | /** Generic adaptive jitter buffer state */ 54 | typedef struct JitterBuffer_ JitterBuffer; 55 | 56 | /** Definition of an incoming packet */ 57 | typedef struct _JitterBufferPacket JitterBufferPacket; 58 | 59 | /** Definition of an incoming packet */ 60 | struct _JitterBufferPacket { 61 | char *data; /**< Data bytes contained in the packet */ 62 | spx_uint32_t len; /**< Length of the packet in bytes */ 63 | spx_uint32_t timestamp; /**< Timestamp for the packet */ 64 | spx_uint32_t span; /**< Time covered by the packet (same units as timestamp) */ 65 | spx_uint16_t sequence; /**< RTP Sequence number if available (0 otherwise) */ 66 | spx_uint32_t user_data; /**< Put whatever data you like here (it's ignored by the jitter buffer) */ 67 | }; 68 | 69 | /** Packet has been retrieved */ 70 | #define JITTER_BUFFER_OK 0 71 | /** Packet is lost or is late */ 72 | #define JITTER_BUFFER_MISSING 1 73 | /** A "fake" packet is meant to be inserted here to increase buffering */ 74 | #define JITTER_BUFFER_INSERTION 2 75 | /** There was an error in the jitter buffer */ 76 | #define JITTER_BUFFER_INTERNAL_ERROR -1 77 | /** Invalid argument */ 78 | #define JITTER_BUFFER_BAD_ARGUMENT -2 79 | 80 | 81 | /** Set minimum amount of extra buffering required (margin) */ 82 | #define JITTER_BUFFER_SET_MARGIN 0 83 | /** Get minimum amount of extra buffering required (margin) */ 84 | #define JITTER_BUFFER_GET_MARGIN 1 85 | /* JITTER_BUFFER_SET_AVAILABLE_COUNT wouldn't make sense */ 86 | 87 | /** Get the amount of available packets currently buffered */ 88 | #define JITTER_BUFFER_GET_AVAILABLE_COUNT 3 89 | /** Included because of an early misspelling (will remove in next release) */ 90 | #define JITTER_BUFFER_GET_AVALIABLE_COUNT 3 91 | 92 | /** Assign a function to destroy unused packet. When setting that, the jitter 93 | buffer no longer copies packet data. */ 94 | #define JITTER_BUFFER_SET_DESTROY_CALLBACK 4 95 | /** */ 96 | #define JITTER_BUFFER_GET_DESTROY_CALLBACK 5 97 | 98 | /** Tell the jitter buffer to only adjust the delay in multiples of the step parameter provided */ 99 | #define JITTER_BUFFER_SET_DELAY_STEP 6 100 | /** */ 101 | #define JITTER_BUFFER_GET_DELAY_STEP 7 102 | 103 | /** Tell the jitter buffer to only do concealment in multiples of the size parameter provided */ 104 | #define JITTER_BUFFER_SET_CONCEALMENT_SIZE 8 105 | #define JITTER_BUFFER_GET_CONCEALMENT_SIZE 9 106 | 107 | /** Absolute max amount of loss that can be tolerated regardless of the delay. Typical loss 108 | should be half of that or less. */ 109 | #define JITTER_BUFFER_SET_MAX_LATE_RATE 10 110 | #define JITTER_BUFFER_GET_MAX_LATE_RATE 11 111 | 112 | /** Equivalent cost of one percent late packet in timestamp units */ 113 | #define JITTER_BUFFER_SET_LATE_COST 12 114 | #define JITTER_BUFFER_GET_LATE_COST 13 115 | 116 | 117 | /** Initialises jitter buffer 118 | * 119 | * @param step_size Starting value for the size of concleanment packets and delay 120 | adjustment steps. Can be changed at any time using JITTER_BUFFER_SET_DELAY_STEP 121 | and JITTER_BUFFER_GET_CONCEALMENT_SIZE. 122 | * @return Newly created jitter buffer state 123 | */ 124 | JitterBuffer *jitter_buffer_init(int step_size); 125 | 126 | /** Restores jitter buffer to its original state 127 | * 128 | * @param jitter Jitter buffer state 129 | */ 130 | void jitter_buffer_reset(JitterBuffer *jitter); 131 | 132 | /** Destroys jitter buffer 133 | * 134 | * @param jitter Jitter buffer state 135 | */ 136 | void jitter_buffer_destroy(JitterBuffer *jitter); 137 | 138 | /** Put one packet into the jitter buffer 139 | * 140 | * @param jitter Jitter buffer state 141 | * @param packet Incoming packet 142 | */ 143 | void jitter_buffer_put(JitterBuffer *jitter, const JitterBufferPacket *packet); 144 | 145 | /** Get one packet from the jitter buffer 146 | * 147 | * @param jitter Jitter buffer state 148 | * @param packet Returned packet 149 | * @param desired_span Number of samples (or units) we wish to get from the buffer (no guarantee) 150 | * @param current_timestamp Timestamp for the returned packet 151 | */ 152 | int jitter_buffer_get(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t desired_span, spx_int32_t *start_offset); 153 | 154 | /** Used right after jitter_buffer_get() to obtain another packet that would have the same timestamp. 155 | * This is mainly useful for media where a single "frame" can be split into several packets. 156 | * 157 | * @param jitter Jitter buffer state 158 | * @param packet Returned packet 159 | */ 160 | int jitter_buffer_get_another(JitterBuffer *jitter, JitterBufferPacket *packet); 161 | 162 | /** Get pointer timestamp of jitter buffer 163 | * 164 | * @param jitter Jitter buffer state 165 | */ 166 | int jitter_buffer_get_pointer_timestamp(JitterBuffer *jitter); 167 | 168 | /** Advance by one tick 169 | * 170 | * @param jitter Jitter buffer state 171 | */ 172 | void jitter_buffer_tick(JitterBuffer *jitter); 173 | 174 | /** Telling the jitter buffer about the remaining data in the application buffer 175 | * @param jitter Jitter buffer state 176 | * @param rem Amount of data buffered by the application (timestamp units) 177 | */ 178 | void jitter_buffer_remaining_span(JitterBuffer *jitter, spx_uint32_t rem); 179 | 180 | /** Used like the ioctl function to control the jitter buffer parameters 181 | * 182 | * @param jitter Jitter buffer state 183 | * @param request ioctl-type request (one of the JITTER_BUFFER_* macros) 184 | * @param ptr Data exchanged to-from function 185 | * @return 0 if no error, -1 if request in unknown 186 | */ 187 | int jitter_buffer_ctl(JitterBuffer *jitter, int request, void *ptr); 188 | 189 | int jitter_buffer_update_delay(JitterBuffer *jitter, JitterBufferPacket *packet, spx_int32_t *start_offset); 190 | 191 | /* @} */ 192 | 193 | #ifdef __cplusplus 194 | } 195 | #endif 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speex_preprocess.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2003 Epic Games 2 | Written by Jean-Marc Valin */ 3 | /** 4 | * @file speex_preprocess.h 5 | * @brief Speex preprocessor. The preprocess can do noise suppression, 6 | * residual echo suppression (after using the echo canceller), automatic 7 | * gain control (AGC) and voice activity detection (VAD). 8 | */ 9 | /* 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are 12 | met: 13 | 14 | 1. Redistributions of source code must retain the above copyright notice, 15 | this list of conditions and the following disclaimer. 16 | 17 | 2. Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in the 19 | documentation and/or other materials provided with the distribution. 20 | 21 | 3. The name of the author may not be used to endorse or promote products 22 | derived from this software without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 25 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 26 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 28 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 32 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 | POSSIBILITY OF SUCH DAMAGE. 35 | */ 36 | 37 | #ifndef SPEEX_PREPROCESS_H 38 | #define SPEEX_PREPROCESS_H 39 | /** @defgroup SpeexPreprocessState SpeexPreprocessState: The Speex preprocessor 40 | * This is the Speex preprocessor. The preprocess can do noise suppression, 41 | * residual echo suppression (after using the echo canceller), automatic 42 | * gain control (AGC) and voice activity detection (VAD). 43 | * @{ 44 | */ 45 | 46 | #include "speexdsp_types.h" 47 | 48 | #ifdef __cplusplus 49 | extern "C" { 50 | #endif 51 | 52 | /** State of the preprocessor (one per channel). Should never be accessed directly. */ 53 | struct SpeexPreprocessState_; 54 | 55 | /** State of the preprocessor (one per channel). Should never be accessed directly. */ 56 | typedef struct SpeexPreprocessState_ SpeexPreprocessState; 57 | 58 | 59 | /** Creates a new preprocessing state. You MUST create one state per channel processed. 60 | * @param frame_size Number of samples to process at one time (should correspond to 10-20 ms). Must be 61 | * the same value as that used for the echo canceller for residual echo cancellation to work. 62 | * @param sampling_rate Sampling rate used for the input. 63 | * @return Newly created preprocessor state 64 | */ 65 | SpeexPreprocessState *speex_preprocess_state_init(int frame_size, int sampling_rate); 66 | 67 | /** Destroys a preprocessor state 68 | * @param st Preprocessor state to destroy 69 | */ 70 | void speex_preprocess_state_destroy(SpeexPreprocessState *st); 71 | 72 | /** Preprocess a frame 73 | * @param st Preprocessor state 74 | * @param x Audio sample vector (in and out). Must be same size as specified in speex_preprocess_state_init(). 75 | * @return Bool value for voice activity (1 for speech, 0 for noise/silence), ONLY if VAD turned on. 76 | */ 77 | int speex_preprocess_run(SpeexPreprocessState *st, spx_int16_t *x); 78 | 79 | /** Preprocess a frame (deprecated, use speex_preprocess_run() instead)*/ 80 | int speex_preprocess(SpeexPreprocessState *st, spx_int16_t *x, spx_int32_t *echo); 81 | 82 | /** Update preprocessor state, but do not compute the output 83 | * @param st Preprocessor state 84 | * @param x Audio sample vector (in only). Must be same size as specified in speex_preprocess_state_init(). 85 | */ 86 | void speex_preprocess_estimate_update(SpeexPreprocessState *st, spx_int16_t *x); 87 | 88 | /** Used like the ioctl function to control the preprocessor parameters 89 | * @param st Preprocessor state 90 | * @param request ioctl-type request (one of the SPEEX_PREPROCESS_* macros) 91 | * @param ptr Data exchanged to-from function 92 | * @return 0 if no error, -1 if request in unknown 93 | */ 94 | int speex_preprocess_ctl(SpeexPreprocessState *st, int request, void *ptr); 95 | 96 | 97 | 98 | /** Set preprocessor denoiser state */ 99 | #define SPEEX_PREPROCESS_SET_DENOISE 0 100 | /** Get preprocessor denoiser state */ 101 | #define SPEEX_PREPROCESS_GET_DENOISE 1 102 | 103 | /** Set preprocessor Automatic Gain Control state */ 104 | #define SPEEX_PREPROCESS_SET_AGC 2 105 | /** Get preprocessor Automatic Gain Control state */ 106 | #define SPEEX_PREPROCESS_GET_AGC 3 107 | 108 | /** Set preprocessor Voice Activity Detection state */ 109 | #define SPEEX_PREPROCESS_SET_VAD 4 110 | /** Get preprocessor Voice Activity Detection state */ 111 | #define SPEEX_PREPROCESS_GET_VAD 5 112 | 113 | /** Set preprocessor Automatic Gain Control level (float) */ 114 | #define SPEEX_PREPROCESS_SET_AGC_LEVEL 6 115 | /** Get preprocessor Automatic Gain Control level (float) */ 116 | #define SPEEX_PREPROCESS_GET_AGC_LEVEL 7 117 | 118 | /** Set preprocessor dereverb state */ 119 | #define SPEEX_PREPROCESS_SET_DEREVERB 8 120 | /** Get preprocessor dereverb state */ 121 | #define SPEEX_PREPROCESS_GET_DEREVERB 9 122 | 123 | /** Set preprocessor dereverb level */ 124 | #define SPEEX_PREPROCESS_SET_DEREVERB_LEVEL 10 125 | /** Get preprocessor dereverb level */ 126 | #define SPEEX_PREPROCESS_GET_DEREVERB_LEVEL 11 127 | 128 | /** Set preprocessor dereverb decay */ 129 | #define SPEEX_PREPROCESS_SET_DEREVERB_DECAY 12 130 | /** Get preprocessor dereverb decay */ 131 | #define SPEEX_PREPROCESS_GET_DEREVERB_DECAY 13 132 | 133 | /** Set probability required for the VAD to go from silence to voice */ 134 | #define SPEEX_PREPROCESS_SET_PROB_START 14 135 | /** Get probability required for the VAD to go from silence to voice */ 136 | #define SPEEX_PREPROCESS_GET_PROB_START 15 137 | 138 | /** Set probability required for the VAD to stay in the voice state (integer percent) */ 139 | #define SPEEX_PREPROCESS_SET_PROB_CONTINUE 16 140 | /** Get probability required for the VAD to stay in the voice state (integer percent) */ 141 | #define SPEEX_PREPROCESS_GET_PROB_CONTINUE 17 142 | 143 | /** Set maximum attenuation of the noise in dB (negative number) */ 144 | #define SPEEX_PREPROCESS_SET_NOISE_SUPPRESS 18 145 | /** Get maximum attenuation of the noise in dB (negative number) */ 146 | #define SPEEX_PREPROCESS_GET_NOISE_SUPPRESS 19 147 | 148 | /** Set maximum attenuation of the residual echo in dB (negative number) */ 149 | #define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS 20 150 | /** Get maximum attenuation of the residual echo in dB (negative number) */ 151 | #define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS 21 152 | 153 | /** Set maximum attenuation of the residual echo in dB when near end is active (negative number) */ 154 | #define SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE 22 155 | /** Get maximum attenuation of the residual echo in dB when near end is active (negative number) */ 156 | #define SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE 23 157 | 158 | /** Set the corresponding echo canceller state so that residual echo suppression can be performed (NULL for no residual echo suppression) */ 159 | #define SPEEX_PREPROCESS_SET_ECHO_STATE 24 160 | /** Get the corresponding echo canceller state */ 161 | #define SPEEX_PREPROCESS_GET_ECHO_STATE 25 162 | 163 | /** Set maximal gain increase in dB/second (int32) */ 164 | #define SPEEX_PREPROCESS_SET_AGC_INCREMENT 26 165 | 166 | /** Get maximal gain increase in dB/second (int32) */ 167 | #define SPEEX_PREPROCESS_GET_AGC_INCREMENT 27 168 | 169 | /** Set maximal gain decrease in dB/second (int32) */ 170 | #define SPEEX_PREPROCESS_SET_AGC_DECREMENT 28 171 | 172 | /** Get maximal gain decrease in dB/second (int32) */ 173 | #define SPEEX_PREPROCESS_GET_AGC_DECREMENT 29 174 | 175 | /** Set maximal gain in dB (int32) */ 176 | #define SPEEX_PREPROCESS_SET_AGC_MAX_GAIN 30 177 | 178 | /** Get maximal gain in dB (int32) */ 179 | #define SPEEX_PREPROCESS_GET_AGC_MAX_GAIN 31 180 | 181 | /* Can't set loudness */ 182 | /** Get loudness */ 183 | #define SPEEX_PREPROCESS_GET_AGC_LOUDNESS 33 184 | 185 | /* Can't set gain */ 186 | /** Get current gain (int32 percent) */ 187 | #define SPEEX_PREPROCESS_GET_AGC_GAIN 35 188 | 189 | /* Can't set spectrum size */ 190 | /** Get spectrum size for power spectrum (int32) */ 191 | #define SPEEX_PREPROCESS_GET_PSD_SIZE 37 192 | 193 | /* Can't set power spectrum */ 194 | /** Get power spectrum (int32[] of squared values) */ 195 | #define SPEEX_PREPROCESS_GET_PSD 39 196 | 197 | /* Can't set noise size */ 198 | /** Get spectrum size for noise estimate (int32) */ 199 | #define SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE 41 200 | 201 | /* Can't set noise estimate */ 202 | /** Get noise estimate (int32[] of squared values) */ 203 | #define SPEEX_PREPROCESS_GET_NOISE_PSD 43 204 | 205 | /* Can't set speech probability */ 206 | /** Get speech probability in last frame (int32). */ 207 | #define SPEEX_PREPROCESS_GET_PROB 45 208 | 209 | /** Set preprocessor Automatic Gain Control level (int32) */ 210 | #define SPEEX_PREPROCESS_SET_AGC_TARGET 46 211 | /** Get preprocessor Automatic Gain Control level (int32) */ 212 | #define SPEEX_PREPROCESS_GET_AGC_TARGET 47 213 | 214 | #ifdef __cplusplus 215 | } 216 | #endif 217 | 218 | /** @}*/ 219 | #endif 220 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speex_stereo.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002 Jean-Marc Valin*/ 2 | /** 3 | @file speex_stereo.h 4 | @brief Describes the handling for intensity stereo 5 | */ 6 | /* 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | - Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | - Neither the name of the Xiph.org Foundation nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #ifndef STEREO_H 36 | #define STEREO_H 37 | /** @defgroup SpeexStereoState SpeexStereoState: Handling Speex stereo files 38 | * This describes the Speex intensity stereo encoding/decoding 39 | * @{ 40 | */ 41 | 42 | #include "speex_types.h" 43 | #include "speex_bits.h" 44 | 45 | 46 | #ifdef __cplusplus 47 | extern "C" { 48 | #endif 49 | 50 | /** If you access any of these fields directly, I'll personally come and bite you */ 51 | typedef struct SpeexStereoState { 52 | float balance; /**< Left/right balance info */ 53 | float e_ratio; /**< Ratio of energies: E(left+right)/[E(left)+E(right)] */ 54 | float smooth_left; /**< Smoothed left channel gain */ 55 | float smooth_right; /**< Smoothed right channel gain */ 56 | float reserved1; /**< Reserved for future use */ 57 | float reserved2; /**< Reserved for future use */ 58 | } SpeexStereoState; 59 | 60 | /** Deprecated. Use speex_stereo_state_init() instead. */ 61 | #define SPEEX_STEREO_STATE_INIT {1,.5,1,1,0,0} 62 | 63 | /** Initialise/create a stereo stereo state */ 64 | SpeexStereoState *speex_stereo_state_init(); 65 | 66 | /** Reset/re-initialise an already allocated stereo state */ 67 | void speex_stereo_state_reset(SpeexStereoState *stereo); 68 | 69 | /** Destroy a stereo stereo state */ 70 | void speex_stereo_state_destroy(SpeexStereoState *stereo); 71 | 72 | /** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ 73 | void speex_encode_stereo(float *data, int frame_size, SpeexBits *bits); 74 | 75 | /** Transforms a stereo frame into a mono frame and stores intensity stereo info in 'bits' */ 76 | void speex_encode_stereo_int(spx_int16_t *data, int frame_size, SpeexBits *bits); 77 | 78 | /** Transforms a mono frame into a stereo frame using intensity stereo info */ 79 | void speex_decode_stereo(float *data, int frame_size, SpeexStereoState *stereo); 80 | 81 | /** Transforms a mono frame into a stereo frame using intensity stereo info */ 82 | void speex_decode_stereo_int(spx_int16_t *data, int frame_size, SpeexStereoState *stereo); 83 | 84 | /** Callback handler for intensity stereo info */ 85 | int speex_std_stereo_request_handler(SpeexBits *bits, void *state, void *data); 86 | 87 | #ifdef __cplusplus 88 | } 89 | #endif 90 | 91 | /** @} */ 92 | #endif 93 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speex_types.h: -------------------------------------------------------------------------------- 1 | /* speex_types.h taken from libogg */ 2 | /******************************************************************** 3 | * * 4 | * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * 5 | * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 6 | * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 7 | * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 8 | * * 9 | * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * 10 | * by the Xiph.Org Foundation http://www.xiph.org/ * 11 | * * 12 | ******************************************************************** 13 | 14 | function: #ifdef jail to whip a few platforms into the UNIX ideal. 15 | last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $ 16 | 17 | ********************************************************************/ 18 | /** 19 | @file speex_types.h 20 | @brief Speex types 21 | */ 22 | #ifndef _SPEEX_TYPES_H 23 | #define _SPEEX_TYPES_H 24 | 25 | #if defined(_WIN32) 26 | 27 | # if defined(__CYGWIN__) 28 | # include <_G_config.h> 29 | typedef _G_int32_t spx_int32_t; 30 | typedef _G_uint32_t spx_uint32_t; 31 | typedef _G_int16_t spx_int16_t; 32 | typedef _G_uint16_t spx_uint16_t; 33 | # elif defined(__MINGW32__) 34 | typedef short spx_int16_t; 35 | typedef unsigned short spx_uint16_t; 36 | typedef int spx_int32_t; 37 | typedef unsigned int spx_uint32_t; 38 | # elif defined(__MWERKS__) 39 | typedef int spx_int32_t; 40 | typedef unsigned int spx_uint32_t; 41 | typedef short spx_int16_t; 42 | typedef unsigned short spx_uint16_t; 43 | # else 44 | /* MSVC/Borland */ 45 | typedef __int32 spx_int32_t; 46 | typedef unsigned __int32 spx_uint32_t; 47 | typedef __int16 spx_int16_t; 48 | typedef unsigned __int16 spx_uint16_t; 49 | # endif 50 | 51 | #elif defined(__MACOS__) 52 | 53 | # include 54 | typedef SInt16 spx_int16_t; 55 | typedef UInt16 spx_uint16_t; 56 | typedef SInt32 spx_int32_t; 57 | typedef UInt32 spx_uint32_t; 58 | 59 | #elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ 60 | 61 | # include 62 | typedef int16_t spx_int16_t; 63 | typedef u_int16_t spx_uint16_t; 64 | typedef int32_t spx_int32_t; 65 | typedef u_int32_t spx_uint32_t; 66 | 67 | #elif defined(__BEOS__) 68 | 69 | /* Be */ 70 | # include 71 | typedef int16_t spx_int16_t; 72 | typedef u_int16_t spx_uint16_t; 73 | typedef int32_t spx_int32_t; 74 | typedef u_int32_t spx_uint32_t; 75 | 76 | #elif defined (__EMX__) 77 | 78 | /* OS/2 GCC */ 79 | typedef short spx_int16_t; 80 | typedef unsigned short spx_uint16_t; 81 | typedef int spx_int32_t; 82 | typedef unsigned int spx_uint32_t; 83 | 84 | #elif defined (DJGPP) 85 | 86 | /* DJGPP */ 87 | typedef short spx_int16_t; 88 | typedef int spx_int32_t; 89 | typedef unsigned int spx_uint32_t; 90 | 91 | #elif defined(R5900) 92 | 93 | /* PS2 EE */ 94 | typedef int spx_int32_t; 95 | typedef unsigned spx_uint32_t; 96 | typedef short spx_int16_t; 97 | 98 | #elif defined(__SYMBIAN32__) 99 | 100 | /* Symbian GCC */ 101 | typedef signed short spx_int16_t; 102 | typedef unsigned short spx_uint16_t; 103 | typedef signed int spx_int32_t; 104 | typedef unsigned int spx_uint32_t; 105 | 106 | #elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) 107 | 108 | typedef short spx_int16_t; 109 | typedef unsigned short spx_uint16_t; 110 | typedef long spx_int32_t; 111 | typedef unsigned long spx_uint32_t; 112 | 113 | #elif defined(CONFIG_TI_C6X) 114 | 115 | typedef short spx_int16_t; 116 | typedef unsigned short spx_uint16_t; 117 | typedef int spx_int32_t; 118 | typedef unsigned int spx_uint32_t; 119 | 120 | #else 121 | 122 | #include "speex_config_types.h" 123 | 124 | #endif 125 | 126 | #endif /* _SPEEX_TYPES_H */ 127 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speexdsp_config_types.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPEEX_TYPES_H__ 2 | #define __SPEEX_TYPES_H__ 3 | typedef short spx_int16_t; 4 | typedef unsigned short spx_uint16_t; 5 | typedef int spx_int32_t; 6 | typedef unsigned int spx_uint32_t; 7 | #endif -------------------------------------------------------------------------------- /audio/src/main/jnilibs/speex_include/speexdsp_types.h: -------------------------------------------------------------------------------- 1 | /* speexdsp_types.h taken from libogg */ 2 | /******************************************************************** 3 | * * 4 | * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * 5 | * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * 6 | * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * 7 | * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * 8 | * * 9 | * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 * 10 | * by the Xiph.Org Foundation http://www.xiph.org/ * 11 | * * 12 | ******************************************************************** 13 | 14 | function: #ifdef jail to whip a few platforms into the UNIX ideal. 15 | last mod: $Id: os_types.h 7524 2004-08-11 04:20:36Z conrad $ 16 | 17 | ********************************************************************/ 18 | /** 19 | @file speexdsp_types.h 20 | @brief Speex types 21 | */ 22 | #ifndef _SPEEX_TYPES_H 23 | #define _SPEEX_TYPES_H 24 | 25 | #if defined(_WIN32) 26 | 27 | # if defined(__CYGWIN__) 28 | # include <_G_config.h> 29 | typedef _G_int32_t spx_int32_t; 30 | typedef _G_uint32_t spx_uint32_t; 31 | typedef _G_int16_t spx_int16_t; 32 | typedef _G_uint16_t spx_uint16_t; 33 | # elif defined(__MINGW32__) 34 | typedef short spx_int16_t; 35 | typedef unsigned short spx_uint16_t; 36 | typedef int spx_int32_t; 37 | typedef unsigned int spx_uint32_t; 38 | # elif defined(__MWERKS__) 39 | typedef int spx_int32_t; 40 | typedef unsigned int spx_uint32_t; 41 | typedef short spx_int16_t; 42 | typedef unsigned short spx_uint16_t; 43 | # else 44 | /* MSVC/Borland */ 45 | typedef __int32 spx_int32_t; 46 | typedef unsigned __int32 spx_uint32_t; 47 | typedef __int16 spx_int16_t; 48 | typedef unsigned __int16 spx_uint16_t; 49 | # endif 50 | 51 | #elif defined(__MACOS__) 52 | 53 | # include 54 | typedef SInt16 spx_int16_t; 55 | typedef UInt16 spx_uint16_t; 56 | typedef SInt32 spx_int32_t; 57 | typedef UInt32 spx_uint32_t; 58 | 59 | #elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */ 60 | 61 | # include 62 | typedef int16_t spx_int16_t; 63 | typedef u_int16_t spx_uint16_t; 64 | typedef int32_t spx_int32_t; 65 | typedef u_int32_t spx_uint32_t; 66 | 67 | #elif defined(__BEOS__) 68 | 69 | /* Be */ 70 | # include 71 | typedef int16_t spx_int16_t; 72 | typedef u_int16_t spx_uint16_t; 73 | typedef int32_t spx_int32_t; 74 | typedef u_int32_t spx_uint32_t; 75 | 76 | #elif defined (__EMX__) 77 | 78 | /* OS/2 GCC */ 79 | typedef short spx_int16_t; 80 | typedef unsigned short spx_uint16_t; 81 | typedef int spx_int32_t; 82 | typedef unsigned int spx_uint32_t; 83 | 84 | #elif defined (DJGPP) 85 | 86 | /* DJGPP */ 87 | typedef short spx_int16_t; 88 | typedef int spx_int32_t; 89 | typedef unsigned int spx_uint32_t; 90 | 91 | #elif defined(R5900) 92 | 93 | /* PS2 EE */ 94 | typedef int spx_int32_t; 95 | typedef unsigned spx_uint32_t; 96 | typedef short spx_int16_t; 97 | 98 | #elif defined(__SYMBIAN32__) 99 | 100 | /* Symbian GCC */ 101 | typedef signed short spx_int16_t; 102 | typedef unsigned short spx_uint16_t; 103 | typedef signed int spx_int32_t; 104 | typedef unsigned int spx_uint32_t; 105 | 106 | #elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) 107 | 108 | typedef short spx_int16_t; 109 | typedef unsigned short spx_uint16_t; 110 | typedef long spx_int32_t; 111 | typedef unsigned long spx_uint32_t; 112 | 113 | #elif defined(CONFIG_TI_C6X) 114 | 115 | typedef short spx_int16_t; 116 | typedef unsigned short spx_uint16_t; 117 | typedef int spx_int32_t; 118 | typedef unsigned int spx_uint32_t; 119 | 120 | #else 121 | 122 | #include "speexdsp_config_types.h" 123 | 124 | #endif 125 | 126 | #endif /* _SPEEX_TYPES_H */ 127 | -------------------------------------------------------------------------------- /audio/src/main/jnilibs/x86/libspeex.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/audio/src/main/jnilibs/x86/libspeex.so -------------------------------------------------------------------------------- /audio/src/main/jnilibs/x86/libspeexdsp.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/audio/src/main/jnilibs/x86/libspeexdsp.so -------------------------------------------------------------------------------- /audio/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /audio/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /audio/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /audio/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | openslesdemo 3 | 4 | -------------------------------------------------------------------------------- /audio/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /audio/src/test/java/dev/mars/audio/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package dev.mars.audio; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.2' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /callme/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /callme/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion "25.0.2" 6 | defaultConfig { 7 | applicationId "dev.mars.callme" 8 | minSdkVersion 19 9 | targetSdkVersion 24 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | externalNativeBuild { 14 | cmake { 15 | cppFlags "" 16 | } 17 | } 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | } 26 | 27 | dependencies { 28 | compile fileTree(include: ['*.jar'], dir: 'libs') 29 | compile files('libs/mina-core-2.0.16.jar') 30 | compile files('libs/slf4j-api-1.7.21.jar') 31 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 32 | exclude group: 'com.android.support', module: 'support-annotations' 33 | }) 34 | compile 'com.android.support:appcompat-v7:24.2.1' 35 | compile 'org.greenrobot:eventbus:3.0.0' 36 | testCompile 'junit:junit:4.12' 37 | compile project(':audio') 38 | compile project(path: ':audio') 39 | } 40 | -------------------------------------------------------------------------------- /callme/libs/mina-core-2.0.16.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/callme/libs/mina-core-2.0.16.jar -------------------------------------------------------------------------------- /callme/libs/slf4j-api-1.7.21.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/callme/libs/slf4j-api-1.7.21.jar -------------------------------------------------------------------------------- /callme/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in F:\IDE\AndroidSDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /callme/src/androidTest/java/dev/mars/callme/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("dev.mars.callme", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /callme/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/CallingActivity.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme; 2 | 3 | import android.content.ComponentName; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.ServiceConnection; 7 | import android.os.IBinder; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.os.Bundle; 10 | import android.view.View; 11 | import android.widget.CheckBox; 12 | import android.widget.CompoundButton; 13 | import android.widget.TextView; 14 | 15 | import org.greenrobot.eventbus.EventBus; 16 | import org.greenrobot.eventbus.Subscribe; 17 | import org.greenrobot.eventbus.ThreadMode; 18 | 19 | import dev.mars.callme.base.BaseActivity; 20 | import dev.mars.callme.event.SessionClosedEvent; 21 | import dev.mars.callme.event.StartCommunicatingEvent; 22 | import dev.mars.callme.service.CommunicateService; 23 | import dev.mars.callme.utils.RingtonePlayer; 24 | 25 | public class CallingActivity extends BaseActivity { 26 | TextView textView; 27 | String otherIP; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | EventBus.getDefault().register(this); 33 | setContentView(R.layout.activity_calling); 34 | textView = (TextView) findViewById(R.id.textView); 35 | init(); 36 | } 37 | 38 | public static void calling(Context context,String ip){ 39 | Intent intent = new Intent(context,CallingActivity.class); 40 | intent.putExtra("IP",ip); 41 | context.startActivity(intent); 42 | } 43 | 44 | private void init() { 45 | otherIP = getIntent().getStringExtra("IP"); 46 | textView.setText("正在呼叫:"+otherIP); 47 | RingtonePlayer.play(getActivity()); 48 | } 49 | 50 | public void stopCalling(View view) { 51 | CommunicateService.stopCalling(getActivity()); 52 | finish(); 53 | } 54 | 55 | @Subscribe(threadMode = ThreadMode.MAIN) 56 | public void onEvent(SessionClosedEvent event){ 57 | showToast("通话被挂断"); 58 | finish(); 59 | } 60 | 61 | @Subscribe(threadMode = ThreadMode.MAIN) 62 | public void onEvent(StartCommunicatingEvent event){ 63 | textView.setText("正在与 "+otherIP+" 通话"); 64 | CommunicatingActivity.enter(getActivity(),otherIP); 65 | finish(); 66 | } 67 | 68 | @Override 69 | protected void onDestroy() { 70 | super.onDestroy(); 71 | EventBus.getDefault().unregister(this); 72 | RingtonePlayer.close(); 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/CommunicatingActivity.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme; 2 | 3 | import android.content.ComponentName; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.content.ServiceConnection; 7 | import android.os.IBinder; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.os.Bundle; 10 | import android.view.View; 11 | import android.widget.CheckBox; 12 | import android.widget.CompoundButton; 13 | import android.widget.TextView; 14 | 15 | import org.greenrobot.eventbus.EventBus; 16 | import org.greenrobot.eventbus.Subscribe; 17 | import org.greenrobot.eventbus.ThreadMode; 18 | 19 | import dev.mars.callme.base.BaseActivity; 20 | import dev.mars.callme.event.SessionClosedEvent; 21 | import dev.mars.callme.event.StartCommunicatingEvent; 22 | import dev.mars.callme.service.CommunicateService; 23 | 24 | public class CommunicatingActivity extends BaseActivity { 25 | 26 | TextView textView; 27 | String otherIP; 28 | CheckBox cbMic,cbSpeaker,cbEchoClear,cbNoiceClear; 29 | 30 | CommunicateService.CommunicateServiceBinder binder; 31 | 32 | ServiceConnection serviceConnection = new ServiceConnection() { 33 | @Override 34 | public void onServiceConnected(ComponentName name, IBinder service) { 35 | binder=(CommunicateService.CommunicateServiceBinder) service; 36 | cbMic.setOnCheckedChangeListener(null); 37 | cbSpeaker.setOnCheckedChangeListener(null); 38 | cbNoiceClear.setOnCheckedChangeListener(null); 39 | cbEchoClear.setOnCheckedChangeListener(null); 40 | 41 | cbMic.setChecked(false); 42 | cbSpeaker.setChecked(false); 43 | cbNoiceClear.setChecked(binder.isNoiceClearEnable()); 44 | cbEchoClear.setChecked(binder.isEchoClearEnable()); 45 | 46 | cbMic.setOnCheckedChangeListener(onCheckedChangeListener); 47 | cbSpeaker.setOnCheckedChangeListener(onCheckedChangeListener); 48 | cbNoiceClear.setOnCheckedChangeListener(onCheckedChangeListener); 49 | cbEchoClear.setOnCheckedChangeListener(onCheckedChangeListener); 50 | 51 | cbMic.setChecked(false); 52 | cbSpeaker.setChecked(false); 53 | cbEchoClear.setChecked(true); 54 | cbNoiceClear.setChecked(true); 55 | } 56 | 57 | @Override 58 | public void onServiceDisconnected(ComponentName name) { 59 | binder = null; 60 | } 61 | }; 62 | 63 | @Override 64 | protected void onCreate(Bundle savedInstanceState) { 65 | super.onCreate(savedInstanceState); 66 | EventBus.getDefault().register(this); 67 | setContentView(R.layout.activity_communicating); 68 | textView = (TextView) findViewById(R.id.textView); 69 | cbMic = (CheckBox) findViewById(R.id.cbMic); 70 | cbSpeaker = (CheckBox)findViewById(R.id.cbSpeaker); 71 | cbNoiceClear = (CheckBox) findViewById(R.id.cbNoiseClear); 72 | cbEchoClear = (CheckBox) findViewById(R.id.cbEchoClear); 73 | 74 | init(); 75 | 76 | Intent intent = new Intent(getActivity(),CommunicateService.class); 77 | bindService(intent,serviceConnection,BIND_AUTO_CREATE); 78 | } 79 | 80 | private CompoundButton.OnCheckedChangeListener onCheckedChangeListener = new CompoundButton.OnCheckedChangeListener() { 81 | @Override 82 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 83 | switch (buttonView.getId()){ 84 | case R.id.cbMic: 85 | setMic(); 86 | break; 87 | case R.id.cbSpeaker: 88 | setSpeaker(); 89 | break; 90 | case R.id.cbNoiseClear: 91 | setNoiseClear(); 92 | break; 93 | case R.id.cbEchoClear: 94 | setEchoClear(); 95 | break; 96 | } 97 | } 98 | }; 99 | 100 | private void setEchoClear() { 101 | binder.setEchoClearEnable(cbEchoClear.isChecked()); 102 | } 103 | 104 | private void setNoiseClear() { 105 | binder.setNoiseClearEnable(cbNoiceClear.isChecked()); 106 | } 107 | 108 | private void setSpeaker() { 109 | if(cbSpeaker.isChecked()){ 110 | binder.turnOnSpeaker(); 111 | }else{ 112 | binder.turnOffSpeaker(); 113 | } 114 | } 115 | 116 | private void setMic() { 117 | if(cbMic.isChecked()){ 118 | binder.turnOnMic(); 119 | }else{ 120 | binder.turnOffMic(); 121 | } 122 | } 123 | 124 | public static void enter(Context context, String ip){ 125 | Intent intent = new Intent(context,CommunicatingActivity.class); 126 | intent.putExtra("IP",ip); 127 | context.startActivity(intent); 128 | } 129 | 130 | private void init() { 131 | otherIP = getIntent().getStringExtra("IP"); 132 | textView.setText("正在与 "+otherIP+" 通话"); 133 | } 134 | 135 | public void stopCalling(View view) { 136 | CommunicateService.stopCalling(getActivity()); 137 | finish(); 138 | } 139 | 140 | @Subscribe(threadMode = ThreadMode.MAIN) 141 | public void onEvent(SessionClosedEvent event){ 142 | showToast("通话被挂断"); 143 | finish(); 144 | } 145 | 146 | @Override 147 | protected void onDestroy() { 148 | super.onDestroy(); 149 | EventBus.getDefault().unregister(this); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/MainActivity.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme; 2 | 3 | import android.Manifest; 4 | import android.content.Context; 5 | import android.content.pm.PackageManager; 6 | import android.os.Build; 7 | import android.support.annotation.NonNull; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.os.Bundle; 10 | import android.telecom.Call; 11 | import android.view.View; 12 | import android.widget.EditText; 13 | import android.widget.TextView; 14 | 15 | import org.greenrobot.eventbus.EventBus; 16 | import org.greenrobot.eventbus.Subscribe; 17 | import org.greenrobot.eventbus.ThreadMode; 18 | 19 | import dev.mars.callme.base.BaseActivity; 20 | import dev.mars.callme.common.Constants; 21 | import dev.mars.callme.event.CallingEvent; 22 | import dev.mars.callme.event.OnCallEvent; 23 | import dev.mars.callme.service.CommunicateService; 24 | import dev.mars.audio.AudioUtils; 25 | import dev.mars.audio.LogUtils; 26 | import dev.mars.audio.NativeLib; 27 | 28 | import static android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE; 29 | 30 | public class MainActivity extends BaseActivity { 31 | 32 | String[] permissions = {Manifest.permission.ACCESS_WIFI_STATE, CHANGE_WIFI_MULTICAST_STATE,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.RECORD_AUDIO}; 33 | EditText editText; 34 | TextView textView; 35 | 36 | @Override 37 | protected void onCreate(Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | setContentView(R.layout.activity_main); 40 | EventBus.getDefault().register(this); 41 | editText = (EditText) findViewById(R.id.etContent); 42 | textView = (TextView) findViewById(R.id.tvContent); 43 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 44 | if (hasPermissions(permissions)) { 45 | init(); 46 | } else { 47 | requestPermissions(permissions, 0); 48 | } 49 | } 50 | 51 | } 52 | 53 | 54 | @Subscribe(threadMode = ThreadMode.MAIN) 55 | public void receiveRemoteTextMessage(String text){ 56 | textView.setText("收到:"+text); 57 | } 58 | 59 | @Override 60 | protected void onDestroy() { 61 | super.onDestroy(); 62 | EventBus.getDefault().unregister(this); 63 | } 64 | 65 | @Override 66 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 67 | if (requestCode == 0) { 68 | if(!hasPermissions(permissions)){ 69 | finish(); 70 | }else{ 71 | init(); 72 | } 73 | } 74 | 75 | } 76 | 77 | private void init() { 78 | CommunicateService.startListen(MainActivity.this, Constants.UDP_PORT,Constants.TCP_PORT); 79 | } 80 | 81 | 82 | public void startCall(View view) { 83 | CommunicateService.startCall(getContext()); 84 | } 85 | 86 | public void endCall(View view) { 87 | CommunicateService.endCall(getContext()); 88 | } 89 | 90 | public void sendText(View view) { 91 | CommunicateService.sendText(getContext(),editText.getText().toString()); 92 | } 93 | 94 | public Context getContext(){ 95 | return MainActivity.this; 96 | } 97 | 98 | @Subscribe(threadMode = ThreadMode.MAIN) 99 | public void onEvent(CallingEvent event){ 100 | CallingActivity.calling(getContext(),event.ip); 101 | } 102 | 103 | @Subscribe(threadMode = ThreadMode.MAIN) 104 | public void onEvent(OnCallEvent event){ 105 | OnCallActivity.onCall(getContext(),event.ip); 106 | } 107 | 108 | 109 | 110 | public void testRecord(View view) { 111 | CommunicateService.startRecord(getActivity()); 112 | } 113 | 114 | public void stopRecord(View view) { 115 | CommunicateService.stopRecord(getActivity()); 116 | } 117 | 118 | public void testPlay(View view) { 119 | CommunicateService.startPlay(getActivity()); 120 | } 121 | 122 | public void stopPlay(View view) { 123 | CommunicateService.stopPlay(getActivity()); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/OnCallActivity.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.TextView; 9 | import android.widget.Toast; 10 | 11 | import org.greenrobot.eventbus.EventBus; 12 | import org.greenrobot.eventbus.Subscribe; 13 | import org.greenrobot.eventbus.ThreadMode; 14 | 15 | import dev.mars.callme.base.BaseActivity; 16 | import dev.mars.callme.event.SessionClosedEvent; 17 | import dev.mars.callme.event.StartCommunicatingEvent; 18 | import dev.mars.callme.service.CommunicateService; 19 | import dev.mars.callme.utils.RingtonePlayer; 20 | 21 | public class OnCallActivity extends BaseActivity { 22 | TextView textView; 23 | String otherIP; 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | EventBus.getDefault().register(this); 29 | setContentView(R.layout.activity_on_call); 30 | textView = (TextView) findViewById(R.id.textView); 31 | init(); 32 | } 33 | 34 | private void init() { 35 | otherIP = getIntent().getStringExtra("IP"); 36 | textView.setText("收到来电:"+otherIP); 37 | RingtonePlayer.play(getActivity()); 38 | } 39 | 40 | public static void onCall(Context context, String ip){ 41 | Intent intent = new Intent(context,OnCallActivity.class); 42 | intent.putExtra("IP",ip); 43 | context.startActivity(intent); 44 | } 45 | 46 | public void answerCall(View view) { 47 | CommunicateService.answerCall(getActivity()); 48 | view.setVisibility(View.GONE); 49 | 50 | } 51 | 52 | @Subscribe(threadMode = ThreadMode.MAIN) 53 | public void onEvent(StartCommunicatingEvent event){ 54 | textView.setText("正在与 "+otherIP+" 通话"); 55 | CommunicatingActivity.enter(getActivity(),otherIP); 56 | finish(); 57 | } 58 | 59 | public void stopCalling(View view) { 60 | CommunicateService.stopCalling(getActivity()); 61 | finish(); 62 | } 63 | 64 | @Subscribe(threadMode = ThreadMode.MAIN) 65 | public void onEvent(SessionClosedEvent event){ 66 | showToast("通话被挂断"); 67 | finish(); 68 | } 69 | 70 | @Override 71 | protected void onDestroy() { 72 | super.onDestroy(); 73 | EventBus.getDefault().unregister(this); 74 | RingtonePlayer.close(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.base; 2 | 3 | import android.Manifest; 4 | import android.annotation.TargetApi; 5 | import android.app.Activity; 6 | import android.content.pm.PackageManager; 7 | import android.os.Build; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.widget.Toast; 10 | 11 | /** 12 | * Created by ma.xuanwei on 2017/3/30. 13 | */ 14 | 15 | public class BaseActivity extends AppCompatActivity { 16 | 17 | public Activity getActivity(){ 18 | return BaseActivity.this; 19 | } 20 | 21 | public void showToast(String str){ 22 | Toast.makeText(getActivity(),str,Toast.LENGTH_SHORT).show(); 23 | } 24 | 25 | @TargetApi(Build.VERSION_CODES.M) 26 | public boolean hasPermissions(String[] pers){ 27 | for(String p:pers){ 28 | if(checkSelfPermission(p) != PackageManager.PERMISSION_GRANTED){ 29 | return false; 30 | } 31 | } 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/base/BaseApplication.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.base; 2 | 3 | import android.app.Application; 4 | 5 | /** 6 | * Created by ma.xuanwei on 2017/3/30. 7 | */ 8 | 9 | public class BaseApplication extends Application { 10 | 11 | @Override 12 | public void onCreate() { 13 | super.onCreate(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/bean/KeepAliveMessage.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.bean; 2 | 3 | 4 | import android.text.TextUtils; 5 | 6 | /** 7 | * 心跳包消息 8 | * body:{ "type":"0"} 9 | * @author ma.xuanwei 10 | * 11 | */ 12 | public class KeepAliveMessage extends SocketMessage { 13 | public KeepAliveMessage(){ 14 | setCommand((byte) -1); 15 | } 16 | 17 | @Override 18 | public boolean equals(Object o) { 19 | try{ 20 | SocketMessage other = (SocketMessage)o; 21 | return other.getCommand()==-1; 22 | }catch (Exception ex){ 23 | ex.printStackTrace(); 24 | } 25 | return false; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/bean/SocketMessage.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.bean; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Socket通信上层消息的基类 10 | * |0x5c|0x74|bodylength|command|data| 11 | * @author mars 12 | * 13 | */ 14 | public class SocketMessage implements Serializable{ 15 | 16 | public static final byte COMMAND_SEND_TEXT= 1; 17 | public static final byte COMMAND_SEND_HEART_BEAT= 0; 18 | public static final byte COMMAND_REQUEST_CALL= 2; 19 | public static final byte COMMAND_REPONSE_CALL_OK= 3; //同意通话 20 | public static final byte COMMAND_REPONSE_CALL_REFUSE= 4; //拒绝通话 21 | public static final byte COMMAND_SEND_VOICE= 5; //发送语音包 22 | 23 | public static final byte HEADER1 = 0x5c; 24 | public static final byte HEADER2 = 0x74; 25 | private byte command; // 0:心跳包 1:发送文字 26 | private byte[] data; 27 | 28 | 29 | 30 | /** 31 | * 设置消息体,一般用json解析 32 | */ 33 | public void setData(byte[] d) { 34 | this.data = d; 35 | } 36 | 37 | public void setCommand(byte b){ 38 | command = b; 39 | } 40 | 41 | public byte getCommand(){ 42 | return command; 43 | } 44 | 45 | public byte[] getData(){ 46 | return data; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/bean/UDPMessage.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.bean; 2 | 3 | import org.json.JSONException; 4 | import org.json.JSONObject; 5 | 6 | import java.io.Serializable; 7 | import java.io.UnsupportedEncodingException; 8 | 9 | 10 | public class UDPMessage implements Serializable{ 11 | public static final int COMMAND_FIND_OTHER =1; 12 | public static final int COMMAND_START_TCP_CONNECTION =2; 13 | int command; 14 | String data; 15 | public void setMessage(int c,String s){ 16 | command = c; 17 | data = s; 18 | } 19 | 20 | public void setJSON(String str){ 21 | try { 22 | JSONObject json = new JSONObject(str); 23 | command = json.getInt("command"); 24 | data = json.getString("data"); 25 | } catch (JSONException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | 30 | public int getCommand(){ 31 | return command; 32 | } 33 | 34 | public String getData(){ 35 | return data; 36 | } 37 | 38 | public String toString(){ 39 | JSONObject json = new JSONObject(); 40 | try { 41 | json.put("command",command); 42 | json.put("data",data); 43 | } catch (JSONException e) { 44 | e.printStackTrace(); 45 | } 46 | return json.toString(); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/common/Constants.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.common; 2 | 3 | import android.os.Environment; 4 | 5 | /** 6 | * Created by ma.xuanwei on 2017/3/28. 7 | */ 8 | 9 | public class Constants { 10 | //默认TCP通信端口 11 | public static final int TCP_PORT = 5999; 12 | //默认UDP通信端口 13 | public static final int UDP_PORT = 5556; 14 | 15 | //默认PCM录制采样率 16 | public static final int SAMPLERATE = 44100; //bit/s 17 | //默认PCM录制通道数 18 | public static final int CHANNELS = 2; //1:单/2:双声道 19 | //默认PCM录制一帧采样时间 20 | public static final int PERIOD_TIME = 20; //ms 21 | //默认PCM录制文件地址 22 | public static final String DEFAULT_PCM_FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/test_pcm.pcm"; 23 | //默认输出PCM文件路径 24 | public static final String DEFAULT_PCM_OUTPUT_FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/output_pcm.pcm"; 25 | //默认输出speex文件路径 26 | public static final String DEFAULT_SPEEX_FILE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/test_speex.raw"; 27 | 28 | /** 29 | * READ_IDLE_TIMEOUT 设置会话读空闲时间 30 | */ 31 | public static final int READ_IDLE_TIMEOUT = 35; //{@link READ_IDLE_TIMEOUT} 32 | 33 | /** 34 | * WRITE_IDLE_TIMEOUT 设置会话写空闲时间,当会话写空闲发送心跳包给服务器 35 | */ 36 | public static final int WRITE_IDLE_TIMEOUT = 20; 37 | 38 | /** 39 | * 发生READ_IDLE_TIMES次 READ IDLE事件后关闭会话 40 | */ 41 | public static final int READ_IDLE_CLOSE_TIMES = 1; 42 | 43 | public static final boolean RING_TONE_PLAY = false; 44 | 45 | //每个单位20ms 46 | public static final int RECORD_QUEUE_SIZE = 50; 47 | public static final int PLAY_QUEUE_SIZE = 50; 48 | } 49 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/event/CallingEvent.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.event; 2 | 3 | /** 4 | * Created by ma.xuanwei on 2017/3/30. 5 | */ 6 | 7 | public class CallingEvent { 8 | public String ip; 9 | } 10 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/event/OnCallEvent.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.event; 2 | 3 | /** 4 | * Created by ma.xuanwei on 2017/3/30. 5 | */ 6 | 7 | public class OnCallEvent { 8 | public String ip; 9 | } 10 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/event/SessionClosedEvent.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.event; 2 | 3 | /** 4 | * Created by ma.xuanwei on 2017/3/30. 5 | */ 6 | 7 | public class SessionClosedEvent { 8 | } 9 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/event/StartCommunicatingEvent.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.event; 2 | 3 | /** 4 | * Created by ma.xuanwei on 2017/3/30. 5 | */ 6 | 7 | public class StartCommunicatingEvent { 8 | } 9 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/UDPUtils.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote; 2 | 3 | import android.content.Context; 4 | import android.net.wifi.WifiManager; 5 | import android.os.Handler; 6 | 7 | import java.io.IOException; 8 | import java.io.UnsupportedEncodingException; 9 | import java.net.DatagramPacket; 10 | import java.net.DatagramSocket; 11 | import java.net.InetAddress; 12 | import java.net.SocketException; 13 | import java.net.UnknownHostException; 14 | import java.nio.ByteBuffer; 15 | import java.util.concurrent.ExecutorService; 16 | import java.util.concurrent.Executors; 17 | import java.util.concurrent.atomic.AtomicBoolean; 18 | 19 | import dev.mars.callme.bean.UDPMessage; 20 | import dev.mars.callme.utils.LogUtils; 21 | 22 | /** 23 | * Created by ma.xuanwei on 2017/3/22. 24 | */ 25 | 26 | public class UDPUtils { 27 | DatagramSocket listenSocket; 28 | DatagramSocket sendSocket; 29 | private int port; 30 | OnReceiveListener onReceiveListener; 31 | private AtomicBoolean listen = new AtomicBoolean(false); 32 | WifiManager manager; 33 | WifiManager.MulticastLock lock_listen; 34 | ExecutorService service = Executors.newFixedThreadPool(2); 35 | Handler handler ; 36 | 37 | public void setPort(int p){ 38 | this.port = p; 39 | } 40 | 41 | public UDPUtils(Context c) { 42 | handler = new Handler(); 43 | manager = (WifiManager) c 44 | .getSystemService(Context.WIFI_SERVICE); 45 | lock_listen = manager.createMulticastLock("listen"); 46 | 47 | } 48 | 49 | public void setOnReceiveListener(OnReceiveListener onReceiveListener){ 50 | this.onReceiveListener = onReceiveListener; 51 | } 52 | 53 | public void send(final String destIP,final UDPMessage msg) { 54 | service.execute(new Runnable() { 55 | @Override 56 | public void run() { 57 | if (sendSocket == null) { 58 | try { 59 | sendSocket = new DatagramSocket(); 60 | sendSocket.setBroadcast(true); 61 | } catch (SocketException e) { 62 | e.printStackTrace(); 63 | return; 64 | } 65 | } 66 | DatagramPacket dp; 67 | try { 68 | String str = msg.toString(); 69 | byte[] strBytes = str.getBytes("UTF-8"); 70 | int length = strBytes.length; 71 | byte[] buf = new byte[length + 4]; 72 | buf[0] = (byte) (length >> 24); 73 | buf[1] = (byte) (length >> 16); 74 | buf[2] = (byte) (length >> 8); 75 | buf[3] = (byte) (length); 76 | for (int i = 4; i < length + 4; i++) { 77 | buf[i] = strBytes[i - 4]; 78 | } 79 | dp = new DatagramPacket(buf, buf.length, 80 | InetAddress.getByName(destIP), port); 81 | LogUtils.D("UDP SEND:" + str+" PORT:"+port); 82 | sendSocket.send(dp); 83 | } catch (UnknownHostException e) { 84 | // TODO Auto-generated catch block 85 | e.printStackTrace(); 86 | } catch (IOException e) { 87 | // TODO Auto-generated catch block 88 | e.printStackTrace(); 89 | } 90 | } 91 | }); 92 | 93 | } 94 | 95 | public void send(final UDPMessage msg) { 96 | send("255.255.255.255",msg); 97 | 98 | } 99 | 100 | public void stopListening() { 101 | listen.set(false); 102 | listenSocket.close(); 103 | listenSocket = null; 104 | lock_listen.release(); 105 | } 106 | 107 | public void listen() { 108 | if(listenSocket!=null&&listenSocket.isBound()){ 109 | return; 110 | } 111 | try { 112 | listenSocket = new DatagramSocket(port); 113 | listenSocket.setBroadcast(true); 114 | } catch (SocketException e) { 115 | e.printStackTrace(); 116 | } 117 | 118 | listen.set(true); 119 | LogUtils.DT("UDP listen PORT:"+port); 120 | service.execute(new Runnable() { 121 | @Override 122 | public void run() { 123 | while (listen.get()) { 124 | byte[] buf = new byte[100]; 125 | DatagramPacket dp = new DatagramPacket(buf, buf.length);// 创建接收数据报的实例 126 | try { 127 | lock_listen.acquire(); 128 | listenSocket.receive(dp);// 阻塞,直到收到数据报后将数据装入IP中 129 | int b0 = buf[0]; 130 | b0 = b0 << 24; 131 | int b1 = buf[1]; 132 | b1 = b1 << 16; 133 | int b2 = buf[2]; 134 | b2 = b2 << 8; 135 | int b3 = buf[3]; 136 | int length = b0 + b1 + b2 + b3; 137 | byte[] dest = new byte[length]; 138 | for (int i = 0; i < length; i++) { 139 | dest[i] = buf[i + 4]; 140 | } 141 | final String str = new String(dest, "UTF-8"); 142 | final UDPMessage udpMessage = new UDPMessage(); 143 | udpMessage.setJSON(str); 144 | handler.post(new Runnable() { 145 | @Override 146 | public void run() { 147 | if (onReceiveListener != null) 148 | onReceiveListener.onReceive(udpMessage); 149 | } 150 | }); 151 | 152 | } catch (IOException e) { 153 | e.printStackTrace(); 154 | } 155 | 156 | } 157 | } 158 | }); 159 | } 160 | 161 | public interface OnReceiveListener { 162 | void onReceive(UDPMessage msg); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/BaseCodecFactory.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina; 2 | 3 | import java.nio.charset.Charset; 4 | 5 | import org.apache.mina.core.session.IoSession; 6 | import org.apache.mina.filter.codec.ProtocolCodecFactory; 7 | import org.apache.mina.filter.codec.ProtocolDecoder; 8 | import org.apache.mina.filter.codec.ProtocolEncoder; 9 | 10 | public class BaseCodecFactory implements ProtocolCodecFactory { 11 | BaseEncoder encoder; 12 | BaseDecoder decoder; 13 | 14 | public BaseCodecFactory() { 15 | // TODO Auto-generated constructor stub 16 | encoder = new BaseEncoder(); 17 | decoder = new BaseDecoder(); 18 | } 19 | 20 | 21 | @Override 22 | public ProtocolDecoder getDecoder(IoSession arg0) throws Exception { 23 | // TODO Auto-generated method stub 24 | return decoder; 25 | } 26 | 27 | @Override 28 | public ProtocolEncoder getEncoder(IoSession arg0) throws Exception { 29 | // TODO Auto-generated method stub 30 | return encoder; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/BaseDecoder.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina; 2 | 3 | import org.apache.mina.core.buffer.IoBuffer; 4 | import org.apache.mina.core.session.IoSession; 5 | import org.apache.mina.filter.codec.CumulativeProtocolDecoder; 6 | import org.apache.mina.filter.codec.ProtocolDecoderOutput; 7 | 8 | import java.nio.charset.Charset; 9 | 10 | import dev.mars.callme.bean.SocketMessage; 11 | import dev.mars.callme.utils.BasicTypeConvertUtils; 12 | import dev.mars.callme.utils.LogUtils; 13 | 14 | 15 | public class BaseDecoder extends CumulativeProtocolDecoder { 16 | 17 | 18 | 19 | public BaseDecoder() { 20 | } 21 | 22 | @Override 23 | protected boolean doDecode(IoSession session, IoBuffer in, 24 | ProtocolDecoderOutput out) throws Exception { 25 | // TODO Auto-generated method stub 26 | LogUtils.DT("1.缓冲区目前数组长度:"+in.remaining()); 27 | if (in.remaining() >= 4) { 28 | // System.out.println("1.缓冲区目前数组长度:"+in.remaining()); 29 | //当可读的缓冲区长度大于4时(前两个字节是占位符,后两个字节是长度) 30 | in.mark(); // 标记当前位置,方便reset 31 | byte[] header = new byte[4]; 32 | in.get(header, 0, header.length); 33 | // System.out.println("receive header[0]:"+header[0]+"|header[1]:"+header[1]); 34 | if (header[0] == SocketMessage.HEADER1 && header[1] == SocketMessage.HEADER2) { 35 | // System.out.println("header[2]:"+header[2]+",header[3]:"+header[3]); 36 | short bodyLength = BasicTypeConvertUtils.byteToShort(header[2], header[3]); 37 | LogUtils.DT("Decode 报文内容长度:"+bodyLength); 38 | LogUtils.DT("2.缓冲区目前数组长度:"+in.remaining()); 39 | 40 | if (in.remaining() >= bodyLength) { 41 | //可读取完整的报文 42 | // System.out.println(in.remaining()>=bodyLength); 43 | SocketMessage msg = new SocketMessage(); 44 | byte command = in.get(); 45 | LogUtils.DT("Decode command = "+command); 46 | msg.setCommand(command); 47 | if(command!=SocketMessage.COMMAND_SEND_HEART_BEAT) { //如果不是心跳包 48 | if(command==SocketMessage.COMMAND_REQUEST_CALL){ 49 | LogUtils.DT("接到通话请求"); 50 | }else{ 51 | byte[] data = new byte[bodyLength - 1]; 52 | in.get(data, 0, data.length); 53 | msg.setData(data); 54 | } 55 | out.write(msg); 56 | } 57 | // System.out.println("3.缓冲区目前数组长度:" + in.remaining()) 58 | if (in.remaining() > 0) { 59 | // System.out.println("粘包,保留未消费数据"); 60 | return true; 61 | } 62 | // System.out.println("不粘包,IoBuffer中的数据已消费"); 63 | } else { 64 | // System.out.println("缓冲区未接收完全应用层报文,继续读取字节流"); 65 | in.reset(); 66 | return false; 67 | } 68 | 69 | } 70 | 71 | } 72 | return false; 73 | } 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/BaseEncoder.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina; 2 | 3 | import android.text.TextUtils; 4 | 5 | import java.nio.ByteOrder; 6 | import java.nio.charset.Charset; 7 | 8 | import org.apache.mina.core.buffer.IoBuffer; 9 | import org.apache.mina.core.session.IoSession; 10 | import org.apache.mina.filter.codec.ProtocolEncoderAdapter; 11 | import org.apache.mina.filter.codec.ProtocolEncoderOutput; 12 | 13 | import dev.mars.callme.bean.SocketMessage; 14 | import dev.mars.callme.utils.LogUtils; 15 | 16 | public class BaseEncoder extends ProtocolEncoderAdapter { 17 | 18 | public BaseEncoder() { 19 | } 20 | 21 | 22 | @Override 23 | public void encode(IoSession session, Object obj, ProtocolEncoderOutput output) 24 | throws Exception { 25 | SocketMessage msg = (SocketMessage) obj; 26 | IoBuffer buffer = IoBuffer.allocate(1024).setAutoExpand(true); 27 | buffer.order(ByteOrder.BIG_ENDIAN); 28 | //put head 29 | buffer.put(SocketMessage.HEADER1); 30 | buffer.put(SocketMessage.HEADER2); 31 | short bodyLength = 1; 32 | 33 | byte[] data = msg.getData(); 34 | if (data != null && data.length != 0) { 35 | bodyLength += (short) data.length; 36 | } 37 | 38 | buffer.putShort(bodyLength); 39 | buffer.put(msg.getCommand()); 40 | 41 | if(data != null && data.length != 0) { 42 | buffer.put(data); 43 | } 44 | 45 | //LogUtils.DT("HEADER:"+ SocketMessage.HEADER1+"|"+ SocketMessage.HEADER2); 46 | LogUtils.DT("Encode Length:" + bodyLength); 47 | LogUtils.DT("Encode command = " + msg.getCommand()); 48 | //LogUtils.DT("will send :"+buffer.toString()); 49 | buffer.flip(); 50 | output.write(buffer); 51 | 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/ISendListener.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina; 2 | 3 | /** 4 | * Created by ma.xuanwei on 2016/12/13. 5 | */ 6 | 7 | public interface ISendListener { 8 | /** 9 | * 发送消息成功回调 10 | */ 11 | public void onSendSuccess(); 12 | 13 | /** 14 | * 发送消息失败 15 | * @param str 16 | */ 17 | public void onSendFailed(String str); 18 | } 19 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/KeepAliveFilter.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina; 2 | 3 | import org.apache.mina.core.filterchain.IoFilterAdapter; 4 | import org.apache.mina.core.session.IdleStatus; 5 | import org.apache.mina.core.session.IoSession; 6 | import org.apache.mina.core.write.WriteRequest; 7 | 8 | import dev.mars.callme.bean.KeepAliveMessage; 9 | import dev.mars.callme.common.Constants; 10 | import dev.mars.callme.utils.LogUtils; 11 | 12 | 13 | /** 14 | * 通过Mina框架实现TCP通讯 15 | * Created by ma.xuanwei on 2016/12/21. 16 | */ 17 | 18 | public class KeepAliveFilter extends IoFilterAdapter{ 19 | private KeepAliveMessage keepAliveMessage = new KeepAliveMessage(); 20 | 21 | @Override 22 | public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception { 23 | if(keepAliveMessage.equals(writeRequest.getMessage())){ 24 | //如果发送的消息是心跳包,拦截该事件 25 | LogUtils.DT(session.getId()+" 向服务器发送心跳包"); 26 | }else { 27 | super.messageSent(nextFilter, session, writeRequest); 28 | } 29 | } 30 | 31 | @Override 32 | public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { 33 | if(keepAliveMessage.equals(message)){ 34 | //如果收到服务器返回的心跳包,拦截该事件 35 | LogUtils.DT(session.getId()+" 收到服务器心跳包"); 36 | }else { 37 | super.messageReceived(nextFilter, session, message); 38 | } 39 | } 40 | 41 | @Override 42 | public void sessionIdle(NextFilter nextFilter, IoSession session, IdleStatus status) throws Exception { 43 | if(status==IdleStatus.WRITER_IDLE){ 44 | session.write(keepAliveMessage); 45 | }else if(status==IdleStatus.READER_IDLE&&session.getIdleCount(IdleStatus.READER_IDLE)== Constants.READ_IDLE_CLOSE_TIMES){ 46 | //READ_IDLE_CLOSE_TIMES次Read空闲就关闭session 47 | session.closeOnFlush(); 48 | // System.out.println(session.getId()+" 未收到服务器心跳包,主动关闭"); 49 | session.setAttribute("reconnect",new Boolean(true)); 50 | }else{ 51 | nextFilter.sessionIdle(session,status); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/client/ClientSessionState.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina.client; 2 | 3 | import org.apache.mina.core.future.ConnectFuture; 4 | import org.apache.mina.core.future.IoFuture; 5 | import org.apache.mina.core.future.IoFutureListener; 6 | 7 | import dev.mars.callme.bean.SocketMessage; 8 | import dev.mars.callme.remote.mina.ISendListener; 9 | 10 | 11 | /** 12 | * 状态模式上层抽象 13 | * Created by ma.xuanwei on 2017/1/4. 14 | */ 15 | 16 | public abstract class ClientSessionState { 17 | 18 | MinaSocketClient minaSocketClient; 19 | 20 | ClientSessionState(MinaSocketClient client){ 21 | minaSocketClient = client; 22 | } 23 | 24 | /** 25 | * 关闭连接 26 | */ 27 | public abstract IoFuture closeConnection(); 28 | 29 | /** 30 | * 请求连接 31 | */ 32 | public abstract void connect(final IoFutureListener ioFutureListener); 33 | 34 | /** 35 | * 发送消息 36 | * 37 | * @param msg 38 | * @param listener 39 | * @param tryConnect 是否在无连接状态下请求连接 40 | */ 41 | public abstract void send(SocketMessage msg, final ISendListener listener, boolean tryConnect); 42 | 43 | @Override 44 | public String toString() { 45 | return this.getClass().getName(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/client/ClientSessionStatus.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina.client; 2 | 3 | /** 4 | * Created by ma.xuanwei on 2017/3/29. 5 | */ 6 | 7 | public enum ClientSessionStatus { 8 | ClOSED, 9 | CONNECTED, 10 | CONNECTING 11 | } 12 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/client/ClosedSessionState.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina.client; 2 | 3 | import org.apache.mina.core.future.ConnectFuture; 4 | import org.apache.mina.core.future.IoFuture; 5 | import org.apache.mina.core.future.IoFutureListener; 6 | 7 | import java.net.InetSocketAddress; 8 | 9 | import dev.mars.callme.bean.SocketMessage; 10 | import dev.mars.callme.remote.mina.ISendListener; 11 | import dev.mars.callme.utils.LogUtils; 12 | 13 | import static dev.mars.callme.remote.mina.client.ClientSessionStatus.CONNECTED; 14 | import static dev.mars.callme.remote.mina.client.ClientSessionStatus.CONNECTING; 15 | 16 | 17 | /** 18 | * Created by ma.xuanwei on 2017/1/4. 19 | */ 20 | 21 | public class ClosedSessionState extends ClientSessionState { 22 | 23 | ClosedSessionState(MinaSocketClient client) { 24 | super(client); 25 | } 26 | 27 | /** 28 | * 关闭连接 29 | */ 30 | @Override 31 | public IoFuture closeConnection() { 32 | //已经在关闭状态,什么都不做 33 | return null; 34 | } 35 | 36 | /** 37 | * 请求连接 38 | */ 39 | @Override 40 | public void connect(final IoFutureListener ioFutureListener) { 41 | LogUtils.DT("TCP 客户端向 "+minaSocketClient.getIP()+" : "+minaSocketClient.getPort()+" 发起请求"); 42 | minaSocketClient.setSessionState(minaSocketClient.sessionStateFactory.newState(CONNECTING)); 43 | minaSocketClient.setConnectFuture((minaSocketClient.connector.connect(new InetSocketAddress(minaSocketClient.getIP(), minaSocketClient.getPort())))); 44 | minaSocketClient.getConnectFuture().addListener(new IoFutureListener() { 45 | @Override 46 | public void operationComplete(ConnectFuture ioFuture) { 47 | if (!ioFuture.isConnected() || ioFuture.isCanceled()) { 48 | minaSocketClient.session = null; 49 | minaSocketClient.setSessionState(new ClosedSessionState(minaSocketClient)); 50 | } else { 51 | minaSocketClient.setSessionState(minaSocketClient.sessionStateFactory.newState(CONNECTED)); 52 | minaSocketClient.session = ioFuture.getSession(); 53 | } 54 | } 55 | }); 56 | minaSocketClient.getConnectFuture().addListener(ioFutureListener); 57 | } 58 | 59 | /** 60 | * 发送消息 61 | * 62 | * @param msg 63 | * @param listener 64 | * @param tryConnect 是否在无连接状态下请求连接 65 | */ 66 | @Override 67 | public void send(final SocketMessage msg, final ISendListener listener, final boolean tryConnect) { 68 | if (tryConnect) { 69 | connect(new IoFutureListener() { 70 | @Override 71 | public void operationComplete(ConnectFuture ioFuture) { 72 | if (minaSocketClient.getStatus() == CONNECTED){ 73 | minaSocketClient.getSessionState().send(msg, listener, tryConnect); 74 | }else { 75 | if (listener != null) { 76 | listener.onSendFailed("发送失败"); 77 | } 78 | } 79 | } 80 | }); 81 | } else { 82 | if (listener != null) { 83 | listener.onSendFailed("发送失败,网络异常。"); 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/client/ConnectedSessionState.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina.client; 2 | 3 | import org.apache.mina.core.future.ConnectFuture; 4 | import org.apache.mina.core.future.IoFuture; 5 | import org.apache.mina.core.future.IoFutureListener; 6 | import org.apache.mina.core.future.WriteFuture; 7 | 8 | import dev.mars.callme.bean.SocketMessage; 9 | import dev.mars.callme.remote.mina.ISendListener; 10 | 11 | 12 | /** 13 | * Created by ma.xuanwei on 2017/1/4. 14 | */ 15 | 16 | public class ConnectedSessionState extends ClientSessionState { 17 | ConnectedSessionState(MinaSocketClient client) { 18 | super(client); 19 | } 20 | 21 | /** 22 | * 关闭连接 23 | */ 24 | @Override 25 | public IoFuture closeConnection() { 26 | minaSocketClient.setSessionState(ClientSessionStatus.ClOSED); 27 | return minaSocketClient.getSession().closeOnFlush(); 28 | } 29 | 30 | /** 31 | * 请求连接 32 | */ 33 | @Override 34 | public void connect(final IoFutureListener ioFutureListener) { 35 | } 36 | 37 | /** 38 | * 发送消息 39 | * 40 | * @param msg 41 | * @param listener 42 | * @param tryConnect 是否在无连接状态下请求连接 43 | */ 44 | @Override 45 | public void send(SocketMessage msg, final ISendListener listener, boolean tryConnect) { 46 | WriteFuture writeFuture = minaSocketClient.session.write(msg); 47 | writeFuture.addListener(new IoFutureListener() { 48 | @Override 49 | public void operationComplete(WriteFuture ioFuture) { 50 | if (listener != null) { 51 | if (ioFuture.isWritten()) { 52 | listener.onSendSuccess(); 53 | } else { 54 | listener.onSendFailed("发送失败"); 55 | } 56 | } 57 | } 58 | }); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/client/ConnectingSessionState.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina.client; 2 | 3 | import org.apache.mina.core.future.ConnectFuture; 4 | import org.apache.mina.core.future.IoFuture; 5 | import org.apache.mina.core.future.IoFutureListener; 6 | 7 | import dev.mars.callme.bean.SocketMessage; 8 | import dev.mars.callme.remote.mina.ISendListener; 9 | 10 | import static dev.mars.callme.remote.mina.client.ClientSessionStatus.CONNECTED; 11 | import static dev.mars.callme.remote.mina.client.ClientSessionStatus.ClOSED; 12 | 13 | 14 | /** 15 | * Created by ma.xuanwei on 2017/1/4. 16 | */ 17 | 18 | public class ConnectingSessionState extends ClientSessionState { 19 | 20 | 21 | ConnectingSessionState(MinaSocketClient client) { 22 | super(client); 23 | } 24 | 25 | /** 26 | * 关闭连接 27 | */ 28 | @Override 29 | public IoFuture closeConnection() { 30 | if (minaSocketClient.connectFuture != null && !minaSocketClient.connectFuture.isDone() && !minaSocketClient.connectFuture.isCanceled()) { 31 | minaSocketClient.connectFuture.cancel(); 32 | } 33 | minaSocketClient.setSessionState(ClOSED); 34 | return minaSocketClient.connectFuture; 35 | } 36 | 37 | /** 38 | * 请求连接 39 | */ 40 | @Override 41 | public void connect(final IoFutureListener ioFutureListener) { 42 | 43 | } 44 | 45 | /** 46 | * 发送消息 47 | * 48 | * @param msg 49 | * @param listener 50 | * @param tryConnect 是否在无连接状态下请求连接 51 | */ 52 | @Override 53 | public void send(final SocketMessage msg, final ISendListener listener, final boolean tryConnect) { 54 | if (tryConnect) { 55 | minaSocketClient.connectFuture.addListener(new IoFutureListener() { 56 | @Override 57 | public void operationComplete(ConnectFuture ioFuture) { 58 | if (minaSocketClient.getStatus() == CONNECTED) { 59 | minaSocketClient.getSessionState().send(msg, listener, tryConnect); 60 | } else { 61 | if (listener != null) { 62 | listener.onSendFailed("发送失败"); 63 | } 64 | } 65 | } 66 | }); 67 | } else { 68 | if (listener != null) { 69 | listener.onSendFailed("发送失败"); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/client/MinaSocketClient.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina.client; 2 | 3 | import org.apache.mina.core.future.ConnectFuture; 4 | import org.apache.mina.core.future.IoFuture; 5 | import org.apache.mina.core.future.IoFutureListener; 6 | import org.apache.mina.core.service.IoHandler; 7 | import org.apache.mina.core.session.IdleStatus; 8 | import org.apache.mina.core.session.IoSession; 9 | import org.apache.mina.filter.codec.ProtocolCodecFilter; 10 | import org.apache.mina.transport.socket.nio.NioSocketConnector; 11 | 12 | import java.nio.charset.Charset; 13 | import java.util.concurrent.ExecutorService; 14 | import java.util.concurrent.Executors; 15 | 16 | import dev.mars.callme.bean.SocketMessage; 17 | import dev.mars.callme.common.Constants; 18 | import dev.mars.callme.remote.mina.BaseCodecFactory; 19 | import dev.mars.callme.remote.mina.ISendListener; 20 | import dev.mars.callme.remote.mina.KeepAliveFilter; 21 | import dev.mars.callme.utils.LogUtils; 22 | 23 | 24 | /** 25 | * MinaSocket Created by ma.xuanwei on 2016/12/13. 26 | */ 27 | 28 | public class MinaSocketClient { 29 | NioSocketConnector connector; 30 | ConnectFuture connectFuture; 31 | //单一session 32 | IoSession session; 33 | ClientSessionState sessionState; 34 | protected String destIP; 35 | protected int destPort; 36 | 37 | MinaSessionStateFactory sessionStateFactory = new MinaSessionStateFactory(); 38 | ExecutorService service = Executors.newCachedThreadPool(); 39 | 40 | public MinaSocketClient() { 41 | super(); 42 | init(); 43 | } 44 | 45 | /** 46 | * 设置IP 47 | * @param str 48 | */ 49 | public void setIP(String str){ 50 | this.destIP = str; 51 | } 52 | 53 | /** 54 | * 设置端口号 55 | * @param port 56 | */ 57 | public void setPort(int port){ 58 | destPort = port; 59 | } 60 | 61 | public String getIP(){ 62 | return destIP; 63 | } 64 | 65 | public int getPort(){ 66 | return destPort; 67 | } 68 | 69 | /** 70 | * 初始化 71 | */ 72 | private void init() { 73 | connector = new NioSocketConnector(); 74 | connector.getSessionConfig().setIdleTime(IdleStatus.READER_IDLE, 75 | Constants.READ_IDLE_TIMEOUT); 76 | connector.getSessionConfig().setIdleTime(IdleStatus.WRITER_IDLE, 77 | Constants.WRITE_IDLE_TIMEOUT); 78 | connector.getFilterChain().addLast( 79 | "BaseFilter", 80 | new ProtocolCodecFilter(new BaseCodecFactory())); 81 | //connector.getFilterChain().addLast("KeepAlive", new KeepAliveFilter()); 82 | // 设置连接超时检查时间 83 | connector.setConnectTimeoutCheckInterval(5000); 84 | connector.setConnectTimeoutMillis(10000); // 10秒后超时 85 | setSessionState(sessionStateFactory.newState(ClientSessionStatus.ClOSED)); 86 | } 87 | 88 | public void setIoHandler(IoHandler ioHandler){ 89 | connector.setHandler(ioHandler); 90 | } 91 | 92 | public void setSession(IoSession session) { 93 | this.session = session; 94 | } 95 | 96 | public IoSession getSession() { 97 | return session; 98 | } 99 | 100 | public void setSessionState(ClientSessionStatus status) { 101 | setSessionState(sessionStateFactory.newState(status)); 102 | } 103 | 104 | public void setSessionState(ClientSessionState s) { 105 | sessionState = s; 106 | } 107 | 108 | public ClientSessionState getSessionState() { 109 | return sessionState; 110 | } 111 | 112 | /** 113 | * 获取连接状态 114 | * 115 | * @return 116 | */ 117 | public ClientSessionStatus getStatus() { 118 | if (session == null || !session.isConnected()) { 119 | if (connectFuture != null && !connectFuture.isDone() 120 | && !connectFuture.isCanceled()) { 121 | return ClientSessionStatus.CONNECTING; 122 | } else { 123 | return ClientSessionStatus.ClOSED; 124 | } 125 | } else { 126 | return ClientSessionStatus.CONNECTED; 127 | } 128 | } 129 | 130 | /** 131 | * 连接 132 | */ 133 | public void connect(final IoFutureListener ioFutureListener) { 134 | service.execute(new Runnable() { 135 | @Override 136 | public void run() { 137 | LogUtils.DT("connect getSessionState:"+getSessionState()); 138 | getSessionState().connect(ioFutureListener); 139 | } 140 | }); 141 | } 142 | 143 | /** 144 | * 发送 145 | * 146 | * @param msg 147 | */ 148 | public void send(final SocketMessage msg, final ISendListener listener, 149 | final boolean tryConnect) { 150 | getSessionState().send(msg, listener, tryConnect); 151 | } 152 | 153 | /** 154 | * 关闭连接 155 | */ 156 | public IoFuture closeSession() { 157 | return getSessionState().closeConnection(); 158 | } 159 | 160 | public void setConnectFuture(ConnectFuture connectFuture) { 161 | this.connectFuture = connectFuture; 162 | } 163 | 164 | public ConnectFuture getConnectFuture() { 165 | return connectFuture; 166 | } 167 | 168 | protected class MinaSessionStateFactory { 169 | public ClientSessionState newState(ClientSessionStatus status) { 170 | switch (status) { 171 | case ClOSED: 172 | return new ClosedSessionState(MinaSocketClient.this); 173 | case CONNECTING: 174 | return new ConnectingSessionState(MinaSocketClient.this); 175 | case CONNECTED: 176 | return new ConnectedSessionState(MinaSocketClient.this); 177 | } 178 | return null; 179 | } 180 | } 181 | 182 | } 183 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/remote/mina/server/MinaSocketServer.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.remote.mina.server; 2 | 3 | import android.os.Process; 4 | 5 | import org.apache.mina.core.future.IoFuture; 6 | import org.apache.mina.core.future.IoFutureListener; 7 | import org.apache.mina.core.future.WriteFuture; 8 | import org.apache.mina.core.service.IoAcceptor; 9 | import org.apache.mina.core.service.IoHandler; 10 | import org.apache.mina.core.service.IoHandlerAdapter; 11 | import org.apache.mina.core.session.IdleStatus; 12 | import org.apache.mina.core.session.IoSession; 13 | import org.apache.mina.filter.codec.ProtocolCodecFilter; 14 | import org.apache.mina.transport.socket.SocketAcceptor; 15 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 16 | 17 | import java.io.IOException; 18 | import java.net.InetSocketAddress; 19 | import java.nio.charset.Charset; 20 | import java.util.concurrent.ExecutorService; 21 | import java.util.concurrent.Executors; 22 | 23 | import dev.mars.callme.bean.SocketMessage; 24 | import dev.mars.callme.common.Constants; 25 | import dev.mars.callme.remote.mina.BaseCodecFactory; 26 | import dev.mars.callme.remote.mina.ISendListener; 27 | import dev.mars.callme.remote.mina.KeepAliveFilter; 28 | import dev.mars.callme.utils.LogUtils; 29 | 30 | 31 | /** 32 | * MinaSocket Created by ma.xuanwei on 2016/12/13. 33 | */ 34 | 35 | public class MinaSocketServer { 36 | private ExecutorService service = Executors.newCachedThreadPool(); 37 | IoAcceptor acceptor; 38 | //监听端口 39 | private int PORT; 40 | //与客户端的唯一会话 41 | private IoSession tcpSession; 42 | 43 | 44 | public MinaSocketServer() { 45 | super(); 46 | init(); 47 | } 48 | 49 | /** 50 | * 初始化 51 | */ 52 | private void init() { 53 | acceptor = new NioSocketAcceptor(); 54 | acceptor.getSessionConfig().setIdleTime(IdleStatus.READER_IDLE, 55 | Constants.READ_IDLE_TIMEOUT); 56 | acceptor.getSessionConfig().setIdleTime(IdleStatus.WRITER_IDLE, 57 | Constants.WRITE_IDLE_TIMEOUT); 58 | acceptor.getFilterChain().addLast( 59 | "BaseFilter", 60 | new ProtocolCodecFilter(new BaseCodecFactory())); 61 | //acceptor.getFilterChain().addLast("KeepAlive", new KeepAliveFilter()); 62 | acceptor.getSessionConfig().setReadBufferSize(2048); 63 | acceptor.setHandler(new IoHandlerAdapter(){ 64 | @Override 65 | public void sessionOpened(IoSession session) throws Exception { 66 | super.sessionOpened(session); 67 | LogUtils.DT("已建立TCP Session"); 68 | if(tcpSession!=null&&tcpSession.isConnected()){ 69 | return; 70 | } 71 | tcpSession = session; 72 | if(ioHandler!=null) 73 | ioHandler.sessionOpened(session); 74 | } 75 | 76 | @Override 77 | public void sessionClosed(IoSession session) throws Exception { 78 | super.sessionClosed(session); 79 | 80 | tcpSession = null; 81 | LogUtils.DT("TCP Session 关闭"); 82 | if(ioHandler!=null) 83 | ioHandler.sessionClosed(session); 84 | unbind(); 85 | } 86 | 87 | @Override 88 | public void messageReceived(IoSession session, Object message) throws Exception { 89 | super.messageReceived(session, message); 90 | if(ioHandler!=null) 91 | ioHandler.messageReceived(session,message); 92 | } 93 | 94 | @Override 95 | public void exceptionCaught(IoSession session, Throwable cause) throws Exception { 96 | super.exceptionCaught(session, cause); 97 | LogUtils.DT("TCP 服务端异常:"+cause.getMessage()); 98 | if (tcpSession != null) { 99 | tcpSession.closeOnFlush(); 100 | } 101 | } 102 | }); 103 | } 104 | 105 | public int getPort() { 106 | return PORT; 107 | } 108 | 109 | /** 110 | * 设置端口号 111 | * 112 | * @param port 113 | */ 114 | public void setPort(int port) { 115 | PORT = port; 116 | } 117 | 118 | public void bind(final OnBindListener listener) { 119 | if (acceptor.isActive()) { 120 | return; 121 | } 122 | service.execute(new Runnable() { 123 | @Override 124 | public void run() { 125 | try { 126 | acceptor.bind(new InetSocketAddress(getPort())); 127 | LogUtils.DT("TCP Server 正在监听 PORT:" + PORT); 128 | if(listener!=null){ 129 | listener.onBindSucess(); 130 | } 131 | } catch (IOException e) { 132 | e.printStackTrace(); 133 | LogUtils.E(e.getMessage()); 134 | if(listener!=null){ 135 | listener.onBindFailed(); 136 | } 137 | } 138 | } 139 | }); 140 | } 141 | 142 | public interface OnBindListener{ 143 | void onBindSucess(); 144 | void onBindFailed(); 145 | } 146 | 147 | public void unbind() { 148 | acceptor.unbind(); 149 | LogUtils.DT("TCP Server 停止监听 PORT:" + PORT); 150 | } 151 | 152 | /** 153 | * 发送 154 | * 155 | * @param msg 156 | */ 157 | public void send(final SocketMessage msg, final ISendListener listener) { 158 | if (tcpSession != null && tcpSession.isConnected()) { 159 | WriteFuture writeFuture = tcpSession.write(msg); 160 | writeFuture.addListener(new IoFutureListener() { 161 | @Override 162 | public void operationComplete(WriteFuture ioFuture) { 163 | if (listener != null) { 164 | if (ioFuture.isWritten()) { 165 | listener.onSendSuccess(); 166 | } else { 167 | listener.onSendFailed("发送失败"); 168 | } 169 | } 170 | } 171 | }); 172 | } 173 | } 174 | 175 | /** 176 | * 关闭连接 177 | */ 178 | public void closeSession() { 179 | if (tcpSession != null && tcpSession.isConnected()) { 180 | tcpSession.closeOnFlush(); 181 | tcpSession = null; 182 | } 183 | } 184 | 185 | private IoHandler ioHandler; 186 | public void setIoHandler(IoHandler handler){ 187 | ioHandler = handler; 188 | } 189 | 190 | } 191 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/utils/BasicTypeConvertUtils.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.utils; 2 | 3 | /** 4 | * 处理基本类型间的转换 5 | * @author ma.xuanwei 6 | * 7 | */ 8 | public class BasicTypeConvertUtils { 9 | 10 | /** 11 | * 将字节数组转换为short 12 | * @param b 13 | * @return 14 | */ 15 | public static short byteToShort(byte[] b) { 16 | return (short) (((b[0] & 0xff) << 8) | (b[1] & 0xff)); 17 | } 18 | 19 | /** 20 | * 将字节数组转换为short 21 | * @param b1 低位字节对应高位 22 | * @param b2 高位字节对应低位 23 | * @return 24 | */ 25 | public static short byteToShort(byte b1,byte b2) { 26 | return (short) (((b1 & 0xff) << 8) | (b2 & 0xff)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/utils/IPUtils.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.utils; 2 | 3 | import java.net.Inet4Address; 4 | import java.net.InetAddress; 5 | import java.net.NetworkInterface; 6 | import java.net.SocketException; 7 | import java.util.Enumeration; 8 | 9 | /** 10 | * Created by ma.xuanwei on 2017/3/22. 11 | */ 12 | 13 | public class IPUtils { 14 | 15 | 16 | public static String getIP() { 17 | Enumeration allNetInterfaces; 18 | InetAddress ip = null; 19 | try { 20 | allNetInterfaces = NetworkInterface.getNetworkInterfaces(); 21 | while (allNetInterfaces.hasMoreElements()) { 22 | NetworkInterface netInterface = (NetworkInterface) allNetInterfaces 23 | .nextElement(); 24 | System.out.println(netInterface.getName()); 25 | Enumeration addresses = netInterface.getInetAddresses(); 26 | while (addresses.hasMoreElements()) { 27 | ip = (InetAddress) addresses.nextElement(); 28 | if (ip != null && ip instanceof Inet4Address) { 29 | System.out.println("本机的IP = " + ip.getHostAddress()); 30 | } 31 | } 32 | } 33 | } catch (SocketException e) { 34 | // TODO Auto-generated catch block 35 | e.printStackTrace(); 36 | } 37 | 38 | 39 | return ip==null?"":ip.getHostAddress(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/utils/LogUtils.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.utils; 2 | 3 | import android.util.Log; 4 | 5 | import java.text.SimpleDateFormat; 6 | import java.util.Date; 7 | 8 | import dev.mars.callme.BuildConfig; 9 | 10 | /** 11 | * Created by ma.xuanwei on 2016/12/6. 12 | */ 13 | 14 | /** 15 | * 用于在DEBUG模式下输出Log 16 | */ 17 | public class LogUtils { 18 | private static final boolean DEBUG = dev.mars.callme.BuildConfig.DEBUG; 19 | private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 20 | private static String TAG = "dev_mars"; 21 | public static void setTAG(String tag){ 22 | TAG = tag; 23 | } 24 | 25 | public static void E(String msg){ 26 | if (DEBUG){ 27 | Log.e(TAG,msg); 28 | } 29 | } 30 | 31 | public static void E(String tag,String msg){ 32 | if (DEBUG){ 33 | Log.e(tag,msg); 34 | } 35 | } 36 | 37 | public static void D(String msg){ 38 | if (DEBUG){ 39 | Log.d(TAG,msg); 40 | } 41 | } 42 | 43 | public static void DT(String msg){ 44 | if (DEBUG){ 45 | Log.d(TAG,sdf.format(new Date())+":"+msg); 46 | } 47 | } 48 | 49 | public static void I(String msg){ 50 | if (DEBUG){ 51 | Log.i(TAG,msg); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/utils/RingtonePlayer.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.utils; 2 | 3 | import android.content.Context; 4 | import android.media.AudioManager; 5 | import android.media.MediaPlayer; 6 | import android.media.RingtoneManager; 7 | import android.net.Uri; 8 | import android.os.Vibrator; 9 | import android.provider.SyncStateContract; 10 | 11 | import dev.mars.callme.common.Constants; 12 | 13 | /** 14 | * Created by mars_ma on 2017/4/5. 15 | */ 16 | 17 | public class RingtonePlayer { 18 | private static MediaPlayer mMediaPlayer; 19 | private static Vibrator vibrator; 20 | 21 | public static void play(Context context) { 22 | if(!Constants.RING_TONE_PLAY) 23 | return; 24 | //-开始播放手机铃声及震动 25 | close(); 26 | try { 27 | Uri alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE); 28 | mMediaPlayer = new MediaPlayer(); 29 | mMediaPlayer.setDataSource(context, alert); 30 | //final AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 31 | mMediaPlayer.setAudioStreamType(AudioManager.STREAM_RING); 32 | mMediaPlayer.setLooping(true); 33 | mMediaPlayer.prepare(); 34 | mMediaPlayer.start(); 35 | } catch (Exception e) { 36 | e.printStackTrace(); 37 | } 38 | 39 | try { 40 | vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 41 | long[] pattern = {800, 150, 400, 130}; // OFF/ON/OFF/ON... 42 | vibrator.vibrate(pattern, 2); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } 46 | } 47 | 48 | public static void close() { 49 | if(!Constants.RING_TONE_PLAY) 50 | return; 51 | try { 52 | if (mMediaPlayer != null) { 53 | if (mMediaPlayer.isPlaying()) { 54 | mMediaPlayer.stop(); 55 | } 56 | } 57 | 58 | } catch (Exception e) { 59 | e.printStackTrace(); 60 | } 61 | 62 | try { 63 | if (null != vibrator) { 64 | vibrator.cancel(); 65 | 66 | } 67 | } catch (Exception e) { 68 | e.printStackTrace(); 69 | } 70 | mMediaPlayer = null; 71 | vibrator = null; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /callme/src/main/java/dev/mars/callme/utils/WifiUtils.java: -------------------------------------------------------------------------------- 1 | package dev.mars.callme.utils; 2 | 3 | import android.content.Context; 4 | import android.net.wifi.WifiInfo; 5 | import android.net.wifi.WifiManager; 6 | 7 | import static android.content.Context.WIFI_SERVICE; 8 | 9 | /** 10 | * Created by ma.xuanwei on 2017/3/23. 11 | */ 12 | 13 | public class WifiUtils { 14 | public static String getWifiIP(Context c) { 15 | WifiManager wifiManager = (WifiManager) c.getSystemService(WIFI_SERVICE); 16 | //获取当前连接的wifi的信息 17 | WifiInfo wifiInfo = wifiManager.getConnectionInfo(); 18 | int ipAddress = wifiInfo.getIpAddress(); 19 | return intToIp(ipAddress); 20 | 21 | } 22 | 23 | private static String intToIp(int i) { 24 | return ((i ) & 0xFF) + "." 25 | 26 | + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + (i>>24 & 0xFF); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /callme/src/main/res/layout/activity_calling.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 16 | 17 |