2013-12-19 2 views
2

Итак, в основном я хочу сыграть в audio files (в основном, в mp3 и в кафе). Но callback никогда не вызван. Только когда я вызываю их, чтобы заправлять очередь.Обратный звонок звуковой дорожки не называется

Вот мои данные структура:

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

Вот моя функция обратного вызова:

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

А вот мой метод:

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

} 

И выход, когда я нажимаю играть:

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

Я попытался заменить CFRunLoopGetCurrent() на CFRunLoopGetMain() и CFRunLoopCommonModes с CFRunLoopDefaultMode, но ничего.

Не должны ли начальные буферы начать играть сразу, я запускаю очередь? Когда я запускаю очередь, никакие обратные вызовы не срабатывают. Что я делаю неправильно? Спасибо за любые идеи

ответ

3

То, что вы в основном пытаетесь сделать здесь, является основным примером воспроизведения звука с использованием звуковых очередей. Не смотря на подробный код, чтобы узнать, чего не хватает (это может занять некоторое время), я бы рекомендовал вам выполнить следующие шаги в this basic sample code, который делает именно то, что вы делаете (без дополнительных функций, которые не очень актуальны. например, почему вы пытаетесь добавить прирост аудио?)

Где-то еще вы пытались воспроизвести аудио с помощью аудиоустройств. Аудиоустройства более сложны, чем основное воспроизведение аудиопотоков, и я бы не стал их пытаться, прежде чем был бы очень удобен в звуковых очередях. Но вы можете посмотреть на этот example project для базового примера звуковых очередей.

В общем, когда дело доходит до программирования Core Audio в iOS, вам лучше не торопиться с основными примерами и строить свой путь вверх .. Проблема с множеством обучающих онлайн заключается в том, что они добавляют дополнительный материал и часто смешивают это с кодом obj-c .., когда Core Audio является чисто C-кодом (т. е. лишний материал ничего не добавит к процессу обучения). Я настоятельно рекомендую вам перечислить книгу Learning Core Audio, если вы еще этого не сделали. Весь образец кода доступен в Интернете, но вы также можете клонировать его с this репо для удобства. Вот как я узнал основные аудио. Требуется время :)

+0

Спасибо abbood, я рассмотрю пример кода;) – Skiny

+0

Наконец-то он работает! Jeeeeez: D в примере с файловым игроком были некоторые вещи, которые я пропустил – Skiny

+0

@Skiny hey man рад, что это сработало. Core Audio - это другое животное, когда дело доходит до iOS .. он требует много обучения и чтения. Снова я настоятельно рекомендую вам прочитать книгу .. и использовать примеры .. они спасатели жизни – abbood

Смежные вопросы