diferencia entre cómo AVAssetReader y AudioFileReadPackets leen audio

considere estos dos escenarios para leer/escribir datos de archivos de audio (con el fin de enviarlos a través de una red):

Escenario 1: Servicios de archivos de audio:
Usar AudioFileReadPackets del Servicios de archivos de audio. Esto genera paquetes de audio que puede enviar fácilmente a través de la red. En el lado receptor se utiliza AudioFileStreamOpen y AudioFileStreamParseBytes para analizar los datos.

AudioFileStreamParseBytes entonces tiene dos funciones de devolución de llamada: AudioFileStream_PropertyListenerProc y AudioFileStream_PacketsProc. Se llama a estos tipos cuando se descubre una nueva propiedad en la transmisión y cuando se reciben paquetes de la transmisión, respectivamente. Una vez que reciba los paquetes, puede enviarlos a una cola de audio usando Servicio de cola de audio que reproduce el archivo muy bien.

Nota: Este método NO funciona con archivos de música almacenados en la biblioteca del iPod, lo que nos lleva al segundo escenario:

Escenario 2: AVAssetReader:
Con AVAssetReader puede leer desde la biblioteca de música del iPod y enviar paquetes a través de la red. Por lo general, cargaría los paquetes directamente en una Cola de audio similar a la anterior. Sin embargo, en este escenario tendrá que crear un subproceso para asegurarse de que bloquea la recepción de paquetes cuando la cola está llena y desbloquea cuando los búferes de la cola están disponibles (consulte este ejemplo).

Pregunta:
¿Es posible usar AVAssetReader para enviar paquetes, solo para que los lea AudioFileStreamParseBytes? (el motivo sería que las devoluciones de llamada de AudioFileStreamParseBytes manejarán el negocio de enhebrado/bloqueo y le ahorrarán ese dolor). Intenté hacerlo así:
1. primero lea el archivo de audio usando AVAssetReader

//NSURL *assetURL = [NSURL URLWithString:@"ipod-library://item/item.m4a?id=1053020204400037178"]; 
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:assetURL options:nil];

NSError * error = nil;
AVAssetReader* reader = [[AVAssetReader alloc] initWithAsset:songAsset error:&error];

AVAssetTrack* track = [songAsset.tracks objectAtIndex:0]; 

// Note: I don't supply an audio format description here, rather I pass on nil to keep the original
// file format. In another piece of code (see here: http://stackoverflow.com/questions/12264799/why-is-audio-coming-up-garbled-when-using-avassetreader-with-audio-queue?answertab=active#tab-top) I can extract the audio format from the track, let's say it's an AAC format.
AVAssetReaderTrackOutput* readerOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track
                                                                                    outputSettings:nil];


[reader addOutput:readerOutput];
[reader startReading];

2. configurar el transmisor

// notice how i manually add the audio file type (for the file hint parameter) 
// using the info from step one.. If i leave it as 0, this call fails and returns
// the typ? error, which is :The specified file type is not supported.  
streamer->err = AudioFileStreamOpen((__bridge void*)streamer, 
                                     ASPropertyListenerProc, ASPacketsProc, 
                                     kAudioFileAAC_ADTSType, &(streamer->audioFileStream)); 

3. una vez que recibo los datos, analizo los bytes:

streamer->err = AudioFileStreamParseBytes(streamer->audioFileStream, inDataByteSize, inData, 0);

problema: Cuando lo hago de esta manera... envío los bytes y AudioFileStreamParseBytes lo hace no fallar. Sin embargo, las devoluciones de llamada *AudioFileStream_PropertyListenerProc* y *AudioFileStream_PacketsProc* nunca se llaman. Lo que me hace pensar que el analizador no ha podido analizar los bytes y extraer cualquier información útil de ellos... en la documentación de AudioStreamParseBytes dice:* Debe proporcionar al menos más de un paquete de datos de archivo de audio, pero es mejor proporcionar unos pocos paquetes de datos de unos pocos segundos a la vez.* Estoy enviando más de 900 bytes, que es solo debajo de los datos de GKSession límitar. Estoy bastante seguro de que 900 bytes son suficientes (al probar esto en el escenario 1, el total de bytes fue de 417 cada vez y funcionó bien).

¿Alguna idea?

preguntado el 08 de septiembre de 12 a las 09:09

1 Respuestas

La respuesta corta es que simplemente no tiene sentido que AudioFileStreamParseBytes analice paquetes de datos de audio... en el documentos AudioFileStreamParseBytes es una función que depende de la existencia de un archivo de audio (por lo tanto, el parámetro inAudioFileStream... que se define como el ID del analizador al que desea pasar los datos. La función AudioFileStreamOpen devuelve el ID del analizador.)

así que lección aprendida: no intentes encasillar las funciones de iOS para que se ajusten a tu situación... debería ser al revés.

Lo que terminé haciendo fue enviar los datos directamente a una cola de audio... sin pasar por todas estas funciones intermedias innecesarias... una forma más detallada sería enviar los datos a las unidades de audio... pero mi aplicación no necesitaba ese nivel de control

respondido 22 nov., 12:13

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.