Skip to content

Commit

Permalink
📝 整理一下文档代码
Browse files Browse the repository at this point in the history
  • Loading branch information
SheTieJun committed Dec 18, 2024
1 parent 3f8c418 commit d7895b2
Show file tree
Hide file tree
Showing 19 changed files with 57 additions and 238 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ abstract class BaseRecorder {
* Mute record
* 静音录制:录制进行,但是录制的声音是静音的,使用场景是用于和其他音视频进行拼接
*/
open fun muteRecord(mute: Boolean)
open fun muteRecord(mute: Boolean) {/*...*/}

//设计背景音乐的url,本地的(网络的可能造成卡死)
abstract fun setBackgroundMusic(url: String): BaseRecorder
Expand Down
19 changes: 6 additions & 13 deletions app/src/main/java/me/shetj/mp3recorder/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ import kotlinx.coroutines.launch
import me.shetj.base.BaseKit
import me.shetj.base.fix.FixPermission
import me.shetj.base.ktx.setAppearance
import me.shetj.base.ktx.start
import me.shetj.base.mvvm.viewbind.BaseBindingActivity
import me.shetj.base.mvvm.viewbind.BaseViewModel
import me.shetj.mp3recorder.databinding.ActivityMainTestBinding
import me.shetj.mp3recorder.record.activity.mix.RecordActivity
import me.shetj.mp3recorder.record.utils.AudioManagerX
import me.shetj.recorder.core.AudioUtils

class MainActivity : BaseBindingActivity<ActivityMainTestBinding, BaseViewModel>() {
private var splashScreen: SplashScreen? =null
Expand Down Expand Up @@ -67,28 +67,21 @@ class MainActivity : BaseBindingActivity<ActivityMainTestBinding, BaseViewModel>
}

val audioManagerX = AudioManagerX(this)
val bestSampleRate = AudioUtils.getBestSampleRate(this@MainActivity)
mBinding.msg.apply {
text = audioManagerX.checkDevice()
append("\n\n\n获取当前手机录音最佳参数:")
append("\n最佳采样率:${getBestSampleRate()}\n")
append("\n录音最小缓存大小(${getBestSampleRate()},1,${AudioFormat.ENCODING_PCM_16BIT}):${AudioRecord.getMinBufferSize(
getBestSampleRate(),
append("\n最佳采样率:${bestSampleRate}\n")
append("\n录音最小缓存大小($bestSampleRate,1,${AudioFormat.ENCODING_PCM_16BIT}):${AudioRecord.getMinBufferSize(
bestSampleRate,
1, AudioFormat.ENCODING_PCM_16BIT
)}\n")
append("音频输出的缓冲:${getBestBufferSize()}\n")
}

}

//获取最佳采样率
private fun getBestSampleRate(): Int {
val am = BaseKit.app.getSystemService(Context.AUDIO_SERVICE) as? AudioManager
val sampleRateStr: String? = am?.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)
val sampleRate: Int = sampleRateStr?.let { str ->
Integer.parseInt(str).takeUnless { it == 0 }
} ?: 44100 // Use a default value if property not found
return sampleRate
}


//
private fun getBestBufferSize(): Int {
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/me/shetj/mp3recorder/Recorder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ fun mp3Recorder(
samplingRate: Int = 44100,
mp3BitRate: Int = 64,//96(高),32(低)
mp3Quality: Int = 1,
@Channel channel: Int = 2,
channel: Int = 2,
permissionListener: PermissionListener? = null,
recordListener: RecordListener? = null,
): BaseRecorder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ open class RecordPage(

override fun onMuteRecordChange(mute: Boolean) {
super.onMuteRecordChange(mute)
binding.muteAudio.text = if (mute) "已静音" else "开启禁音"
binding.muteAudio.text = if (mute) "已静音录制" else "开启静音录制"
}

override fun onMaxChange(time: Long) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ object MediaRecorderKit {
mMediaRecorder!!.setMaxFileSize(10*1024*1024)
savePath = EnvironmentStorage.getPath(packagePath = "record") + "/" + System.currentTimeMillis() + ".m4a"
mMediaRecorder!!.setOutputFile(savePath)
val nextSavePath = File(EnvironmentStorage.getPath(packagePath = "record") + "/" + System.currentTimeMillis() + ".m4a")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mMediaRecorder!!.setNextOutputFile(nextSavePath)
}
/* ③准备 */
mMediaRecorder!!.prepare()
/* ④开始 */
Expand All @@ -59,6 +55,13 @@ object MediaRecorderKit {
}
}

fun setNextSavePath(){
val nextSavePath = File(EnvironmentStorage.getPath(packagePath = "record") + "/" + System.currentTimeMillis() + ".m4a")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mMediaRecorder!!.setNextOutputFile(nextSavePath)
}
}

fun pause(){
mMediaRecorder?.pause()
}
Expand Down
65 changes: 0 additions & 65 deletions app/src/main/res/layout/activity_mix_record.xml

This file was deleted.

2 changes: 1 addition & 1 deletion app/src/main/res/layout/page_record_mix.xml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
android:padding="15dp"
android:layout_above="@id/rl_record_view"
android:background="@drawable/bg_record_add_music"
android:text="开启静音"/>
android:text="开启静音录制"/>

<LinearLayout
android:id="@+id/ll_add_music"
Expand Down
8 changes: 5 additions & 3 deletions doc/MediaRecorder.MD
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
## MediaRecorder介绍

我自己做过录音功能,用的AudioRecord,因为以前MediaRecorder不支持暂停和恢复录制,现在MediaRecorder也支持暂停和恢复录制了,部分场景下使用MediaRecorder更加方便。
7.0之后的版本MediaRecorder也支持暂停和恢复录制了,部分场景下使用MediaRecorder更加方便。

当然AudioRecord也有自己的优势,录制过程可以处理PCM,可以做混音,降噪等等。

现在Android版本分布在7.0以上占96%,8.0以上占93%,所以我们可以放心的使用MediaRecorder。~前提是你说法产品,哈哈
现在Android版本分布在7.0以上占96%,8.0以上占93%,所以我们可以放心的使用MediaRecorder。~前提是你**说服**产品,哈哈

## 方法介绍

Expand Down Expand Up @@ -57,4 +57,6 @@

## 总结
1. 7.0之后的版本,`pause()``resume()`方法可以用来暂停和恢复录制。
2. 8.0之后的版本,`setNextOutputFile(File file)`方法可以在当前输出文件达到最大大小或最大持续时间时,录制将继续到下一个文件。应用场景:每60秒发送一个音频。
2. 8.0之后的版本,`setNextOutputFile(File file)`方法可以在当前输出文件达到最大大小或最大持续时间时,录制将继续到下一个文件。应用场景:每60秒发送一个音频。

当然我的这个lib,也都支持上面的功能
12 changes: 12 additions & 0 deletions recorder-core/src/main/java/me/shetj/recorder/core/AudioUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
package me.shetj.recorder.core

import android.content.Context
import android.media.AudioManager
import android.media.MediaExtractor
import android.media.MediaFormat
import android.net.Uri
Expand Down Expand Up @@ -53,7 +54,18 @@ object AudioUtils {
}
}


fun getAudioChannel(context: Context, url: Uri): Int {
return getAudioFormat(context, url).getInteger(MediaFormat.KEY_CHANNEL_COUNT)
}

//获取最佳采样率
fun getBestSampleRate(context: Context): Int {
val am = context.getSystemService(Context.AUDIO_SERVICE) as? AudioManager
val sampleRateStr: String? = am?.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)
val sampleRate: Int = sampleRateStr?.let { str ->
Integer.parseInt(str).takeUnless { it == 0 }
} ?: 44100 // Use a default value if property not found
return sampleRate
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ abstract class BaseRecorder {
* *
* * 48000 一般就够了,太大也会影响文件的大小
*/
protected var mSamplingRate = 44100
protected var mSamplingRate = 48000
protected var is2Channel = false // 默认是单声道

//设置过滤器
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ data class Mp3Option(
// 声音来源:默认麦克风;如果使用VOICE_COMMUNICATION,系统会自动优化录音,但是声音会变小
@Source var audioSource: Int = AudioSource.MIC,
// 声道设置:单双声道,1单声道,2双声道
@Channel var audioChannel: Int = 1,
var audioChannel: Int = 1,
// debug,输出录音过程日志
var isDebug: Boolean = false,
// 最大录制时间毫秒
Expand All @@ -38,6 +38,7 @@ fun recorder(block: Mp3Option.() -> Unit): Mp3Option {
return Mp3Option().apply(block)
}


/** *
* * CAMCORDER 录音来源于同方向的相机麦克风相同,若相机无内置相机或无法识别,则使用预设的麦克风
* * DEFAULT 默认音频源
Expand All @@ -63,6 +64,3 @@ fun recorder(block: Mp3Option.() -> Unit): Mp3Option {
@Retention(AnnotationRetention.SOURCE)
annotation class Source

@IntDef(value = [1, 2])
@Retention(AnnotationRetention.SOURCE)
annotation class Channel
120 changes: 5 additions & 115 deletions recorder-mix/ReadMe.MD
Original file line number Diff line number Diff line change
@@ -1,118 +1,8 @@
[TOC]

# MixRecorder
- [MixRecordUtils](https://github.com/SheTieJun/Mp3Recorder/blob/master/app/src/main/java/me/shetj/mp3recorder/record/utils/MixRecordUtils.kt)
### 背景音频要求

```
44k ,双声道,16位
必须保持和录音的参数一样,如果不一样需要自行转码音频或者修改库代码
```

```
fix : 已经添加参数设置声道数量
但是如果设置单声道,然后播放的双声道音乐,音乐会被拉长
```

### 背景音乐实现思路

1. 播放音乐,可以得到PCM:[PlayBackMusic](https://github.com/SheTieJun/Mp3Recorder/blob/master/doc/PlayBackMusic.MD)
2. AudioRecord 得到麦克风的声音:PCM
3. 2个PCM进行声音混合,然后Lame转码成MP3 写入到文件
4. 支持耳机,但是分2种情况,设置了PlugConfig 和没有设置PlugConfig
5. 可以设置释放使用PlugConfig,如果使用将会使用 :没有连接耳机,只用外放的背景音乐;连接耳机,会使用写入合成背景音乐的方式

#### 1. 初始化


```kotlin
recorder {
recordListener = this@MixRecordUtils
permissionListener = this@MixRecordUtils
isDebug = false
pcmListener = this@RecordUtils
}.buildMix(context)
```

#### 2. 开始录音

```kotlin
mixRecorder!!.start()
```

#### 3. 暂停、重新开始录音

```kotlin
mRecorder?.onPause() //暂停
mRecorder?.onResume() //重新开始
mRecorder?.state //当前录音的状态 3个专题,停止,录音中,暂停
```

#### 4. 背景音乐相关

```kotlin
mRecorder?.setBackgroundMusic(musicUrl)//设置背景音乐
mRecorder?.setVolume(volume)//设置背景音乐大小0-1,即使没有把手机的声音关闭,也会按照该比例记录到录制的声音中
mRecorder?.startPlayMusic() //开始播放背景音乐
mRecorder?.isPlayMusic() //是否播放了背景应用
mRecorder?.pauseMusic() //暂停背景音乐
mRecorder?.isPauseMusic()// 背景音乐是否暂停
mRecorder?.resumeMusic() //重新开始播放
```
#### 5.中途替换输出文件
```
//filePath 新的文件
mRecorder.updateDataEncode(filePath)
```

#### 6.中途暂停、重置
```
mRecorder.onReset() //会回调 Listener: onReset()
```
或者
```
mRecorder.onDestroy() //没有任何回调
```

#### 6. 停止录音

```kotlin
mRecorder?.stop() //完成录音
```

#### 7. 强制启动写入的混音


#### 单双声道

Lame 在使用lame_encode_buffer 在转码双声道时 会出现噪音

解决方法
```
if (is2CHANNEL) {
readSize = buffer.size / 2
encodedSize = LameUtils.encodeInterleaved(buffer,readSize,mMp3Buffer)
} else {
readSize = buffer.size
encodedSize = LameUtils.encode(buffer, buffer, readSize, mMp3Buffer)
}
```

[音频基础知识](https://blog.csdn.net/StjunF/article/details/121296111)

```
/*
* 16Kbps= 电话音质
* 24Kbps= 增加电话音质、短波广播、长波广播、欧洲制式中波广播
* 40Kbps= 美国制式中波广播
* 56Kbps= 话音
* 64Kbps= 增加话音(手机铃声最佳比特率设定值、手机单声道MP3播放器最佳设定值)
* 112Kbps= FM调频立体声广播
* 128Kbps= 磁带(手机立体声MP3播放器最佳设定值、低档MP3播放器最佳设定值)
* 160Kbps= HIFI高保真(中高档MP3播放器最佳设定值)
* 192Kbps= CD(高档MP3播放器最佳设定值)
* 256Kbps= Studio音乐工作室(音乐发烧友适用)
* 实际上随着技术的进步,比特率也越来越高,MP3的最高比特率为320Kbps,但一些格式可以达到更高的比特率和更高的音质。
* 比如正逐渐兴起的APE音频格式,能够提供真正发烧级的无损音质和相对于WAV格式更小的体积,其比特率通常为550kbps-----950kbps。
*/
```
- 边录边转码MP3,默认启动系统自带[如果手机支持]的AEC、NC、AGC,可以通过`enableAudioEffect`进行开启和关闭,除1.9.1是默认关闭的(因为部分手机外接麦克风时,如果是【MIC+AEC、NC、AGC】,会没有声音),其他版本都是默认开启。
- 支持暂停,实时返回已**录制时长**和当前**声音大小**,已录制的那段音频是**可以播放**
- 支持添加背景音乐,可以设置背景音乐声音的大小(但是不建议设置,因为通过算法声音的会失真)
- 支持静音录制
- 支持录制时间返回,【1.9.2 已优化误差,在这之前录制越长误差越大】
Loading

0 comments on commit d7895b2

Please sign in to comment.