2011-10-24 28 views
12

Pracuję nad uzyskaniem dźwięku do iPhone'a w formie, w której mogę przekazać go do algorytmu analizy (C++). Istnieje oczywiście wiele opcji: samouczek AudioQueue at trailsinthesand uruchamia się.Jak uzyskać tablicę danych audio float z AudioQueueRef w systemie iOS?

Odwołanie audio daje jednak AudioQueueRef, a dokumentacja Apple'a jest cienka po tej stronie rzeczy. Wbudowane metody zapisu do pliku, ale nic, co faktycznie znajduje się wewnątrz pakietów, aby wyświetlić dane.

Potrzebuję danych. Nie chcę niczego zapisywać w pliku, na co wydaje się, że wszystkie samouczki - a nawet obiekty wygody Apple'a - celują. Apple's AVAudioRecorder (irytująco) da ci poziomy i zapisze dane, ale nie da ci dostępu do niego. Chyba że czegoś brakuje ...

Jak to zrobić? W poniższym kodzie znajduje się inBuffer->mAudioData, która jest kusząco bliska, ale nie mogę znaleźć informacji o tym, w jakim formacie są te "dane" i jak uzyskać do niego dostęp.

AudioQueue oddzwaniania:

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); 
} 

I kod do zapisu dźwięku do pliku:

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; 
} 

Odpowiedz

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; 

Wtedy masz (w tym przypadku SInt16) tablica samples które można dostęp z samples[0] do samples[sampleCount-1]. .

+0

ta "próbka" tablica, ile sekund próbkowania zawiera? to jest ta binarna reprezentacja nagranego audio? –

+0

"próbki" zawiera próbki o wartości jednego bufora. Długość sekund zależy od rozmiaru bufora i częstotliwości próbkowania: 512 próbek przy 44,1 kHz to 512/44100 = .011609977 sek. – buildsucceeded

0

Powyższe rozwiązanie nie działa dla mnie, był już zły sam przykładowych danych (an endian problem) Jeżeli okrywać ktoś robi źle przykładowych danych w przyszłości, mam nadzieję, że to pomaga:

- (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); 
}