Audio Player

http://stackoverflow.com/questions/17963435/ios-audio-queue-services-queue-starvation-causes-silence

#define kNumAQBufs 1
#define kAudioBufferSeconds 3

void audioQueueOutputCallback(void *inClientData, AudioQueueRef inAQ,
                              AudioQueueBufferRef inBuffer)
{
    BaseSecurityMediaView *baseSecurity = (__bridge BaseSecurityMediaView*)inClientData;
    [baseSecurity audioQueueOutputCallback:inAQ inBuffer:inBuffer];
}

/**
 * This is basically called in response to getting audio frames over the network
 * asynchronously.
 */
- (void)doAudioRendering:(NSData *)data
{
    [m_audioPacketQueue addObject:data];
    m_audioPacketQueueSize += [data length];

    // must start the audio queue once enough queued
    if(!m_audioQueueStarted && [m_audioPacketQueue count] >= kNumAQBufs) {
        [self startAudioQueue];
    }

    // manually enqueue buffers?
    if(m_audioQueueStarted) {
        for (NSInteger i = 0; i < kNumAQBufs; ++i) {
            [self enqueueAudioBuffer:m_audioQueueBuffer[i]];
        }
    }
}
- (void)startAudioQueue
{
    if(m_audioQueueStarted) {
        AudioQueueStart(m_audioQueue, NULL);
    }
    else {
        [self createAudioQueue];
        [self startQueue];
    }

    // prime the buffers?
    for(NSInteger i = 0; i < kNumAQBufs; i++) {
        [self enqueueAudioBuffer:m_audioQueueBuffer[i]];
    }

    m_audioQueueState = AUDIO_STATE_PLAYING;
}
- (BOOL)createAudioQueue
{
    m_audioQueueState = AUDIO_STATE_READY;
    m_audioQueueFinished = NO;

    m_audioStreamBasicDesc.mFormatID = kAudioFormatULaw;
    m_audioStreamBasicDesc.mSampleRate = m_audioSampleRate;
    m_audioStreamBasicDesc.mFormatFlags = 0;
    m_audioStreamBasicDesc.mFramesPerPacket = 1;
    m_audioStreamBasicDesc.mChannelsPerFrame = m_audioNumChannels;
    m_audioStreamBasicDesc.mBitsPerChannel = 8;
    m_audioStreamBasicDesc.mBytesPerPacket = 1;
    m_audioStreamBasicDesc.mBytesPerFrame = 1;

    OSStatus status = AudioQueueNewOutput(&m_audioStreamBasicDesc, audioQueueOutputCallback, (__bridge void*)self, NULL, NULL, 0, &m_audioQueue);
    if(status != noErr) {
        NSLog(@"Could not create new output.");
        return NO;
    }

    // allocate buffers
    for(NSInteger i = 0; i < kNumAQBufs; i++) {
        status = AudioQueueAllocateBufferWithPacketDescriptions(m_audioQueue,
                                                                m_audioStreamBasicDesc.mSampleRate * kAudioBufferSeconds / 8,
                                                                m_audioStreamBasicDesc.mSampleRate * kAudioBufferSeconds /
                                                                m_audioStreamBasicDesc.mBytesPerFrame + 1,
                                                                &m_audioQueueBuffer[i]);
        if(status != noErr) {
            NSLog(@"Could not allocate buffer.");
            return NO;
        }
    }

    return YES;
}

- (void)audioQueueOutputCallback:(AudioQueueRef)inAQ inBuffer:(AudioQueueBufferRef)inBuffer
{

    if(m_audioQueueState == AUDIO_STATE_PLAYING) {
        [self enqueueAudioBuffer:inBuffer];
    }
}

- (OSStatus)enqueueAudioBuffer:(AudioQueueBufferRef)buffer {
    OSStatus status = noErr;
    buffer->mAudioDataByteSize = 0;
    buffer->mPacketDescriptionCount = 0;

    // this seems to happen a lot
    if(m_audioPacketQueue.count <= 0) {
        return status;
    }

    while(m_audioPacketQueue.count && buffer->mPacketDescriptionCount < buffer->mPacketDescriptionCapacity) {
        // grab packet that was received from network
        NSData *packet = [m_audioPacketQueue objectAtIndex:0];
        m_audioPacketQueueSize -= [packet length];
        [m_audioPacketQueue removeObjectAtIndex:0];

        // move data in
        if(buffer->mAudioDataBytesCapacity - buffer->mAudioDataByteSize >= [packet length]) {
            memcpy((uint8_t *)buffer->mAudioData + buffer->mAudioDataByteSize, [packet bytes], [packet length]);
            buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mStartOffset = buffer->mAudioDataByteSize;
            buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mDataByteSize = [packet length];
            buffer->mPacketDescriptions[buffer->mPacketDescriptionCount].mVariableFramesInPacket = m_audioStreamBasicDesc.mBytesPerFrame;

            buffer->mAudioDataByteSize += [packet length];
            buffer->mPacketDescriptionCount++;
        }
        else {
            break;
        }
    }
    if(buffer->mPacketDescriptionCount > 0) {
        status = AudioQueueEnqueueBuffer(m_audioQueue, buffer, 0, NULL);
        if(status != noErr) {
            NSLog(@"Could not enqueue buffer.");
        }
    }

    return status;
}

- (OSStatus)startQueue
{
    OSStatus status = noErr;

    if(!m_audioQueueStarted) {
        status = AudioQueueStart(m_audioQueue, NULL);
        if(status == noErr) {
            m_audioQueueStarted = YES;
        }
        else {
            NSLog(@"Could not start audio queue.");
        }
    }

    return status;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值