2013-12-19 2 views
2

기본적으로 나는 audio files (mp3 및 caf 대부분)을 재생하려고합니다. 그러나 콜백은 결코 호출되지 않습니다. 큐를 프라임하도록 호출 할 때만.오디오 큐 콜백이 호출되지 않음

struct AQPlayerState 
{ 
    CAStreamBasicDescription  mDataFormat; 
    AudioQueueRef     mQueue; 
    AudioQueueBufferRef    mBuffers[kBufferNum]; 
    AudioFileID      mAudioFile; 
    UInt32       bufferByteSize; 
    SInt64       mCurrentPacket; 
    UInt32       mNumPacketsToRead; 
    AudioStreamPacketDescription *mPacketDescs; 
    bool       mIsRunning; 
}; 

가 여기 내 콜백 함수입니다 :

가 여기 내 데이터 구조체의 내가 플레이를 누를 때

- (void)playFile 
{ 
    AQPlayerState aqData; 

    // get the source file 
    NSString *p = [[NSBundle mainBundle] pathForResource:@"1_Female" ofType:@"mp3"]; 
    NSURL *url2 = [NSURL fileURLWithPath:p]; 
    CFURLRef srcFile = (__bridge CFURLRef)url2; 

    OSStatus result = AudioFileOpenURL(srcFile, 0x1/*fsRdPerm*/, 0/*inFileTypeHint*/, &aqData.mAudioFile); 
    CFRelease (srcFile); 

    CheckError(result, "Error opinning sound file"); 

    UInt32 size = sizeof(aqData.mDataFormat); 
    CheckError(AudioFileGetProperty(aqData.mAudioFile, kAudioFilePropertyDataFormat, &size, &aqData.mDataFormat), 
       "Error getting file's data format"); 

    CheckError(AudioQueueNewOutput(&aqData.mDataFormat, HandleOutputBuffer, &aqData, CFRunLoopGetCurrent(), kCFRunLoopCommonModes, 0, &aqData.mQueue), 
       "Error AudioQueueNewOutPut"); 

    // we need to calculate how many packets we read at a time and how big a buffer we need 
    // we base this on the size of the packets in the file and an approximate duration for each buffer 
    { 
     bool isFormatVBR = (aqData.mDataFormat.mBytesPerPacket == 0 || aqData.mDataFormat.mFramesPerPacket == 0); 

     // first check to see what the max size of a packet is - if it is bigger 
     // than our allocation default size, that needs to become larger 
     UInt32 maxPacketSize; 
     size = sizeof(maxPacketSize); 
     CheckError(AudioFileGetProperty(aqData.mAudioFile, kAudioFilePropertyPacketSizeUpperBound, &size, &maxPacketSize), 
        "Error getting max packet size"); 

     // adjust buffer size to represent about a second of audio based on this format 
     CalculateBytesForTime(aqData.mDataFormat, maxPacketSize, 1.0/*seconds*/, &aqData.bufferByteSize, &aqData.mNumPacketsToRead); 

     if (isFormatVBR) { 
      aqData.mPacketDescs = new AudioStreamPacketDescription [aqData.mNumPacketsToRead]; 
     } else { 
      aqData.mPacketDescs = NULL; // we don't provide packet descriptions for constant bit rate formats (like linear PCM) 
     } 

     printf ("Buffer Byte Size: %d, Num Packets to Read: %d\n", (int)aqData.bufferByteSize, (int)aqData.mNumPacketsToRead); 
    } 

    // if the file has a magic cookie, we should get it and set it on the AQ 
    size = sizeof(UInt32); 
    result = AudioFileGetPropertyInfo(aqData.mAudioFile, kAudioFilePropertyMagicCookieData, &size, NULL); 

    if (!result && size) { 
     char* cookie = new char [size]; 
     CheckError(AudioFileGetProperty(aqData.mAudioFile, kAudioFilePropertyMagicCookieData, &size, cookie), 
        "Error getting cookie from file"); 
     CheckError(AudioQueueSetProperty(aqData.mQueue, kAudioQueueProperty_MagicCookie, cookie, size), 
        "Error setting cookie to file"); 
     delete[] cookie; 
    } 

    aqData.mCurrentPacket = 0; 
    for (int i = 0; i < kBufferNum; ++i) { 
     CheckError(AudioQueueAllocateBuffer (aqData.mQueue, 
              aqData.bufferByteSize, 
              &aqData.mBuffers[i]), 
        "Error AudioQueueAllocateBuffer"); 

     HandleOutputBuffer (&aqData, 
          aqData.mQueue, 
          aqData.mBuffers[i]); 
    } 

    // set queue's gain 

    Float32 gain = 1.0; 
    CheckError(AudioQueueSetParameter (aqData.mQueue, 
             kAudioQueueParam_Volume, 
             gain), 
       "Error AudioQueueSetParameter"); 

    aqData.mIsRunning = true; 
    CheckError(AudioQueueStart(aqData.mQueue, 
           NULL), 
       "Error AudioQueueStart"); 

} 

그리고 출력 : 여기

static void HandleOutputBuffer (void *aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) 
{ 
    NSLog(@"HandleOutput"); 
    AQPlayerState *pAqData = (AQPlayerState *) aqData; 

    if (pAqData->mIsRunning == false) return; 

    UInt32 numBytesReadFromFile; 
    UInt32 numPackets = pAqData->mNumPacketsToRead; 
    AudioFileReadPackets (pAqData->mAudioFile, 
          false, 
          &numBytesReadFromFile, 
          pAqData->mPacketDescs, 
          pAqData->mCurrentPacket, 
          &numPackets, 
          inBuffer->mAudioData); 
    if (numPackets > 0) {  
     inBuffer->mAudioDataByteSize = numBytesReadFromFile; 
     AudioQueueEnqueueBuffer (pAqData->mQueue, 
           inBuffer, 
           (pAqData->mPacketDescs ? numPackets : 0), 
           pAqData->mPacketDescs); 
     pAqData->mCurrentPacket += numPackets; 
    } else { 
//  AudioQueueStop(pAqData->mQueue, false); 
//  AudioQueueDispose(pAqData->mQueue, true); 
//  AudioFileClose (pAqData->mAudioFile); 
//  free(pAqData->mPacketDescs); 
//  free(pAqData->mFloatBuffer); 
     pAqData->mIsRunning = false; 
    } 
} 

그리고 나의 방법이다

Buffer Byte Size: 40310, Num Packets to Read: 38 
HandleOutput start 
HandleOutput start 
HandleOutput start 

CFRunLoopGetCurrent()CFRunLoopGetMain()CFRunLoopCommonModes으로 바꾸어 시도했지만 아무런 결과가 없습니다.

줄무늬가있는 버퍼가 즉시 재생되기 시작해서는 안되며 큐를 시작해야합니까? 대기열을 시작할 때 콜백이 발생하지 않습니다. 내가 뭘 잘못하고 있니? 어떤 아이디어를 가져 주셔서 감사합니다

답변

3

기본적으로 여기에서하려고하는 것은 오디오 대기열을 사용하는 오디오 재생의 기본 예입니다. 세부 사항에서 귀하의 코드를 보지 않고 (오랜 시간이 걸릴 수 있음) 오히려 당신이 정확히 무엇을하고 있는지를 (this basic sample code)의 단계를 따르는 것이 좋습니다. 예를 들어 왜 오디오 게인을 추가하려고하는 것입니까?)

오디오 단위를 사용하여 오디오를 재생하려고했던 곳이 있습니다. 오디오 단위는 기본 오디오 대기열 재생보다 더 복잡합니다. 오디오 대기열에 매우 익숙해지기 전에 시도하지 않겠습니다. 그러나 오디오 큐의 기본 예제는 example project에서 확인할 수 있습니다.

일반적으로 iOS의 Core Audio 프로그래밍에 관해서는 기본 예제로 시간을 보내고 길을 만드는 것이 가장 좋습니다. 온라인 자습서의 많은 문제점은 추가 자료를 추가하고 종종 혼합합니다. 그것은 obj-c 코드로 .. Core Audio가 순전히 C 코드 일 때 (즉, 여분의 것들은 학습 과정에 아무 것도 추가하지 않을 것입니다). 아직 책이 없다면 Learning Core Audio 책을 읽으시기 바랍니다. 모든 샘플 코드는 온라인에서 사용할 수 있지만 편의를 위해 this repo에서 복제 할 수도 있습니다. 이것이 내가 핵심 오디오를 배웠던 방식입니다. 그것은 시간이 걸립니다 :)

+0

감사합니다 abbood, 나는 샘플 코드를 통해 갈거야;) – Skiny

+0

마침내 작동! Jeeeeez : D 파일 플레이어 예를 들어 내가 놓친 것 몇 가지가 있습니다. – Skiny

+0

@Skiny 헤이 남자가 다행 이네요. Core Audio는 iOS에 관해서는 다른 동물입니다. 많은 교육과 독서가 필요합니다. 다시 책을 읽고 사례를 사용하는 것이 좋습니다. 그들은 생명의 은인입니다. – abbood

관련 문제