2011-10-24 4 views
12

나는 (C++) 분석 알고리즘에 전달할 수있는 형태로 오디오를 iPhone으로 가져오고 있습니다. 물론 많은 옵션이 있습니다 : AudioQueue 튜토리얼 at trailsinthesand이 시작됩니다.iOS의 AudioQueueRef에서 플로트 오디오 데이터의 배열을 얻는 방법은 무엇입니까?

오디오 콜백은 AudioQueueRef이며, Apple 측의 설명서는이 부분에 희미합니다. 파일에 쓸 수있는 내장 메소드는 있지만 실제로 패킷 내부에서 데이터를 볼 수있는 곳은 없습니다.

데이터가 필요합니다. 필자는 파일에 무엇이든 쓰고 싶지 않습니다. 모든 튜토리얼과 심지어 Apple의 편리한 I/O 객체조차도 목표로 삼고있는 것입니다. 애플의 AVAudioRecorder (분노하게)은 당신에게 레벨을주고 데이터를 쓸 것이지만 실제로는 액세스 할 수는 없습니다. 내가 뭔가를 놓치지 않는 한 ...

어떻게하는가? 아래의 코드에는이 있습니다.이 정보는 거의 알려지지 않았지만이 '데이터'형식이나 액세스 방법에 대한 정보는 찾을 수 없습니다.

AudioQueue 콜백 :

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

그리고 코드가 파일에 오디오 쓰기 : 배열 samples (이 경우 SInt16에)

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

답변

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; 

그런 다음 당신은 당신이를하는 당신이 할 수있는 samples[0]에서 samples[sampleCount-1]으로 액세스하십시오. .

+0

이 "샘플"배열에는 샘플링에 몇 초가 들어 있습니까? 녹음 된 오디오의 이진 표현입니까? –

+0

"samples"에는 하나의 버퍼에 해당하는 샘플이 들어 있습니다. 길이는 버퍼 크기와 샘플 속도에 따라 다르며, 44.1kHz에서 512 샘플은 512/44100 = .011609977 초입니다. – buildsucceeded

0

위의 솔루션은 나를 위해 작동하지 않았다, 내가 잘못 샘플 데이터 자체를 얻고 있었다 (엔디안 문제) 넣다 사람이 미래에 잘못된 샘플 데이터를 가져 오는 경우,이 당신에게 도움이되기를 바랍니다 :

- (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); 
} 
관련 문제