Как настроить чувствительность микрофона при записи звука в 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);
}