java 在android中录制音频时如何调整麦克风灵敏度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25441166/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to adjust microphone sensitivity while recording audio in android
提问by Anton Savin
I'm working on a voice recording app. In it, I have a Seekbar to change the input voice gain. I couldn't find any way to adjust the input voice gain.
我正在开发一个录音应用程序。在其中,我有一个 Seekbar 来更改输入语音增益。我找不到任何方法来调整输入语音增益。
I am using the AudioRecord
class to record voice.
我正在使用该AudioRecord
课程来录制语音。
recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
RECORDER_SAMPLERATE, RECORDER_CHANNELS,
RECORDER_AUDIO_ENCODING, bufferSize);
recorder.startRecording();
I've seen an app in the Google Play Storeusing this functionality.
我曾在 Google Play 商店中看到使用此功能的应用程序。
回答by Anton Savin
As I understand you don't want any automatic adjustments, only manual from the UI. There is no built-in functionality for this in Android, instead you have to modify your data manually.
据我了解,您不需要任何自动调整,只需要从 UI 手动进行调整。Android 中没有为此内置功能,您必须手动修改数据。
Suppose you use read (short[] audioData, int offsetInShorts, int sizeInShorts)for reading the stream. So you should just do something like this:
假设您使用read (short[] audioData, int offsetInShorts, int sizeInShorts)来读取流。所以你应该做这样的事情:
float gain = getGain(); // taken from the UI control, perhaps in range from 0.0 to 2.0
int numRead = read(audioData, 0, SIZE);
if (numRead > 0) {
for (int i = 0; i < numRead; ++i) {
audioData[i] = (short)Math.min((int)(audioData[i] * gain), (int)Short.MAX_VALUE);
}
}
Math.min
is used to prevent overflow if gain
is greater than 1.
Math.min
如果gain
大于 1,则用于防止溢出。
回答by Seyfülislam ?zdemir
Dynamic microphone sensitivity is not a thing that the hardware or operating system is capable of as it requires analysis on the recorded sound. You should implement your own algorithm to analyze the recorded sound and adjust (amplify or decrease) the sound level on your own.
动态麦克风灵敏度不是硬件或操作系统能够做到的,因为它需要对录制的声音进行分析。您应该实现自己的算法来分析录制的声音并自行调整(放大或降低)声级。
You can start by analyzing last few seconds and find a multiplier that is going to "balance" the average amplitude. The multiplier must be inversely proportional to the average amplitude to balance it.
您可以从分析最后几秒开始,找到一个可以“平衡”平均幅度的乘数。乘数必须与平均幅度成反比以平衡它。
PS: If you still want to do it, the mic levels are accessible when you have a root access, but I am still not sure -and don't think it is possible- if you can change the settings while recording. Hint: "/system/etc/snd_soc_msm" file.
PS:如果您仍然想这样做,当您具有 root 访问权限时可以访问麦克风级别,但我仍然不确定 - 并且不认为这是可能的 - 如果您可以在录制时更改设置。提示:“/system/etc/snd_soc_msm”文件。
回答by C?ur
Solution by OP.
OP的解决方案。
I have done it using
我已经使用
final int USHORT_MASK = (1 << 16) - 1;
final ByteBuffer buf = ByteBuffer.wrap(data).order(
ByteOrder.LITTLE_ENDIAN);
final ByteBuffer newBuf = ByteBuffer.allocate(
data.length).order(ByteOrder.LITTLE_ENDIAN);
int sample;
while (buf.hasRemaining()) {
sample = (int) buf.getShort() & USHORT_MASK;
sample *= db_value_global;
newBuf.putShort((short) (sample & USHORT_MASK));
}
data = newBuf.array();
os.write(data);
回答by Dmide
This is working implementation based on ByteBuffer
for 16bit audio. It's important to clamp the increased value from both sides since short is signed. It's also important to set the native byte order to ByteBuffer
since audioRecord.read()
returns native endian bytes.
这是基于ByteBuffer
16 位音频的工作实现。由于 short 是有符号的,因此从双方钳制增加的值很重要。将本机字节顺序设置为也很重要,ByteBuffer
因为audioRecord.read()
返回本机字节序。
You may also want to perform audioRecord.read()
and following code in a loop, calling data.clear()
after each iteration.
您可能还想audioRecord.read()
在循环中执行和跟踪代码,data.clear()
在每次迭代后调用。
double gain = 2.0;
ByteBuffer data = ByteBuffer.allocateDirect(SAMPLES_PER_FRAME).order(ByteOrder.nativeOrder());
int audioInputLengthBytes = audioRecord.read(data, SAMPLES_PER_FRAME);
ShortBuffer shortBuffer = data.asShortBuffer();
for (int i = 0; i < audioInputLengthBytes / 2; i++) { // /2 because we need the length in shorts
short s = shortBuffer.get(i);
int increased = (int) (s * gain);
s = (short) Math.min(Math.max(increased, Short.MIN_VALUE), Short.MAX_VALUE);
shortBuffer.put(i, s);
}