Как настроить чувствительность микрофона при записи звука в android

Я работаю над приложением для записи голоса. в приложении у меня есть панель поиска для изменения входного усиления голоса. Я не мог найти способ настроить усиление входного голоса.

Я использую класс AudioRecord для записи голоса.

 recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
            RECORDER_SAMPLERATE, RECORDER_CHANNELS,
            RECORDER_AUDIO_ENCODING, bufferSize);

    recorder.startRecording();

Я видел приложение также в play store, которые используют эту функциональность.

https://play.google.com/store/apps/details?id=com.grace.microphone

4 ответов


как я понимаю, вы не хотите никаких автоматических регулировок, только вручную из пользовательского интерфейса. Для этого в 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 используется для предотвращения переполнения if gain больше 1.


динамическая чувствительность микрофона-это не то, на что способно оборудование или операционная система, поскольку она требует анализа записанного звука. Вы должны реализовать свой собственный алгоритм анализа записанного звука и настроить (усилить или уменьшить) уровень звука самостоятельно.

вы можете начать с анализа последних нескольких секунд и найти множитель, который собирается "сбалансировать" среднюю амплитуду. Множитель должен быть обратно пропорционален средней амплитуды сбалансировать его.

PS: Если вы все еще хотите это сделать, уровни микрофона доступны, когда у вас есть корневой доступ, но я все еще не уверен-и не думаю, что это возможно - если вы можете изменить настройки во время записи. Подсказка: файл" /system/etc/snd_soc_msm".


решение OP.

Я сделал это с помощью

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

это рабочая реализация на основе ByteBuffer для 16бит аудио. Важно зажать увеличенное значение с обеих сторон, так как short подписан. Также важно установить собственный порядок байтов в ByteBuffer С audioRecord.read() возвращает собственные байты endian.

вы также можете выполнить 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);
    }