博主查阅很多帖子、博文,这里是最一团浆糊的地方。有的博文取600,是基于它视噪音的振幅为600的假设,此时算出来的是相对背景噪音的分贝值,要是用户不对麦克风发出声音,算出的基本都是0分贝。而用户实际使用场景下的背景噪音大小千差万别,咱要是也照葫芦画瓢就不对了,尤其是对于那些制作绝对分贝计的需求,应找出20微帕声压值对应的振幅(或者也可以拿一个标准分贝计做校准参考)。
这个类可以获得具体的音源数据值。将一段音源数据用
read(byte[] audioData, int offsetInBytes, int sizeInBytes)
方法从缓冲区读取到我们传入的字节数组audioData后,便可以对其进行操作,如求平方和或绝对值的平均值。这样可以避免个别极端值的影响,使计算的结果更加稳定。求得平均值之后,如果是平方和则代入
常数系数为10
的公式中,如果是绝对值的则代入
常数系数为20
的公式中,算出分贝值。
演示代码如下:
-
package
com.example.myapp;
-
-
import
android.media.AudioFormat;
-
import
android.media.AudioRecord;
-
import
android.media.MediaRecorder;
-
import
android.util.Log;
-
-
-
-
-
public
class
AudioRecordDemo {
-
-
private
static
final
String TAG =
"AudioRecord"
;
-
static
final
int
SAMPLE_RATE_IN_HZ =
8000
;
-
static
final
int
BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ,
-
AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT);
-
AudioRecord mAudioRecord;
-
boolean
isGetVoiceRun;
-
Object mLock;
-
-
public
AudioRecordDemo() {
-
mLock =
new
Object();
-
}
-
-
public
void
getNoiseLevel() {
-
if
(isGetVoiceRun) {
-
Log.e(TAG,
"还在录着呢"
);
-
return
;
-
}
-
mAudioRecord =
new
AudioRecord(MediaRecorder.AudioSource.MIC,
-
SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_IN_DEFAULT,
-
AudioFormat.ENCODING_PCM_16BIT, BUFFER_SIZE);
-
if
(mAudioRecord ==
null
) {
-
Log.e(
"sound"
,
"mAudioRecord初始化失败"
);
-
}
-
isGetVoiceRun =
true
;
-
-
new
Thread(
new
Runnable() {
-
@Override
-
public
void
run() {
-
mAudioRecord.startRecording();
-
short
[] buffer =
new
short
[BUFFER_SIZE];
-
while
(isGetVoiceRun) {
-
-
int
r = mAudioRecord.read(buffer,
0
, BUFFER_SIZE);
-
long
v =
0
;
-
-
for
(
int
i =
0
; i < buffer.length; i++) {
-
v += buffer[i] * buffer[i];
-
}
-
-
double
mean = v / (
double
) r;
-
double
volume =
10
* Math.log10(mean);
-
Log.d(TAG,
"分贝值:"
+ volume);
-
-
synchronized
(mLock) {
-
try
{
-
mLock.wait(
100
);
-
}
catch
(InterruptedException e) {
-
e.printStackTrace();
-
}
-
}
-
}
-
mAudioRecord.stop();
-
mAudioRecord.release();
-
mAudioRecord =
null
;
-
}
-
}).start();
-
}
-
}
实测结果(设备小米2S),MediaRecorderDemo波动很大,只要对麦克风一吹气,分贝值就能上90:
而AudioRecordDemo就很稳定了,很用力吹气也很难到88以上:
基础知识度量声音强度,大家最熟悉的单位就是分贝(decibel,缩写为dB)。这是一个无纲量的相对单位,计算公式如下:分子是测量值的声压,分母是参考值的声压(20微帕,人类所能听到的最小声压)。因此日常中说道声音强度是多少多少分贝时,都是默认了一个很小的参考值的。而Android设备传感器可以提供的物理量是场的幅值(amplitude),常用下列公式计算分贝值:从SDK中读取了某段音频数据的振幅后...
这个方法是用来
获取
在前一次调用此方法之后录音中出现的最大振幅,文档解释如下:
Returns the maximum absolute amplitude that was sampled since the last call to this method. Call this only after the setAudioSource().
很多人遇到问题,说是返回值为0,文档中解释如下:...
2.MediaRecorder mMediaRecorder;
3.int ratio = mMediaRecorder.getMaxAmplitude() / BASE;
4.int db = 0;//
分贝
也可以理解为定义的
音量
大小
5.if (ratio > 1)
6.db = (int) (20 * M...
```java
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
int targetVolume = currentVolume + 1;
if(targetVolume > maxVolume) {
targetVolume = maxVolume;
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, targetVolume, AudioManager.FLAG_SHOW_UI);
上面的代码将会增加
音量
。如果要降低
音量
,将targetVolume减少即可。