Skip to content

Commit

Permalink
增加设置录音是否为wav格式的功能 默认为true 增加英文readme
Browse files Browse the repository at this point in the history
  • Loading branch information
ideastudios committed May 14, 2019
1 parent 8831fdf commit e68caef
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 44 deletions.
3 changes: 3 additions & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# IdealRecorder
an ideal WAV PCM recorder library for Android
an ideal WAV PCM recorder library for Android
## [English ](https://github.com/Jay-Goo/WaveLineView)

安卓上录制 WAV 或者PCM语音的库, 支持音量、录音数据、录音状态、文件路径回调



## [README of English][README_EN]
## 效果图
<img src="gif/screenrecorder.gif"/>

Expand Down
102 changes: 102 additions & 0 deletions README_EN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# IdealRecorder
an ideal WAV PCM recorder library for Android

Record WAV or PCM voice library on Android, support volume, recording data, recording status, file path callback

## [README of Chinese][README]

## GIF
<img src="gif/screenrecorder.gif"/>

## feature

- Customizable recording parameters (sampling rate, number of bits, single and dual channel)
- Easy to use, call start to start recording, call stop to stop recording.
- Support for setting the maximum recording voice duration. It will automatically stop when maximum duration comes.
- Support saving WAV files when you set the save path.
- You can set the volume callback interval duration, support return buffer data when recording.
- Callback when no record permission



## Initialization

Add code in the Application or Activity onCreate () method,pass context

```java
IdealRecorder.getInstance().init(this);
```



## How to use

Start recording
```java
idealRecorder = IdealRecorder.getInstance();

idealRecorder.setRecordFilePath(getSaveFilePath());
//If you need to save the recording file, set the path and save it automatically.
//you can save it on you own by getting data in onRecordData callback

idealRecorder.setRecordConfig(recordConfig).setMaxRecordTime(20000).setVolumeInterval(200);

idealRecorder.setStatusListener(statusListener);
//set listener

idealRecorder.start();
//start record
```


setRecordFilePath path should be absolutePath

recordConfig look IdealRecorder.RecordConfig class


Please refer to the demo code .


Stop recording
```java

idealRecorder.stop();

```





## Note

- The project manifest has declared the RECORD_AUDIO and WRITE_EXTERNAL_STORAGE permission .However, after Android 6.0, you still need to request permission on you own.


## Gradle
[![](https://www.jitpack.io/v/ideastudios/IdealRecorder.svg)](https://www.jitpack.io/#ideastudios/IdealRecorder)
1. Add it in your root build.gradle at the end of repositories:
```
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
```

2. Add the dependency
```
dependencies {
implementation'com.github.ideastudios:IdealRecorder:2.0.1'
}
```


## Thanks

WaveLineView[Jay-Goo/WaveLineView](https://github.com/Jay-Goo/WaveLineView)
AndPermission[yanzhenjie/AndPermission](https://github.com/yanzhenjie/AndPermission)

2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ dependencies {
testCompile 'junit:junit:4.12'
compile 'com.yanzhenjie:permission:1.1.0'
compile 'com.github.Jay-Goo:WaveLineView:v1.0.3'
compile 'com.github.ideastudios:IdealRecorder:2.0.2'
compile 'com.github.ideastudios:IdealRecorder:2.0.3'
}
11 changes: 4 additions & 7 deletions app/src/main/java/tech/oom/idealrecorderdemo/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,9 @@ public class MainActivity extends AppCompatActivity {
private WaveView waveView;
private WaveLineView waveLineView;
private TextView tips;
/**
* IdealRecorder的实例
*/

private IdealRecorder idealRecorder;
/**
* Recorder的配置信息 采样率 采样位数
*/

private IdealRecorder.RecordConfig recordConfig;

private RationaleListener rationaleListener = new RationaleListener() {
Expand Down Expand Up @@ -158,7 +154,7 @@ public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
recordConfig = new IdealRecorder.RecordConfig(MediaRecorder.AudioSource.MIC, IdealRecorder.RecordConfig.SAMPLE_RATE_22K_HZ, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
recordConfig = new IdealRecorder.RecordConfig(MediaRecorder.AudioSource.MIC, 48000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);

}

Expand All @@ -180,6 +176,7 @@ private void readyRecord() {
private void record() {
//如果需要保存录音文件 设置好保存路径就会自动保存 也可以通过onRecordData 回调自己保存 不设置 不会保存录音
idealRecorder.setRecordFilePath(getSaveFilePath());
// idealRecorder.setWavFormat(false);
//设置录音配置 最长录音时长 以及音量回调的时间间隔
idealRecorder.setRecordConfig(recordConfig).setMaxRecordTime(20000).setVolumeInterval(200);
//设置录音时各种状态的监听
Expand Down
8 changes: 8 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
buildscript {
repositories {
jcenter()
maven {
url 'https://maven.google.com/'
name 'Google'
}
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
Expand All @@ -16,6 +20,10 @@ allprojects {
repositories {
jcenter()
maven { url 'https://jitpack.io' }
maven {
url 'https://maven.google.com/'
name 'Google'
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ dependencies {
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.+'
compile 'com.android.support:appcompat-v7:26.0.0'
testCompile 'junit:junit:4.12'
}
14 changes: 13 additions & 1 deletion library/src/main/java/tech/oom/idealrecorder/IdealRecorder.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
Expand Down Expand Up @@ -116,7 +117,7 @@ public IdealRecorder setVolumeInterval(long intervalMillis) {
*/
public IdealRecorder setRecordFilePath(String path) {
if (!TextUtils.isEmpty(path) && audioFileHelper != null) {
if (!isWriteExternalStoragePermissionGranted()) {
if (path.startsWith(Environment.getExternalStorageDirectory().getAbsolutePath()) && !isWriteExternalStoragePermissionGranted()) {
Log.e(TAG, "set recorder file path failed,because no WRITE_EXTERNAL_STORAGE permission was granted");

return this;
Expand All @@ -130,6 +131,17 @@ public IdealRecorder setRecordFilePath(String path) {
return this;
}

/**
* 设置录音保存的格式是否为wav 默认保存为wav格式 true 保存为wav格式 false 文件保存问pcm格式
*
* @param isWav 是否为wav格式 默认为true 保存为wav格式 ;false 文件保存问pcm格式
* @return
*/
public IdealRecorder setWavFormat(boolean isWav) {
audioFileHelper.setWav(isWav);
return this;
}

/**
* 设置录音时各种状态的监听
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class AudioFileHelper {
private RandomAccessFile randomAccessFile;
private File targetFile;
private IdealRecorder.RecordConfig config;
private boolean isWav = true;

public AudioFileHelper(AudioFileListener listener) {
this.listener = listener;
Expand All @@ -36,6 +37,9 @@ public void setRecorderConfig(IdealRecorder.RecordConfig config) {
this.config = config;
}

public void setWav(boolean wav) {
this.isWav = wav;
}

public void start() {
try {
Expand Down Expand Up @@ -81,11 +85,11 @@ public void finish() {

private void open(String path) throws IOException {
if (TextUtils.isEmpty(path)) {
Log.d(TAG,"Path not set , data will not save");
Log.d(TAG, "Path not set , data will not save");
return;
}
if(this.config == null){
Log.d(TAG,"RecordConfig not set , data will not save");
if (this.config == null) {
Log.d(TAG, "RecordConfig not set , data will not save");
return;
}
targetFile = new File(path);
Expand Down Expand Up @@ -115,29 +119,32 @@ private void open(String path) throws IOException {
sRate = config.getSampleRate();
randomAccessFile = new RandomAccessFile(targetFile, "rw");
randomAccessFile.setLength(0);
// Set file length to
// 0, to prevent unexpected behavior in case the file already existed
// 16K、16bit、单声道
/* RIFF header */
randomAccessFile.writeBytes("RIFF"); // riff id
randomAccessFile.writeInt(0); // riff chunk size *PLACEHOLDER*
randomAccessFile.writeBytes("WAVE"); // wave type

/* fmt chunk */
randomAccessFile.writeBytes("fmt "); // fmt id
randomAccessFile.writeInt(Integer.reverseBytes(16)); // fmt chunk size
randomAccessFile.writeShort(Short.reverseBytes((short) 1)); // AudioFormat,1 for PCM
randomAccessFile.writeShort(Short.reverseBytes(nChannels));// Number of channels, 1 for mono, 2 for stereo
randomAccessFile.writeInt(Integer.reverseBytes(sRate)); // Sample rate
randomAccessFile.writeInt(Integer.reverseBytes(sRate * bSamples * nChannels / 8)); // Byte rate,SampleRate*NumberOfChannels*BitsPerSample/8
randomAccessFile.writeShort(Short.reverseBytes((short) (nChannels * bSamples / 8))); // Block align, NumberOfChannels*BitsPerSample/8
randomAccessFile.writeShort(Short.reverseBytes(bSamples)); // Bits per sample

/* data chunk */
randomAccessFile.writeBytes("data"); // data id
randomAccessFile.writeInt(0); // data chunk size *PLACEHOLDER*

Log.d(TAG, "wav path: " + path);
if (isWav) {
// Set file length to
// 0, to prevent unexpected behavior in case the file already existed
// 16K、16bit、单声道
/* RIFF header */
randomAccessFile.writeBytes("RIFF"); // riff id
randomAccessFile.writeInt(0); // riff chunk size *PLACEHOLDER*
randomAccessFile.writeBytes("WAVE"); // wave type

/* fmt chunk */
randomAccessFile.writeBytes("fmt "); // fmt id
randomAccessFile.writeInt(Integer.reverseBytes(16)); // fmt chunk size
randomAccessFile.writeShort(Short.reverseBytes((short) 1)); // AudioFormat,1 for PCM
randomAccessFile.writeShort(Short.reverseBytes(nChannels));// Number of channels, 1 for mono, 2 for stereo
randomAccessFile.writeInt(Integer.reverseBytes(sRate)); // Sample rate
randomAccessFile.writeInt(Integer.reverseBytes(sRate * bSamples * nChannels / 8)); // Byte rate,SampleRate*NumberOfChannels*BitsPerSample/8
randomAccessFile.writeShort(Short.reverseBytes((short) (nChannels * bSamples / 8))); // Block align, NumberOfChannels*BitsPerSample/8
randomAccessFile.writeShort(Short.reverseBytes(bSamples)); // Bits per sample

/* data chunk */
randomAccessFile.writeBytes("data"); // data id
randomAccessFile.writeInt(0); // data chunk size *PLACEHOLDER*
}


Log.d(TAG, "saved file path: " + path);

}

Expand All @@ -154,12 +161,14 @@ private void close() throws IOException {
}
return;
}
randomAccessFile.seek(4); // riff chunk size
randomAccessFile.writeInt(Integer.reverseBytes((int) (randomAccessFile.length() - 8)));
randomAccessFile.seek(40); // data chunk size
randomAccessFile.writeInt(Integer.reverseBytes((int) (randomAccessFile.length() - 44)));
if (isWav) {
randomAccessFile.seek(4); // riff chunk size
randomAccessFile.writeInt(Integer.reverseBytes((int) (randomAccessFile.length() - 8)));
randomAccessFile.seek(40); // data chunk size
randomAccessFile.writeInt(Integer.reverseBytes((int) (randomAccessFile.length() - 44)));
}

Log.d(TAG, "wav size: " + randomAccessFile.length());
Log.d(TAG, "file size: " + randomAccessFile.length());
if (listener != null) {
listener.onSuccess(savePath);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


public class Recorder {
public static final int TIMER_INTERVAL = 100;
public static final int TIMER_INTERVAL = 20;
private static final String TAG = "Recorder";
private IdealRecorder.RecordConfig recordConfig;
private AudioRecord mAudioRecorder = null;
Expand Down

0 comments on commit e68caef

Please sign in to comment.