2011-10-24 8 views
12

Estoy trabajando para obtener audio en el iPhone de forma que pueda pasarlo a un algoritmo de análisis (C++). Hay, por supuesto, muchas opciones: el tutorial de AudioQueue at trailsinthesand hace que las cosas comiencen.¿Cómo obtener una matriz de datos flotantes de AudioQueueRef en iOS?

La devolución de llamada de audio, sin embargo, da un AudioQueueRef, y estoy encontrando la documentación de Apple delgada de este lado de las cosas. Métodos integrados para escribir en un archivo, pero no hay nada donde realmente mire dentro de los paquetes para ver los datos.

Necesito los datos. No quiero escribir nada en un archivo, que es a lo que todos los tutoriales, e incluso los convenientes objetos de E/S de Apple, parecen apuntar. El número AVAudioRecorder de Apple (exasperante) le dará niveles y escribirá los datos, pero no le dará acceso a ellos. A menos que me falta algo ...

¿Cómo hacer esto? En el siguiente código está el inBuffer->mAudioData, que está tentadoramente cerca, pero no puedo encontrar información sobre el formato en el que se encuentran estos "datos" ni cómo acceder a ellos.

AudioQueue de devolución de llamada:

void AudioInputCallback(void *inUserData, 
    AudioQueueRef inAQ, 
    AudioQueueBufferRef inBuffer, 
    const AudioTimeStamp *inStartTime, 
    UInt32 inNumberPacketDescriptions, 
    const AudioStreamPacketDescription *inPacketDescs) 
{ 
    static int count = 0; 
    RecordState* recordState = (RecordState*)inUserData;  
    AudioQueueEnqueueBuffer(recordState->queue, inBuffer, 0, NULL); 

    ++count; 
    printf("Got buffer %d\n", count); 
} 

Y el código para escribir el audio a un archivo:

OSStatus status = AudioFileWritePackets(recordState->audioFile, 
       false, 
       inBuffer->mAudioDataByteSize, 
       inPacketDescs, 
       recordState->currentPacket, 
       &inNumberPacketDescriptions, 
       inBuffer->mAudioData); // THIS! This is what I want to look inside of. 
if(status == 0) 
{ 
    recordState->currentPacket += inNumberPacketDescriptions; 
} 

Respuesta

10
// so you don't have to hunt them all down when you decide to switch to float: 
    #define AUDIO_DATA_TYPE_FORMAT SInt16 

    // the actual sample-grabbing code: 
    int sampleCount = inBuffer->mAudioDataBytesCapacity/sizeof(AUDIO_DATA_TYPE_FORMAT); 
    AUDIO_DATA_TYPE_FORMAT *samples = (AUDIO_DATA_TYPE_FORMAT*)inBuffer->mAudioData; 

entonces usted tiene su (en este caso SInt16) matriz samples las cuales se puede acceso desde samples[0] a samples[sampleCount-1]. .

+0

este conjunto de "muestras", ¿cuántos segundos de muestreo contiene? esta es esta representación binaria del audio grabado? –

+0

"samples" contiene el valor de una muestra de buffer. La duración en segundos depende del tamaño del búfer y la frecuencia de muestreo: 512 muestras a 44.1kHz son 512/44100 = .011609977 seg. – buildsucceeded

0

La solución anterior no funcionó para mí, que estaba recibiendo los datos de muestra equivocada en sí (un problema endian) Si incase alguien está recibiendo datos de las muestras erróneas en el futuro, espero que esto le ayuda a:

- (void) feedSamplesToEngine: (UInt32) audioDataBytesCapacity audioData: (void *) audioData { int sampleCount = audioDataBytesCapacity/sizeof (SAMPLE_TYPE);

SAMPLE_TYPE *samples = (SAMPLE_TYPE*)audioData; 
//SAMPLE_TYPE *sample_le = (SAMPLE_TYPE *)malloc(sizeof(SAMPLE_TYPE)*sampleCount);//for swapping endians 

std::string shorts; 
double power = pow(2,10); 
for(int i = 0; i < sampleCount; i++) 
{ 
    SAMPLE_TYPE sample_le = (0xff00 & (samples[i] << 8)) | (0x00ff & (samples[i] >> 8)) ; //Endianess issue 
    char dataInterim[30]; 
    sprintf(dataInterim,"%f ", sample_le/power); // normalize it. 
    shorts.append(dataInterim); 
} 
Cuestiones relacionadas