Cómo ajustar la sensibilidad del micrófono mientras se graba audio en Android

Estoy trabajando en una aplicación de grabación de voz. en la aplicación tengo una barra de búsqueda para cambiar la ganancia de voz de entrada. No pude encontrar ninguna forma de ajustar la ganancia de voz de entrada.

Estoy usando la clase AudioRecord para grabar voz.

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

También he visto una aplicación en Play Store que usa esta funcionalidad.

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

Como entiendo, no quiere ningún ajuste automático, solo manual de la interfaz de usuario. No hay funcionalidad incorporada para esto en Android, en su lugar debe modificar sus datos manualmente.

Supongamos que utiliza leer (short [] audioData, int offsetInShorts, int sizeInShorts) para leer la secuencia. Entonces deberías hacer algo como esto:

 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 se usa para evitar el desbordamiento si la gain es mayor que 1.

La sensibilidad dinámica del micrófono no es algo que el hardware o el sistema operativo es capaz de hacer, ya que requiere un análisis del sonido grabado. Debe implementar su propio algoritmo para analizar el sonido grabado y ajustar (amplificar o disminuir) el nivel de sonido por su cuenta.

Puede comenzar analizando los últimos segundos y encontrar un multiplicador que va a “equilibrar” la amplitud promedio. El multiplicador debe ser inversamente proporcional a la amplitud promedio para equilibrarlo.

PD: Si aún quieres hacerlo, los niveles de micrófono están accesibles cuando tienes acceso de root, pero todavía no estoy seguro (y no creo que sea posible) si puedes cambiar la configuración mientras grabas. Sugerencia: archivo “/ system / etc / snd_soc_msm”.

Solución por OP.

Lo he hecho usando

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

Esta es una implementación funcional basada en ByteBuffer para audio de 16 bits. Es importante sujetar el valor aumentado de ambos lados ya que el short está firmado. También es importante establecer el orden de bytes nativos en ByteBuffer ya que audioRecord.read() devuelve bytes endian nativos.

También puede realizar audioRecord.read() y el siguiente código en un bucle, llamando a data.clear() después de cada iteración.

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