如何在Android录制音频时调整麦克风灵敏度

10
我正在开发一个语音录制应用程序,在其中使用SeekBar更改输入语音增益。 我找不到任何调整输入语音增益的方法。我正在使用AudioRecord类来录制声音。
 recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
            RECORDER_SAMPLERATE, RECORDER_CHANNELS,
            RECORDER_AUDIO_ENCODING, bufferSize);

    recorder.startRecording();

我曾在Google Play商店看到一款使用该功能的应用程序。 查看该应用
4个回答

22

据我理解,您不想要任何自动调整,只需要通过用户界面手动进行调整。Android 中没有内置的此功能,因此您必须手动修改数据。

假设您使用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 用于防止当 gain 大于 1 时发生溢出。


感谢您的帮助。我对您的代码进行了一些修改,现在我的问题已经解决了。 - user3472378
1
你还需要调用Math.max(intValue, Short.MIN_VALUE),因为Java的short是有符号的,详见下面我的回答。 - Dmide
在网上搜索了很久后,只有这个答案有效。我不得不将“增益”设置为超过7才能看到一些很棒的效果!谢谢! - Farmaker

3
动态麦克风的灵敏度并非硬件或操作系统所能实现的,因为它需要对录制的声音进行分析。您应该实现自己的算法来分析录制的声音并自行调整(放大或减少)声音级别。您可以通过分析最近几秒钟的声音,并找到一个乘子来“平衡”平均振幅来开始。这个乘数必须与平均振幅成反比来平衡它。
提示:如果您仍然想这样做,当您拥有根访问权限时,可以访问麦克风电平,但我仍不确定 -也不认为- 您可以在录制时更改设置。提示:"/system/etc/snd_soc_msm"文件。

0

楼主的解决方案。

我已经使用以下方法完成了它

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);

-1

这是基于 ByteBuffer 实现的 16 位音频的工作实现。由于 short 是有符号数,因此重复值必须从两侧夹紧。将本机字节顺序设置为 ByteBuffer 也很重要,因为 audioRecord.read() 返回本机字节顺序。

您可能还想在循环中执行 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);
    }

所以这根本不起作用...周围都是静电噪声。 - TacB0sS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接