Grabar un archivo wav desde el micrófono en Android – problemas
Necesito poder crear un archivo WAV usando el micrófono en Android. Actualmente, estoy teniendo muchos problemas. Hasta ahora, esta es mi situación. Estoy utilizando partes del código del proyecto micDroid para registrar así:
//read thread int sampleRate = 44100; int bufferSize = AudioRecord.getMinBufferSize(sampleRate,android.media.AudioFormat.CHANNEL_CONFIGURATION_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT); AudioRecord ar = new AudioRecord(AudioSource.MIC,sampleRate,android.media.AudioFormat.CHANNEL_CONFIGURATION_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT,bufferSize); short[] buffer = new short[bufferSize]; ar.startRecording(); while(isRunning){ try{ int numSamples = ar.read(buffer, 0, buffer.length); queue.put(new Sample(buffer, numSamples)); } catch (InterruptedException e){ e.printStackTrace(); } } //write thread int sampleRate = 44100; WaveWriter writer = new WaveWriter("/sdcard","recOut.wav",sampleRate,android.media.AudioFormat.CHANNEL_CONFIGURATION_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT); try { writer.createWaveFile(); } catch (IOException e) { e.printStackTrace(); } while(isRunning){ try { Sample sample = queue.take(); writer.write(sample.buffer, sample.bufferSize); } catch (IOException e) { //snip } }
Lo que parece funcionar bien, sin embargo el resultado final reconociblemente contiene lo que he dicho, pero es horriblemente distorsionado. Aquí hay una tapa de pantalla de audacity (WMP se niega a reproducir el archivo).
- Realizar N llamadas de api secuenciales usando RxJava y Retrofit
- XmlPullParserException función no admitida
- Android Cómo calcular el uso de la red de paquetes / datos
- Android: ¿qué hace el método "setTextFilterEnabled"?
- Android: no se puede llamar a setOnItemClickListener desde un ListView
Cualquier ayuda sería apreciada grandemente, déjeme saber si usted necesita más código / Info.
Actualizar
Siguiendo las sugerencias de markus, aquí está mi código actualizado:
int sampleRate = 16000; writer = new WaveWriter("/sdcard","recOut.wav",sampleRate,android.media.AudioFormat.CHANNEL_IN_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT); int bufferSize = AudioRecord.getMinBufferSize(sampleRate,android.media.AudioFormat.CHANNEL_IN_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT); AudioRecord ar = new AudioRecord(AudioSource.MIC,sampleRate,android.media.AudioFormat.CHANNEL_IN_MONO,android.media.AudioFormat.ENCODING_PCM_16BIT,bufferSize); byte[] buffer = new byte[bufferSize]; //all references changed from short to byte type
… y otro screencap audacity:
- Dagger 2, supertypeInjector es nulo
- Android - ¿Cómo obtener un archivo de imagen de Fresco caché de disco?
- ¿Cualquier manera de agarrar un icono de la insignia del URL del Web site, programmatically?
- Detectar orientación con javascript en dispositivos Android
- Error de generación de Gradle: no se puede acceder al archivo de clase ITest bad: Método por defecto de ITest.class encontrado en la versión 50.0 classfile
- recv falló (errno = 11) en la aplicación de streaming (MediaPlayer) en Nexus
- Al ofuscar con ProGuard, ¿hace -keepattributes SourceFile, LineNumberTable hacer el apk resultante más fácil de ingeniería inversa?
- Lotes de array byte Android
CHANNEL_CONFIGURATION_MONO está obsoleto por lo que sé, use CHANNEL_IN_MONO. considere la posibilidad de mirar el proyecto de ensayo de ensayo , afaik que utilizan la clase AudioRecord, también. los samplerates se deben elegir para caber las tarifas estándar de la muestra según lo explicado en este artículo de wikipedia .
Puede establecer un búfer para que sea little-endian utilizando lo siguiente:
buffer.order(ByteOrder.LITTLE_ENDIAN);
Tengo un montón de teorías:
- si tuviste una señal saturada de ruido y no puedes entender nada o puedes entender algo. Puede ser que usted tiene un problema con el endian grande y poco endian. Cuando usted graba 16bit (2bytes) se puede almacenar como AB o como BA (donde A y B es un byte). En java todo es endian grande ( http://mindprod.com/jgloss/endian.html ) así que usted está almacenando una muestra de 16 pedacitos como corto en endian grande, después usted intenta construir un wav, pero un wav necesita tener datos almacenados en little endian ( https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ ). Bueno, el resultado es claro y tienes una captura de pantalla. La solución es usar byte siempre, lo habías hecho y probablemente todo está bien ahora
si no check queue.put y queue.take Creo que no las necesitas porque almacenaste tu audio en y array que es suficiente. En la primera vez que iba a reemplazar queue.put por una función para almacenar el búfer en una enorme matriz de bytes con todos los bytes. Entonces usted puede poner el encabezado del wav.
Recuerde que un wav tiene el encabezado y los bytes del audio, tal vez usted ha olvidado el encabezado y el programa que está utilizando está inventando un encabezado para jugarlo.
La otra opción es: tiene el problema en el encabezado wav de 44 bytes. compruebe su función WaveWriter. si escribes código malo en él, puedes oír muchos sonidos diferentes de tu voz.
nota: Había visto la función WaveWriter o similar en el código fuente de android pero no había estado listo para usar hace tres meses. Algunos nuevos sobre waveheader?
Es bastante claro, Audacity piensa que su archivo es punto flotante. Ya sea que el encabezado de WAV esté arruinado o bien es cómo lo abrió.
Haga una grabación. En Audacity, ábralo usando Project / Import Raw Data Establezca los parámetros de cómo piensa que lo grabó. Apuesto a que juega bien.
- No se puede acceder a los sensores en Android
- Hacer personalizado Parcelable que contiene byte array