2010-11-28 30 views
7

Estoy intentando acceder a los datos brutos de un archivo de audio en el iPhone/iPad. Tengo el siguiente código, que es un comienzo básico en el camino que necesito. Sin embargo, estoy perplejo sobre qué hacer una vez que tengo un AudioBuffer.Determinar el número de fotogramas en un Core Audio AudioBuffer

AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:urlAsset error:nil]; 
AVAssetReaderTrackOutput *assetReaderOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:[[urlAsset tracks] objectAtIndex:0] outputSettings:nil]; 
[assetReader addOutput:assetReaderOutput]; 
[assetReader startReading]; 

CMSampleBufferRef ref; 
NSArray *outputs = assetReader.outputs; 
AVAssetReaderOutput *output = [outputs objectAtIndex:0]; 
int y = 0; 
while (ref = [output copyNextSampleBuffer]) { 
    AudioBufferList audioBufferList; 
    CMBlockBufferRef blockBuffer; 
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(ref, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer); 
    for (y=0; y<audioBufferList.mNumberBuffers; y++) { 
     AudioBuffer audioBuffer = audioBufferList.mBuffers[y]; 
     SInt16 *frames = audioBuffer.mData; 
     for(int i = 0; i < 24000; i++) { // This sometimes crashes 
      Float32 currentFrame = frames[i]/32768.0f; 
     } 
    } 
} 

Esencialmente no sé cómo decirle cuántos fotogramas cada búfer contiene así que no puedo extraer de forma fiable los datos de ellos. Soy nuevo en el trabajo con datos de audio en bruto, por lo que estoy abierto a cualquier sugerencia sobre cómo leer mejor la propiedad mData de la estructura de AudioBuffer. Tampoco he hecho mucho con punteros vacíos en el pasado, así que ayuda con eso en este contexto también sería genial.

+0

¡Excelente pregunta! Tu pregunta ayudó a resolver mi problema similar. – user523234

+0

está filtrando blockBuffer –

Respuesta

13

audioBuffer.mDataByteSize le indica el tamaño del búfer. Sabias esto? Solo en caso de que no lo hicieras, no podrías haber visto la declaración de struct AudioBuffer. Siempre debe mirar los archivos de encabezado, así como los documentos.

Para que mDataByteSize tenga sentido, debe conocer el formato de los datos. El recuento de valores de salida es mDataByteSize/sizeof (outputType). Sin embargo, pareces confundido con el formato, debes haberlo especificado en alguna parte. En primer lugar usted lo trata como de 16 bits firmado int

SInt16 *frames = audioBuffer.mData

entonces se trata como flotante de 32 bits

Float32 currentFrame = frames[i]/32768.0f

entre medio se supone que existen 24000 valores, por supuesto, esto fallar si no hay exactamente 24000 valores de 16 bits. Además, se refiere a los datos como 'marcos', pero lo que realmente quiere decir son muestras. Cada valor que usted llame 'currentFrame' es una muestra del audio. 'Frame' normalmente se referiría a un bloque de muestras como .mData

Por lo tanto, suponiendo que el formato de datos es Float de 32 bits (y tenga en cuenta que no sé si lo es, podría ser de 8 bits int o de 32 bits Fixed por lo que sé)

for(int y=0; y<audioBufferList.mNumberBuffers; y++) 
{ 
    AudioBuffer audioBuffer = audioBufferList.mBuffers[y]; 
    int bufferSize = audioBuffer.mDataByteSize/sizeof(Float32); 
    Float32 *frame = audioBuffer.mData; 
    for(int i=0; i<bufferSize; i++) { 
    Float32 currentSample = frame[i]; 
    } 
} 

Nota, sizeof (Float32) siempre es 4, pero lo dejé en ser claro.

+0

audioBuffer.mDataByteSize/sizeof (Float32) fue la parte que necesitaba gracias! – macinjosh

+0

Si hace clic en cmd en AudioBuffer, xcode debe pasar a la declaración estricta en el archivo de encabezado. Útil para verificar lo que está tratando. – hooleyhoop

+4

Una digresión, pero la definición de Core Audio de un marco es una muestra en todos los canales. – sbooth

Cuestiones relacionadas