AVAudioRecorder no escribe el encabezado correcto del archivo WAV

Estoy trabajando en un proyecto en el iPhone donde estoy grabando audio desde el micrófono del dispositivo usando AVAudioRecorder, y luego manipularé la grabación.

Para asegurarme de que estoy leyendo las muestras del archivo correctamente, estoy usando el módulo de onda de python para ver si devuelve las mismas muestras.

Sin embargo, el módulo wave de python devuelve “falta un fragmento de fmt y / o un fragmento de datos” cuando se intenta abrir el archivo wav que se guarda con AVAudioRecorder.

Estas son las configuraciones que estoy usando para grabar el archivo:

[audioSettings setObject:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey:AVFormatIDKey]; [audioSettings setObject:[NSNumber numberWithInt:16] forKey:AVLinearPCMBitDepthKey]; [audioSettings setObject:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsBigEndianKey]; [audioSettings setObject:[NSNumber numberWithFloat:4096] forKey:AVSampleRateKey]; [audioSettings setObject:[NSNumber numberWithInt:1] forKey:AVNumberOfChannelsKey]; [audioSettings setObject:[NSNumber numberWithBool:YES] forKey:AVLinearPCMIsNonInterleaved]; [audioSettings setObject:[NSNumber numberWithBool:NO] forKey:AVLinearPCMIsFloatKey]; 

Después de eso, solo estoy haciendo una llamada a recordForDuration para hacer realmente la grabación.

    La grabación se realiza correctamente: puedo reproducir el archivo, etc., y puedo leer las muestras utilizando los servicios de AudioFile, pero no puedo validarlo porque no puedo abrir el archivo con el módulo de onda de Python.

    Así es como se ven los primeros 128 bytes del archivo:

     1215N:~/Downloads$ od -c --read-bytes 128 testFile.wav 0000000 RIFF x H 001 \0 WAVE fmt 0000020 020 \0 \0 \0 001 \0 001 \0 @ 037 \0 \0 200 > \0 \0 0000040 002 \0 020 \0 FLLR 314 017 \0 \0 \0 \0 \0 \0 0000060 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 * 0000200 

    ¿Alguna idea de lo que debo hacer para asegurarme de que AVAudioRecorder escribe un encabezado WAV correcto?

    El software de Apple a menudo crea archivos WAVE con un "FLLR" FLLR "FLLR" no estándar (pero que "FLLR" especificaciones”) después del "fmt " fmt "fmt " y antes del subchunk "data" . Asumo que “FLLR” significa “relleno”, y asumo que el propósito del subchunk es habilitar algún tipo de optimización de alineación de datos. El subchunk suele tener una longitud de unos 4000 bytes, pero su longitud real puede variar dependiendo de la longitud de los datos que lo preceden.

    Agregar subunidades arbitrarias a archivos WAVE generalmente se considera que cumple con las especificaciones porque WAVE es un subconjunto de RIFF , y la práctica común en el procesamiento de archivos RIFF es ignorar fragmentos y subunidades que tienen un identificador no reconocido. El identificador "FLLR" es “no estándar” y, por lo tanto, debe ser ignorado por cualquier software que lo encuentre.

    Existe una buena cantidad de software que trata el formato WAVE de manera mucho más rígida de lo que debería, y sospecho que la biblioteca que está utilizando puede ser una de esas piezas de software. Por ejemplo, he visto un software que asume que los bytes de audio siempre comienzan en el desplazamiento 44, esta es una suposición incorrecta.

    De hecho, la búsqueda de los bytes de audio en un archivo WAVE se debe realizar buscando la ubicación y el tamaño del subchunk "data" dentro del RIFF; Esta es la forma correcta de ubicar los bytes de audio dentro de un archivo WAVE.

    La lectura correcta de los archivos WAVE debe comenzar realmente como un ejercicio de localización e identificación de subgrupos RIFF. Los subchunks RIFF tienen un encabezado de 8 bytes: 4 bytes para un campo de identificador / nombre que se rellena tradicionalmente con caracteres ASCII legibles (por ejemplo, "fmt " ) y un entero sin signo little-endian de 4 bytes que especifica el número de bytes en La carga de datos de los subchunk – la carga de datos de los subchunk sigue inmediatamente después de su encabezado de 8 bytes.

    El formato de archivo WAVE reserva ciertos identificadores de subchunk (o “nombres”) como significativos para el formato WAVE. Hay un mínimo de dos subchunks que siempre deben aparecer en cada archivo WAVE:

    1. "fmt " : el subchunk con este identificador tiene una carga útil que describe la información básica sobre el formato del audio: frecuencia de muestreo, profundidad de bits, etc.
    2. "data" : el subchunk con este identificador tiene los bytes de audio reales en su carga útil

    "fact" es el siguiente identificador de subchunk más común. Por lo general, se encuentra en archivos WAVE que usan un códec comprimido, como μ-law. Consulte esta página web para entusiastas para obtener más información acerca de algunos de los diversos identificadores de subchunk que se utilizan en la actualidad en su hábitat natural, e información sobre su estructura de carga útil.

    Desde una perspectiva puramente RIFF, los subchunks no tienen que aparecer en ningún orden en particular en el archivo, o en ningún desplazamiento fijo en particular. Sin embargo, en la práctica, casi todo el software espera que el "fmt " fmt "fmt " sea ​​el primer subchunk. Esta es una concesión a la practicidad: es conveniente saber desde el principio en el flujo de datos qué formato de audio contiene la WAVE; esto hace que sea más fácil reproducir un archivo wave desde un flujo de red, por ejemplo. Si el archivo WAVE utiliza un formato comprimido, como μ-law, generalmente se supone que el subchunk "fact" aparecerá directamente después de "fmt " .

    Una vez que los fragmentos que especifican el formato están fuera del camino, se deben abandonar las suposiciones sobre la ubicación, el orden y la denominación de los subconjuntos. En este punto, el software debe ubicar los subconjuntos esperados solo por nombre (por ejemplo, "data" ). Si se encuentran subchunks que tienen nombres no reconocidos (por ejemplo, "FLLR" ), esos subchunks simplemente deben omitirse e ignorarse. Para omitir un subchunk, es necesario leer su longitud para que pueda omitir el número correcto de bytes.

    Lo que Apple ha hecho con el "FLLR" es un poco inusual, y no me sorprende que se haya disparado algún software. Sospecho que la biblioteca que está utilizando simplemente no está preparada para hacer frente a la presencia del "FLLR" FLLR "FLLR" . Yo consideraría esto como un defecto en la biblioteca. El error que han cometido los autores de la biblioteca es probablemente algo como:

    1. Es posible que esperen que aparezca el subchunk "data" dentro de los primeros N bytes del comienzo del archivo, donde N es algo menos de ~ 4kB. Pueden dejar de mirar si tienen que escanear demasiado en el archivo. El "FLLR" Apple empuja el subchunk "data" a una posición> ~ 4kB en el archivo.

    2. Pueden estar esperando que el subchunk "data" tenga una posición de subchunk ordinal específica o un offset de byte dentro del RIFF. Tal vez esperan que los "data" aparezcan inmediatamente después de "fmt " . Sin embargo, esta es una forma incorrecta de procesar un archivo RIFF. La posición ordinal y / o la posición de desplazamiento del subchunk "data" no se deben asumir.

    Mientras hablemos del procesamiento correcto del archivo WAVE, también podría recordar a todos que los bytes de audio (la carga útil del subchunk de datos) pueden no ejecutarse exactamente hasta el final del archivo. Es posible insertar subchunks después de la carga útil de data . Algunos progtwigs usan esto para almacenar un campo de “comentario” textual al final del archivo. Si lee ciegamente desde el inicio de la carga útil de data hasta el EOF, puede extraer algunos subchunks de metadatos como audio, que suena como un “clic” al final de la reproducción. Debe respetar el campo de longitud del subchunk de data y dejar de leer el audio una vez que haya consumido toda la carga útil de los datos, no detenerse cuando llegue a EOF.

    ¿Cuál es el nombre del archivo que está grabando en el disco? Tuve un problema similar y simplemente lo resolví pegando en .wav hasta el final de mi nombre de archivo … Creo que AVAudioRecorder necesita una extensión para resolver las cosas.