首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CoreAudio AudioQueue停止问题

CoreAudio AudioQueue停止问题
EN

Stack Overflow用户
提问于 2013-10-27 22:51:39
回答 1查看 940关注 0票数 3

我正在制作一个基于CoreAudio的FLAC播放器,并与AudioQueues遇到了一个顽皮的问题。我正在像这样初始化我的内容(以下划线开头的变量是实例变量):

代码语言:javascript
复制
    _flacDecoder = FLAC__stream_decoder_new();

    AudioStreamBasicDescription asbd = {
        .mFormatID = kAudioFormatLinearPCM,
        .mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked,
        .mSampleRate = 44100,
        .mChannelsPerFrame = 2,
        .mBitsPerChannel = 16,
        .mBytesPerPacket = 4,
        .mFramesPerPacket = 1,
        .mBytesPerFrame = 4,
        .mReserved = 0
    };

    AudioQueueNewOutput(&asbd, HandleOutputBuffer, (__bridge void *)(self), CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &_audioQueue);

    for (int i = 0; i < kNumberBuffers; ++i) {
        AudioQueueAllocateBuffer(_audioQueue, 0x10000, &_audioQueueBuffers[i]);
    }

    AudioQueueSetParameter(_audioQueue, kAudioQueueParam_Volume, 1.0);

16位立体声PCM在44.1 kHz,相当基本的设置。kNumberBuffers为3,每个缓冲区为0x10000字节。我用以下回调填充缓冲区:

代码语言:javascript
复制
static void HandleOutputBuffer(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer){

    FLACPlayer * self = (__bridge FLACPlayer*)inUserData;

    UInt32 largestBlockSizeInBytes = self->_currentStreamInfo.max_blocksize * self->_currentStreamInfo.channels * self->_currentStreamInfo.bits_per_sample/8;

    inBuffer->mAudioDataByteSize = 0;
    self->_buffer = inBuffer;

    while(inBuffer->mAudioDataByteSize <= inBuffer->mAudioDataBytesCapacity - largestBlockSizeInBytes){
        FLAC__bool result = FLAC__stream_decoder_process_single(self->_flacDecoder);
        assert(result);

        if(FLAC__stream_decoder_get_state(self->_flacDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM){
            AudioQueueStop(self->_audioQueue, false);
            break;
        }
    }

    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
}

static FLAC__StreamDecoderWriteStatus flacDecoderWriteCallback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data){

    FLACPlayer * self = (__bridge FLACPlayer *)client_data;

    assert(frame->header.bits_per_sample == 16); // TODO

    int16_t * bufferWritePosition = (int16_t*)((uint8_t*)self->_buffer->mAudioData + self->_buffer->mAudioDataByteSize);
    for(int i = 0; i < frame->header.blocksize; i++){
        for(int j = 0; j < frame->header.channels; j++){
            *bufferWritePosition = (int16_t)buffer[j][i];
            bufferWritePosition++;
        }
    }

    int totalFramePayloadInBytes = frame->header.channels * frame->header.blocksize * frame->header.bits_per_sample/8;
    self->_buffer->mAudioDataByteSize += totalFramePayloadInBytes;

    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}

static void flacDecoderMetadataCallback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data){

    FLACPlayer * self = (__bridge FLACPlayer*) client_data;

    if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO){
        self->_currentStreamInfo = metadata->data.stream_info;
    }
}

基本上,当队列请求一个新缓冲区时,我从FLAC__stream_decoder中填充缓冲区,然后对它进行排队。就像其他人一样。当libFLAC告诉我我已经到达文件的末尾时,我告诉AudioQueue异步停止,直到它已经消耗了所有缓冲区的内容。然而,回放并没有一直播放到最后,而是在它应该播放之前停止了一点点。如果我删除这一行:

代码语言:javascript
复制
AudioQueueStop(self->_audioQueue, false);

一切都很好;音频点对点播放,尽管我的队列一直在运行到时间的尽头。如果我把这一行改为:

代码语言:javascript
复制
AudioQueueStop(self->_audioQueue, true);

然后,播放会立即/同步停止,正如您从Apple文档中所期望的那样:

如果传递true,则立即停止(即同步)。如果传递false,函数将立即返回,但音频队列在播放或记录其排队缓冲区之前不会停止(也就是说,停止是异步发生的)。在队列实际停止之前,将根据需要调用音频队列回调。

我的问题是:-我做错什么了吗?-我怎么才能播放我的音频直到结束,并适当地关闭队列?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-10-27 23:00:09

当然,经过几个小时的努力,我在发布这个问题几分钟后找到了解决方案。问题是,AudioQueue不关心在调用AudioQueueStop(.,false)后排队的缓冲区。所以现在我就像这样排队,一切都很有魅力:

代码语言:javascript
复制
static void HandleOutputBuffer(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer){

    FLACPlayer * self = (__bridge FLACPlayer*)inUserData;

    UInt32 largestBlockSizeInBytes = self->_currentStreamInfo.max_blocksize * self->_currentStreamInfo.channels * self->_currentStreamInfo.bits_per_sample/8;

    inBuffer->mAudioDataByteSize = 0;
    self->_buffer = inBuffer;

    bool shouldStop = false;

    while(inBuffer->mAudioDataByteSize <= inBuffer->mAudioDataBytesCapacity - largestBlockSizeInBytes){
        FLAC__bool result = FLAC__stream_decoder_process_single(self->_flacDecoder);
        assert(result);

        if(FLAC__stream_decoder_get_state(self->_flacDecoder) == FLAC__STREAM_DECODER_END_OF_STREAM){
            shouldStop = true;
            break;
        }
    }

    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
    if(shouldStop){
        AudioQueueStop(self->_audioQueue, false);
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19624605

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档