2013-09-23 2 views
1

У меня странная проблема. Мой код отлично работает как на iOS 5 & 6, но при работе на iOS 7 я получаю пустые буферы на обратном вызове AudioQueue.Обратный вызов AudioQueue получает пустой буфер только на iOS 7

Возможный соответствующий код:

- (void)setUpAudioFormat 
{ 
audioFormat.mFormatID   = kAudioFormatLinearPCM; 
audioFormat.mSampleRate  = SAMPLE_RATE;//16000.0; 
audioFormat.mChannelsPerFrame = CHANNELS;//1; 
audioFormat.mBitsPerChannel = 16; 
audioFormat.mFramesPerPacket = 1; 
audioFormat.mBytesPerFrame = audioFormat.mChannelsPerFrame * sizeof(SInt16); 
audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket; 
audioFormat.mFormatFlags  = kLinearPCMFormatFlagIsSignedInteger 
| kLinearPCMFormatFlagIsPacked; 

bufferNumPackets = 2048; // must be power of 2 for FFT! 
bufferByteSize = [self byteSizeForNumPackets:bufferNumPackets]; 

} 

- (UInt32)numPacketsForTime:(Float64)seconds 
{ 
return (UInt32) (seconds * audioFormat.mSampleRate/audioFormat.mFramesPerPacket); 
} 

- (UInt32)byteSizeForNumPackets:(UInt32)numPackets 
{ 
return numPackets * audioFormat.mBytesPerPacket; 
} 

- (void)setUpRecordQueue 
{ 
NSLog(@"\n+++ setUpRecordQueue"); 
OSStatus errorStatus = AudioQueueNewInput(
        &audioFormat, 
        recordCallback, 
        self,    // userData 
        CFRunLoopGetMain(), // run loop 
        NULL,    // run loop mode 
        0,     // flags 
        &recordQueue); 

if (errorStatus) { 
    NSLog(@"\n\n ERROR : Error %ld on AudioQueueNewInput\n", errorStatus); 
} 


if (recordQueue == nil) { 
    NSLog(@"\n\n ----- Record Queue is nil! -----"); 
} 

UInt32 trueValue = true; 
     AudioQueueSetProperty(recordQueue,kAudioQueueProperty_EnableLevelMetering,&trueValue,sizeof (UInt32)); 
} 

- (void)setUpRecordQueueBuffers 
{ 
NSLog(@"\n+++ setUpRecordQueueBuffers"); 
assert(recordQueue != nil); 
for (int t = 0; t < NUMBER_AUDIO_DATA_BUFFERS; ++t) 
{ 
    OSStatus errorStatus = AudioQueueAllocateBuffer(
          recordQueue, 
          bufferByteSize, 
          &recordQueueBuffers[t]); 
    if (errorStatus) { 
     NSLog(@"\n\n ERROR : Error %ld on AudioQueueAllocateBuffer\n", errorStatus); 
    } 
} 
} 

- (void)primeRecordQueueBuffers 
{ 
NSLog(@"\n+++ primeRecordQueueBuffers"); 
assert(recordQueue != nil); 
for (int t = 0; t < NUMBER_AUDIO_DATA_BUFFERS; ++t) 
{ 
    OSStatus errorStatus = AudioQueueEnqueueBuffer(
          recordQueue, 
          recordQueueBuffers[t], 
          0, 
          NULL); 
    if (errorStatus) { 
     NSLog(@"\n\n ERROR : Error %ld on AudioQueueEnqueueBuffer\n", errorStatus); 
    } 
} 
} 

- (void)startRecording 
{ 
[self startRecording:FALSE]; 
} 

- (void)startRecording:(BOOL) autoStop 
{ 
NSLog(@"Starting to record"); 

recording = YES; 
shouldStopRecording = NO; 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 
       , ^{ 
    NSLog(@"PPPP C1"); 
    _frameIndex= 0; 
    self.fileWasCreated = NO; 
    [self setUpRecordQueue]; 
    NSLog(@"PPPP C2"); 
    [self setUpRecordQueueBuffers]; 
    NSLog(@"PPPP C3"); 
    [self primeRecordQueueBuffers]; 
    NSLog(@"PPPP C4"); 

    AudioQueueStart(recordQueue, NULL); 
    NSLog(@"PPPP C5"); 

    if (autoStop) { 
     [self stopRecording]; 
    } 

}); 

} 

- (void)stopRecording 
{ 
NSLog(@"Stoping to record"); 
if (recordQueue != nil) { 
    NSString *osVersion = [[UIDevice currentDevice] systemVersion]; 

    if ([osVersion doubleValue]<6){ 
     AudioQueueDispose(recordQueue, TRUE); 
    } 
    else { 
     AudioQueueStop(recordQueue, FALSE); 
    } 

    recordQueue = nil; 
} 

NSLog(@"Stopped recording"); 

shouldStopRecording = YES; 
recording = NO; 

} 

обратные вызовов:

static void recordCallback(
         void* inUserData, 
         AudioQueueRef inAudioQueue, 
         AudioQueueBufferRef inBuffer, 
         const AudioTimeStamp* inStartTime, 
         UInt32 inNumPackets, 
         const AudioStreamPacketDescription* inPacketDesc) 
{ 
NSLog(@"recordCallback %u", (unsigned int)inBuffer->mAudioDataByteSize); 
// I get always zero here... 

} 

Btw, мик разрешения нормально (разрешить доступ к микрофону).

ОБНОВЛЕНИЕ: Похоже, что ошибка AudioQueueStart с ошибкой -50. Это происходит только на iOS 7. Есть ли проблема с параметрами, которые я установил?

+0

вы когда-нибудь найти решение о вашем проблема на ошибке -50? – Saliom

+0

просто хотел сказать большое толстое спасибо вам, благодаря вашему примеру кода и книге, которую вы связали в своем ответе, я смог сделать то, что мне нужно :) – Saliom

+0

просто хедз-ап, если кто-то пытается сделать ваш код работа и заканчивает получение сбоя на ios 7: попробуйте с этим: audioFormat.mBytesPerFrame = (audioFormat.mBitsPerChannel/8) * audioFormat.mCannelsPerFrame; audioFormat.mBytesPerPacket = (audioFormat.mBitsPerChannel/8) * audioFormat.mCannelsPerFrame; – Saliom

ответ

6

Я нашел проблему! похоже, на iOS 7 есть необходимость установить это также (я предполагаю, что это только практически поэтому трудно найти, нигде не написано). Просто добавьте этот код перед вызовом любой функции AudioQueue:

AudioSessionInitialize(NULL, 
         NULL, 
         nil, 
         (void *)(self) 
         ); 

UInt32 sessionCategory = kAudioSessionCategory_PlayAndRecord; 
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, 
         sizeof(sessionCategory), 
         &sessionCategory 
         ); 

AudioSessionSetActive(true); 

Надеюсь, что это поможет другим.

Еще один ресурс, который может помочь найти here.

+1

У меня также есть аналогичная проблема и решение добавив вышеприведенную строку кода, но эти методы амортизируются в iOS 7. –

+0

@MuhammadZeeshan Это старый ответ, но он все еще работает. Вы нашли новое решение? (Я буду рад обновить этот) – Idan

5

@Idan вашего ответ является правильным и работает, но это только показывает предупреждение, если цель приложение Minimun развертывания IOS 7. Для прошивки 7 мы можем сделать что-то вроде этого:

NSError *audioSessionError; 
AVAudioSession *audioSession = [AVAudioSession sharedInstance]; 
[audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:&audioSessionError]; 

if(audioSessionError) 
{ 
    NSLog(@"AVAudioSession error setting category:%@",audioSessionError); 
} 
else 
{ 
    [audioSession setActive:YES error:&audioSessionError]; 
    if(audioSessionError) 
     NSLog(@"AVAudioSession error activating: %@",audioSessionError); 
} 
Смежные вопросы