├── .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 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/callme/src/main/res/layout/activity_communicating.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
16 |
17 |
22 |
23 |
29 |
30 |
35 |
36 |
41 |
42 |
47 |
48 |
--------------------------------------------------------------------------------
/callme/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
19 |
20 |
25 |
26 |
31 |
32 |
37 |
38 |
43 |
44 |
49 |
50 |
55 |
56 |
60 |
61 |
66 |
67 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/callme/src/main/res/layout/activity_on_call.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
17 |
18 |
23 |
28 |
29 |
--------------------------------------------------------------------------------
/callme/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/callme/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/callme/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/callme/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/callme/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/callme/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/callme/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/callme/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/callme/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/callme/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/callme/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/callme/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/callme/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/callme/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | CallMe
3 |
4 |
--------------------------------------------------------------------------------
/callme/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/callme/src/test/java/dev/mars/callme/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package dev.mars.callme;
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 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':callme', ':audio', ':video'
2 |
--------------------------------------------------------------------------------
/video/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/video/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 |
7 | defaultConfig {
8 | applicationId "mars.dev.video"
9 | minSdkVersion 15
10 | targetSdkVersion 25
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
15 |
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | compile fileTree(dir: 'libs', include: ['*.jar'])
27 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
28 | exclude group: 'com.android.support', module: 'support-annotations'
29 | })
30 | compile 'com.android.support:appcompat-v7:25.0.1'
31 | testCompile 'junit:junit:4.12'
32 | }
33 |
--------------------------------------------------------------------------------
/video/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 D:\android_sdk/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 |
--------------------------------------------------------------------------------
/video/src/androidTest/java/mars/dev/video/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package mars.dev.video;
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("mars.dev.video", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/video/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/video/src/main/java/mars/dev/video/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package mars.dev.video;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Activity;
5 | import android.content.pm.PackageManager;
6 | import android.os.Build;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.widget.Toast;
9 |
10 | /**
11 | * Created by mars_ma on 2017/4/11.
12 | */
13 |
14 | public class BaseActivity extends AppCompatActivity{
15 | public Activity getActivity(){
16 | return BaseActivity.this;
17 | }
18 |
19 | public void showToast(String str){
20 | Toast.makeText(getActivity(),str,Toast.LENGTH_SHORT).show();
21 | }
22 |
23 | @TargetApi(Build.VERSION_CODES.M)
24 | public boolean hasPermissions(String[] pers){
25 | for(String p:pers){
26 | if(checkSelfPermission(p) != PackageManager.PERMISSION_GRANTED){
27 | return false;
28 | }
29 | }
30 | return true;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/video/src/main/java/mars/dev/video/LogUtils.java:
--------------------------------------------------------------------------------
1 | package mars.dev.video;
2 |
3 | import android.util.Log;
4 |
5 | import java.text.SimpleDateFormat;
6 | import java.util.Date;
7 |
8 |
9 | /**
10 | * Created by ma.xuanwei on 2016/12/6.
11 | */
12 |
13 | /**
14 | * 用于在DEBUG模式下输出Log
15 | */
16 | public class LogUtils {
17 | private static final boolean DEBUG = true;
18 | private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
19 | private static String TAG = "dev_mars";
20 | public static void setTAG(String tag){
21 | TAG = tag;
22 | }
23 |
24 | public static void E(String msg){
25 | if (DEBUG){
26 | Log.e(TAG,msg);
27 | }
28 | }
29 |
30 | public static void E(String tag,String msg){
31 | if (DEBUG){
32 | Log.e(tag,msg);
33 | }
34 | }
35 |
36 | public static void D(String msg){
37 | if (DEBUG){
38 | Log.d(TAG,msg);
39 | }
40 | }
41 |
42 | public static void DT(String msg){
43 | if (DEBUG){
44 | Log.d(TAG,sdf.format(new Date())+":"+msg);
45 | }
46 | }
47 |
48 | public static void I(String msg){
49 | if (DEBUG){
50 | Log.i(TAG,msg);
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/video/src/main/java/mars/dev/video/MainActivity.java:
--------------------------------------------------------------------------------
1 | package mars.dev.video;
2 |
3 | import android.Manifest;
4 | import android.content.pm.ActivityInfo;
5 | import android.os.Build;
6 | import android.support.annotation.NonNull;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.os.Bundle;
9 | import android.view.View;
10 |
11 | import static android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE;
12 |
13 | public class MainActivity extends BaseActivity{
14 | String[] permissions = {Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE};
15 | @Override
16 | protected void onCreate(Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
19 | setContentView(R.layout.activity_main);
20 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
21 | if (hasPermissions(permissions)) {
22 | } else {
23 | requestPermissions(permissions, 0);
24 | }
25 | }
26 | }
27 |
28 | @Override
29 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
30 | if (requestCode == 0) {
31 | if(!hasPermissions(permissions)){
32 | finish();
33 | }else{
34 | }
35 | }
36 |
37 | }
38 |
39 | public void enterVideoTest(View view) {
40 | VideoActivity.enter(getActivity());
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/video/src/main/java/mars/dev/video/VideoActivity.java:
--------------------------------------------------------------------------------
1 | package mars.dev.video;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.content.res.Configuration;
6 | import android.hardware.Camera;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.os.Bundle;
9 | import android.util.Log;
10 | import android.view.SurfaceHolder;
11 | import android.view.SurfaceView;
12 | import android.widget.CompoundButton;
13 | import android.widget.LinearLayout;
14 | import android.widget.Switch;
15 |
16 | import java.io.IOException;
17 |
18 | public class VideoActivity extends AppCompatActivity implements SurfaceHolder.Callback {
19 |
20 | SurfaceView surfaceView;
21 | SurfaceHolder holder;
22 | Camera camera;
23 |
24 | Switch cameraSwitch;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_video);
30 | surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
31 | cameraSwitch = (Switch) findViewById(R.id.cameraSwitch);
32 | init();
33 |
34 | }
35 |
36 | private void init() {
37 | holder = surfaceView.getHolder();//获得句柄
38 | holder.addCallback(this);//添加回调
39 | cameraSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
40 | @Override
41 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
42 | switchCamera(isChecked);
43 | }
44 | });
45 | }
46 |
47 | private void switchCamera(boolean front) {
48 | //切换前后摄像头
49 | int cameraCount = 0;
50 | Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
51 | cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数
52 | LogUtils.DT("摄像头个数:"+cameraCount);
53 | if(cameraCount<=1){
54 | return;
55 | }
56 |
57 | for(int i = 0; i < cameraCount; i ++) {
58 | Camera.getCameraInfo(i, cameraInfo);//得到每一个摄像头的信息
59 | if(front) {
60 | if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置
61 | camera.stopPreview();//停掉原来摄像头的预览
62 | camera.release();//释放资源
63 | camera = null;//取消原来摄像头
64 | camera = Camera.open(i);//打开当前选中的摄像头
65 | try {
66 | camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面
67 | resetCameraDisplayOrientation();
68 | camera.startPreview();//开始预览
69 | } catch (IOException e) {
70 | // TODO Auto-generated catch block
71 | e.printStackTrace();
72 | }
73 | break;
74 | }
75 | } else {
76 | if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置
77 | camera.stopPreview();//停掉原来摄像头的预览
78 | camera.release();//释放资源
79 | camera = null;//取消原来摄像头
80 | camera = Camera.open(i);//打开当前选中的摄像头
81 | try {
82 | camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面
83 | resetCameraDisplayOrientation();
84 | camera.startPreview();//开始预览
85 | } catch (IOException e) {
86 | // TODO Auto-generated catch block
87 | e.printStackTrace();
88 | }
89 | break;
90 | }
91 | }
92 |
93 | }
94 | }
95 |
96 | private void resetCameraDisplayOrientation(){
97 | Camera.Parameters parameters = camera.getParameters();
98 | if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
99 | {
100 | //如果是竖屏
101 | parameters.set("orientation", "portrait");
102 | camera.setDisplayOrientation(90);
103 | } else{
104 | parameters.set("orientation", "landscape");
105 | camera.setDisplayOrientation(0);
106 | }
107 | camera.setParameters(parameters);
108 | }
109 |
110 | @Override
111 | public void surfaceCreated(SurfaceHolder holder) {
112 | if (camera == null) {
113 | camera = Camera.open();
114 | try {
115 | camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面
116 | resetCameraDisplayOrientation();
117 | camera.startPreview();//开始预览
118 |
119 |
120 | } catch (IOException e) {
121 | // TODO Auto-generated catch block
122 | e.printStackTrace();
123 | }
124 | }
125 | }
126 |
127 | private void relayout(int surfaceWidth, int surfaceHeight) {
128 | Camera.Parameters parameters = camera.getParameters();
129 | Camera.Size size = parameters.getPictureSize();
130 | LogUtils.DT("surfaceview width "+surfaceWidth+" height "+surfaceHeight);
131 | LogUtils.DT("camera width "+size.width+" height "+size.height);
132 | }
133 |
134 | @Override
135 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
136 | relayout(width, height);
137 | // camera.startPreview();// 开始预览
138 | }
139 |
140 | @Override
141 | public void surfaceDestroyed(SurfaceHolder holder) {
142 | camera.stopPreview();
143 | camera.release();
144 | camera = null;
145 | }
146 |
147 | public static void enter(Context context) {
148 | Intent intent = new Intent(context, VideoActivity.class);
149 | context.startActivity(intent);
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/video/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
--------------------------------------------------------------------------------
/video/src/main/res/layout/activity_video.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
21 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/video/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/video/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/video/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/video/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/video/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/video/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/video/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/video/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/video/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mars-ma/CallMe/9fca853d296eec2cd0428f5dd3e282dd9907d487/video/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/video/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/video/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/video/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/video/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | video
3 |
4 |
--------------------------------------------------------------------------------
/video/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/video/src/test/java/mars/dev/video/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package mars.dev.video;
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 | }
--------------------------------------------------------------------------------