2010-12-07 12 views
5

He estado trabajando en una aplicación de detección de frecuencia para iOS y tengo un problema al llenar un AudioBufferList definido por el usuario con muestras de audio del micrófono.Grabación con E/S remotas, AudioUnitRender -50 código de retorno

Obtengo un código de retorno de -50 cuando llamo AudioUnitRender en mi método InputCallback. Creo que esto significa que uno de mis parámetros no es válido. Supongo que es la AudioBufferList, pero no he podido averiguar qué está mal con ella. Creo que lo he configurado para que coincida con el formato de datos que he especificado en mi ASBD.

A continuación se muestra la configuración de E/S remotas y llamadas a funciones que creo que podría ser incorrecta:

ASBD:

size_t bytesPerSample = sizeof(AudioUnitSampleType); 
AudioStreamBasicDescription localStreamFormat = {0}; 
localStreamFormat.mFormatID = kAudioFormatLinearPCM; 
localStreamFormat.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical; 
localStreamFormat.mBytesPerPacket = bytesPerSample; 
localStreamFormat.mBytesPerFrame = bytesPerSample; 
localStreamFormat.mFramesPerPacket = 1; 
localStreamFormat.mBitsPerChannel = 8 * bytesPerSample; 
localStreamFormat.mChannelsPerFrame = 2; 
localStreamFormat.mSampleRate = sampleRate; 

Declaración InputCallback:

err = AudioUnitSetProperty(ioUnit, kAudioOutputUnitProperty_SetInputCallback, 
          kAudioUnitScope_Input, 
          kOutputBus, &callbackStruct, sizeof(callbackStruct)); 

Declaración AudioBufferList:

// Allocate AudioBuffers 
bufferList = (AudioBufferList *)malloc(sizeof(AudioBuffer)); 
bufferList->mNumberBuffers = 1; 
bufferList->mBuffers[0].mNumberChannels = 2; 

bufferList->mBuffers[0].mDataByteSize = 1024; 
bufferList->mBuffers[0].mData = calloc(256, sizeof(uint32_t)); 

InputCallback Función:

AudioUnit rioUnit = THIS->ioUnit; 
OSStatus renderErr; 
UInt32 bus1 = 1; 
renderErr = AudioUnitRender(rioUnit, ioActionFlags, inTimeStamp, bus1, inNumberFrames, THIS->bufferList); 

Algunas cosas a tener en cuenta:

  • frecuencia de muestreo = 22050 Hz
  • Dado que el formato canónico de E/datos O es punto fijo 8,24 bits, I Supongo que las muestras son de 32 bits cada una (o 4 bytes). Como un int sin signo tiene 4 bytes, lo estoy usando para asignar mi buffer de audio.
  • Puedo obtener el mismo código para procesar el audio correctamente si implemento el flujo de datos de audio como PassThru en lugar de solo la entrada.
  • Ya he visto Michael Tyson's blog post en E/S remotas. No vi nada allí diferente de lo que estoy haciendo.

Gracias de nuevo, ¡ustedes son geniales!

Demetri

+0

Finalmente finalicé la aplicación de detección de frecuencia que mencioné. He publicado un informe junto con el código fuente para los interesados. EDITAR: el enlace ... http: //sleepyleaf.com/2011/01/25/pitch-detection-in-ios-4-x/ – irtemed88

+0

No se ha encontrado ningún código en los mencionados .. Enlaces sleepyleaf.com/2011/ 01/25/pitch-detection-in-ios-4-x - irtemed88 –

+0

Vaya, lo siento, actualicé mi dominio. Nuevo enlace: http://demetrimiller.com/2011/01/25/pitch-detection-in-ios-4-x/ – irtemed88

Respuesta

4

Si tiene 2 canales por cuadro, no puede tener bytesPerSample como el tamaño del marco. Dado que la terminología es un poco confuso:

  • A muestra es un solo valor en una posición dada en una forma de onda
  • Un canal se refiere a los datos asociados con un flujo de audio particular, es decir, izquierda/canal derecho para estéreo, un solo canal para mono, etc.
  • Un marco contiene las muestras para todos los canales para una posición dada en una forma de onda
  • Un paquete contiene uno o más marcos

Así que, básicamente, es necesario utilizar bytesPerSample * mChannelsPerFrame para mBytesPerFrame, y use mBytesPerFrame * mFramesPerPacket para mBytesPerPacket.

También noté que está usando 32 bits para su tamaño de muestra. No estoy seguro de si realmente desea hacer esto; generalmente, desea grabar audio usando muestras de 16 bits. La diferencia de sonido entre audio de 16 y 32 bits es casi imposible de escuchar para la mayoría de los oyentes (el CD promedio se domina a 44.1kHz, PCM de 16 bits) y le ahorrará el 50% de los costos de E/S y almacenamiento.

+0

Ok gracias! Estaba un poco confundido porque la documentación indica que el formato de muestra de audio canónico es de punto fijo de 8,24 bits. Supuse que era el formato que tenía que usar y tenía 32 bits. Si estoy usando muestras de 16 bits, ¿eso significa que los tipos de muestra son entradas firmadas de 16 bits? – irtemed88

+0

Sí, 16 bits significaría que sus datos están almacenados técnicamente como cortos firmados, o 'SInt16'. Y sí, mientras que 8-24 bits representa el rango más común, casi todas las cosas de grabación diaria usan 16 bits. 8 bit suena terrible, y nadie puede escuchar la diferencia entre 16 y 24.;) –

0

Una diferencia es que blog RemoteIO de Tyson utiliza 2 bytes por muestra de PCM lineal. Entonces, este podría ser un error de formato incompatible.

+0

No estoy seguro de por qué esto sería un problema ya que he configurado kAudioFormatFlagsAudioUnitCanonical para el formato banderas. La documentación indica que se trata de un formato de punto fijo de 8,24 bits. – irtemed88

0

La línea bufferList = (AudioBufferList *)malloc(sizeof(AudioBuffer)); también es incorrecta. Como AudioBuffer es más pequeño que AudioBufferList, no asigna suficiente memoria.

Cuestiones relacionadas