├── .gitattributes
├── .gitignore
├── .idea
├── codeStyles
│ └── Project.xml
├── gradle.xml
├── misc.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── zlw
│ │ └── audio_recorder
│ │ ├── MainActivity.java
│ │ ├── TestHzActivity.java
│ │ ├── base
│ │ └── MyApp.java
│ │ └── widget
│ │ └── AudioView.java
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ └── ic_launcher_background.xml
│ ├── layout
│ ├── activity_hz.xml
│ └── activity_main.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── doc
└── demo.jpg
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── jitpack.yml
├── recorderlib
├── .gitignore
├── build.gradle
├── libs
│ ├── arm64-v8a
│ │ └── libmp3lame.so
│ ├── armeabi-v7a
│ │ └── libmp3lame.so
│ ├── armeabi
│ │ └── libmp3lame.so
│ ├── mips
│ │ └── libmp3lame.so
│ ├── mips64
│ │ └── libmp3lame.so
│ ├── x86
│ │ └── libmp3lame.so
│ └── x86_64
│ │ └── libmp3lame.so
├── proguard-rules.pro
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ ├── com
│ │ │ └── zlw
│ │ │ │ └── main
│ │ │ │ └── recorderlib
│ │ │ │ ├── RecordManager.java
│ │ │ │ ├── recorder
│ │ │ │ ├── RecordConfig.java
│ │ │ │ ├── RecordHelper.java
│ │ │ │ ├── RecordService.java
│ │ │ │ ├── listener
│ │ │ │ │ ├── RecordDataListener.java
│ │ │ │ │ ├── RecordFftDataListener.java
│ │ │ │ │ ├── RecordResultListener.java
│ │ │ │ │ ├── RecordSoundSizeListener.java
│ │ │ │ │ └── RecordStateListener.java
│ │ │ │ ├── mp3
│ │ │ │ │ ├── Mp3EncodeThread.java
│ │ │ │ │ ├── Mp3Encoder.java
│ │ │ │ │ └── Mp3Utils.java
│ │ │ │ └── wav
│ │ │ │ │ └── WavUtils.java
│ │ │ │ └── utils
│ │ │ │ ├── ByteUtils.java
│ │ │ │ ├── FileUtils.java
│ │ │ │ ├── Logger.java
│ │ │ │ └── RecordUtils.java
│ │ └── fftlib
│ │ │ ├── ByteUtils.java
│ │ │ ├── Complex.java
│ │ │ ├── FFT.java
│ │ │ └── FftFactory.java
│ ├── jni
│ │ ├── Android.mk
│ │ ├── Application.mk
│ │ ├── Mp3Encoder.c
│ │ ├── Mp3Encoder.h
│ │ └── lame-3.100_libmp3lame
│ │ │ ├── VbrTag.c
│ │ │ ├── VbrTag.h
│ │ │ ├── bitstream.c
│ │ │ ├── bitstream.h
│ │ │ ├── encoder.c
│ │ │ ├── encoder.h
│ │ │ ├── fft.c
│ │ │ ├── fft.h
│ │ │ ├── gain_analysis.c
│ │ │ ├── gain_analysis.h
│ │ │ ├── id3tag.c
│ │ │ ├── id3tag.h
│ │ │ ├── l3side.h
│ │ │ ├── lame-analysis.h
│ │ │ ├── lame.c
│ │ │ ├── lame.h
│ │ │ ├── lame_global_flags.h
│ │ │ ├── lameerror.h
│ │ │ ├── machine.h
│ │ │ ├── mpglib_interface.c
│ │ │ ├── newmdct.c
│ │ │ ├── newmdct.h
│ │ │ ├── presets.c
│ │ │ ├── psymodel.c
│ │ │ ├── psymodel.h
│ │ │ ├── quantize.c
│ │ │ ├── quantize.h
│ │ │ ├── quantize_pvt.c
│ │ │ ├── quantize_pvt.h
│ │ │ ├── reservoir.c
│ │ │ ├── reservoir.h
│ │ │ ├── set_get.c
│ │ │ ├── set_get.h
│ │ │ ├── tables.c
│ │ │ ├── tables.h
│ │ │ ├── takehiro.c
│ │ │ ├── util.c
│ │ │ ├── util.h
│ │ │ ├── vbrquantize.c
│ │ │ ├── vbrquantize.h
│ │ │ ├── version.c
│ │ │ └── version.h
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── zlw
│ └── main
│ └── recorderlib
│ └── ExampleUnitTest.java
└── settings.gradle
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.c linguist-language=Java
2 | *.h linguist-language=Java
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | /.idea/
7 | /.idea/.*
8 | .DS_Store
9 | /build
10 | /captures
11 | .externalNativeBuild
12 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ZlwAudioRecorder
2 |
3 | ### 功能
4 | 1. 使用AudioRecord进行录音
5 | 2. 实现pcm、wav、mp3音频的录制
6 | 3. 实时获取录音的音量、及录音byte数据
7 | 4. 获取wav/mp3录音文件的时长
8 | 5. 可配置录音的采样率、位宽 (v1.04更新)
9 | 5. 录音可视化 (v1.05更新)
10 | 5. 音源支持内录(Android10及以上版本支持) (v1.09更新)
11 |
12 | ### 博客
13 | https://www.jianshu.com/p/c0222de2faed
14 |
15 | ### Gradle
16 | [](https://jitpack.io/#zhaolewei/ZlwAudioRecorder)
17 |
18 | dependencies {
19 | implementation 'com.github.zhaolewei:ZlwAudioRecorder:v1.09'
20 | }
21 |
22 | allprojects {
23 | repositories {
24 | ...
25 | maven { url 'https://www.jitpack.io' }
26 | }
27 | }
28 | ### 如何使用
29 |
30 | 1. 初始化
31 | * init
32 | ```java
33 | /**
34 | * 参数1: Application 实例
35 | * 参数2: 是否打印日志
36 | */
37 | RecordManager.getInstance().init(MyApp.getInstance(), false);
38 | ```
39 | * 在清单文件中注册Services
40 |
41 | ```java
42 |
43 | ```
44 | * 确保有录音权限
45 |
46 | 2. 配置录音参数
47 |
48 | * 修改录音格式(默认:WAV)
49 | ```java
50 | RecordManager.getInstance().changeFormat(RecordConfig.RecordFormat.WAV);
51 | ```
52 |
53 | * 修改录音配置
54 | ```java
55 | RecordManager.getInstance().changeRecordConfig(recordManager.getRecordConfig().setSampleRate(16000));
56 | RecordManager.getInstance().changeRecordConfig(recordManager.getRecordConfig().setEncodingConfig(AudioFormat.ENCODING_PCM_8BIT));
57 | ```
58 | * 修改录音音源
59 | ```java
60 | RecordManager.getInstance().setSource(RecordConfig.SOURCE_MIC); // 麦克风
61 | RecordManager.getInstance().setSource(RecordConfig.SOURCE_SYSTEM); //系统内录
62 | ```
63 | * 修改录音文件存放位置(默认sdcard/Record)
64 | ```java
65 | RecordManager.getInstance().changeRecordDir(recordDir);
66 | ```
67 | * 录音状态监听
68 | ```java
69 | RecordManager.getInstance().setRecordStateListener(new RecordStateListener() {
70 | @Override
71 | public void onStateChange(RecordHelper.RecordState state) {
72 | }
73 | }
74 |
75 | @Override
76 | public void onError(String error) {
77 | }
78 | });
79 | ```
80 | * 录音结果监听
81 | ```java
82 | RecordManager.getInstance().setRecordResultListener(new RecordResultListener() {
83 | @Override
84 | public void onResult(File result) {
85 | }
86 | });
87 | ```
88 | * 声音大小监听
89 | ```java
90 | RecordManager.getInstance().setRecordSoundSizeListener(new RecordSoundSizeListener() {
91 | @Override
92 | public void onSoundSize(int soundSize) {
93 | }
94 | });
95 | ```
96 | * 音频数据监听
97 | ```java
98 | recordManager.setRecordDataListener(new RecordDataListener() {
99 | @Override
100 | public void onData(byte[] data) {
101 | }
102 | });
103 | ```
104 | * 音频可视化数据监听
105 | ```java
106 | recordManager.setRecordFftDataListener(new RecordFftDataListener() {
107 | @Override
108 | public void onFftData(byte[] data) {
109 | audioView.setWaveData(data);
110 | }
111 | });
112 | ```
113 | 3. 录音控制
114 | * 开始录音
115 | ```java
116 | RecordManager.getInstance().start();
117 | ```
118 | * 暂停录音
119 | ```java
120 | RecordManager.getInstance().pasue();
121 | ```
122 | * 恢复录音
123 | ```java
124 | RecordManager.getInstance().resume();
125 | ```
126 | * 停止
127 | ```java
128 | RecordManager.getInstance().stop();
129 | ```
130 |
131 | ### Demo
132 | 
133 | * 演示视频>>> https://www.bilibili.com/video/av48748708?from=search&seid=7409882966117066343
134 |
135 |
136 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'org.jetbrains.kotlin.android'
4 | }
5 |
6 | publishing {
7 | publications {
8 | // 这个mavenJava可以随便填,只是一个任务名字而已
9 | // MavenPublication必须有,这个是调用的任务类
10 | mavenJava(MavenPublication) {
11 | // 这里头是artifacts的配置信息,不填会采用默认的
12 | groupId = 'org.gradle.sample'
13 | artifactId = 'library'
14 | version = '1.1'
15 | }
16 | }
17 | }
18 |
19 | android {
20 | namespace 'com.zlw.audio_recorder'
21 | compileSdk 33
22 |
23 | defaultConfig {
24 | applicationId "com.zlw.audio_recorder"
25 | minSdk 24
26 | versionCode 1
27 | versionName "1.0"
28 |
29 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
30 | vectorDrawables {
31 | useSupportLibrary true
32 | }
33 | }
34 |
35 | buildTypes {
36 | release {
37 | minifyEnabled false
38 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
39 | }
40 | }
41 | compileOptions {
42 | sourceCompatibility JavaVersion.VERSION_1_8
43 | targetCompatibility JavaVersion.VERSION_1_8
44 | }
45 | kotlinOptions {
46 | jvmTarget = '1.8'
47 | }
48 | buildFeatures {
49 | compose true
50 | }
51 | composeOptions {
52 | kotlinCompilerExtensionVersion '1.4.3'
53 | }
54 | packaging {
55 | resources {
56 | excludes += '/META-INF/{AL2.0,LGPL2.1}'
57 | }
58 | }
59 | }
60 |
61 | dependencies {
62 | implementation 'androidx.core:core-ktx:1.9.0'
63 | implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2'
64 | implementation 'androidx.activity:activity-compose:1.7.2'
65 | implementation platform('androidx.compose:compose-bom:2023.03.00')
66 | implementation 'androidx.compose.ui:ui'
67 | implementation 'androidx.compose.ui:ui-graphics'
68 | implementation 'androidx.compose.ui:ui-tooling-preview'
69 | implementation 'androidx.compose.material3:material3'
70 |
71 | implementation 'com.blankj:utilcodex:1.31.1'
72 | implementation 'com.yanzhenjie:permission:2.0.3'
73 | implementation 'com.github.zhaolewei:Logger:1.0.2'
74 | implementation project(path: ':recorderlib')
75 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
34 |
35 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zlw/audio_recorder/TestHzActivity.java:
--------------------------------------------------------------------------------
1 | package com.zlw.audio_recorder;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.graphics.Color;
5 | import android.os.Bundle;
6 | import android.os.Environment;
7 | import android.view.View;
8 | import android.view.Window;
9 | import android.view.WindowManager;
10 | import android.widget.AdapterView;
11 | import android.widget.ArrayAdapter;
12 | import android.widget.Button;
13 | import android.widget.Spinner;
14 | import android.widget.TextView;
15 | import android.widget.Toast;
16 |
17 | import androidx.activity.ComponentActivity;
18 |
19 | import com.yanzhenjie.permission.AndPermission;
20 | import com.yanzhenjie.permission.runtime.Permission;
21 | import com.zlw.audio_recorder.base.MyApp;
22 | import com.zlw.audio_recorder.widget.AudioView;
23 | import com.zlw.loggerlib.Logger;
24 | import com.zlw.main.recorderlib.RecordManager;
25 | import com.zlw.main.recorderlib.recorder.RecordConfig;
26 | import com.zlw.main.recorderlib.recorder.RecordHelper;
27 | import com.zlw.main.recorderlib.recorder.listener.RecordFftDataListener;
28 | import com.zlw.main.recorderlib.recorder.listener.RecordResultListener;
29 | import com.zlw.main.recorderlib.recorder.listener.RecordStateListener;
30 |
31 | import java.io.File;
32 | import java.util.Locale;
33 |
34 |
35 | public class TestHzActivity extends ComponentActivity implements AdapterView.OnItemSelectedListener, View.OnClickListener {
36 | private static final String TAG = TestHzActivity.class.getSimpleName();
37 |
38 | Button btRecord;
39 | Button btStop;
40 | TextView tvState;
41 | AudioView audioView;
42 | Spinner spUpStyle;
43 | Spinner spDownStyle;
44 |
45 | private boolean isStart = false;
46 | private boolean isPause = false;
47 | final RecordManager recordManager = RecordManager.getInstance();
48 | private static final String[] STYLE_DATA = new String[]{"STYLE_ALL", "STYLE_NOTHING", "STYLE_WAVE", "STYLE_HOLLOW_LUMP"};
49 |
50 |
51 | @Override
52 | protected void onCreate(Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | requestWindowFeature(Window.FEATURE_NO_TITLE);
55 | this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
56 | getWindow().setStatusBarColor(Color.TRANSPARENT);
57 | setContentView(R.layout.activity_hz);
58 | initView();
59 | initPermission();
60 | initAudioView();
61 | }
62 |
63 | private void initView() {
64 | btRecord = findViewById(R.id.btRecord);
65 | btStop = findViewById(R.id.btStop);
66 | tvState = findViewById(R.id.tvState);
67 | audioView = findViewById(R.id.audioView);
68 | spUpStyle = findViewById(R.id.spUpStyle);
69 | spDownStyle = findViewById(R.id.spDownStyle);
70 | btRecord.setOnClickListener(this);
71 | btStop.setOnClickListener(this);
72 | }
73 |
74 | @Override
75 | protected void onResume() {
76 | super.onResume();
77 | initRecord();
78 | }
79 |
80 | @Override
81 | protected void onStop() {
82 | super.onStop();
83 | recordManager.stop();
84 | }
85 |
86 | private void initAudioView() {
87 | audioView.setStyle(AudioView.ShowStyle.STYLE_ALL, AudioView.ShowStyle.STYLE_ALL);
88 | tvState.setVisibility(View.GONE);
89 |
90 | ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, STYLE_DATA);
91 | adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
92 | spUpStyle.setAdapter(adapter);
93 | spDownStyle.setAdapter(adapter);
94 | spUpStyle.setOnItemSelectedListener(this);
95 | spDownStyle.setOnItemSelectedListener(this);
96 | }
97 |
98 |
99 | private void initPermission() {
100 | AndPermission.with(this)
101 | .runtime()
102 | .permission(new String[]{Permission.READ_EXTERNAL_STORAGE, Permission.WRITE_EXTERNAL_STORAGE,
103 | Permission.RECORD_AUDIO})
104 | .start();
105 | }
106 |
107 | private void initRecord() {
108 | recordManager.init(MyApp.getInstance(), true);
109 | recordManager.changeFormat(RecordConfig.RecordFormat.WAV);
110 | String recordDir = String.format(Locale.getDefault(), "%s/Record/com.zlw.main/",
111 | Environment.getExternalStorageDirectory().getAbsolutePath());
112 | recordManager.changeRecordDir(recordDir);
113 |
114 | recordManager.setRecordStateListener(new RecordStateListener() {
115 | @Override
116 | public void onStateChange(RecordHelper.RecordState state) {
117 | Logger.i(TAG, "onStateChange %s", state.name());
118 |
119 | switch (state) {
120 | case PAUSE:
121 | tvState.setText("暂停中");
122 | break;
123 | case IDLE:
124 | tvState.setText("空闲中");
125 | break;
126 | case RECORDING:
127 | tvState.setText("录音中");
128 | break;
129 | case STOP:
130 | tvState.setText("停止");
131 | break;
132 | case FINISH:
133 | tvState.setText("录音结束");
134 | break;
135 | default:
136 | break;
137 | }
138 | }
139 |
140 | @Override
141 | public void onError(String error) {
142 | Logger.i(TAG, "onError %s", error);
143 | }
144 | });
145 | recordManager.setRecordResultListener(new RecordResultListener() {
146 | @Override
147 | public void onResult(File result) {
148 | Toast.makeText(TestHzActivity.this, "录音文件: " + result.getAbsolutePath(), Toast.LENGTH_SHORT).show();
149 | }
150 | });
151 | recordManager.setRecordFftDataListener(new RecordFftDataListener() {
152 | @Override
153 | public void onFftData(byte[] data) {
154 | byte[] newdata = new byte[data.length - 36];
155 | for (int i = 0; i < newdata.length; i++) {
156 | newdata[i] = data[i + 36];
157 | }
158 | audioView.setWaveData(data);
159 | }
160 | });
161 | }
162 |
163 | @Override
164 | public void onClick(View view) {
165 | if (view.getId() == R.id.btRecord) {
166 | if (isStart) {
167 | recordManager.pause();
168 | btRecord.setText("开始");
169 | isPause = true;
170 | isStart = false;
171 | } else {
172 | if (isPause) {
173 | recordManager.resume();
174 | } else {
175 | recordManager.start();
176 | }
177 | btRecord.setText("暂停");
178 | isStart = true;
179 | }
180 | } else if (view.getId() == R.id.btStop) {
181 | recordManager.stop();
182 | btRecord.setText("开始");
183 | isPause = false;
184 | isStart = false;
185 | }
186 | }
187 |
188 | @SuppressLint("NonConstantResourceId")
189 | @Override
190 | public void onItemSelected(AdapterView> parent, View view, int position, long id) {
191 | int parentId = parent.getId();
192 | if (parentId == R.id.spUpStyle) {
193 | audioView.setStyle(AudioView.ShowStyle.getStyle(STYLE_DATA[position]), audioView.getDownStyle());
194 | } else if (parentId == R.id.spDownStyle) {
195 | audioView.setStyle(audioView.getUpStyle(), AudioView.ShowStyle.getStyle(STYLE_DATA[position]));
196 | }
197 | }
198 |
199 | @Override
200 | public void onNothingSelected(AdapterView> parent) {
201 |
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zlw/audio_recorder/base/MyApp.java:
--------------------------------------------------------------------------------
1 | package com.zlw.audio_recorder.base;
2 |
3 | import android.app.Application;
4 |
5 | /**
6 | * @author zlw on 2018/7/4.
7 | */
8 | public class MyApp extends Application {
9 |
10 | private static MyApp instance;
11 |
12 | @Override
13 | public void onCreate() {
14 | super.onCreate();
15 | instance = this;
16 | }
17 |
18 | public static MyApp getInstance() {
19 | return instance;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/zlw/audio_recorder/widget/AudioView.java:
--------------------------------------------------------------------------------
1 | package com.zlw.audio_recorder.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.graphics.Path;
8 | import android.graphics.Point;
9 | import android.util.AttributeSet;
10 | import android.view.View;
11 |
12 | import androidx.annotation.Nullable;
13 |
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | /**
18 | * @author zhaolewei on 2018/8/17.
19 | */
20 | public class AudioView extends View {
21 |
22 | /**
23 | * 频谱数量
24 | */
25 | private static final int LUMP_COUNT = 128 * 2;
26 | private static final int LUMP_WIDTH = 6;
27 | private static final int LUMP_SPACE = 2;
28 | private static final int LUMP_MIN_HEIGHT = LUMP_WIDTH;
29 | private static final int LUMP_MAX_HEIGHT = 200;//TODO: HEIGHT
30 | private static final int LUMP_SIZE = LUMP_WIDTH + LUMP_SPACE;
31 | private static final int LUMP_COLOR = Color.parseColor("#6de8fd");
32 |
33 | private static final int WAVE_SAMPLING_INTERVAL = 5;
34 |
35 | private static final float SCALE = LUMP_MAX_HEIGHT / 128;
36 |
37 | private ShowStyle upShowStyle = ShowStyle.STYLE_HOLLOW_LUMP;
38 | private ShowStyle downShowStyle = ShowStyle.STYLE_WAVE;
39 |
40 | private byte[] waveData;
41 | List pointList;
42 |
43 | private Paint lumpUpPaint, lumpDownPaint;
44 | Path wavePathUp = new Path();
45 | Path wavePathDown = new Path();
46 |
47 |
48 | public AudioView(Context context) {
49 | super(context);
50 | init();
51 | }
52 |
53 | public AudioView(Context context, @Nullable AttributeSet attrs) {
54 | super(context, attrs);
55 | init();
56 | }
57 |
58 | public AudioView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
59 | super(context, attrs, defStyleAttr);
60 | init();
61 | }
62 |
63 | private void init() {
64 | lumpUpPaint = new Paint();
65 | lumpUpPaint.setAntiAlias(true);
66 | lumpUpPaint.setColor(LUMP_COLOR);
67 | lumpUpPaint.setStrokeWidth(3);
68 | lumpUpPaint.setStyle(Paint.Style.FILL);
69 |
70 | lumpDownPaint = new Paint();
71 | lumpDownPaint.setAntiAlias(true);
72 | lumpDownPaint.setColor(LUMP_COLOR);
73 | lumpDownPaint.setStrokeWidth(3);
74 | lumpDownPaint.setStyle(Paint.Style.STROKE);
75 | }
76 |
77 | public void setWaveData(byte[] data) {
78 | this.waveData = readyData(data);
79 | genSamplingPoint(data);
80 | invalidate();
81 | }
82 |
83 | public void setStyle(ShowStyle upShowStyle, ShowStyle downShowStyle) {
84 | this.upShowStyle = upShowStyle;
85 | this.downShowStyle = downShowStyle;
86 | if (upShowStyle == ShowStyle.STYLE_HOLLOW_LUMP || upShowStyle == ShowStyle.STYLE_ALL) {
87 | lumpUpPaint.setColor(Color.parseColor("#A4D3EE"));
88 | }
89 | if (downShowStyle == ShowStyle.STYLE_HOLLOW_LUMP || downShowStyle == ShowStyle.STYLE_ALL) {
90 | lumpDownPaint.setColor(Color.parseColor("#A4D3EE"));
91 | }
92 | }
93 |
94 | public ShowStyle getUpStyle() {
95 | return upShowStyle;
96 | }
97 |
98 | public ShowStyle getDownStyle() {
99 | return downShowStyle;
100 | }
101 |
102 | @Override
103 | protected void onDraw(Canvas canvas) {
104 | super.onDraw(canvas);
105 | wavePathUp.reset();
106 | wavePathDown.reset();
107 |
108 | for (int i = 0; i < LUMP_COUNT; i++) {
109 | if (waveData == null) {
110 | canvas.drawRect((LUMP_WIDTH + LUMP_SPACE) * i,
111 | LUMP_MAX_HEIGHT - LUMP_MIN_HEIGHT,
112 | (LUMP_WIDTH + LUMP_SPACE) * i + LUMP_WIDTH,
113 | LUMP_MAX_HEIGHT,
114 | lumpUpPaint);
115 | continue;
116 | }
117 |
118 | if (upShowStyle != null) {
119 | switch (upShowStyle) {
120 | case STYLE_HOLLOW_LUMP:
121 | drawLump(canvas, i, true);
122 | break;
123 | case STYLE_WAVE:
124 | drawWave(canvas, i, true);
125 | break;
126 | case STYLE_ALL:
127 | drawLump(canvas, i, true);
128 | drawWave(canvas, i, true);
129 | default:
130 | break;
131 | }
132 | }
133 | if (downShowStyle != null) {
134 | switch (downShowStyle) {
135 | case STYLE_HOLLOW_LUMP:
136 | drawLump(canvas, i, false);
137 | break;
138 | case STYLE_WAVE:
139 | drawWave(canvas, i, false);
140 | break;
141 | case STYLE_ALL:
142 | drawLump(canvas, i, false);
143 | drawWave(canvas, i, false);
144 | default:
145 | break;
146 | }
147 | }
148 | }
149 | }
150 |
151 | /**
152 | * 预处理数据
153 | *
154 | * @return
155 | */
156 | private static byte[] readyData(byte[] fft) {
157 | byte[] newData = new byte[LUMP_COUNT];
158 | for (int i = 0; i < Math.min(fft.length, LUMP_COUNT); i++) {
159 | newData[i] = (byte) Math.abs(fft[i]);
160 | }
161 | return newData;
162 | }
163 |
164 | /**
165 | * 绘制曲线
166 | *
167 | * @param canvas
168 | * @param i
169 | * @param reversal
170 | */
171 | private void drawWave(Canvas canvas, int i, boolean reversal) {
172 | if (pointList == null || pointList.size() < 2) {
173 | return;
174 | }
175 | float ratio = SCALE * (reversal ? 1 : -1);
176 | if (i < pointList.size() - 2) {
177 | Point point = pointList.get(i);
178 | Point nextPoint = pointList.get(i + 1);
179 | int midX = (point.x + nextPoint.x) >> 1;
180 | if (reversal) {
181 | if (i == 0) {
182 | wavePathUp.moveTo(point.x, LUMP_MAX_HEIGHT - point.y * ratio);
183 | }
184 | wavePathUp.cubicTo(midX, LUMP_MAX_HEIGHT - point.y * ratio,
185 | midX, LUMP_MAX_HEIGHT - nextPoint.y * ratio,
186 | nextPoint.x, LUMP_MAX_HEIGHT - nextPoint.y * ratio);
187 | canvas.drawPath(wavePathUp, lumpDownPaint);
188 | } else {
189 | if (i == 0) {
190 | wavePathDown.moveTo(point.x, LUMP_MAX_HEIGHT - point.y * ratio);
191 | }
192 | wavePathDown.cubicTo(midX, LUMP_MAX_HEIGHT - point.y * ratio,
193 | midX, LUMP_MAX_HEIGHT - nextPoint.y * ratio,
194 | nextPoint.x, LUMP_MAX_HEIGHT - nextPoint.y * ratio);
195 | canvas.drawPath(wavePathDown, lumpDownPaint);
196 | }
197 |
198 | }
199 | }
200 |
201 | /**
202 | * 绘制矩形条
203 | * reversal: true: 上
204 | */
205 | private void drawLump(Canvas canvas, int i, boolean reversal) {
206 | int minus = reversal ? 1 : -1;
207 | float top;
208 |
209 | if ((reversal && upShowStyle == ShowStyle.STYLE_ALL) || (!reversal && downShowStyle == ShowStyle.STYLE_ALL)) {
210 | top = (LUMP_MAX_HEIGHT - (LUMP_MIN_HEIGHT + waveData[i] / 4 * SCALE) * minus);
211 | } else {
212 | top = (LUMP_MAX_HEIGHT - (LUMP_MIN_HEIGHT + waveData[i] * SCALE) * minus);
213 | }
214 | canvas.drawRect(LUMP_SIZE * i,
215 | top,
216 | LUMP_SIZE * i + LUMP_WIDTH,
217 | LUMP_MAX_HEIGHT,
218 | lumpUpPaint);
219 |
220 | }
221 |
222 | /**
223 | * 生成波形图的采样数据,减少计算量
224 | *
225 | * @param data
226 | */
227 | private void genSamplingPoint(byte[] data) {
228 | if (upShowStyle != ShowStyle.STYLE_WAVE && downShowStyle != ShowStyle.STYLE_WAVE && upShowStyle != ShowStyle.STYLE_ALL && downShowStyle != ShowStyle.STYLE_ALL) {
229 | return;
230 | }
231 | if (pointList == null) {
232 | pointList = new ArrayList<>();
233 | } else {
234 | pointList.clear();
235 | }
236 | pointList.add(new Point(0, 0));
237 | for (int i = WAVE_SAMPLING_INTERVAL; i < LUMP_COUNT; i += WAVE_SAMPLING_INTERVAL) {
238 | pointList.add(new Point(LUMP_SIZE * i, waveData[i]));
239 | }
240 | pointList.add(new Point(LUMP_SIZE * LUMP_COUNT, 0));
241 | }
242 |
243 |
244 | /**
245 | * 可视化样式
246 | */
247 | public enum ShowStyle {
248 | /**
249 | * 空心的矩形小块
250 | */
251 | STYLE_HOLLOW_LUMP,
252 |
253 | /**
254 | * 曲线
255 | */
256 | STYLE_WAVE,
257 |
258 | /**
259 | * 不显示
260 | */
261 | STYLE_NOTHING,
262 | /**
263 | * 都显示
264 | */
265 | STYLE_ALL;
266 |
267 | public static ShowStyle getStyle(String name) {
268 | for (ShowStyle style : ShowStyle.values()) {
269 | if (style.name().equals(name)) {
270 | return style;
271 | }
272 | }
273 |
274 | return STYLE_NOTHING;
275 | }
276 | }
277 |
278 | }
279 |
280 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_hz.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
15 |
16 |
24 |
25 |
26 |
30 |
31 |
35 |
36 |
41 |
42 |
47 |
48 |
49 |
55 |
56 |
62 |
63 |
64 |
68 |
69 |
73 |
74 |
75 |
76 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
16 |
17 |
22 |
23 |
29 |
30 |
34 |
35 |
40 |
41 |
47 |
48 |
54 |
55 |
62 |
63 |
64 |
65 |
71 |
72 |
76 |
77 |
82 |
83 |
89 |
90 |
97 |
98 |
104 |
105 |
106 |
112 |
113 |
117 |
118 |
123 |
124 |
130 |
131 |
138 |
139 |
140 |
141 |
145 |
146 |
151 |
152 |
159 |
160 |
166 |
167 |
168 |
174 |
175 |
180 |
181 |
186 |
187 |
191 |
192 |
196 |
197 |
201 |
202 |
206 |
207 |
212 |
213 |
214 |
218 |
219 |
223 |
224 |
229 |
230 |
231 |
232 |
236 |
237 |
242 |
243 |
244 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | ZlwAudioRecorder
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application' version '8.1.0' apply false
3 | id 'org.jetbrains.kotlin.android' version '1.8.10' apply false
4 | id 'maven-publish'
5 | }
6 |
--------------------------------------------------------------------------------
/doc/demo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/doc/demo.jpg
--------------------------------------------------------------------------------
/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=-Xmx2048m -Dfile.encoding=UTF-8
13 | # When configured, Gradle will run in incubating parallel mode.
14 | # This option should only be used with decoupled projects. More details, visit
15 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
16 | # org.gradle.parallel=true
17 | android.useDeprecatedNDK=false
18 | kotlin.code.style=official
19 | android.useAndroidX=true
20 | android.nonTransitiveRClass=true
21 | android.enableJetifier=true
22 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Sep 10 20:34:27 CST 2023
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
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 |
--------------------------------------------------------------------------------
/jitpack.yml:
--------------------------------------------------------------------------------
1 | jdk:
2 | - openjdk17
--------------------------------------------------------------------------------
/recorderlib/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/recorderlib/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | //apply plugin: 'com.github.dcendents.android-maven'
3 | group='com.github.zhaolewei'
4 |
5 | android {
6 | namespace = "com.zlw.main.recorderlib"
7 | compileSdkVersion 33
8 | defaultConfig {
9 | minSdkVersion 16
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 | }
15 |
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | sourceSets.main {
23 | jni.srcDirs = []//disable automatic ndk-build call
24 | jniLibs.srcDirs = ['libs']
25 | }
26 | }
27 |
28 | dependencies {
29 | implementation fileTree(dir: 'libs', include: ['*.jar'])
30 | }
31 |
--------------------------------------------------------------------------------
/recorderlib/libs/arm64-v8a/libmp3lame.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/recorderlib/libs/arm64-v8a/libmp3lame.so
--------------------------------------------------------------------------------
/recorderlib/libs/armeabi-v7a/libmp3lame.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/recorderlib/libs/armeabi-v7a/libmp3lame.so
--------------------------------------------------------------------------------
/recorderlib/libs/armeabi/libmp3lame.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/recorderlib/libs/armeabi/libmp3lame.so
--------------------------------------------------------------------------------
/recorderlib/libs/mips/libmp3lame.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/recorderlib/libs/mips/libmp3lame.so
--------------------------------------------------------------------------------
/recorderlib/libs/mips64/libmp3lame.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/recorderlib/libs/mips64/libmp3lame.so
--------------------------------------------------------------------------------
/recorderlib/libs/x86/libmp3lame.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/recorderlib/libs/x86/libmp3lame.so
--------------------------------------------------------------------------------
/recorderlib/libs/x86_64/libmp3lame.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zhaolewei/ZlwAudioRecorder/f2eb0221f2a8d4558256d18183f281214d5fff4c/recorderlib/libs/x86_64/libmp3lame.so
--------------------------------------------------------------------------------
/recorderlib/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/recorderlib/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/RecordManager.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib;
2 |
3 |
4 | import android.annotation.SuppressLint;
5 | import android.app.Application;
6 | import android.media.projection.MediaProjection;
7 | import android.os.Build;
8 |
9 | import com.zlw.main.recorderlib.recorder.RecordConfig;
10 | import com.zlw.main.recorderlib.recorder.RecordHelper;
11 | import com.zlw.main.recorderlib.recorder.RecordService;
12 | import com.zlw.main.recorderlib.recorder.listener.RecordDataListener;
13 | import com.zlw.main.recorderlib.recorder.listener.RecordFftDataListener;
14 | import com.zlw.main.recorderlib.recorder.listener.RecordResultListener;
15 | import com.zlw.main.recorderlib.recorder.listener.RecordSoundSizeListener;
16 | import com.zlw.main.recorderlib.recorder.listener.RecordStateListener;
17 | import com.zlw.main.recorderlib.utils.Logger;
18 |
19 | /**
20 | * @author zhaolewei on 2018/7/10.
21 | */
22 | public class RecordManager {
23 | private static final String TAG = RecordManager.class.getSimpleName();
24 | @SuppressLint("StaticFieldLeak")
25 | private volatile static RecordManager instance;
26 | private Application context;
27 |
28 | private MediaProjection mediaProjection;
29 |
30 | private RecordManager() {
31 | }
32 |
33 | public static RecordManager getInstance() {
34 | if (instance == null) {
35 | synchronized (RecordManager.class) {
36 | if (instance == null) {
37 | instance = new RecordManager();
38 | }
39 | }
40 | }
41 | return instance;
42 | }
43 |
44 | /**
45 | * 初始化
46 | *
47 | * @param application Application
48 | * @param showLog 是否开启日志
49 | */
50 | public void init(Application application, boolean showLog) {
51 | this.context = application;
52 | Logger.IsDebug = showLog;
53 | }
54 |
55 | public void start() {
56 | if (context == null) {
57 | Logger.e(TAG, "未进行初始化");
58 | return;
59 | }
60 | Logger.i(TAG, "start...");
61 | RecordService.startRecording(context);
62 | }
63 |
64 | public void stop() {
65 | if (context == null) {
66 | return;
67 | }
68 | RecordService.stopRecording(context);
69 | }
70 |
71 | public void resume() {
72 | if (context == null) {
73 | return;
74 | }
75 | RecordService.resumeRecording(context);
76 | }
77 |
78 | public void pause() {
79 | if (context == null) {
80 | return;
81 | }
82 | RecordService.pauseRecording(context);
83 | }
84 |
85 | /**
86 | * 录音状态监听回调
87 | */
88 | public void setRecordStateListener(RecordStateListener listener) {
89 | RecordService.setRecordStateListener(listener);
90 | }
91 |
92 | /**
93 | * 录音数据监听回调
94 | */
95 | public void setRecordDataListener(RecordDataListener listener) {
96 | RecordService.setRecordDataListener(listener);
97 | }
98 |
99 | /**
100 | * 录音可视化数据回调,傅里叶转换后的频域数据
101 | */
102 | public void setRecordFftDataListener(RecordFftDataListener recordFftDataListener) {
103 | RecordService.setRecordFftDataListener(recordFftDataListener);
104 | }
105 |
106 | /**
107 | * 录音文件转换结束回调
108 | */
109 | public void setRecordResultListener(RecordResultListener listener) {
110 | RecordService.setRecordResultListener(listener);
111 | }
112 |
113 | /**
114 | * 录音音量监听回调
115 | */
116 | public void setRecordSoundSizeListener(RecordSoundSizeListener listener) {
117 | RecordService.setRecordSoundSizeListener(listener);
118 | }
119 |
120 |
121 | public boolean changeFormat(RecordConfig.RecordFormat recordFormat) {
122 | return RecordService.changeFormat(recordFormat);
123 | }
124 |
125 |
126 | public boolean changeRecordConfig(RecordConfig recordConfig) {
127 | return RecordService.changeRecordConfig(recordConfig);
128 | }
129 |
130 | /**
131 | * RecordConfig.SOURCE_MIC
132 | * RecordConfig.SOURCE_SYSTEM
133 | *
134 | * @param source 音源
135 | */
136 | public boolean setSource(int source) {
137 | if (Build.VERSION.SDK_INT >= 29) {
138 | RecordService.getRecordConfig().setSource(source);
139 | return true;
140 | }
141 | return false;
142 | }
143 |
144 | public RecordConfig getRecordConfig() {
145 | return RecordService.getRecordConfig();
146 | }
147 |
148 | /**
149 | * 修改录音文件存放路径
150 | */
151 | public void changeRecordDir(String recordDir) {
152 | RecordService.changeRecordDir(recordDir);
153 | }
154 |
155 | /**
156 | * 获取当前的录音状态
157 | *
158 | * @return 状态
159 | */
160 | public RecordHelper.RecordState getState() {
161 | return RecordService.getState();
162 | }
163 |
164 | public void setMediaProjection(MediaProjection mediaProjection) {
165 | this.mediaProjection = mediaProjection;
166 | }
167 |
168 | public MediaProjection getMediaProjection() {
169 | return mediaProjection;
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/recorder/RecordConfig.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.recorder;
2 |
3 | import android.media.AudioFormat;
4 | import android.os.Environment;
5 |
6 | import java.io.Serializable;
7 | import java.util.Locale;
8 |
9 | /**
10 | * @author zhaolewei on 2018/7/11.
11 | */
12 | public class RecordConfig implements Serializable {
13 |
14 | /**
15 | * 音源:麦克风
16 | */
17 | public static int SOURCE_MIC = 0;
18 | /**
19 | * 音源:系统声音(内录)Android 10及以上版本支持
20 | */
21 | public static int SOURCE_SYSTEM = 1;
22 |
23 | /**
24 | * 录音格式 默认WAV格式
25 | */
26 | private RecordFormat format = RecordFormat.WAV;
27 | /**
28 | * 通道数:默认单通道
29 | */
30 | private int channelConfig = AudioFormat.CHANNEL_IN_MONO;
31 |
32 | /**
33 | * 位宽
34 | */
35 | private int encodingConfig = AudioFormat.ENCODING_PCM_16BIT;
36 |
37 | /**
38 | * 音源
39 | * 0: 麦克风
40 | * 1: 系统声音(内录)
41 | */
42 | private int source = 0;
43 |
44 | /**
45 | * 采样率
46 | */
47 | private int sampleRate = 16000;
48 |
49 | /*
50 | * 录音文件存放路径,默认sdcard/Record
51 | */
52 | private String recordDir = String.format(Locale.getDefault(),
53 | "%s/Record/",
54 | Environment.getExternalStorageDirectory().getAbsolutePath());
55 |
56 | public RecordConfig() {
57 | }
58 |
59 | public RecordConfig(RecordFormat format) {
60 | this.format = format;
61 | }
62 |
63 | /**
64 | * @param format 录音文件的格式
65 | * @param channelConfig 声道配置
66 | * 单声道:See {@link AudioFormat#CHANNEL_IN_MONO}
67 | * 双声道:See {@link AudioFormat#CHANNEL_IN_STEREO}
68 | * @param encodingConfig 位宽配置
69 | * 8Bit: See {@link AudioFormat#ENCODING_PCM_8BIT}
70 | * 16Bit: See {@link AudioFormat#ENCODING_PCM_16BIT},
71 | * @param sampleRate 采样率 hz: 8000/16000/44100
72 | */
73 | public RecordConfig(RecordFormat format, int channelConfig, int encodingConfig, int sampleRate) {
74 | this.format = format;
75 | this.channelConfig = channelConfig;
76 | this.encodingConfig = encodingConfig;
77 | this.sampleRate = sampleRate;
78 | }
79 |
80 |
81 | public String getRecordDir() {
82 | return recordDir;
83 | }
84 |
85 | public void setRecordDir(String recordDir) {
86 | this.recordDir = recordDir;
87 | }
88 |
89 | /**
90 | * 获取当前录音的采样位宽 单位bit
91 | *
92 | * @return 采样位宽 0: error
93 | */
94 | public int getEncoding() {
95 | if (format == RecordFormat.MP3) { //mp3后期转换
96 | return 16;
97 | }
98 |
99 | if (encodingConfig == AudioFormat.ENCODING_PCM_8BIT) {
100 | return 8;
101 | } else if (encodingConfig == AudioFormat.ENCODING_PCM_16BIT) {
102 | return 16;
103 | } else {
104 | return 0;
105 | }
106 | }
107 |
108 | public void setSource(int source) {
109 | this.source = source;
110 | }
111 |
112 | public int getSource() {
113 | return source;
114 | }
115 |
116 | /**
117 | * 获取当前录音的采样位宽 单位bit
118 | *
119 | * @return 采样位宽 0: error
120 | */
121 | public int getRealEncoding() {
122 | if (encodingConfig == AudioFormat.ENCODING_PCM_8BIT) {
123 | return 8;
124 | } else if (encodingConfig == AudioFormat.ENCODING_PCM_16BIT) {
125 | return 16;
126 | } else {
127 | return 0;
128 | }
129 | }
130 |
131 | /**
132 | * 当前的声道数
133 | *
134 | * @return 声道数: 0:error
135 | */
136 | public int getChannelCount() {
137 | if (channelConfig == AudioFormat.CHANNEL_IN_MONO) {
138 | return 1;
139 | } else if (channelConfig == AudioFormat.CHANNEL_IN_STEREO) {
140 | return 2;
141 | } else {
142 | return 0;
143 | }
144 | }
145 |
146 | //get&set
147 |
148 | public RecordFormat getFormat() {
149 | return format;
150 | }
151 |
152 | public RecordConfig setFormat(RecordFormat format) {
153 | this.format = format;
154 | return this;
155 | }
156 |
157 | public int getChannelConfig() {
158 | return channelConfig;
159 | }
160 |
161 | public RecordConfig setChannelConfig(int channelConfig) {
162 | this.channelConfig = channelConfig;
163 | return this;
164 | }
165 |
166 | public int getEncodingConfig() {
167 | if (format == RecordFormat.MP3) {//mp3后期转换
168 | return AudioFormat.ENCODING_PCM_16BIT;
169 | }
170 | return encodingConfig;
171 | }
172 |
173 | public RecordConfig setEncodingConfig(int encodingConfig) {
174 | this.encodingConfig = encodingConfig;
175 | return this;
176 | }
177 |
178 | public int getSampleRate() {
179 | return sampleRate;
180 | }
181 |
182 | public RecordConfig setSampleRate(int sampleRate) {
183 | this.sampleRate = sampleRate;
184 | return this;
185 | }
186 |
187 |
188 | @Override
189 | public String toString() {
190 | return String.format(Locale.getDefault(), "录制格式: %s,采样率:%sHz,位宽:%s bit,声道数:%s", format, sampleRate, getEncoding(), getChannelCount());
191 | }
192 |
193 | public enum RecordFormat {
194 | /**
195 | * mp3格式
196 | */
197 | MP3(".mp3"),
198 | /**
199 | * wav格式
200 | */
201 | WAV(".wav"),
202 | /**
203 | * pcm格式
204 | */
205 | PCM(".pcm");
206 |
207 | private String extension;
208 |
209 | public String getExtension() {
210 | return extension;
211 | }
212 |
213 | RecordFormat(String extension) {
214 | this.extension = extension;
215 | }
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/recorder/RecordService.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.recorder;
2 |
3 | import android.app.Service;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.os.IBinder;
8 |
9 | import com.zlw.main.recorderlib.recorder.listener.RecordDataListener;
10 | import com.zlw.main.recorderlib.recorder.listener.RecordFftDataListener;
11 | import com.zlw.main.recorderlib.recorder.listener.RecordResultListener;
12 | import com.zlw.main.recorderlib.recorder.listener.RecordSoundSizeListener;
13 | import com.zlw.main.recorderlib.recorder.listener.RecordStateListener;
14 | import com.zlw.main.recorderlib.utils.FileUtils;
15 | import com.zlw.main.recorderlib.utils.Logger;
16 |
17 | import java.text.SimpleDateFormat;
18 | import java.util.Locale;
19 |
20 | /**
21 | * 录音服务
22 | *
23 | * @author zhaolewei
24 | */
25 | public class RecordService extends Service {
26 | private static final String TAG = RecordService.class.getSimpleName();
27 |
28 | /**
29 | * 录音配置
30 | */
31 | private static RecordConfig currentConfig = new RecordConfig();
32 |
33 | private final static String ACTION_NAME = "action_type";
34 |
35 | private final static int ACTION_INVALID = 0;
36 |
37 | private final static int ACTION_START_RECORD = 1;
38 |
39 | private final static int ACTION_STOP_RECORD = 2;
40 |
41 | private final static int ACTION_RESUME_RECORD = 3;
42 |
43 | private final static int ACTION_PAUSE_RECORD = 4;
44 |
45 | private final static String PARAM_PATH = "path";
46 |
47 |
48 | public RecordService() {
49 | }
50 |
51 | @Override
52 | public IBinder onBind(Intent intent) {
53 | return null;
54 | }
55 |
56 | @Override
57 | public int onStartCommand(Intent intent, int flags, int startId) {
58 | if (intent == null) {
59 | return super.onStartCommand(intent, flags, startId);
60 | }
61 | Bundle bundle = intent.getExtras();
62 | if (bundle != null && bundle.containsKey(ACTION_NAME)) {
63 | switch (bundle.getInt(ACTION_NAME, ACTION_INVALID)) {
64 | case ACTION_START_RECORD:
65 | doStartRecording(bundle.getString(PARAM_PATH));
66 | break;
67 | case ACTION_STOP_RECORD:
68 | doStopRecording();
69 | break;
70 | case ACTION_RESUME_RECORD:
71 | doResumeRecording();
72 | break;
73 | case ACTION_PAUSE_RECORD:
74 | doPauseRecording();
75 | break;
76 | default:
77 | break;
78 | }
79 | return START_STICKY;
80 | }
81 |
82 | return super.onStartCommand(intent, flags, startId);
83 | }
84 |
85 |
86 | public static void startRecording(Context context) {
87 | Intent intent = new Intent(context, RecordService.class);
88 | intent.putExtra(ACTION_NAME, ACTION_START_RECORD);
89 | intent.putExtra(PARAM_PATH, getFilePath());
90 | context.startService(intent);
91 | }
92 |
93 | public static void stopRecording(Context context) {
94 | Intent intent = new Intent(context, RecordService.class);
95 | intent.putExtra(ACTION_NAME, ACTION_STOP_RECORD);
96 | context.startService(intent);
97 | }
98 |
99 | public static void resumeRecording(Context context) {
100 | Intent intent = new Intent(context, RecordService.class);
101 | intent.putExtra(ACTION_NAME, ACTION_RESUME_RECORD);
102 | context.startService(intent);
103 | }
104 |
105 | public static void pauseRecording(Context context) {
106 | Intent intent = new Intent(context, RecordService.class);
107 | intent.putExtra(ACTION_NAME, ACTION_PAUSE_RECORD);
108 | context.startService(intent);
109 | }
110 |
111 | /**
112 | * 改变录音格式
113 | */
114 | public static boolean changeFormat(RecordConfig.RecordFormat recordFormat) {
115 | if (getState() == RecordHelper.RecordState.IDLE) {
116 | currentConfig.setFormat(recordFormat);
117 | return true;
118 | }
119 | return false;
120 | }
121 |
122 | /**
123 | * 改变录音配置
124 | */
125 | public static boolean changeRecordConfig(RecordConfig recordConfig) {
126 | if (getState() == RecordHelper.RecordState.IDLE) {
127 | currentConfig = recordConfig;
128 | return true;
129 | }
130 | return false;
131 | }
132 |
133 | /**
134 | * 获取录音配置参数
135 | */
136 | public static RecordConfig getRecordConfig() {
137 | return currentConfig;
138 | }
139 |
140 | public static void changeRecordDir(String recordDir) {
141 | currentConfig.setRecordDir(recordDir);
142 | }
143 |
144 | /**
145 | * 获取当前的录音状态
146 | */
147 | public static RecordHelper.RecordState getState() {
148 | return RecordHelper.getInstance().getState();
149 | }
150 |
151 | public static void setRecordStateListener(RecordStateListener recordStateListener) {
152 | RecordHelper.getInstance().setRecordStateListener(recordStateListener);
153 | }
154 |
155 | public static void setRecordDataListener(RecordDataListener recordDataListener) {
156 | RecordHelper.getInstance().setRecordDataListener(recordDataListener);
157 | }
158 |
159 | public static void setRecordSoundSizeListener(RecordSoundSizeListener recordSoundSizeListener) {
160 | RecordHelper.getInstance().setRecordSoundSizeListener(recordSoundSizeListener);
161 | }
162 |
163 | public static void setRecordResultListener(RecordResultListener recordResultListener) {
164 | RecordHelper.getInstance().setRecordResultListener(recordResultListener);
165 | }
166 |
167 | public static void setRecordFftDataListener(RecordFftDataListener recordFftDataListener) {
168 | RecordHelper.getInstance().setRecordFftDataListener(recordFftDataListener);
169 | }
170 |
171 | private void doStartRecording(String path) {
172 | Logger.v(TAG, "doStartRecording path: %s", path);
173 | RecordHelper.getInstance().start(path, currentConfig);
174 | }
175 |
176 | private void doResumeRecording() {
177 | Logger.v(TAG, "doResumeRecording");
178 | RecordHelper.getInstance().resume();
179 | }
180 |
181 | private void doPauseRecording() {
182 | Logger.v(TAG, "doResumeRecording");
183 | RecordHelper.getInstance().pause();
184 | }
185 |
186 | private void doStopRecording() {
187 | Logger.v(TAG, "doStopRecording");
188 | RecordHelper.getInstance().stop();
189 | stopSelf();
190 | }
191 |
192 | public static RecordConfig getCurrentConfig() {
193 | return currentConfig;
194 | }
195 |
196 | public static void setCurrentConfig(RecordConfig currentConfig) {
197 | RecordService.currentConfig = currentConfig;
198 | }
199 |
200 | /**
201 | * 根据当前的时间生成相应的文件名
202 | * 实例 record_20160101_13_15_12
203 | */
204 | private static String getFilePath() {
205 |
206 | String fileDir =
207 | currentConfig.getRecordDir();
208 | if (!FileUtils.createOrExistsDir(fileDir)) {
209 | Logger.w(TAG, "文件夹创建失败:%s", fileDir);
210 | return null;
211 | }
212 | String fileName = String.format(Locale.getDefault(), "record_%s", FileUtils.getNowString(new SimpleDateFormat("yyyyMMdd_HH_mm_ss", Locale.SIMPLIFIED_CHINESE)));
213 | return String.format(Locale.getDefault(), "%s%s%s", fileDir, fileName, currentConfig.getFormat().getExtension());
214 | }
215 |
216 |
217 | }
218 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/recorder/listener/RecordDataListener.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.recorder.listener;
2 |
3 | /**
4 | * @author zhaolewei on 2018/7/11.
5 | */
6 | public interface RecordDataListener {
7 |
8 | /**
9 | * 当前的录音状态发生变化
10 | *
11 | * @param data 当前音频数据
12 | */
13 | void onData(byte[] data);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/recorder/listener/RecordFftDataListener.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.recorder.listener;
2 |
3 | /**
4 | * @author zhaolewei on 2019/3/11.
5 | */
6 | public interface RecordFftDataListener {
7 |
8 | /**
9 | * @param data 录音可视化数据,即傅里叶转换后的数据:fftData
10 | */
11 | void onFftData(byte[] data);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/recorder/listener/RecordResultListener.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.recorder.listener;
2 |
3 | import java.io.File;
4 |
5 | /**
6 | * 录音完成回调
7 | */
8 | public interface RecordResultListener {
9 |
10 | /**
11 | * 录音文件
12 | *
13 | * @param result 录音文件
14 | */
15 | void onResult(File result);
16 | }
17 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/recorder/listener/RecordSoundSizeListener.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.recorder.listener;
2 |
3 | /**
4 | * @author zhaolewei on 2018/7/11.
5 | */
6 | public interface RecordSoundSizeListener {
7 |
8 | /**
9 | * 实时返回音量大小
10 | *
11 | * @param soundSize 当前音量大小
12 | */
13 | void onSoundSize(int soundSize);
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/recorder/listener/RecordStateListener.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.recorder.listener;
2 |
3 | import com.zlw.main.recorderlib.recorder.RecordHelper;
4 |
5 | /**
6 | * @author zhaolewei on 2018/7/11.
7 | */
8 | public interface RecordStateListener {
9 |
10 | /**
11 | * 当前的录音状态发生变化
12 | *
13 | * @param state 当前状态
14 | */
15 | void onStateChange(RecordHelper.RecordState state);
16 |
17 | /**
18 | * 录音错误
19 | *
20 | * @param error 错误
21 | */
22 | void onError(String error);
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/recorder/mp3/Mp3EncodeThread.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.recorder.mp3;
2 |
3 | import com.zlw.main.recorderlib.recorder.RecordConfig;
4 | import com.zlw.main.recorderlib.recorder.RecordService;
5 | import com.zlw.main.recorderlib.utils.Logger;
6 |
7 | import java.io.File;
8 | import java.io.FileNotFoundException;
9 | import java.io.FileOutputStream;
10 | import java.io.IOException;
11 | import java.util.Collections;
12 | import java.util.LinkedList;
13 | import java.util.List;
14 |
15 | /**
16 | * @author zhaolewei on 2018/8/2.
17 | */
18 | public class Mp3EncodeThread extends Thread {
19 | private static final String TAG = Mp3EncodeThread.class.getSimpleName();
20 | private List cacheBufferList = Collections.synchronizedList(new LinkedList());
21 | private File file;
22 | private FileOutputStream os;
23 | private byte[] mp3Buffer;
24 | private EncordFinishListener encordFinishListener;
25 |
26 | /**
27 | * 是否已停止录音
28 | */
29 | private volatile boolean isOver = false;
30 |
31 | /**
32 | * 是否继续轮询数据队列
33 | */
34 | private volatile boolean start = true;
35 |
36 | public Mp3EncodeThread(File file, int bufferSize) {
37 | this.file = file;
38 | mp3Buffer = new byte[(int) (7200 + (bufferSize * 2 * 1.25))];
39 | RecordConfig currentConfig = RecordService.getCurrentConfig();
40 | int sampleRate = currentConfig.getSampleRate();
41 |
42 | Logger.w(TAG, "in_sampleRate:%s,getChannelCount:%s ,out_sampleRate:%s 位宽: %s,",
43 | sampleRate, currentConfig.getChannelCount(), sampleRate, currentConfig.getRealEncoding());
44 | Mp3Encoder.init(sampleRate, currentConfig.getChannelCount(), sampleRate, currentConfig.getRealEncoding());
45 | }
46 |
47 | @Override
48 | public void run() {
49 | try {
50 | this.os = new FileOutputStream(file);
51 | } catch (FileNotFoundException e) {
52 | Logger.e(e, TAG, e.getMessage());
53 | return;
54 | }
55 |
56 | while (start) {
57 | ChangeBuffer next = next();
58 | Logger.v(TAG, "处理数据:%s", next == null ? "null" : next.getReadSize());
59 | lameData(next);
60 | }
61 | }
62 |
63 | public void addChangeBuffer(ChangeBuffer changeBuffer) {
64 | if (changeBuffer != null) {
65 | cacheBufferList.add(changeBuffer);
66 | synchronized (this) {
67 | notify();
68 | }
69 | }
70 | }
71 |
72 | public void stopSafe(EncordFinishListener encordFinishListener) {
73 | this.encordFinishListener = encordFinishListener;
74 | isOver = true;
75 | synchronized (this) {
76 | notify();
77 | }
78 | }
79 |
80 | private ChangeBuffer next() {
81 | for (; ; ) {
82 | if (cacheBufferList == null || cacheBufferList.size() == 0) {
83 | try {
84 | if (isOver) {
85 | finish();
86 | }
87 | synchronized (this) {
88 | wait();
89 | }
90 | } catch (Exception e) {
91 | Logger.e(e, TAG, e.getMessage());
92 | }
93 | } else {
94 | return cacheBufferList.remove(0);
95 | }
96 | }
97 | }
98 |
99 | private void lameData(ChangeBuffer changeBuffer) {
100 | if (changeBuffer == null) {
101 | return;
102 | }
103 | short[] buffer = changeBuffer.getData();
104 | int readSize = changeBuffer.getReadSize();
105 | if (readSize > 0) {
106 | int encodedSize = Mp3Encoder.encode(buffer, buffer, readSize, mp3Buffer);
107 | if (encodedSize < 0) {
108 | Logger.e(TAG, "Lame encoded size: " + encodedSize);
109 | }
110 | try {
111 | os.write(mp3Buffer, 0, encodedSize);
112 | } catch (IOException e) {
113 | Logger.e(e, TAG, "Unable to write to file");
114 | }
115 | }
116 | }
117 |
118 | private void finish() {
119 | start = false;
120 | final int flushResult = Mp3Encoder.flush(mp3Buffer);
121 | if (flushResult > 0) {
122 | try {
123 | os.write(mp3Buffer, 0, flushResult);
124 | os.close();
125 | } catch (final IOException e) {
126 | Logger.e(TAG, e.getMessage());
127 | }
128 | }
129 | Logger.d(TAG, "转换结束 :%s", file.length());
130 | if (encordFinishListener != null) {
131 | encordFinishListener.onFinish();
132 | }
133 | }
134 |
135 | public static class ChangeBuffer {
136 | private short[] rawData;
137 | private int readSize;
138 |
139 | public ChangeBuffer(short[] rawData, int readSize) {
140 | this.rawData = rawData.clone();
141 | this.readSize = readSize;
142 | }
143 |
144 | short[] getData() {
145 | return rawData;
146 | }
147 |
148 | int getReadSize() {
149 | return readSize;
150 | }
151 | }
152 |
153 | public interface EncordFinishListener {
154 | /**
155 | * 格式转换完毕
156 | */
157 | void onFinish();
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/recorder/mp3/Mp3Encoder.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.recorder.mp3;
2 |
3 | /**
4 | * @author zhaolewei on 2018/8/2.
5 | */
6 | public class Mp3Encoder {
7 |
8 | static {
9 | System.loadLibrary("mp3lame");
10 | }
11 |
12 | public native static void close();
13 |
14 | public native static int encode(short[] buffer_l, short[] buffer_r, int samples, byte[] mp3buf);
15 |
16 | public native static int flush(byte[] mp3buf);
17 |
18 | public native static void init(int inSampleRate, int outChannel, int outSampleRate, int outBitrate, int quality);
19 |
20 | public static void init(int inSampleRate, int outChannel, int outSampleRate, int outBitrate) {
21 | init(inSampleRate, outChannel, outSampleRate, outBitrate, 7);
22 | }
23 | }
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/recorder/mp3/Mp3Utils.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.recorder.mp3;
2 |
3 | import android.media.MediaExtractor;
4 | import android.media.MediaFormat;
5 |
6 | import com.zlw.main.recorderlib.recorder.RecordConfig;
7 | import com.zlw.main.recorderlib.utils.FileUtils;
8 | import com.zlw.main.recorderlib.utils.Logger;
9 |
10 | import java.io.IOException;
11 |
12 | /**
13 | * @author zhaolewei on 2018/8/3.
14 | */
15 | public class Mp3Utils {
16 | private static final String TAG = Mp3Utils.class.getSimpleName();
17 |
18 | /**
19 | * 获取mp3音频的总时长 单位:ms
20 | *
21 | * @param mp3FilePath MP3文件路径
22 | * @return 时长
23 | */
24 | public static long getDuration(String mp3FilePath) {
25 | if (!FileUtils.isFileExists(mp3FilePath)) {
26 | return 0;
27 | }
28 | if (!mp3FilePath.endsWith(RecordConfig.RecordFormat.MP3.getExtension())) {
29 | return 0;
30 | }
31 | MediaExtractor mex = null;
32 | try {
33 | mex = new MediaExtractor();
34 | mex.setDataSource(mp3FilePath);
35 | MediaFormat mf = mex.getTrackFormat(0);
36 | long duration = mf.getLong(MediaFormat.KEY_DURATION) / 1000L;
37 | return duration;
38 | } catch (IOException e) {
39 | Logger.e(e, TAG, e.getMessage());
40 | } finally {
41 | if (mex != null) {
42 | mex.release();
43 | }
44 | }
45 | return 0;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/recorder/wav/WavUtils.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.recorder.wav;
2 |
3 | import com.zlw.main.recorderlib.recorder.RecordConfig;
4 | import com.zlw.main.recorderlib.utils.ByteUtils;
5 | import com.zlw.main.recorderlib.utils.FileUtils;
6 | import com.zlw.main.recorderlib.utils.Logger;
7 |
8 | import java.io.ByteArrayOutputStream;
9 | import java.io.File;
10 | import java.io.FileInputStream;
11 | import java.io.IOException;
12 | import java.io.RandomAccessFile;
13 |
14 | /**
15 | * @author zhaolewei on 2018/7/3.
16 | * pcm 转 wav 工具类
17 | * http://soundfile.sapp.org/doc/WaveFormat/
18 | */
19 | public class WavUtils {
20 | private static final String TAG = WavUtils.class.getSimpleName();
21 |
22 | /**
23 | * 生成wav格式的Header
24 | * wave是RIFF文件结构,每一部分为一个chunk,其中有RIFF WAVE chunk,
25 | * FMT Chunk,Fact chunk(可选),Data chunk
26 | *
27 | * @param totalAudioLen 不包括header的音频数据总长度
28 | * @param sampleRate 采样率,也就是录制时使用的频率
29 | * @param channels audioRecord的频道数量
30 | * @param sampleBits 位宽
31 | */
32 | public static byte[] generateWavFileHeader(int totalAudioLen, int sampleRate, int channels, int sampleBits) {
33 | WavHeader wavHeader = new WavHeader(totalAudioLen, sampleRate, (short) channels, (short) sampleBits);
34 | return wavHeader.getHeader();
35 | }
36 |
37 | /**
38 | * 将header写入到pcm文件中 不修改文件名
39 | *
40 | * @param file 写入的pcm文件
41 | * @param header wav头数据
42 | */
43 | public static void writeHeader(File file, byte[] header) {
44 | if (!FileUtils.isFile(file)) {
45 | return;
46 | }
47 |
48 | RandomAccessFile wavRaf = null;
49 | try {
50 | wavRaf = new RandomAccessFile(file, "rw");
51 | wavRaf.seek(0);
52 | wavRaf.write(header);
53 | wavRaf.close();
54 | } catch (Exception e) {
55 | Logger.e(e, TAG, e.getMessage());
56 | } finally {
57 | try {
58 | if (wavRaf != null) {
59 | wavRaf.close();
60 | }
61 | } catch (IOException e) {
62 | Logger.e(e, TAG, e.getMessage());
63 |
64 | }
65 | }
66 | }
67 |
68 |
69 | /**
70 | * Pcm 转 WAV 文件
71 | *
72 | * @param pcmFile File
73 | * @param header wavHeader
74 | * @throws IOException Exception
75 | */
76 | public static void pcmToWav(File pcmFile, byte[] header) throws IOException {
77 | if (!FileUtils.isFile(pcmFile)) {
78 | return;
79 | }
80 | String pcmPath = pcmFile.getAbsolutePath();
81 | String wavPath = pcmPath.substring(0, pcmPath.length() - 4) + ".wav";
82 | writeHeader(new File(wavPath), header);
83 | }
84 |
85 | /**
86 | * 获取WAV文件的头信息
87 | *
88 | * @param wavFilePath 文件地址
89 | * @return header
90 | */
91 | private static byte[] getHeader(String wavFilePath) {
92 | if (!new File(wavFilePath).isFile()) {
93 | return null;
94 | }
95 | byte[] buffer = null;
96 | File file = new File(wavFilePath);
97 | final int size = 44;
98 | FileInputStream fis = null;
99 | ByteArrayOutputStream bos = null;
100 | try {
101 | fis = new FileInputStream(file);
102 | bos = new ByteArrayOutputStream(size);
103 | byte[] b = new byte[size];
104 | int len;
105 | if ((len = fis.read(b)) != size) {
106 | Logger.e(TAG, "读取失败 len: %s", len);
107 | return null;
108 | }
109 | bos.write(b, 0, len);
110 | buffer = bos.toByteArray();
111 | } catch (Exception e) {
112 | Logger.e(e, TAG, e.getMessage());
113 | } finally {
114 | try {
115 | if (fis != null) {
116 | fis.close();
117 | fis = null;
118 | }
119 | if (bos != null) {
120 | bos.close();
121 | bos = null;
122 | }
123 | } catch (IOException e) {
124 | Logger.e(e, TAG, e.getMessage());
125 | }
126 | }
127 | return buffer;
128 | }
129 |
130 | /**
131 | * 获取wav音频时长 ms
132 | *
133 | * @param filePath wav文件路径
134 | * @return 时长 -1: 获取失败
135 | */
136 | public static long getWavDuration(String filePath) {
137 | if (!filePath.endsWith(RecordConfig.RecordFormat.WAV.getExtension())) {
138 | return -1;
139 | }
140 | byte[] header = getHeader(filePath);
141 | return getWavDuration(header);
142 | }
143 |
144 | /**
145 | * 获取wav音频时长 ms
146 | *
147 | * @param header wav音频文件字节数组
148 | * @return 时长 -1: 获取失败
149 | */
150 | public static long getWavDuration(byte[] header) {
151 | if (header == null || header.length < 44) {
152 | Logger.e(TAG, "header size有误");
153 | return -1;
154 | }
155 | int byteRate = ByteUtils.toInt(header, 28);//28-31
156 | int waveSize = ByteUtils.toInt(header, 40);//40-43
157 | return waveSize * 1000L / byteRate;
158 | }
159 |
160 | public static String headerToString(byte[] header) {
161 | if (header == null || header.length < 44) {
162 | return null;
163 | }
164 | StringBuilder stringBuilder = new StringBuilder();
165 |
166 | for (int i = 0; i < 4; i++) {
167 | stringBuilder.append((char) header[i]);
168 | }
169 | stringBuilder.append(",");
170 |
171 | stringBuilder.append(ByteUtils.toInt(header, 4));
172 | stringBuilder.append(",");
173 |
174 | for (int i = 8; i < 16; i++) {
175 | stringBuilder.append((char) header[i]);
176 | }
177 | stringBuilder.append(",");
178 |
179 | for (int i = 16; i < 24; i++) {
180 | stringBuilder.append(header[i]);
181 | }
182 | stringBuilder.append(",");
183 |
184 | stringBuilder.append(ByteUtils.toInt(header, 24));
185 | stringBuilder.append(",");
186 |
187 | stringBuilder.append(ByteUtils.toInt(header, 28));
188 | stringBuilder.append(",");
189 |
190 | for (int i = 32; i < 36; i++) {
191 | stringBuilder.append(header[i]);
192 | }
193 | stringBuilder.append(",");
194 |
195 | for (int i = 36; i < 40; i++) {
196 | stringBuilder.append((char) header[i]);
197 | }
198 | stringBuilder.append(",");
199 |
200 | stringBuilder.append(ByteUtils.toInt(header, 40));
201 |
202 | return stringBuilder.toString();
203 | }
204 |
205 | public static class WavHeader {
206 | /**
207 | * RIFF数据块
208 | */
209 | final String riffChunkId = "RIFF";
210 | int riffChunkSize;
211 | final String riffType = "WAVE";
212 |
213 | /**
214 | * FORMAT 数据块
215 | */
216 | final String formatChunkId = "fmt ";
217 | final int formatChunkSize = 16;
218 | final short audioFormat = 1;
219 | short channels;
220 | int sampleRate;
221 | int byteRate;
222 | short blockAlign;
223 | short sampleBits;
224 |
225 | /**
226 | * FORMAT 数据块
227 | */
228 | final String dataChunkId = "data";
229 | int dataChunkSize;
230 |
231 | WavHeader(int totalAudioLen, int sampleRate, short channels, short sampleBits) {
232 | this.riffChunkSize = totalAudioLen;
233 | this.channels = channels;
234 | this.sampleRate = sampleRate;
235 | this.byteRate = sampleRate * sampleBits / 8 * channels;
236 | this.blockAlign = (short) (channels * sampleBits / 8);
237 | this.sampleBits = sampleBits;
238 | this.dataChunkSize = totalAudioLen - 44;
239 | }
240 |
241 | public byte[] getHeader() {
242 | byte[] result;
243 | result = ByteUtils.merger(ByteUtils.toBytes(riffChunkId), ByteUtils.toBytes(riffChunkSize));
244 | result = ByteUtils.merger(result, ByteUtils.toBytes(riffType));
245 | result = ByteUtils.merger(result, ByteUtils.toBytes(formatChunkId));
246 | result = ByteUtils.merger(result, ByteUtils.toBytes(formatChunkSize));
247 | result = ByteUtils.merger(result, ByteUtils.toBytes(audioFormat));
248 | result = ByteUtils.merger(result, ByteUtils.toBytes(channels));
249 | result = ByteUtils.merger(result, ByteUtils.toBytes(sampleRate));
250 | result = ByteUtils.merger(result, ByteUtils.toBytes(byteRate));
251 | result = ByteUtils.merger(result, ByteUtils.toBytes(blockAlign));
252 | result = ByteUtils.merger(result, ByteUtils.toBytes(sampleBits));
253 | result = ByteUtils.merger(result, ByteUtils.toBytes(dataChunkId));
254 | result = ByteUtils.merger(result, ByteUtils.toBytes(dataChunkSize));
255 | return result;
256 | }
257 | }
258 |
259 | }
260 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/utils/ByteUtils.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.utils;
2 |
3 | import java.nio.ByteBuffer;
4 | import java.util.Arrays;
5 |
6 | /**
7 | * @author zhaoleweion 2018/8/3.
8 | */
9 | public class ByteUtils {
10 |
11 |
12 | /**
13 | * short[] 转 byte[]
14 | */
15 | public static byte[] toBytes(short[] src) {
16 | int count = src.length;
17 | byte[] dest = new byte[count << 1];
18 | for (int i = 0; i < count; i++) {
19 | dest[i * 2] = (byte) (src[i]);
20 | dest[i * 2 + 1] = (byte) (src[i] >> 8);
21 | }
22 |
23 | return dest;
24 | }
25 |
26 |
27 | /**
28 | * short[] 转 byte[]
29 | */
30 | public static byte[] toBytes(short src) {
31 | byte[] dest = new byte[2];
32 | dest[0] = (byte) (src);
33 | dest[1] = (byte) (src >> 8);
34 |
35 | return dest;
36 | }
37 |
38 | /**
39 | * int 转 byte[]
40 | */
41 | public static byte[] toBytes(int i) {
42 | byte[] b = new byte[4];
43 | b[0] = (byte) (i & 0xff);
44 | b[1] = (byte) ((i >> 8) & 0xff);
45 | b[2] = (byte) ((i >> 16) & 0xff);
46 | b[3] = (byte) ((i >> 24) & 0xff);
47 | return b;
48 | }
49 |
50 |
51 | /**
52 | * String 转 byte[]
53 | */
54 | public static byte[] toBytes(String str) {
55 | return str.getBytes();
56 | }
57 |
58 | /**
59 | * long类型转成byte数组
60 | */
61 | public static byte[] toBytes(long number) {
62 | ByteBuffer buffer = ByteBuffer.allocate(8);
63 | buffer.putLong(0, number);
64 | return buffer.array();
65 | }
66 |
67 | public static int toInt(byte[] src, int offset) {
68 | return ((src[offset] & 0xFF)
69 | | ((src[offset + 1] & 0xFF) << 8)
70 | | ((src[offset + 2] & 0xFF) << 16)
71 | | ((src[offset + 3] & 0xFF) << 24));
72 | }
73 |
74 | public static int toInt(byte[] src) {
75 | return toInt(src, 0);
76 | }
77 |
78 | /**
79 | * 字节数组到long的转换.
80 | */
81 | public static long toLong(byte[] b) {
82 | ByteBuffer buffer = ByteBuffer.allocate(8);
83 | buffer.put(b, 0, b.length);
84 | return buffer.getLong();
85 | }
86 |
87 | /**
88 | * byte[] 转 short[]
89 | * short: 2字节
90 | */
91 | public static short[] toShorts(byte[] src) {
92 | int count = src.length >> 1;
93 | short[] dest = new short[count];
94 | for (int i = 0; i < count; i++) {
95 | dest[i] = (short) ((src[i * 2] & 0xff) | ((src[2 * i + 1] & 0xff) << 8));
96 | }
97 | return dest;
98 | }
99 |
100 | public static byte[] merger(byte[] bt1, byte[] bt2) {
101 | byte[] bt3 = new byte[bt1.length + bt2.length];
102 | System.arraycopy(bt1, 0, bt3, 0, bt1.length);
103 | System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
104 | return bt3;
105 | }
106 |
107 | public static String toString(byte[] b) {
108 | return Arrays.toString(b);
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/utils/FileUtils.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.utils;
2 |
3 |
4 | import java.io.File;
5 | import java.util.Date;
6 |
7 | /**
8 | * @author zhaolewei on 2018/7/10.
9 | */
10 | public class FileUtils {
11 |
12 | public static boolean isFile(final File file) {
13 | return file != null && file.exists() && file.isFile();
14 | }
15 |
16 | /**
17 | * Create a directory if it doesn't exist, otherwise do nothing.
18 | *
19 | * @param dirPath The path of directory.
20 | * @return {@code true}: exists or creates successfully
{@code false}: otherwise
21 | */
22 | public static boolean createOrExistsDir(final String dirPath) {
23 | return createOrExistsDir(getFileByPath(dirPath));
24 | }
25 |
26 | public static boolean createOrExistsDir(final File file) {
27 | return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
28 | }
29 |
30 | public static File getFileByPath(final String filePath) {
31 | return isSpace(filePath) ? null : new File(filePath);
32 | }
33 |
34 | private static boolean isSpace(final String s) {
35 | if (s == null) {
36 | return true;
37 | }
38 | for (int i = 0, len = s.length(); i < len; ++i) {
39 | if (!Character.isWhitespace(s.charAt(i))) {
40 | return false;
41 | }
42 | }
43 | return true;
44 | }
45 |
46 | public static String getNowString(final java.text.DateFormat format) {
47 | return millis2String(System.currentTimeMillis(), format);
48 | }
49 |
50 | /**
51 | * Milliseconds to the formatted time string.
52 | *
53 | * @param millis The milliseconds.
54 | * @param format The format.
55 | * @return the formatted time string
56 | */
57 | public static String millis2String(final long millis, final java.text.DateFormat format) {
58 | return format.format(new Date(millis));
59 | }
60 |
61 | /**
62 | * Return whether the file exists.
63 | *
64 | * @param filePath The path of file.
65 | * @return {@code true}: yes
{@code false}: no
66 | */
67 | public static boolean isFileExists(final String filePath) {
68 | return isFileExists(getFileByPath(filePath));
69 | }
70 |
71 | /**
72 | * Return whether the file exists.
73 | *
74 | * @param file The file.
75 | * @return {@code true}: yes
{@code false}: no
76 | */
77 | public static boolean isFileExists(final File file) {
78 | return file != null && file.exists();
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/utils/Logger.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.utils;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.os.Build;
6 | import android.os.Environment;
7 | import android.os.SystemClock;
8 | import android.util.Log;
9 |
10 | import java.io.File;
11 | import java.util.Locale;
12 |
13 | public class Logger {
14 | private static final String PRE = "^_^";
15 | private static final String TAG = Logger.class.getSimpleName();
16 | private static final int LOG_LENGTH_LIMITATION = 4000;
17 |
18 | public static boolean IsDebug = true;
19 |
20 | private static final String space = "====================================================================================================";
21 | private static boolean LOGV = true;
22 | private static boolean LOGD = true;
23 | private static boolean LOGI = true;
24 | private static boolean LOGW = true;
25 | private static boolean LOGE = true;
26 |
27 | public enum LogLevel {
28 | V, D, I, W, E
29 | }
30 |
31 | // private static boolean LOGV = false;
32 | // private static boolean LOGD = false;
33 | // private static boolean LOGI = false;
34 | // private static boolean LOGW = false;
35 | // private static boolean LOGE = false;
36 |
37 | public static void v(String tag, String format, Object... args) {
38 | if (LOGV) {
39 | String message = buildMessage(format, args);
40 | tag = formatLength(PRE + tag, 28);
41 |
42 | Log.v(tag, message);
43 | cacheLongLog(tag, message);
44 | }
45 | }
46 |
47 | public static void v(Throwable throwable, String tag, String format, Object... args) {
48 | if (LOGV) {
49 | String message = buildMessage(format, args);
50 | tag = formatLength(PRE + tag, 28);
51 |
52 | Log.v(tag, message, throwable);
53 | cacheLongLog(tag, message, throwable);
54 | }
55 | }
56 |
57 | public static void d(String tag, String format, Object... args) {
58 | if (LOGD) {
59 | String message = buildMessage(format, args);
60 | tag = formatLength(PRE + tag, 28);
61 |
62 | Log.d(tag, message);
63 | cacheLongLog(tag, message);
64 | }
65 | }
66 |
67 | public static void d(Throwable throwable, String tag, String format, Object... args) {
68 | if (LOGD) {
69 | String message = buildMessage(format, args);
70 | tag = formatLength(PRE + tag, 28);
71 |
72 | Log.d(tag, message, throwable);
73 | cacheLongLog(tag, message, throwable);
74 | }
75 | }
76 |
77 | public static void i(String tag, String format, Object... args) {
78 | if (LOGI) {
79 | String message = buildMessage(format, args);
80 | tag = formatLength(PRE + tag, 28);
81 |
82 | Log.i(tag, message);
83 | cacheLongLog(tag, message);
84 | }
85 | }
86 |
87 | public static void i(Throwable throwable, String tag, String format, Object... args) {
88 | if (LOGI) {
89 | String message = buildMessage(format, args);
90 | tag = formatLength(PRE + tag, 28);
91 |
92 | Log.i(tag, message, throwable);
93 | cacheLongLog(tag, message, throwable);
94 | }
95 | }
96 |
97 | public static void w(String tag, String format, Object... args) {
98 | if (LOGW) {
99 | String message = buildMessage(format, args);
100 | tag = formatLength(PRE + tag, 28);
101 |
102 | Log.w(tag, message);
103 | cacheLongLog(tag, message);
104 | }
105 | }
106 |
107 | public static void w(Throwable throwable, String tag, String format, Object... args) {
108 | if (LOGW) {
109 | String message = buildMessage(format, args);
110 | tag = formatLength(PRE + tag, 28);
111 |
112 | Log.w(tag, message, throwable);
113 | cacheLongLog(tag, message, throwable);
114 | }
115 | }
116 |
117 | public static void e(String tag, String format, Object... args) {
118 | if (LOGE) {
119 | String message = buildMessage(format, args);
120 | tag = formatLength(PRE + tag, 28);
121 |
122 | Log.e(tag, message);
123 | cacheLongLog(tag, message);
124 | }
125 | }
126 |
127 | public static void e(Throwable throwable, String tag, String format, Object... args) {
128 | if (LOGE) {
129 | String message = buildMessage(format, args);
130 | tag = formatLength(PRE + tag, 28);
131 |
132 | Log.e(tag, message, throwable);
133 | cacheLongLog(tag, message, throwable);
134 | }
135 | }
136 |
137 | /**
138 | * Please refer to comment of {@link #cacheLongLog(String, String, Throwable)}
139 | *
140 | * @param tag TAG name.
141 | * @param logContent Log content.
142 | */
143 | private static void cacheLongLog(String tag, String logContent) {
144 | cacheLongLog(tag, logContent, null);
145 | }
146 |
147 | /**
148 | * Due to length limitation of Logcat, over long log content won't be shown completely in log window,
149 | * so cache it to local file at particular path for convenient checking.
150 | *
151 | * @param tag TAG name.
152 | * @param logContent Log content.
153 | * @param throwable Throwable instance, for printing stack trace.
154 | */
155 | @TargetApi(Build.VERSION_CODES.KITKAT)
156 | private static void cacheLongLog(String tag, String logContent, Throwable throwable) {
157 |
158 | }
159 |
160 | /**
161 | * 打印调用者栈信息
162 | * 本方法使用System.out输出, 对log进行过滤时请注意
163 | */
164 | public static void printCaller() {
165 | if (!IsDebug) {
166 | return;
167 | }
168 |
169 | try {
170 | String caller, callingClass, callFile;
171 | int lineNumber;
172 | StackTraceElement[] trace = new Throwable().fillInStackTrace().getStackTrace();
173 | StringBuilder infoBuffer = new StringBuilder();
174 | infoBuffer.append("print caller info\n==========BEGIN OF CALLER INFO============\n");
175 | for (int i = 2; i < trace.length; i++) {
176 | callingClass = trace[i].getClassName();
177 | callingClass = callingClass.substring(callingClass.lastIndexOf('.') + 1);
178 | caller = trace[i].getMethodName();
179 | callFile = trace[i].getFileName();
180 | lineNumber = trace[i].getLineNumber();
181 | String method = String.format(Locale.US, "[%03d] %s.%s(%s:%d)"
182 | , Thread.currentThread().getId(), callingClass, caller, callFile, lineNumber);
183 | infoBuffer.append(method);
184 | infoBuffer.append("\n");
185 | }
186 | infoBuffer.append("==========END OF CALLER INFO============");
187 | Logger.i(TAG, infoBuffer.toString());
188 | } catch (Exception e) {
189 | Logger.e(e, TAG, e.getMessage());
190 | }
191 | }
192 |
193 | private static String buildMessage(String format, Object[] args) {
194 | try {
195 | String msg = (args == null || args.length == 0) ? format : String.format(Locale.US, format, args);
196 | if (!IsDebug) {
197 | return msg;
198 | }
199 | StackTraceElement[] trace = new Throwable().fillInStackTrace().getStackTrace();
200 | String caller = "";
201 | String callingClass = "";
202 | String callFile = "";
203 | int lineNumber = 0;
204 | for (int i = 2; i < trace.length; i++) {
205 | Class> clazz = trace[i].getClass();
206 | if (!clazz.equals(Logger.class)) {
207 | callingClass = trace[i].getClassName();
208 | callingClass = callingClass.substring(callingClass
209 | .lastIndexOf('.') + 1);
210 | caller = trace[i].getMethodName();
211 | callFile = trace[i].getFileName();
212 | lineNumber = trace[i].getLineNumber();
213 | break;
214 | }
215 | }
216 |
217 | String method = String.format(Locale.US, "[%03d] %s.%s(%s:%d)"
218 | , Thread.currentThread().getId(), callingClass, caller, callFile, lineNumber);
219 |
220 | return String.format(Locale.US, "%s> %s", formatLength(method, 93), msg);
221 | } catch (Exception e) {
222 | Logger.e(e, TAG, e.getMessage());
223 | }
224 | return "----->ERROR LOG STRING<------";
225 | }
226 |
227 | private static String formatLength(String src, int len) {
228 | StringBuilder sb = new StringBuilder();
229 | if (src.length() >= len) {
230 | sb.append(src);
231 | } else {
232 | sb.append(src);
233 | sb.append(space.substring(0, len - src.length()));
234 | }
235 | return sb.toString();
236 | }
237 |
238 | @TargetApi(Build.VERSION_CODES.KITKAT)
239 | public static File getAvailableExternalCacheDir(Context ctx) {
240 | File[] cacheDirectories = ctx.getExternalCacheDirs();
241 | for (int index = cacheDirectories.length - 1; index >= 0; index--) {
242 | File file = cacheDirectories[index];
243 | if (null != file && Environment.MEDIA_MOUNTED.equals(Environment.getStorageState(file))) {
244 | return file;
245 | }
246 | }
247 | return null;
248 | }
249 |
250 | /**
251 | * 判断文件是否存在
252 | *
253 | * @param filePath 文件路径
254 | * @return {@code true}: 存在
{@code false}: 不存在
255 | */
256 | public static boolean isFileExists(String filePath) {
257 | return isFileExists(new File(filePath));
258 | }
259 |
260 |
261 | /**
262 | * 判断文件是否存在
263 | *
264 | * @param file 文件
265 | * @return {@code true}: 存在
{@code false}: 不存在
266 | */
267 | public static boolean isFileExists(File file) {
268 | return file != null && file.exists();
269 | }
270 |
271 | public static class TimeCalculator {
272 | long start;
273 |
274 | public TimeCalculator() {
275 | start = SystemClock.elapsedRealtime();
276 | }
277 |
278 | public long end() {
279 | return SystemClock.elapsedRealtime() - start;
280 | }
281 | }
282 | }
283 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/com/zlw/main/recorderlib/utils/RecordUtils.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib.utils;
2 |
3 | import java.nio.ByteBuffer;
4 | import java.nio.ByteOrder;
5 | import java.nio.FloatBuffer;
6 |
7 | /**
8 | * @author zhaolewei on 2018/7/31.
9 | */
10 | public class RecordUtils {
11 | /**
12 | * 获取录音的声音分贝值
13 | * 计算公式:dB = 20 * log(a / a0);
14 | * @return 声音分贝值
15 | */
16 | public static long getMaxDecibels(byte[] input) {
17 | short[] amplitudes = ByteUtils.toShorts(input);
18 | if (amplitudes == null) {
19 | return 0;
20 | }
21 | float maxAmplitude = 2;
22 | for (float amplitude : amplitudes) {
23 | if (Math.abs(maxAmplitude) < Math.abs(amplitude)) {
24 | maxAmplitude = amplitude;
25 | }
26 | }
27 | return Math.round(20 * Math.log10(maxAmplitude));
28 | }
29 |
30 |
31 | public static float[] byteToFloat(byte[] input) {
32 | if (input == null) {
33 | return null;
34 | }
35 | int bytesPerSample = 2;
36 | ByteBuffer buffer = ByteBuffer.wrap(input);
37 | buffer.order(ByteOrder.LITTLE_ENDIAN);
38 | FloatBuffer floatBuffer = FloatBuffer.allocate(input.length / bytesPerSample);
39 | for (int i = 0; i < floatBuffer.capacity(); i++) {
40 | floatBuffer.put(buffer.getShort(i * bytesPerSample));
41 | }
42 | return floatBuffer.array();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/fftlib/ByteUtils.java:
--------------------------------------------------------------------------------
1 | package fftlib;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.File;
5 | import java.io.FileInputStream;
6 | import java.io.RandomAccessFile;
7 | import java.nio.ByteBuffer;
8 | import java.util.Arrays;
9 |
10 | /**
11 | * @author zhaoleweion 2018/8/3.
12 | */
13 | public class ByteUtils {
14 | private static final String TAG = ByteUtils.class.getSimpleName();
15 |
16 | /**
17 | * short[] 转 byte[]
18 | */
19 | public static byte[] toBytes(short[] src) {
20 | int count = src.length;
21 | byte[] dest = new byte[count << 1];
22 | for (int i = 0; i < count; i++) {
23 | dest[i * 2] = (byte) (src[i]);
24 | dest[i * 2 + 1] = (byte) (src[i] >> 8);
25 | }
26 |
27 | return dest;
28 | }
29 |
30 | /**
31 | * 浮点转换为字节
32 | */
33 | public static byte[] toBytes(float f) {
34 | // 把float转换为byte[]
35 | int fbit = Float.floatToIntBits(f);
36 |
37 | byte[] b = new byte[4];
38 | for (int i = 0; i < 4; i++) {
39 | b[i] = (byte) (fbit >> (24 - i * 8));
40 | }
41 |
42 | int len = b.length;
43 | byte[] dest = new byte[len];
44 | System.arraycopy(b, 0, dest, 0, len);
45 | byte temp;
46 | for (int i = 0; i < len / 2; ++i) {
47 | temp = dest[i];
48 | dest[i] = dest[len - i - 1];
49 | dest[len - i - 1] = temp;
50 | }
51 | return dest;
52 |
53 | }
54 |
55 | public static byte[] byteMerger(byte[] bt1, byte[] bt2) {
56 | byte[] bt3 = new byte[bt1.length + bt2.length];
57 | System.arraycopy(bt1, 0, bt3, 0, bt1.length);
58 | System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
59 | return bt3;
60 | }
61 |
62 | /**
63 | * short[] 转 byte[]
64 | */
65 | public static byte[] toBytes(short src) {
66 | byte[] dest = new byte[2];
67 | dest[0] = (byte) (src);
68 | dest[1] = (byte) (src >> 8);
69 |
70 | return dest;
71 | }
72 |
73 | /**
74 | * int 转 byte[]
75 | */
76 | public static byte[] toBytes(int i) {
77 | byte[] b = new byte[4];
78 | b[0] = (byte) (i & 0xff);
79 | b[1] = (byte) ((i >> 8) & 0xff);
80 | b[2] = (byte) ((i >> 16) & 0xff);
81 | b[3] = (byte) ((i >> 24) & 0xff);
82 | return b;
83 | }
84 |
85 |
86 | /**
87 | * String 转 byte[]
88 | */
89 | public static byte[] toBytes(String str) {
90 | return str.getBytes();
91 | }
92 |
93 | /**
94 | * long类型转成byte数组
95 | */
96 | public static byte[] toBytes(long number) {
97 | ByteBuffer buffer = ByteBuffer.allocate(8);
98 | buffer.putLong(0, number);
99 | return buffer.array();
100 | }
101 |
102 | public static int toInt(byte[] src, int offset) {
103 | return ((src[offset] & 0xFF)
104 | | ((src[offset + 1] & 0xFF) << 8)
105 | | ((src[offset + 2] & 0xFF) << 16)
106 | | ((src[offset + 3] & 0xFF) << 24));
107 | }
108 |
109 | public static int toInt(byte[] src) {
110 | return toInt(src, 0);
111 | }
112 |
113 | /**
114 | * 字节数组到long的转换.
115 | */
116 | public static long toLong(byte[] b) {
117 | ByteBuffer buffer = ByteBuffer.allocate(8);
118 | buffer.put(b, 0, b.length);
119 | return buffer.getLong();
120 | }
121 |
122 | /**
123 | * byte[] 转 short[]
124 | * short: 2字节
125 | */
126 | public static short[] toShorts(byte[] src) {
127 | int count = src.length >> 1;
128 | short[] dest = new short[count];
129 | for (int i = 0; i < count; i++) {
130 | dest[i] = (short) ((src[i * 2] & 0xff) | ((src[2 * i + 1] & 0xff) << 8));
131 | }
132 | return dest;
133 | }
134 |
135 | public static byte[] merger(byte[] bt1, byte[] bt2) {
136 | byte[] bt3 = new byte[bt1.length + bt2.length];
137 | System.arraycopy(bt1, 0, bt3, 0, bt1.length);
138 | System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
139 | return bt3;
140 | }
141 |
142 | public static String toString(byte[] b) {
143 | return Arrays.toString(b);
144 | }
145 |
146 | /**
147 | * 将byte[] 追加到文件末尾
148 | */
149 | public static void byte2File(byte[] buf, File file) {
150 | try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw")) {
151 | long fileLength = file.length();
152 | randomAccessFile.seek(fileLength);
153 | randomAccessFile.write(buf);
154 | } catch (Exception e) {
155 | }
156 | }
157 |
158 | /**
159 | * 将byte[] 追加到文件末尾
160 | */
161 | public static byte[] byte2FileForResult(byte[] buf, File file) {
162 | try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw")) {
163 | long fileLength = file.length();
164 | randomAccessFile.seek(fileLength);
165 | randomAccessFile.write(buf);
166 | } catch (Exception e) {
167 | }
168 | return file2Bytes(file);
169 |
170 | }
171 |
172 |
173 | public static byte[] file2Bytes(File file) {
174 |
175 | byte[] buffer = null;
176 | try (FileInputStream fis = new FileInputStream(file);
177 | ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
178 |
179 | byte[] b = new byte[1024];
180 | int n;
181 | while ((n = fis.read(b)) != -1) {
182 | bos.write(b, 0, n);
183 | }
184 | buffer = bos.toByteArray();
185 | } catch (Exception e) {
186 | }
187 | return buffer;
188 | }
189 |
190 | public static double[] toHardDouble(short[] shorts) {
191 | int length = 512;
192 | double[] ds = new double[length];
193 | for (int i = 0; i < length; i++) {
194 | ds[i] = shorts[i];
195 | }
196 | return ds;
197 | }
198 |
199 | public static byte[] toHardBytes(double[] doubles) {
200 | byte[] bytes = new byte[doubles.length];
201 | for (int i = 0; i < doubles.length; i++) {
202 | double item = doubles[i];
203 | bytes[i] = (byte) (item > 127 ? 127 : item);
204 | }
205 | return bytes;
206 | }
207 |
208 | public static short[] toHardShort(double[] doubles) {
209 | short[] bytes = new short[doubles.length];
210 | for (int i = 0; i < doubles.length; i++) {
211 | double item = doubles[i];
212 | bytes[i] = (short) (item > 32767 ? 32767 : item);
213 | }
214 | return bytes;
215 | }
216 |
217 | public static byte[] toSoftBytes(double[] doubles) {
218 | double max = getMax(doubles);
219 |
220 | double sc = 1f;
221 | if (max > 127) {
222 | sc = (max / 128f);
223 | }
224 |
225 | byte[] bytes = new byte[doubles.length];
226 | for (int i = 0; i < doubles.length; i++) {
227 | double item = doubles[i] / sc;
228 | bytes[i] = (byte) (item > 127 ? 127 : item);
229 | }
230 | return bytes;
231 | }
232 |
233 | public static short[] toSoftShorts(double[] doubles) {
234 | double max = getMax(doubles);
235 |
236 | double sc = 1f;
237 | if (max > 127) {
238 | sc = (max / 128f);
239 | }
240 |
241 | short[] bytes = new short[doubles.length];
242 | for (int i = 0; i < doubles.length; i++) {
243 | double item = doubles[i] / sc;
244 | bytes[i] = (short) (item > 32767 ? 32767 : item);
245 | }
246 | return bytes;
247 | }
248 |
249 | public static double getMax(double[] data) {
250 | double max = 0;
251 | for (int i = 0; i < data.length; i++) {
252 | if (data[i] > max) {
253 | max = data[i];
254 | }
255 | }
256 | return max;
257 | }
258 | }
259 |
--------------------------------------------------------------------------------
/recorderlib/src/main/java/fftlib/Complex.java:
--------------------------------------------------------------------------------
1 | package fftlib;
2 |
3 | import java.util.Objects;
4 |
5 | /**
6 | * 复数
7 | *
8 | * @author test
9 | */
10 | public class Complex {
11 |
12 | /**
13 | * 实数部分
14 | */
15 | private final double real;
16 |
17 | /**
18 | * 虚数部分 imaginary
19 | */
20 | private final double im;
21 |
22 | public Complex(double real, double imag) {
23 | this.real = real;
24 | im = imag;
25 | }
26 |
27 | @Override
28 | public String toString() {
29 | return String.format("hypot: %s, complex: %s+%si", hypot(), real, im);
30 | }
31 |
32 | public double hypot() {
33 | return Math.hypot(real, im);
34 | }
35 |
36 | public double phase() {
37 | return Math.atan2(im, real);
38 | }
39 |
40 | /**
41 | * 复数求和
42 | */
43 | public Complex plus(Complex b) {
44 | double real = this.real + b.real;
45 | double imag = this.im + b.im;
46 | return new Complex(real, imag);
47 | }
48 |
49 | // return a new Complex object whose value is (this - b)
50 | public Complex minus(Complex b) {
51 | double real = this.real - b.real;
52 | double imag = this.im - b.im;
53 | return new Complex(real, imag);
54 | }
55 |
56 | // return a new Complex object whose value is (this * b)
57 | public Complex times(Complex b) {
58 | Complex a = this;
59 | double real = a.real * b.real - a.im * b.im;
60 | double imag = a.real * b.im + a.im * b.real;
61 | return new Complex(real, imag);
62 | }
63 |
64 | // return a new object whose value is (this * alpha)
65 | public Complex scale(double alpha) {
66 | return new Complex(alpha * real, alpha * im);
67 | }
68 |
69 | // return a new Complex object whose value is the conjugate of this
70 | public Complex conjugate() {
71 | return new Complex(real, -im);
72 | }
73 |
74 | // return a new Complex object whose value is the reciprocal of this
75 | public Complex reciprocal() {
76 | double scale = real * real + im * im;
77 | return new Complex(real / scale, -im / scale);
78 | }
79 |
80 | // return the real or imaginary part
81 | public double re() {
82 | return real;
83 | }
84 |
85 | public double im() {
86 | return im;
87 | }
88 |
89 | // return a / b
90 | public Complex divides(Complex b) {
91 | Complex a = this;
92 | return a.times(b.reciprocal());
93 | }
94 |
95 | // return a new Complex object whose value is the complex exponential of this
96 | public Complex exp() {
97 | return new Complex(Math.exp(real) * Math.cos(im), Math.exp(real) * Math.sin(im));
98 | }
99 |
100 | // return a new Complex object whose value is the complex sine of this
101 | public Complex sin() {
102 | return new Complex(Math.sin(real) * Math.cosh(im), Math.cos(real) * Math.sinh(im));
103 | }
104 |
105 | // return a new Complex object whose value is the complex cosine of this
106 | public Complex cos() {
107 | return new Complex(Math.cos(real) * Math.cosh(im), -Math.sin(real) * Math.sinh(im));
108 | }
109 |
110 | // return a new Complex object whose value is the complex tangent of this
111 | public Complex tan() {
112 | return sin().divides(cos());
113 | }
114 |
115 |
116 | // a static version of plus
117 | public static Complex plus(Complex a, Complex b) {
118 | double real = a.real + b.real;
119 | double imag = a.im + b.im;
120 | Complex sum = new Complex(real, imag);
121 | return sum;
122 | }
123 |
124 | // See Section 3.3.
125 | @Override
126 | public boolean equals(Object x) {
127 | if (x == null) return false;
128 | if (this.getClass() != x.getClass()) return false;
129 | Complex that = (Complex) x;
130 | return (this.real == that.real) && (this.im == that.im);
131 | }
132 |
133 | // See Section 3.3.
134 | @Override
135 | public int hashCode() {
136 | return Objects.hash(real, im);
137 | }
138 |
139 | }
--------------------------------------------------------------------------------
/recorderlib/src/main/java/fftlib/FFT.java:
--------------------------------------------------------------------------------
1 | package fftlib;
2 |
3 |
4 | public class FFT {
5 |
6 | // compute the FFT of x[], assuming its length is a power of 2
7 | public static Complex[] fft(Complex[] x) {
8 | int n = x.length;
9 |
10 | // base case
11 | if (n == 1) return new Complex[]{x[0]};
12 |
13 | // radix 2 Cooley-Tukey FFT
14 | if (n % 2 != 0) {
15 | throw new IllegalArgumentException("n is not a power of 2");
16 | }
17 |
18 | // fft of even terms
19 | Complex[] even = new Complex[n / 2];
20 | for (int k = 0; k < n / 2; k++) {
21 | even[k] = x[2 * k];
22 | }
23 | Complex[] q = fft(even);
24 |
25 | // fft of odd terms
26 | for (int k = 0; k < n / 2; k++) {
27 | even[k] = x[2 * k + 1];
28 | }
29 | Complex[] r = fft(even);
30 |
31 | // combine
32 | Complex[] y = new Complex[n];
33 | for (int k = 0; k < n / 2; k++) {
34 | double kth = -2 * k * Math.PI / n;
35 | Complex wk = new Complex(Math.cos(kth), Math.sin(kth));
36 | y[k] = q[k].plus(wk.times(r[k]));
37 | y[k + n / 2] = q[k].minus(wk.times(r[k]));
38 | }
39 | return y;
40 | }
41 |
42 | public static double[] fft(double[] x, int sc) {
43 | int len = x.length;
44 | if (len == 1) {
45 | return x;
46 | }
47 | Complex[] cs = new Complex[len];
48 | double[] ds = new double[len / 2];
49 | for (int i = 0; i < len; i++) {
50 | cs[i] = new Complex(x[i], 0);
51 | }
52 | Complex[] ffts = fft(cs);
53 |
54 | for (int i = 0; i < ds.length; i++) {
55 | ds[i] = Math.sqrt(Math.pow(ffts[i].re(), 2) + Math.pow(ffts[i].im(), 2)) / x.length;
56 | }
57 | return ds;
58 | }
59 |
60 | // compute the inverse FFT of x[], assuming its length is a power of 2
61 | public static Complex[] ifft(Complex[] x) {
62 | int n = x.length;
63 | Complex[] y = new Complex[n];
64 |
65 | // take conjugate
66 | for (int i = 0; i < n; i++) {
67 | y[i] = x[i].conjugate();
68 | }
69 |
70 | // compute forward FFT
71 | y = fft(y);
72 |
73 | // take conjugate again
74 | for (int i = 0; i < n; i++) {
75 | y[i] = y[i].conjugate();
76 | }
77 |
78 | // divide by n
79 | for (int i = 0; i < n; i++) {
80 | y[i] = y[i].scale(1.0 / n);
81 | }
82 |
83 | return y;
84 |
85 | }
86 |
87 | // compute the circular convolution of x and y
88 | public static Complex[] cconvolve(Complex[] x, Complex[] y) {
89 |
90 | // should probably pad x and y with 0s so that they have same length
91 | // and are powers of 2
92 | if (x.length != y.length) {
93 | throw new IllegalArgumentException("Dimensions don't agree");
94 | }
95 |
96 | int n = x.length;
97 |
98 | // compute FFT of each sequence
99 | Complex[] a = fft(x);
100 | Complex[] b = fft(y);
101 |
102 | // point-wise multiply
103 | Complex[] c = new Complex[n];
104 | for (int i = 0; i < n; i++) {
105 | c[i] = a[i].times(b[i]);
106 | }
107 |
108 | // compute inverse FFT
109 | return ifft(c);
110 | }
111 |
112 |
113 | // compute the linear convolution of x and y
114 | public static Complex[] convolve(Complex[] x, Complex[] y) {
115 | Complex ZERO = new Complex(0, 0);
116 |
117 | Complex[] a = new Complex[2 * x.length];
118 | for (int i = 0; i < x.length; i++) a[i] = x[i];
119 | for (int i = x.length; i < 2 * x.length; i++) a[i] = ZERO;
120 |
121 | Complex[] b = new Complex[2 * y.length];
122 | for (int i = 0; i < y.length; i++) b[i] = y[i];
123 | for (int i = y.length; i < 2 * y.length; i++) b[i] = ZERO;
124 |
125 | return cconvolve(a, b);
126 | }
127 |
128 | // display an array of Complex numbers to standard output
129 | public static void show(Complex[] x, String title) {
130 | System.out.println(title);
131 | System.out.println("-------------------");
132 | for (int i = 0; i < SIZE; i++) {
133 | System.out.println(x[i]);
134 | }
135 | System.out.println();
136 | }
137 |
138 | private static final int SIZE = 16384 / 4;
139 |
140 | public static double fun(int x) {
141 | return Math.sin(15f * x);//f= 3.142
142 | }
143 |
144 | public static double getY(double[] d) {
145 | double y = 0;
146 | int x = 0;
147 | for (int i = 0; i < d.length; i++) {
148 | if (d[i] > y) {
149 | y = d[i];
150 | x = i;
151 | }
152 | }
153 | x++;
154 | log(String.format("x: %s , y: %s", x, y));
155 | log(String.format("频率: %sHz", (float) x / SIZE));
156 | log(String.format("频率2: %sHz", (float) (SIZE - x) / SIZE));
157 | log(String.format("振幅: %s", y));
158 | return y;
159 | }
160 |
161 | public static void log(String s) {
162 | System.out.println(s);
163 | }
164 |
165 | }
--------------------------------------------------------------------------------
/recorderlib/src/main/java/fftlib/FftFactory.java:
--------------------------------------------------------------------------------
1 | package fftlib;
2 |
3 | import com.zlw.main.recorderlib.utils.Logger;
4 |
5 | /**
6 | * FFT 数据处理工厂
7 | */
8 | public class FftFactory {
9 | private static final String TAG = FftFactory.class.getSimpleName();
10 | private Level level = Level.Original;
11 |
12 | public FftFactory(Level level) {
13 | // this.level = level;
14 | }
15 |
16 | public byte[] makeFftData(byte[] pcmData) {
17 | // Logger.d(TAG, "pcmData length: %s", pcmData.length);
18 | if (pcmData.length < 1024) {
19 | Logger.d(TAG, "makeFftData");
20 | return null;
21 | }
22 |
23 | double[] doubles = ByteUtils.toHardDouble(ByteUtils.toShorts(pcmData));
24 | double[] fft = FFT.fft(doubles, 0);
25 |
26 | switch (level) {
27 | case Original:
28 | return ByteUtils.toSoftBytes(fft);
29 | case Maximal:
30 | // return doFftMaximal(fft);
31 | default:
32 | return ByteUtils.toHardBytes(fft);
33 | }
34 | }
35 |
36 |
37 | private byte[] doFftMaximal(double[] fft) {
38 | byte[] bytes = ByteUtils.toSoftBytes(fft);
39 | byte[] result = new byte[bytes.length];
40 |
41 | for (int i = 0; i < bytes.length; i++) {
42 |
43 | if (isSimpleData(bytes, i)) {
44 | result[i] = bytes[i];
45 | } else {
46 | result[Math.max(i - 1, 0)] = (byte) (bytes[i] / 2);
47 | result[Math.min(i + 1, result.length - 1)] = (byte) (bytes[i] / 2);
48 | }
49 | }
50 |
51 | return result;
52 | }
53 |
54 | private boolean isSimpleData(byte[] data, int i) {
55 |
56 | int start = Math.max(0, i - 5);
57 | int end = Math.min(data.length, i + 5);
58 |
59 | byte max = 0, min = 127;
60 | for (int j = start; j < end; j++) {
61 | if (data[j] > max) {
62 | max = data[j];
63 | }
64 | if (data[j] < min) {
65 | min = data[j];
66 | }
67 | }
68 |
69 | return data[i] == min || data[i] == max;
70 | }
71 |
72 |
73 | /**
74 | * FFT 处理等级
75 | */
76 | public enum Level {
77 |
78 | /**
79 | * 原始数据,不做任何优化
80 | */
81 | Original,
82 |
83 | /**
84 | * 对音乐进行优化
85 | */
86 | Music,
87 |
88 | /**
89 | * 对人声进行优化
90 | */
91 | People,
92 |
93 | /**
94 | * 极限优化
95 | */
96 | Maximal
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 |
5 | LAME_LIBMP3_DIR := lame-3.100_libmp3lame
6 |
7 | LOCAL_MODULE := mp3lame
8 |
9 | LOCAL_SRC_FILES :=\
10 | $(LAME_LIBMP3_DIR)/bitstream.c \
11 | $(LAME_LIBMP3_DIR)/fft.c \
12 | $(LAME_LIBMP3_DIR)/id3tag.c \
13 | $(LAME_LIBMP3_DIR)/mpglib_interface.c \
14 | $(LAME_LIBMP3_DIR)/presets.c \
15 | $(LAME_LIBMP3_DIR)/quantize.c \
16 | $(LAME_LIBMP3_DIR)/reservoir.c \
17 | $(LAME_LIBMP3_DIR)/tables.c \
18 | $(LAME_LIBMP3_DIR)/util.c \
19 | $(LAME_LIBMP3_DIR)/VbrTag.c \
20 | $(LAME_LIBMP3_DIR)/encoder.c \
21 | $(LAME_LIBMP3_DIR)/gain_analysis.c \
22 | $(LAME_LIBMP3_DIR)/lame.c \
23 | $(LAME_LIBMP3_DIR)/newmdct.c \
24 | $(LAME_LIBMP3_DIR)/psymodel.c \
25 | $(LAME_LIBMP3_DIR)/quantize_pvt.c \
26 | $(LAME_LIBMP3_DIR)/set_get.c \
27 | $(LAME_LIBMP3_DIR)/takehiro.c \
28 | $(LAME_LIBMP3_DIR)/vbrquantize.c \
29 | $(LAME_LIBMP3_DIR)/version.c \
30 | MP3Encoder.c
31 |
32 | include $(BUILD_SHARED_LIBRARY)
33 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/Application.mk:
--------------------------------------------------------------------------------
1 | APP_ABI := armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mips64
2 | APP_MODULES := mp3lame
3 | APP_CFLAGS += -DSTDC_HEADERS
4 | APP_PLATFORM := android-21
5 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/Mp3Encoder.c:
--------------------------------------------------------------------------------
1 | #include "lame-3.100_libmp3lame/lame.h"
2 | #include "Mp3Encoder.h"
3 |
4 | static lame_global_flags *glf = NULL;
5 |
6 | JNIEXPORT void JNICALL Java_com_zlw_main_recorderlib_recorder_mp3_Mp3Encoder_init(
7 | JNIEnv *env, jclass cls, jint inSamplerate, jint outChannel,
8 | jint outSamplerate, jint outBitrate, jint quality) {
9 | if (glf != NULL) {
10 | lame_close(glf);
11 | glf = NULL;
12 | }
13 | glf = lame_init();
14 | lame_set_in_samplerate(glf, inSamplerate);
15 | lame_set_num_channels(glf, outChannel);
16 | lame_set_out_samplerate(glf, outSamplerate);
17 | lame_set_brate(glf, outBitrate);
18 | lame_set_quality(glf, quality);
19 | lame_init_params(glf);
20 | }
21 |
22 | JNIEXPORT jint JNICALL Java_com_zlw_main_recorderlib_recorder_mp3_Mp3Encoder_encode(
23 | JNIEnv *env, jclass cls, jshortArray buffer_l, jshortArray buffer_r,
24 | jint samples, jbyteArray mp3buf) {
25 | jshort* j_buffer_l = (*env)->GetShortArrayElements(env, buffer_l, NULL);
26 |
27 | jshort* j_buffer_r = (*env)->GetShortArrayElements(env, buffer_r, NULL);
28 |
29 | const jsize mp3buf_size = (*env)->GetArrayLength(env, mp3buf);
30 | jbyte* j_mp3buf = (*env)->GetByteArrayElements(env, mp3buf, NULL);
31 |
32 | int result = lame_encode_buffer(glf, j_buffer_l, j_buffer_r,
33 | samples, j_mp3buf, mp3buf_size);
34 |
35 | (*env)->ReleaseShortArrayElements(env, buffer_l, j_buffer_l, 0);
36 | (*env)->ReleaseShortArrayElements(env, buffer_r, j_buffer_r, 0);
37 | (*env)->ReleaseByteArrayElements(env, mp3buf, j_mp3buf, 0);
38 |
39 | return result;
40 | }
41 |
42 | JNIEXPORT jint JNICALL Java_com_zlw_main_recorderlib_recorder_mp3_Mp3Encoder_flush(
43 | JNIEnv *env, jclass cls, jbyteArray mp3buf) {
44 | const jsize mp3buf_size = (*env)->GetArrayLength(env, mp3buf);
45 | jbyte* j_mp3buf = (*env)->GetByteArrayElements(env, mp3buf, NULL);
46 |
47 | int result = lame_encode_flush(glf, j_mp3buf, mp3buf_size);
48 |
49 | (*env)->ReleaseByteArrayElements(env, mp3buf, j_mp3buf, 0);
50 |
51 | return result;
52 | }
53 |
54 | JNIEXPORT void JNICALL Java_com_zlw_main_recorderlib_recorder_mp3_Mp3Encoder_close(
55 | JNIEnv *env, jclass cls) {
56 | lame_close(glf);
57 | glf = NULL;
58 | }
59 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/Mp3Encoder.h:
--------------------------------------------------------------------------------
1 | /* DO NOT EDIT THIS FILE - it is machine generated */
2 | #include
3 |
4 | #ifndef _Included_Mp3Encoder
5 | #define _Included_Mp3Encoder
6 | #ifdef __cplusplus
7 | extern "C" {
8 | #endif
9 | /*
10 | * Class: com.zlw.main.recorderlib.recorder.mp3.Mp3Encoder
11 | * Method: init
12 | */
13 | JNIEXPORT void JNICALL Java_com_zlw_main_recorderlib_recorder_mp3_Mp3Encoder_init
14 | (JNIEnv *, jclass, jint, jint, jint, jint, jint);
15 |
16 | JNIEXPORT jint JNICALL Java_com_zlw_main_recorderlib_recorder_mp3_Mp3Encoder_encode
17 | (JNIEnv *, jclass, jshortArray, jshortArray, jint, jbyteArray);
18 |
19 | JNIEXPORT jint JNICALL Java_com_zlw_main_recorderlib_recorder_mp3_Mp3Encoder_flush
20 | (JNIEnv *, jclass, jbyteArray);
21 |
22 | JNIEXPORT void JNICALL Java_com_zlw_main_recorderlib_recorder_mp3_Mp3Encoder_close
23 | (JNIEnv *, jclass);
24 |
25 | #ifdef __cplusplus
26 | }
27 | #endif
28 | #endif
29 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/VbrTag.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Xing VBR tagging for LAME.
3 | *
4 | * Copyright (c) 1999 A.L. Faber
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_VRBTAG_H
23 | #define LAME_VRBTAG_H
24 |
25 |
26 | /* -----------------------------------------------------------
27 | * A Vbr header may be present in the ancillary
28 | * data field of the first frame of an mp3 bitstream
29 | * The Vbr header (optionally) contains
30 | * frames total number of audio frames in the bitstream
31 | * bytes total number of bytes in the bitstream
32 | * toc table of contents
33 |
34 | * toc (table of contents) gives seek points
35 | * for random access
36 | * the ith entry determines the seek point for
37 | * i-percent duration
38 | * seek point in bytes = (toc[i]/256.0) * total_bitstream_bytes
39 | * e.g. half duration seek point = (toc[50]/256.0) * total_bitstream_bytes
40 | */
41 |
42 |
43 | #define FRAMES_FLAG 0x0001
44 | #define BYTES_FLAG 0x0002
45 | #define TOC_FLAG 0x0004
46 | #define VBR_SCALE_FLAG 0x0008
47 |
48 | #define NUMTOCENTRIES 100
49 |
50 | #ifndef lame_internal_flags_defined
51 | #define lame_internal_flags_defined
52 | struct lame_internal_flags;
53 | typedef struct lame_internal_flags lame_internal_flags;
54 | #endif
55 |
56 |
57 | /*structure to receive extracted header */
58 | /* toc may be NULL*/
59 | typedef struct {
60 | int h_id; /* from MPEG header, 0=MPEG2, 1=MPEG1 */
61 | int samprate; /* determined from MPEG header */
62 | int flags; /* from Vbr header data */
63 | int frames; /* total bit stream frames from Vbr header data */
64 | int bytes; /* total bit stream bytes from Vbr header data */
65 | int vbr_scale; /* encoded vbr scale from Vbr header data */
66 | unsigned char toc[NUMTOCENTRIES]; /* may be NULL if toc not desired */
67 | int headersize; /* size of VBR header, in bytes */
68 | int enc_delay; /* encoder delay */
69 | int enc_padding; /* encoder paddign added at end of stream */
70 | } VBRTAGDATA;
71 |
72 | int GetVbrTag(VBRTAGDATA * pTagData, const unsigned char *buf);
73 |
74 | int InitVbrTag(lame_global_flags * gfp);
75 | int PutVbrTag(lame_global_flags const *gfp, FILE * fid);
76 | void AddVbrFrame(lame_internal_flags * gfc);
77 | void UpdateMusicCRC(uint16_t * crc, const unsigned char *buffer, int size);
78 |
79 | #endif
80 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/bitstream.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MP3 bitstream Output interface for LAME
3 | *
4 | * Copyright (c) 1999 Takehiro TOMINAGA
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_BITSTREAM_H
23 | #define LAME_BITSTREAM_H
24 |
25 | int getframebits(const lame_internal_flags * gfc);
26 |
27 | int format_bitstream(lame_internal_flags * gfc);
28 |
29 | void flush_bitstream(lame_internal_flags * gfc);
30 | void add_dummy_byte(lame_internal_flags * gfc, unsigned char val, unsigned int n);
31 |
32 | int copy_buffer(lame_internal_flags * gfc, unsigned char *buffer, int buffer_size,
33 | int update_crc);
34 | void init_bit_stream_w(lame_internal_flags * gfc);
35 | void CRC_writeheader(lame_internal_flags const *gfc, char *buffer);
36 | int compute_flushbits(const lame_internal_flags * gfp, int *nbytes);
37 |
38 | int get_max_frame_buffer_size_by_constraint(SessionConfig_t const * cfg, int constraint);
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/encoder.h:
--------------------------------------------------------------------------------
1 | /*
2 | * encoder.h include file
3 | *
4 | * Copyright (c) 2000 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 |
23 | #ifndef LAME_ENCODER_H
24 | #define LAME_ENCODER_H
25 |
26 | /***********************************************************************
27 | *
28 | * encoder and decoder delays
29 | *
30 | ***********************************************************************/
31 |
32 | /*
33 | * layer III enc->dec delay: 1056 (1057?) (observed)
34 | * layer II enc->dec delay: 480 (481?) (observed)
35 | *
36 | * polyphase 256-16 (dec or enc) = 240
37 | * mdct 256+32 (9*32) (dec or enc) = 288
38 | * total: 512+16
39 | *
40 | * My guess is that delay of polyphase filterbank is actualy 240.5
41 | * (there are technical reasons for this, see postings in mp3encoder).
42 | * So total Encode+Decode delay = ENCDELAY + 528 + 1
43 | */
44 |
45 | /*
46 | * ENCDELAY The encoder delay.
47 | *
48 | * Minimum allowed is MDCTDELAY (see below)
49 | *
50 | * The first 96 samples will be attenuated, so using a value less than 96
51 | * will result in corrupt data for the first 96-ENCDELAY samples.
52 | *
53 | * suggested: 576
54 | * set to 1160 to sync with FhG.
55 | */
56 |
57 | #define ENCDELAY 576
58 |
59 |
60 |
61 | /*
62 | * make sure there is at least one complete frame after the
63 | * last frame containing real data
64 | *
65 | * Using a value of 288 would be sufficient for a
66 | * a very sophisticated decoder that can decode granule-by-granule instead
67 | * of frame by frame. But lets not assume this, and assume the decoder
68 | * will not decode frame N unless it also has data for frame N+1
69 | *
70 | */
71 | /*#define POSTDELAY 288*/
72 | #define POSTDELAY 1152
73 |
74 |
75 |
76 | /*
77 | * delay of the MDCT used in mdct.c
78 | * original ISO routines had a delay of 528!
79 | * Takehiro's routines:
80 | */
81 |
82 | #define MDCTDELAY 48
83 | #define FFTOFFSET (224+MDCTDELAY)
84 |
85 | /*
86 | * Most decoders, including the one we use, have a delay of 528 samples.
87 | */
88 |
89 | #define DECDELAY 528
90 |
91 |
92 | /* number of subbands */
93 | #define SBLIMIT 32
94 |
95 | /* parition bands bands */
96 | #define CBANDS 64
97 |
98 | /* number of critical bands/scale factor bands where masking is computed*/
99 | #define SBPSY_l 21
100 | #define SBPSY_s 12
101 |
102 | /* total number of scalefactor bands encoded */
103 | #define SBMAX_l 22
104 | #define SBMAX_s 13
105 | #define PSFB21 6
106 | #define PSFB12 6
107 |
108 |
109 |
110 | /* FFT sizes */
111 | #define BLKSIZE 1024
112 | #define HBLKSIZE (BLKSIZE/2 + 1)
113 | #define BLKSIZE_s 256
114 | #define HBLKSIZE_s (BLKSIZE_s/2 + 1)
115 |
116 |
117 | /* #define switch_pe 1800 */
118 | #define NORM_TYPE 0
119 | #define START_TYPE 1
120 | #define SHORT_TYPE 2
121 | #define STOP_TYPE 3
122 |
123 | /*
124 | * Mode Extention:
125 | * When we are in stereo mode, there are 4 possible methods to store these
126 | * two channels. The stereo modes -m? are using a subset of them.
127 | *
128 | * -ms: MPG_MD_LR_LR
129 | * -mj: MPG_MD_LR_LR and MPG_MD_MS_LR
130 | * -mf: MPG_MD_MS_LR
131 | * -mi: all
132 | */
133 | #if 0
134 | #define MPG_MD_LR_LR 0
135 | #define MPG_MD_LR_I 1
136 | #define MPG_MD_MS_LR 2
137 | #define MPG_MD_MS_I 3
138 | #endif
139 | enum MPEGChannelMode
140 | { MPG_MD_LR_LR = 0
141 | , MPG_MD_LR_I = 1
142 | , MPG_MD_MS_LR = 2
143 | , MPG_MD_MS_I = 3
144 | };
145 |
146 | #ifndef lame_internal_flags_defined
147 | #define lame_internal_flags_defined
148 | struct lame_internal_flags;
149 | typedef struct lame_internal_flags lame_internal_flags;
150 | #endif
151 |
152 | int lame_encode_mp3_frame(lame_internal_flags * gfc,
153 | sample_t const *inbuf_l,
154 | sample_t const *inbuf_r, unsigned char *mp3buf, int mp3buf_size);
155 |
156 | #endif /* LAME_ENCODER_H */
157 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/fft.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Fast Fourier Transform include file
3 | *
4 | * Copyright (c) 2000 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_FFT_H
23 | #define LAME_FFT_H
24 |
25 | void fft_long(lame_internal_flags const *const gfc, FLOAT x_real[BLKSIZE],
26 | int chn, const sample_t *const data[2]);
27 |
28 | void fft_short(lame_internal_flags const *const gfc, FLOAT x_real[3][BLKSIZE_s],
29 | int chn, const sample_t *const data[2]);
30 |
31 | void init_fft(lame_internal_flags * const gfc);
32 |
33 | #endif
34 |
35 | /* End of fft.h */
36 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/gain_analysis.h:
--------------------------------------------------------------------------------
1 | /*
2 | * ReplayGainAnalysis - analyzes input samples and give the recommended dB change
3 | * Copyright (C) 2001 David Robinson and Glen Sawyer
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 2.1 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Lesser General Public
16 | * License along with this library; if not, write to the Free Software
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 | *
19 | * concept and filter values by David Robinson (David@Robinson.org)
20 | * -- blame him if you think the idea is flawed
21 | * coding by Glen Sawyer (mp3gain@hotmail.com) 735 W 255 N, Orem, UT 84057-4505 USA
22 | * -- blame him if you think this runs too slowly, or the coding is otherwise flawed
23 | *
24 | * For an explanation of the concepts and the basic algorithms involved, go to:
25 | * http://www.replaygain.org/
26 | */
27 |
28 | #ifndef GAIN_ANALYSIS_H
29 | #define GAIN_ANALYSIS_H
30 |
31 | #ifdef HAVE_INTTYPES_H
32 | # include
33 | #else
34 | # ifdef HAVE_STDINT_H
35 | # include
36 | # endif
37 | #endif
38 |
39 | #ifdef __cplusplus
40 | extern "C" {
41 | #endif
42 |
43 |
44 | typedef sample_t Float_t; /* Type used for filtering */
45 |
46 |
47 | #define PINK_REF 64.82 /* 298640883795 */ /* calibration value for 89dB */
48 |
49 |
50 | #define YULE_ORDER 10
51 | #define BUTTER_ORDER 2
52 | #define YULE_FILTER filterYule
53 | #define BUTTER_FILTER filterButter
54 | #define RMS_PERCENTILE 0.95 /* percentile which is louder than the proposed level */
55 | #define MAX_SAMP_FREQ 48000L /* maximum allowed sample frequency [Hz] */
56 | #define RMS_WINDOW_TIME_NUMERATOR 1L
57 | #define RMS_WINDOW_TIME_DENOMINATOR 20L /* numerator / denominator = time slice size [s] */
58 | #define STEPS_per_dB 100 /* Table entries per dB */
59 | #define MAX_dB 120 /* Table entries for 0...MAX_dB (normal max. values are 70...80 dB) */
60 |
61 | enum { GAIN_NOT_ENOUGH_SAMPLES = -24601, GAIN_ANALYSIS_ERROR = 0, GAIN_ANALYSIS_OK =
62 | 1, INIT_GAIN_ANALYSIS_ERROR = 0, INIT_GAIN_ANALYSIS_OK = 1
63 | };
64 |
65 | enum { MAX_ORDER = (BUTTER_ORDER > YULE_ORDER ? BUTTER_ORDER : YULE_ORDER)
66 | , MAX_SAMPLES_PER_WINDOW = ((MAX_SAMP_FREQ * RMS_WINDOW_TIME_NUMERATOR) / RMS_WINDOW_TIME_DENOMINATOR + 1) /* max. Samples per Time slice */
67 | };
68 |
69 | struct replaygain_data {
70 | Float_t linprebuf[MAX_ORDER * 2];
71 | Float_t *linpre; /* left input samples, with pre-buffer */
72 | Float_t lstepbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
73 | Float_t *lstep; /* left "first step" (i.e. post first filter) samples */
74 | Float_t loutbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
75 | Float_t *lout; /* left "out" (i.e. post second filter) samples */
76 | Float_t rinprebuf[MAX_ORDER * 2];
77 | Float_t *rinpre; /* right input samples ... */
78 | Float_t rstepbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
79 | Float_t *rstep;
80 | Float_t routbuf[MAX_SAMPLES_PER_WINDOW + MAX_ORDER];
81 | Float_t *rout;
82 | long sampleWindow; /* number of samples required to reach number of milliseconds required for RMS window */
83 | long totsamp;
84 | double lsum;
85 | double rsum;
86 | int freqindex;
87 | int first;
88 | uint32_t A[STEPS_per_dB * MAX_dB];
89 | uint32_t B[STEPS_per_dB * MAX_dB];
90 |
91 | };
92 | #ifndef replaygain_data_defined
93 | #define replaygain_data_defined
94 | typedef struct replaygain_data replaygain_t;
95 | #endif
96 |
97 |
98 |
99 |
100 | int InitGainAnalysis(replaygain_t * rgData, long samplefreq);
101 | int AnalyzeSamples(replaygain_t * rgData, const Float_t * left_samples,
102 | const Float_t * right_samples, size_t num_samples, int num_channels);
103 | Float_t GetTitleGain(replaygain_t * rgData);
104 |
105 |
106 | #ifdef __cplusplus
107 | }
108 | #endif
109 | #endif /* GAIN_ANALYSIS_H */
110 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/id3tag.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef LAME_ID3_H
3 | #define LAME_ID3_H
4 |
5 |
6 | #define CHANGED_FLAG (1U << 0)
7 | #define ADD_V2_FLAG (1U << 1)
8 | #define V1_ONLY_FLAG (1U << 2)
9 | #define V2_ONLY_FLAG (1U << 3)
10 | #define SPACE_V1_FLAG (1U << 4)
11 | #define PAD_V2_FLAG (1U << 5)
12 |
13 | enum {
14 | MIMETYPE_NONE = 0,
15 | MIMETYPE_JPEG,
16 | MIMETYPE_PNG,
17 | MIMETYPE_GIF
18 | };
19 |
20 | typedef struct FrameDataNode {
21 | struct FrameDataNode *nxt;
22 | uint32_t fid; /* Frame Identifier */
23 | char lng[4]; /* 3-character language descriptor */
24 | struct {
25 | union {
26 | char *l; /* ptr to Latin-1 chars */
27 | unsigned short *u; /* ptr to UCS-2 text */
28 | unsigned char *b; /* ptr to raw bytes */
29 | } ptr;
30 | size_t dim;
31 | int enc; /* 0:Latin-1, 1:UCS-2, 2:RAW */
32 | } dsc , txt;
33 | } FrameDataNode;
34 |
35 |
36 | typedef struct id3tag_spec {
37 | /* private data members */
38 | unsigned int flags;
39 | int year;
40 | char *title;
41 | char *artist;
42 | char *album;
43 | char *comment;
44 | int track_id3v1;
45 | int genre_id3v1;
46 | unsigned char *albumart;
47 | unsigned int albumart_size;
48 | unsigned int padding_size;
49 | int albumart_mimetype;
50 | char language[4]; /* the language of the frame's content, according to ISO-639-2 */
51 | FrameDataNode *v2_head, *v2_tail;
52 | } id3tag_spec;
53 |
54 |
55 | /* write tag into stream at current position */
56 | extern int id3tag_write_v2(lame_global_flags * gfp);
57 | extern int id3tag_write_v1(lame_global_flags * gfp);
58 | /*
59 | * NOTE: A version 2 tag will NOT be added unless one of the text fields won't
60 | * fit in a version 1 tag (e.g. the title string is longer than 30 characters),
61 | * or the "id3tag_add_v2" or "id3tag_v2_only" functions are used.
62 | */
63 |
64 | #endif
65 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/l3side.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Layer 3 side include file
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_L3SIDE_H
23 | #define LAME_L3SIDE_H
24 |
25 | /* max scalefactor band, max(SBMAX_l, SBMAX_s*3, (SBMAX_s-3)*3+8) */
26 | #define SFBMAX (SBMAX_s*3)
27 |
28 | /* Layer III side information. */
29 | typedef struct {
30 | int l[1 + SBMAX_l];
31 | int s[1 + SBMAX_s];
32 | int psfb21[1 + PSFB21];
33 | int psfb12[1 + PSFB12];
34 | } scalefac_struct;
35 |
36 |
37 | typedef struct {
38 | FLOAT l[SBMAX_l];
39 | FLOAT s[SBMAX_s][3];
40 | } III_psy_xmin;
41 |
42 | typedef struct {
43 | III_psy_xmin thm;
44 | III_psy_xmin en;
45 | } III_psy_ratio;
46 |
47 | typedef struct {
48 | FLOAT xr[576];
49 | int l3_enc[576];
50 | int scalefac[SFBMAX];
51 | FLOAT xrpow_max;
52 |
53 | int part2_3_length;
54 | int big_values;
55 | int count1;
56 | int global_gain;
57 | int scalefac_compress;
58 | int block_type;
59 | int mixed_block_flag;
60 | int table_select[3];
61 | int subblock_gain[3 + 1];
62 | int region0_count;
63 | int region1_count;
64 | int preflag;
65 | int scalefac_scale;
66 | int count1table_select;
67 |
68 | int part2_length;
69 | int sfb_lmax;
70 | int sfb_smin;
71 | int psy_lmax;
72 | int sfbmax;
73 | int psymax;
74 | int sfbdivide;
75 | int width[SFBMAX];
76 | int window[SFBMAX];
77 | int count1bits;
78 | /* added for LSF */
79 | const int *sfb_partition_table;
80 | int slen[4];
81 |
82 | int max_nonzero_coeff;
83 | char energy_above_cutoff[SFBMAX];
84 | } gr_info;
85 |
86 | typedef struct {
87 | gr_info tt[2][2];
88 | int main_data_begin;
89 | int private_bits;
90 | int resvDrain_pre;
91 | int resvDrain_post;
92 | int scfsi[2][4];
93 | } III_side_info_t;
94 |
95 | #endif
96 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/lame-analysis.h:
--------------------------------------------------------------------------------
1 | /*
2 | * GTK plotting routines source file
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_GTKANAL_H
23 | #define LAME_GTKANAL_H
24 |
25 |
26 | #define READ_AHEAD 40 /* number of frames to read ahead */
27 | #define MAXMPGLAG READ_AHEAD /* if the mpg123 lag becomes bigger than this
28 | we have to stop */
29 | #define NUMBACK 6 /* number of frames we can back up */
30 | #define NUMPINFO (NUMBACK+READ_AHEAD+1)
31 |
32 |
33 |
34 | struct plotting_data {
35 | int frameNum; /* current frame number */
36 | int frameNum123;
37 | int num_samples; /* number of pcm samples read for this frame */
38 | double frametime; /* starting time of frame, in seconds */
39 | double pcmdata[2][1600];
40 | double pcmdata2[2][1152 + 1152 - DECDELAY];
41 | double xr[2][2][576];
42 | double mpg123xr[2][2][576];
43 | double ms_ratio[2];
44 | double ms_ener_ratio[2];
45 |
46 | /* L,R, M and S values */
47 | double energy_save[4][BLKSIZE]; /* psymodel is one ahead */
48 | double energy[2][4][BLKSIZE];
49 | double pe[2][4];
50 | double thr[2][4][SBMAX_l];
51 | double en[2][4][SBMAX_l];
52 | double thr_s[2][4][3 * SBMAX_s];
53 | double en_s[2][4][3 * SBMAX_s];
54 | double ers_save[4]; /* psymodel is one ahead */
55 | double ers[2][4];
56 |
57 | double sfb[2][2][SBMAX_l];
58 | double sfb_s[2][2][3 * SBMAX_s];
59 | double LAMEsfb[2][2][SBMAX_l];
60 | double LAMEsfb_s[2][2][3 * SBMAX_s];
61 |
62 | int LAMEqss[2][2];
63 | int qss[2][2];
64 | int big_values[2][2];
65 | int sub_gain[2][2][3];
66 |
67 | double xfsf[2][2][SBMAX_l];
68 | double xfsf_s[2][2][3 * SBMAX_s];
69 |
70 | int over[2][2];
71 | double tot_noise[2][2];
72 | double max_noise[2][2];
73 | double over_noise[2][2];
74 | int over_SSD[2][2];
75 | int blocktype[2][2];
76 | int scalefac_scale[2][2];
77 | int preflag[2][2];
78 | int mpg123blocktype[2][2];
79 | int mixed[2][2];
80 | int mainbits[2][2];
81 | int sfbits[2][2];
82 | int LAMEmainbits[2][2];
83 | int LAMEsfbits[2][2];
84 | int framesize, stereo, js, ms_stereo, i_stereo, emph, bitrate, sampfreq, maindata;
85 | int crc, padding;
86 | int scfsi[2], mean_bits, resvsize;
87 | int totbits;
88 | };
89 | #ifndef plotting_data_defined
90 | #define plotting_data_defined
91 | typedef struct plotting_data plotting_data;
92 | #endif
93 | #if 0
94 | extern plotting_data *pinfo;
95 | #endif
96 | #endif
97 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/lame_global_flags.h:
--------------------------------------------------------------------------------
1 | #ifndef LAME_GLOBAL_FLAGS_H
2 | #define LAME_GLOBAL_FLAGS_H
3 |
4 | #ifndef lame_internal_flags_defined
5 | #define lame_internal_flags_defined
6 | struct lame_internal_flags;
7 | typedef struct lame_internal_flags lame_internal_flags;
8 | #endif
9 |
10 |
11 | typedef enum short_block_e {
12 | short_block_not_set = -1, /* allow LAME to decide */
13 | short_block_allowed = 0, /* LAME may use them, even different block types for L/R */
14 | short_block_coupled, /* LAME may use them, but always same block types in L/R */
15 | short_block_dispensed, /* LAME will not use short blocks, long blocks only */
16 | short_block_forced /* LAME will not use long blocks, short blocks only */
17 | } short_block_t;
18 |
19 | /***********************************************************************
20 | *
21 | * Control Parameters set by User. These parameters are here for
22 | * backwards compatibility with the old, non-shared lib API.
23 | * Please use the lame_set_variablename() functions below
24 | *
25 | *
26 | ***********************************************************************/
27 | struct lame_global_struct {
28 | unsigned int class_id;
29 |
30 | /* input description */
31 | unsigned long num_samples; /* number of samples. default=2^32-1 */
32 | int num_channels; /* input number of channels. default=2 */
33 | int samplerate_in; /* input_samp_rate in Hz. default=44.1 kHz */
34 | int samplerate_out; /* output_samp_rate.
35 | default: LAME picks best value
36 | at least not used for MP3 decoding:
37 | Remember 44.1 kHz MP3s and AC97 */
38 | float scale; /* scale input by this amount before encoding
39 | at least not used for MP3 decoding */
40 | float scale_left; /* scale input of channel 0 (left) by this
41 | amount before encoding */
42 | float scale_right; /* scale input of channel 1 (right) by this
43 | amount before encoding */
44 |
45 | /* general control params */
46 | int analysis; /* collect data for a MP3 frame analyzer? */
47 | int write_lame_tag; /* add Xing VBR tag? */
48 | int decode_only; /* use lame/mpglib to convert mp3 to wav */
49 | int quality; /* quality setting 0=best, 9=worst default=5 */
50 | MPEG_mode mode; /* see enum in lame.h
51 | default = LAME picks best value */
52 | int force_ms; /* force M/S mode. requires mode=1 */
53 | int free_format; /* use free format? default=0 */
54 | int findReplayGain; /* find the RG value? default=0 */
55 | int decode_on_the_fly; /* decode on the fly? default=0 */
56 | int write_id3tag_automatic; /* 1 (default) writes ID3 tags, 0 not */
57 |
58 | int nogap_total;
59 | int nogap_current;
60 |
61 | int substep_shaping;
62 | int noise_shaping;
63 | int subblock_gain; /* 0 = no, 1 = yes */
64 | int use_best_huffman; /* 0 = no. 1=outside loop 2=inside loop(slow) */
65 |
66 | /*
67 | * set either brate>0 or compression_ratio>0, LAME will compute
68 | * the value of the variable not set.
69 | * Default is compression_ratio = 11.025
70 | */
71 | int brate; /* bitrate */
72 | float compression_ratio; /* sizeof(wav file)/sizeof(mp3 file) */
73 |
74 |
75 | /* frame params */
76 | int copyright; /* mark as copyright. default=0 */
77 | int original; /* mark as original. default=1 */
78 | int extension; /* the MP3 'private extension' bit.
79 | Meaningless */
80 | int emphasis; /* Input PCM is emphased PCM (for
81 | instance from one of the rarely
82 | emphased CDs), it is STRONGLY not
83 | recommended to use this, because
84 | psycho does not take it into account,
85 | and last but not least many decoders
86 | don't care about these bits */
87 | int error_protection; /* use 2 bytes per frame for a CRC
88 | checksum. default=0 */
89 | int strict_ISO; /* enforce ISO spec as much as possible */
90 |
91 | int disable_reservoir; /* use bit reservoir? */
92 |
93 | /* quantization/noise shaping */
94 | int quant_comp;
95 | int quant_comp_short;
96 | int experimentalY;
97 | int experimentalZ;
98 | int exp_nspsytune;
99 |
100 | int preset;
101 |
102 | /* VBR control */
103 | vbr_mode VBR;
104 | float VBR_q_frac; /* Range [0,...,1[ */
105 | int VBR_q; /* Range [0,...,9] */
106 | int VBR_mean_bitrate_kbps;
107 | int VBR_min_bitrate_kbps;
108 | int VBR_max_bitrate_kbps;
109 | int VBR_hard_min; /* strictly enforce VBR_min_bitrate
110 | normaly, it will be violated for analog
111 | silence */
112 |
113 |
114 | /* resampling and filtering */
115 | int lowpassfreq; /* freq in Hz. 0=lame choses.
116 | -1=no filter */
117 | int highpassfreq; /* freq in Hz. 0=lame choses.
118 | -1=no filter */
119 | int lowpasswidth; /* freq width of filter, in Hz
120 | (default=15%) */
121 | int highpasswidth; /* freq width of filter, in Hz
122 | (default=15%) */
123 |
124 |
125 |
126 | /*
127 | * psycho acoustics and other arguments which you should not change
128 | * unless you know what you are doing
129 | */
130 | float maskingadjust;
131 | float maskingadjust_short;
132 | int ATHonly; /* only use ATH */
133 | int ATHshort; /* only use ATH for short blocks */
134 | int noATH; /* disable ATH */
135 | int ATHtype; /* select ATH formula */
136 | float ATHcurve; /* change ATH formula 4 shape */
137 | float ATH_lower_db; /* lower ATH by this many db */
138 | int athaa_type; /* select ATH auto-adjust scheme */
139 | float athaa_sensitivity; /* dB, tune active region of auto-level */
140 | short_block_t short_blocks;
141 | int useTemporal; /* use temporal masking effect */
142 | float interChRatio;
143 | float msfix; /* Naoki's adjustment of Mid/Side maskings */
144 |
145 | int tune; /* 0 off, 1 on */
146 | float tune_value_a; /* used to pass values for debugging and stuff */
147 |
148 | float attackthre; /* attack threshold for L/R/M channel */
149 | float attackthre_s; /* attack threshold for S channel */
150 |
151 |
152 | struct {
153 | void (*msgf) (const char *format, va_list ap);
154 | void (*debugf) (const char *format, va_list ap);
155 | void (*errorf) (const char *format, va_list ap);
156 | } report;
157 |
158 | /************************************************************************/
159 | /* internal variables, do not set... */
160 | /* provided because they may be of use to calling application */
161 | /************************************************************************/
162 |
163 | int lame_allocated_gfp; /* is this struct owned by calling
164 | program or lame? */
165 |
166 |
167 |
168 | /**************************************************************************/
169 | /* more internal variables are stored in this structure: */
170 | /**************************************************************************/
171 | lame_internal_flags *internal_flags;
172 |
173 |
174 | struct {
175 | int mmx;
176 | int amd3dnow;
177 | int sse;
178 |
179 | } asm_optimizations;
180 | };
181 |
182 | int is_lame_global_flags_valid(const lame_global_flags * gfp);
183 |
184 | #endif /* LAME_GLOBAL_FLAGS_H */
185 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/lameerror.h:
--------------------------------------------------------------------------------
1 | /*
2 | * A collection of LAME Error Codes
3 | *
4 | * Please use the constants defined here instead of some arbitrary
5 | * values. Currently the values starting at -10 to avoid intersection
6 | * with the -1, -2, -3 and -4 used in the current code.
7 | *
8 | * May be this should be a part of the include/lame.h.
9 | */
10 |
11 | typedef enum {
12 | LAME_OKAY = 0,
13 | LAME_NOERROR = 0,
14 | LAME_GENERICERROR = -1,
15 | LAME_NOMEM = -10,
16 | LAME_BADBITRATE = -11,
17 | LAME_BADSAMPFREQ = -12,
18 | LAME_INTERNALERROR = -13,
19 |
20 | FRONTEND_READERROR = -80,
21 | FRONTEND_WRITEERROR = -81,
22 | FRONTEND_FILETOOLARGE = -82,
23 |
24 | } lame_errorcodes_t;
25 |
26 | /* end of lameerror.h */
27 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/machine.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Machine dependent defines/includes for LAME.
3 | *
4 | * Copyright (c) 1999 A.L. Faber
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_MACHINE_H
23 | #define LAME_MACHINE_H
24 |
25 | #include "version.h"
26 |
27 | #include
28 | #include
29 |
30 | #ifdef STDC_HEADERS
31 | # include
32 | # include
33 | #else
34 | # ifndef HAVE_STRCHR
35 | # define strchr index
36 | # define strrchr rindex
37 | # endif
38 | char *strchr(), *strrchr();
39 | # ifndef HAVE_MEMCPY
40 | # define memcpy(d, s, n) bcopy ((s), (d), (n))
41 | # define memmove(d, s, n) bcopy ((s), (d), (n))
42 | # endif
43 | #endif
44 |
45 | #if defined(__riscos__) && defined(FPA10)
46 | # include "ymath.h"
47 | #else
48 | # include
49 | #endif
50 | #include
51 |
52 | #include
53 |
54 | #ifdef HAVE_ERRNO_H
55 | # include
56 | #endif
57 | #ifdef HAVE_FCNTL_H
58 | # include
59 | #endif
60 |
61 | #if defined(macintosh)
62 | # include
63 | # include
64 | #else
65 | # include
66 | # include
67 | #endif
68 |
69 | #ifdef HAVE_INTTYPES_H
70 | # include
71 | #else
72 | # ifdef HAVE_STDINT_H
73 | # include
74 | # endif
75 | #endif
76 |
77 | #ifdef WITH_DMALLOC
78 | #include
79 | #endif
80 |
81 | /*
82 | * 3 different types of pow() functions:
83 | * - table lookup
84 | * - pow()
85 | * - exp() on some machines this is claimed to be faster than pow()
86 | */
87 |
88 | #define POW20(x) (assert(0 <= (x+Q_MAX2) && x < Q_MAX), pow20[x+Q_MAX2])
89 | /*#define POW20(x) pow(2.0,((double)(x)-210)*.25) */
90 | /*#define POW20(x) exp( ((double)(x)-210)*(.25*LOG2) ) */
91 |
92 | #define IPOW20(x) (assert(0 <= x && x < Q_MAX), ipow20[x])
93 | /*#define IPOW20(x) exp( -((double)(x)-210)*.1875*LOG2 ) */
94 | /*#define IPOW20(x) pow(2.0,-((double)(x)-210)*.1875) */
95 |
96 | /* in case this is used without configure */
97 | #ifndef inline
98 | # define inline
99 | #endif
100 |
101 | #if defined(_MSC_VER)
102 | # undef inline
103 | # define inline _inline
104 | #elif defined(__SASC) || defined(__GNUC__) || defined(__ICC) || defined(__ECC)
105 | /* if __GNUC__ we always want to inline, not only if the user requests it */
106 | # undef inline
107 | # define inline __inline
108 | #endif
109 |
110 | #if defined(_MSC_VER)
111 | # pragma warning( disable : 4244 )
112 | /*# pragma warning( disable : 4305 ) */
113 | #endif
114 |
115 | /*
116 | * FLOAT for variables which require at least 32 bits
117 | * FLOAT8 for variables which require at least 64 bits
118 | *
119 | * On some machines, 64 bit will be faster than 32 bit. Also, some math
120 | * routines require 64 bit float, so setting FLOAT=float will result in a
121 | * lot of conversions.
122 | */
123 |
124 | #if ( defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__) )
125 | # define WIN32_LEAN_AND_MEAN
126 | # include
127 | # include
128 | # define FLOAT_MAX FLT_MAX
129 | #else
130 | # ifndef FLOAT
131 | typedef float FLOAT;
132 | # ifdef FLT_MAX
133 | # define FLOAT_MAX FLT_MAX
134 | # else
135 | # define FLOAT_MAX 1e37 /* approx */
136 | # endif
137 | # endif
138 | #endif
139 |
140 | #ifndef FLOAT8
141 | typedef double FLOAT8;
142 | # ifdef DBL_MAX
143 | # define FLOAT8_MAX DBL_MAX
144 | # else
145 | # define FLOAT8_MAX 1e99 /* approx */
146 | # endif
147 | #else
148 | # ifdef FLT_MAX
149 | # define FLOAT8_MAX FLT_MAX
150 | # else
151 | # define FLOAT8_MAX 1e37 /* approx */
152 | # endif
153 | #endif
154 |
155 | /* sample_t must be floating point, at least 32 bits */
156 | typedef FLOAT sample_t;
157 |
158 | #define dimension_of(array) (sizeof(array)/sizeof(array[0]))
159 | #define beyond(array) (array+dimension_of(array))
160 | #define compiletime_assert(expression) enum{static_assert_##FILE##_##LINE = 1/((expression)?1:0)}
161 | #define lame_calloc(TYPE, COUNT) ((TYPE*)calloc(COUNT, sizeof(TYPE)))
162 | #define multiple_of(CHUNK, COUNT) (\
163 | ( (COUNT) < 1 || (CHUNK) < 1 || (COUNT) % (CHUNK) == 0 ) \
164 | ? (COUNT) \
165 | : ((COUNT) + (CHUNK) - (COUNT) % (CHUNK)) \
166 | )
167 |
168 | #if 1
169 | #define EQ(a,b) (\
170 | (fabs(a) > fabs(b)) \
171 | ? (fabs((a)-(b)) <= (fabs(a) * 1e-6f)) \
172 | : (fabs((a)-(b)) <= (fabs(b) * 1e-6f)))
173 | #else
174 | #define EQ(a,b) (fabs((a)-(b))<1E-37)
175 | #endif
176 |
177 | #define NEQ(a,b) (!EQ(a,b))
178 |
179 | #ifdef _MSC_VER
180 | # if _MSC_VER < 1400
181 | # define fabsf fabs
182 | # define powf pow
183 | # define log10f log10
184 | # endif
185 | #endif
186 |
187 | #endif
188 |
189 | /* end of machine.h */
190 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/newmdct.h:
--------------------------------------------------------------------------------
1 | /*
2 | * New Modified DCT include file
3 | *
4 | * Copyright (c) 1999 Takehiro TOMINAGA
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_NEWMDCT_H
23 | #define LAME_NEWMDCT_H
24 |
25 | void mdct_sub48(lame_internal_flags * gfc, const sample_t * w0, const sample_t * w1);
26 |
27 | #endif /* LAME_NEWMDCT_H */
28 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/psymodel.h:
--------------------------------------------------------------------------------
1 | /*
2 | * psymodel.h
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_PSYMODEL_H
23 | #define LAME_PSYMODEL_H
24 |
25 |
26 | int L3psycho_anal_ns(lame_internal_flags * gfc,
27 | const sample_t *const buffer[2], int gr,
28 | III_psy_ratio ratio[2][2],
29 | III_psy_ratio MS_ratio[2][2],
30 | FLOAT pe[2], FLOAT pe_MS[2], FLOAT ener[2], int blocktype_d[2]);
31 |
32 | int L3psycho_anal_vbr(lame_internal_flags * gfc,
33 | const sample_t *const buffer[2], int gr,
34 | III_psy_ratio ratio[2][2],
35 | III_psy_ratio MS_ratio[2][2],
36 | FLOAT pe[2], FLOAT pe_MS[2], FLOAT ener[2], int blocktype_d[2]);
37 |
38 |
39 | int psymodel_init(lame_global_flags const* gfp);
40 |
41 |
42 | #define rpelev 2
43 | #define rpelev2 16
44 | #define rpelev_s 2
45 | #define rpelev2_s 16
46 |
47 | /* size of each partition band, in barks: */
48 | #define DELBARK .34
49 |
50 |
51 | /* tuned for output level (sensitive to energy scale) */
52 | #define VO_SCALE (1./( 14752*14752 )/(BLKSIZE/2))
53 |
54 | #define temporalmask_sustain_sec 0.01
55 |
56 | #define NS_PREECHO_ATT0 0.8
57 | #define NS_PREECHO_ATT1 0.6
58 | #define NS_PREECHO_ATT2 0.3
59 |
60 | #define NS_MSFIX 3.5
61 | #define NSATTACKTHRE 4.4
62 | #define NSATTACKTHRE_S 25
63 |
64 | #endif /* LAME_PSYMODEL_H */
65 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/quantize.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MP3 quantization
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_QUANTIZE_H
23 | #define LAME_QUANTIZE_H
24 |
25 | void CBR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2],
26 | const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]);
27 |
28 | void VBR_old_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2],
29 | const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]);
30 |
31 | void VBR_new_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2],
32 | const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]);
33 |
34 | void ABR_iteration_loop(lame_internal_flags * gfc, const FLOAT pe[2][2],
35 | const FLOAT ms_ratio[2], const III_psy_ratio ratio[2][2]);
36 |
37 |
38 | #endif /* LAME_QUANTIZE_H */
39 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/quantize_pvt.h:
--------------------------------------------------------------------------------
1 | /*
2 | * quantize_pvt include file
3 | *
4 | * Copyright (c) 1999 Takehiro TOMINAGA
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_QUANTIZE_PVT_H
23 | #define LAME_QUANTIZE_PVT_H
24 |
25 | #define IXMAX_VAL 8206 /* ix always <= 8191+15. see count_bits() */
26 |
27 | /* buggy Winamp decoder cannot handle values > 8191 */
28 | /* #define IXMAX_VAL 8191 */
29 |
30 | #define PRECALC_SIZE (IXMAX_VAL+2)
31 |
32 |
33 | extern const int nr_of_sfb_block[6][3][4];
34 | extern const int pretab[SBMAX_l];
35 | extern const int slen1_tab[16];
36 | extern const int slen2_tab[16];
37 |
38 | extern const scalefac_struct sfBandIndex[9];
39 |
40 | extern FLOAT pow43[PRECALC_SIZE];
41 | #ifdef TAKEHIRO_IEEE754_HACK
42 | extern FLOAT adj43asm[PRECALC_SIZE];
43 | #else
44 | extern FLOAT adj43[PRECALC_SIZE];
45 | #endif
46 |
47 | #define Q_MAX (256+1)
48 | #define Q_MAX2 116 /* minimum possible number of
49 | -cod_info->global_gain
50 | + ((scalefac[] + (cod_info->preflag ? pretab[sfb] : 0))
51 | << (cod_info->scalefac_scale + 1))
52 | + cod_info->subblock_gain[cod_info->window[sfb]] * 8;
53 |
54 | for long block, 0+((15+3)<<2) = 18*4 = 72
55 | for short block, 0+(15<<2)+7*8 = 15*4+56 = 116
56 | */
57 |
58 | extern FLOAT pow20[Q_MAX + Q_MAX2 + 1];
59 | extern FLOAT ipow20[Q_MAX];
60 |
61 | typedef struct calc_noise_result_t {
62 | FLOAT over_noise; /* sum of quantization noise > masking */
63 | FLOAT tot_noise; /* sum of all quantization noise */
64 | FLOAT max_noise; /* max quantization noise */
65 | int over_count; /* number of quantization noise > masking */
66 | int over_SSD; /* SSD-like cost of distorted bands */
67 | int bits;
68 | } calc_noise_result;
69 |
70 |
71 | /**
72 | * allows re-use of previously
73 | * computed noise values
74 | */
75 | typedef struct calc_noise_data_t {
76 | int global_gain;
77 | int sfb_count1;
78 | int step[39];
79 | FLOAT noise[39];
80 | FLOAT noise_log[39];
81 | } calc_noise_data;
82 |
83 |
84 | int on_pe(lame_internal_flags * gfc, const FLOAT pe[2][2],
85 | int targ_bits[2], int mean_bits, int gr, int cbr);
86 |
87 | void reduce_side(int targ_bits[2], FLOAT ms_ener_ratio, int mean_bits, int max_bits);
88 |
89 |
90 | void iteration_init(lame_internal_flags * gfc);
91 |
92 |
93 | int calc_xmin(lame_internal_flags const *gfc,
94 | III_psy_ratio const *const ratio, gr_info * const cod_info, FLOAT * l3_xmin);
95 |
96 | int calc_noise(const gr_info * const cod_info,
97 | const FLOAT * l3_xmin,
98 | FLOAT * distort, calc_noise_result * const res, calc_noise_data * prev_noise);
99 |
100 | void set_frame_pinfo(lame_internal_flags * gfc, const III_psy_ratio ratio[2][2]);
101 |
102 |
103 |
104 |
105 | /* takehiro.c */
106 |
107 | int count_bits(lame_internal_flags const *const gfc, const FLOAT * const xr,
108 | gr_info * const cod_info, calc_noise_data * prev_noise);
109 | int noquant_count_bits(lame_internal_flags const *const gfc,
110 | gr_info * const cod_info, calc_noise_data * prev_noise);
111 |
112 |
113 | void best_huffman_divide(const lame_internal_flags * const gfc, gr_info * const cod_info);
114 |
115 | void best_scalefac_store(const lame_internal_flags * gfc, const int gr, const int ch,
116 | III_side_info_t * const l3_side);
117 |
118 | int scale_bitcount(const lame_internal_flags * gfc, gr_info * cod_info);
119 |
120 | void huffman_init(lame_internal_flags * const gfc);
121 |
122 | void init_xrpow_core_init(lame_internal_flags * const gfc);
123 |
124 | FLOAT athAdjust(FLOAT a, FLOAT x, FLOAT athFloor, float ATHfixpoint);
125 |
126 | #define LARGE_BITS 100000
127 |
128 | #endif /* LAME_QUANTIZE_PVT_H */
129 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/reservoir.h:
--------------------------------------------------------------------------------
1 | /*
2 | * bit reservoir include file
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_RESERVOIR_H
23 | #define LAME_RESERVOIR_H
24 |
25 | int ResvFrameBegin(lame_internal_flags * gfc, int *mean_bits);
26 | void ResvMaxBits(lame_internal_flags * gfc, int mean_bits, int *targ_bits, int *max_bits,
27 | int cbr);
28 | void ResvAdjust(lame_internal_flags * gfc, gr_info const *gi);
29 | void ResvFrameEnd(lame_internal_flags * gfc, int mean_bits);
30 |
31 | #endif /* LAME_RESERVOIR_H */
32 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/set_get.h:
--------------------------------------------------------------------------------
1 | /*
2 | * set_get.h -- Internal set/get definitions
3 | *
4 | * Copyright (C) 2003 Gabriel Bouvigne / Lame project
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the Free Software
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifndef __SET_GET_H__
22 | #define __SET_GET_H__
23 |
24 |
25 | #if defined(__cplusplus)
26 | extern "C" {
27 | #endif
28 |
29 | /* select psychoacoustic model */
30 |
31 | /* manage short blocks */
32 | int CDECL lame_set_short_threshold(lame_global_flags *, float, float);
33 | int CDECL lame_set_short_threshold_lrm(lame_global_flags *, float);
34 | float CDECL lame_get_short_threshold_lrm(const lame_global_flags *);
35 | int CDECL lame_set_short_threshold_s(lame_global_flags *, float);
36 | float CDECL lame_get_short_threshold_s(const lame_global_flags *);
37 |
38 |
39 | int CDECL lame_set_maskingadjust(lame_global_flags *, float);
40 | float CDECL lame_get_maskingadjust(const lame_global_flags *);
41 |
42 | int CDECL lame_set_maskingadjust_short(lame_global_flags *, float);
43 | float CDECL lame_get_maskingadjust_short(const lame_global_flags *);
44 |
45 | /* select ATH formula 4 shape */
46 | int CDECL lame_set_ATHcurve(lame_global_flags *, float);
47 | float CDECL lame_get_ATHcurve(const lame_global_flags *);
48 |
49 | int CDECL lame_set_preset_notune(lame_global_flags *, int);
50 |
51 | /* substep shaping method */
52 | int CDECL lame_set_substep(lame_global_flags *, int);
53 | int CDECL lame_get_substep(const lame_global_flags *);
54 |
55 | /* scalefactors scale */
56 | int CDECL lame_set_sfscale(lame_global_flags *, int);
57 | int CDECL lame_get_sfscale(const lame_global_flags *);
58 |
59 | /* subblock gain */
60 | int CDECL lame_set_subblock_gain(lame_global_flags *, int);
61 | int CDECL lame_get_subblock_gain(const lame_global_flags *);
62 |
63 |
64 |
65 | /*presets*/
66 | int apply_preset(lame_global_flags *, int preset, int enforce);
67 |
68 | void CDECL lame_set_tune(lame_t, float); /* FOR INTERNAL USE ONLY */
69 | void CDECL lame_set_msfix(lame_t gfp, double msfix);
70 |
71 |
72 | #if defined(__cplusplus)
73 | }
74 | #endif
75 | #endif
76 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/tables.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MPEG layer 3 tables include file
3 | *
4 | * Copyright (c) 1999 Albert L Faber
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_TABLES_H
23 | #define LAME_TABLES_H
24 |
25 | #if 0
26 | typedef struct {
27 | unsigned char no;
28 | unsigned char width;
29 | unsigned char minval_2;
30 | float quiet_thr;
31 | float norm;
32 | float bark;
33 | } type1_t;
34 |
35 | typedef struct {
36 | unsigned char no;
37 | unsigned char width;
38 | float quiet_thr;
39 | float norm;
40 | float SNR;
41 | float bark;
42 | } type2_t;
43 |
44 | typedef struct {
45 | unsigned int no:5;
46 | unsigned int cbw:3;
47 | unsigned int bu:6;
48 | unsigned int bo:6;
49 | unsigned int w1_576:10;
50 | unsigned int w2_576:10;
51 | } type34_t;
52 |
53 | typedef struct {
54 | size_t len1;
55 | const type1_t *const tab1;
56 | size_t len2;
57 | const type2_t *const tab2;
58 | size_t len3;
59 | const type34_t *const tab3;
60 | size_t len4;
61 | const type34_t *const tab4;
62 | } type5_t;
63 |
64 | extern const type5_t table5[6];
65 |
66 | #endif
67 |
68 | #define HTN 34
69 |
70 | struct huffcodetab {
71 | const unsigned int xlen; /* max. x-index+ */
72 | const unsigned int linmax; /* max number to be stored in linbits */
73 | const uint16_t *table; /* pointer to array[xlen][ylen] */
74 | const uint8_t *hlen; /* pointer to array[xlen][ylen] */
75 | };
76 |
77 | extern const struct huffcodetab ht[HTN];
78 | /* global memory block */
79 | /* array of all huffcodtable headers */
80 | /* 0..31 Huffman code table 0..31 */
81 | /* 32,33 count1-tables */
82 |
83 | extern const uint8_t t32l[];
84 | extern const uint8_t t33l[];
85 |
86 | extern const uint32_t largetbl[16 * 16];
87 | extern const uint32_t table23[3 * 3];
88 | extern const uint32_t table56[4 * 4];
89 |
90 | extern const int scfsi_band[5];
91 |
92 | extern const int bitrate_table [3][16];
93 | extern const int samplerate_table [3][ 4];
94 |
95 | #endif /* LAME_TABLES_H */
96 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/vbrquantize.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MP3 VBR quantization
3 | *
4 | * Copyright (c) 1999 Mark Taylor
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_VBRQUANTIZE_H
23 | #define LAME_VBRQUANTIZE_H
24 |
25 | int VBR_encode_frame(lame_internal_flags * gfc, const FLOAT xr34orig[2][2][576],
26 | const FLOAT l3_xmin[2][2][SFBMAX], const int maxbits[2][2]);
27 |
28 | #endif /* LAME_VBRQUANTIZE_H */
29 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/version.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Version numbering for LAME.
3 | *
4 | * Copyright (c) 1999 A.L. Faber
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | /*!
23 | \file version.c
24 | \brief Version numbering for LAME.
25 |
26 | Contains functions which describe the version of LAME.
27 |
28 | \author A.L. Faber
29 | \version \$Id: version.c,v 1.34 2011/11/18 09:51:02 robert Exp $
30 | \ingroup libmp3lame
31 | */
32 |
33 |
34 | #ifdef HAVE_CONFIG_H
35 | # include
36 | #endif
37 |
38 |
39 | #include "lame.h"
40 | #include "machine.h"
41 |
42 | #include "version.h" /* macros of version numbers */
43 |
44 |
45 |
46 |
47 |
48 | /*! Get the LAME version string. */
49 | /*!
50 | \param void
51 | \return a pointer to a string which describes the version of LAME.
52 | */
53 | const char *
54 | get_lame_version(void)
55 | { /* primary to write screen reports */
56 | /* Here we can also add informations about compile time configurations */
57 |
58 | #if LAME_ALPHA_VERSION
59 | static /*@observer@ */ const char *const str =
60 | STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " "
61 | "(alpha " STR(LAME_PATCH_VERSION) ", " __DATE__ " " __TIME__ ")";
62 | #elif LAME_BETA_VERSION
63 | static /*@observer@ */ const char *const str =
64 | STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " "
65 | "(beta " STR(LAME_PATCH_VERSION) ", " __DATE__ ")";
66 | #elif LAME_RELEASE_VERSION && (LAME_PATCH_VERSION > 0)
67 | static /*@observer@ */ const char *const str =
68 | STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) "." STR(LAME_PATCH_VERSION);
69 | #else
70 | static /*@observer@ */ const char *const str =
71 | STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION);
72 | #endif
73 |
74 | return str;
75 | }
76 |
77 |
78 | /*! Get the short LAME version string. */
79 | /*!
80 | It's mainly for inclusion into the MP3 stream.
81 |
82 | \param void
83 | \return a pointer to the short version of the LAME version string.
84 | */
85 | const char *
86 | get_lame_short_version(void)
87 | {
88 | /* adding date and time to version string makes it harder for output
89 | validation */
90 |
91 | #if LAME_ALPHA_VERSION
92 | static /*@observer@ */ const char *const str =
93 | STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " (alpha " STR(LAME_PATCH_VERSION) ")";
94 | #elif LAME_BETA_VERSION
95 | static /*@observer@ */ const char *const str =
96 | STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) " (beta " STR(LAME_PATCH_VERSION) ")";
97 | #elif LAME_RELEASE_VERSION && (LAME_PATCH_VERSION > 0)
98 | static /*@observer@ */ const char *const str =
99 | STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) "." STR(LAME_PATCH_VERSION);
100 | #else
101 | static /*@observer@ */ const char *const str =
102 | STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION);
103 | #endif
104 |
105 | return str;
106 | }
107 |
108 | /*! Get the _very_ short LAME version string. */
109 | /*!
110 | It's used in the LAME VBR tag only.
111 |
112 | \param void
113 | \return a pointer to the short version of the LAME version string.
114 | */
115 | const char *
116 | get_lame_very_short_version(void)
117 | {
118 | /* adding date and time to version string makes it harder for output
119 | validation */
120 | #if LAME_ALPHA_VERSION
121 | #define P "a"
122 | #elif LAME_BETA_VERSION
123 | #define P "b"
124 | #elif LAME_RELEASE_VERSION && (LAME_PATCH_VERSION > 0)
125 | #define P "r"
126 | #else
127 | #define P " "
128 | #endif
129 | static /*@observer@ */ const char *const str =
130 | #if (LAME_PATCH_VERSION > 0)
131 | "LAME" STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) P STR(LAME_PATCH_VERSION)
132 | #else
133 | "LAME" STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) P
134 | #endif
135 | ;
136 | return str;
137 | }
138 |
139 | /*! Get the _very_ short LAME version string. */
140 | /*!
141 | It's used in the LAME VBR tag only, limited to 9 characters max.
142 | Due to some 3rd party HW/SW decoders, it has to start with LAME.
143 |
144 | \param void
145 | \return a pointer to the short version of the LAME version string.
146 | */
147 | const char*
148 | get_lame_tag_encoder_short_version(void)
149 | {
150 | static /*@observer@ */ const char *const str =
151 | /* FIXME: new scheme / new version counting / drop versioning here ? */
152 | "LAME" STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) P
153 | ;
154 | return str;
155 | }
156 |
157 | /*! Get the version string for GPSYCHO. */
158 | /*!
159 | \param void
160 | \return a pointer to a string which describes the version of GPSYCHO.
161 | */
162 | const char *
163 | get_psy_version(void)
164 | {
165 | #if PSY_ALPHA_VERSION > 0
166 | static /*@observer@ */ const char *const str =
167 | STR(PSY_MAJOR_VERSION) "." STR(PSY_MINOR_VERSION)
168 | " (alpha " STR(PSY_ALPHA_VERSION) ", " __DATE__ " " __TIME__ ")";
169 | #elif PSY_BETA_VERSION > 0
170 | static /*@observer@ */ const char *const str =
171 | STR(PSY_MAJOR_VERSION) "." STR(PSY_MINOR_VERSION)
172 | " (beta " STR(PSY_BETA_VERSION) ", " __DATE__ ")";
173 | #else
174 | static /*@observer@ */ const char *const str =
175 | STR(PSY_MAJOR_VERSION) "." STR(PSY_MINOR_VERSION);
176 | #endif
177 |
178 | return str;
179 | }
180 |
181 |
182 | /*! Get the URL for the LAME website. */
183 | /*!
184 | \param void
185 | \return a pointer to a string which is a URL for the LAME website.
186 | */
187 | const char *
188 | get_lame_url(void)
189 | {
190 | static /*@observer@ */ const char *const str = LAME_URL;
191 |
192 | return str;
193 | }
194 |
195 |
196 | /*! Get the numerical representation of the version. */
197 | /*!
198 | Writes the numerical representation of the version of LAME and
199 | GPSYCHO into lvp.
200 |
201 | \param lvp
202 | */
203 | void
204 | get_lame_version_numerical(lame_version_t * lvp)
205 | {
206 | static /*@observer@ */ const char *const features = ""; /* obsolete */
207 |
208 | /* generic version */
209 | lvp->major = LAME_MAJOR_VERSION;
210 | lvp->minor = LAME_MINOR_VERSION;
211 | #if LAME_ALPHA_VERSION
212 | lvp->alpha = LAME_PATCH_VERSION;
213 | lvp->beta = 0;
214 | #elif LAME_BETA_VERSION
215 | lvp->alpha = 0;
216 | lvp->beta = LAME_PATCH_VERSION;
217 | #else
218 | lvp->alpha = 0;
219 | lvp->beta = 0;
220 | #endif
221 |
222 | /* psy version */
223 | lvp->psy_major = PSY_MAJOR_VERSION;
224 | lvp->psy_minor = PSY_MINOR_VERSION;
225 | lvp->psy_alpha = PSY_ALPHA_VERSION;
226 | lvp->psy_beta = PSY_BETA_VERSION;
227 |
228 | /* compile time features */
229 | /*@-mustfree@ */
230 | lvp->features = features;
231 | /*@=mustfree@ */
232 | }
233 |
234 |
235 | const char *
236 | get_lame_os_bitness(void)
237 | {
238 | static /*@observer@ */ const char *const strXX = "";
239 | static /*@observer@ */ const char *const str32 = "32bits";
240 | static /*@observer@ */ const char *const str64 = "64bits";
241 |
242 | switch (sizeof(void *)) {
243 | case 4:
244 | return str32;
245 |
246 | case 8:
247 | return str64;
248 |
249 | default:
250 | return strXX;
251 | }
252 | }
253 |
254 | /* end of version.c */
255 |
--------------------------------------------------------------------------------
/recorderlib/src/main/jni/lame-3.100_libmp3lame/version.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Version numbering for LAME.
3 | *
4 | * Copyright (c) 1999 A.L. Faber
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Library General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Library General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Library General Public
17 | * License along with this library; if not, write to the
18 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 | * Boston, MA 02111-1307, USA.
20 | */
21 |
22 | #ifndef LAME_VERSION_H
23 | #define LAME_VERSION_H
24 |
25 |
26 | /*
27 | * To make a string from a token, use the # operator:
28 | */
29 | #ifndef STR
30 | # define __STR(x) #x
31 | # define STR(x) __STR(x)
32 | #endif
33 |
34 | # define LAME_URL "http://lame.sf.net"
35 |
36 |
37 | # define LAME_MAJOR_VERSION 3 /* Major version number */
38 | # define LAME_MINOR_VERSION 100 /* Minor version number */
39 | # define LAME_TYPE_VERSION 2 /* 0:alpha 1:beta 2:release */
40 | # define LAME_PATCH_VERSION 0 /* Patch level */
41 | # define LAME_ALPHA_VERSION (LAME_TYPE_VERSION==0)
42 | # define LAME_BETA_VERSION (LAME_TYPE_VERSION==1)
43 | # define LAME_RELEASE_VERSION (LAME_TYPE_VERSION==2)
44 |
45 | # define PSY_MAJOR_VERSION 1 /* Major version number */
46 | # define PSY_MINOR_VERSION 0 /* Minor version number */
47 | # define PSY_ALPHA_VERSION 0 /* Set number if this is an alpha version, otherwise zero */
48 | # define PSY_BETA_VERSION 0 /* Set number if this is a beta version, otherwise zero */
49 |
50 | #if LAME_ALPHA_VERSION
51 | #define LAME_PATCH_LEVEL_STRING " alpha " STR(LAME_PATCH_VERSION)
52 | #endif
53 | #if LAME_BETA_VERSION
54 | #define LAME_PATCH_LEVEL_STRING " beta " STR(LAME_PATCH_VERSION)
55 | #endif
56 | #if LAME_RELEASE_VERSION
57 | #if LAME_PATCH_VERSION
58 | #define LAME_PATCH_LEVEL_STRING " release " STR(LAME_PATCH_VERSION)
59 | #else
60 | #define LAME_PATCH_LEVEL_STRING ""
61 | #endif
62 | #endif
63 |
64 | # define LAME_VERSION_STRING STR(LAME_MAJOR_VERSION) "." STR(LAME_MINOR_VERSION) LAME_PATCH_LEVEL_STRING
65 |
66 | #endif /* LAME_VERSION_H */
67 |
68 | /* End of version.h */
69 |
--------------------------------------------------------------------------------
/recorderlib/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | recorderlib
3 |
4 |
--------------------------------------------------------------------------------
/recorderlib/src/test/java/com/zlw/main/recorderlib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.zlw.main.recorderlib;
2 |
3 | /**
4 | * Example local unit test, which will execute on the development machine (host).
5 | *
6 | * @see Testing documentation
7 | */
8 | public class ExampleUnitTest {
9 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | gradlePluginPortal()
6 | }
7 | }
8 | dependencyResolutionManagement {
9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10 | repositories {
11 | maven { url 'https://www.jitpack.io' }
12 | maven { url 'https://maven.aliyun.com/repository/public' }
13 | maven { url 'https://maven.aliyun.com/repository/google' }
14 | google()
15 | mavenCentral()
16 | }
17 | }
18 |
19 | rootProject.name = "ZlwAudioRecorder"
20 | include ':app', ':recorderlib'
21 |
--------------------------------------------------------------------------------