当前,我正在做一个小测试项目,以查看是否可以从AVAssetReader获取样本以在iOS上使用AudioQueue进行播放。

我读过这个:
(Play raw uncompressed sound with AudioQueue, no sound)
这是(How to correctly read decoded PCM samples on iOS using AVAssetReader -- currently incorrect decoding),

两者实际上都有帮助。在阅读之前,我什么都没听到。现在,我正在获取声音,但是音频正在快速播放。这是我第一次涉足音频编程,因此深表感谢。

我因此初始化了读者:

NSDictionary * outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
                                         [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,
                                         [NSNumber numberWithFloat:44100.0], AVSampleRateKey,
                                         [NSNumber numberWithInt:2], AVNumberOfChannelsKey,
                                         [NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,
                                         [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,
                                         [NSNumber numberWithBool:NO], AVLinearPCMIsFloatKey,
                                         [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,

                                         nil];

        output = [[AVAssetReaderAudioMixOutput alloc] initWithAudioTracks:uasset.tracks audioSettings:outputSettings];
        [reader addOutput:output];
...

因此,我抓取了数据:
CMSampleBufferRef ref= [output copyNextSampleBuffer];
    // NSLog(@"%@",ref);
    if(ref==NULL)
        return;
    //copy data to file
    //read next one
    AudioBufferList audioBufferList;
    NSMutableData *data = [NSMutableData data];
    CMBlockBufferRef blockBuffer;
    CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(ref, NULL, &audioBufferList, sizeof(audioBufferList), NULL, NULL, 0, &blockBuffer);
    // NSLog(@"%@",blockBuffer);

    if(blockBuffer==NULL)
    {
        [data release];
        return;
    }
    if(&audioBufferList==NULL)
    {
        [data release];
        return;
    }

    //stash data in same object
    for( int y=0; y<audioBufferList.mNumberBuffers; y++ )
    {
//        NSData* throwData;
        AudioBuffer audioBuffer = audioBufferList.mBuffers[y];
        [self.delegate streamer:self didGetAudioBuffer:audioBuffer];
        /*
        Float32 *frame = (Float32*)audioBuffer.mData;
        throwData = [NSData dataWithBytes:audioBuffer.mData length:audioBuffer.mDataByteSize];
        [self.delegate streamer:self didGetAudioBuffer:throwData];
        [data appendBytes:audioBuffer.mData length:audioBuffer.mDataByteSize];
         */
    }

最终将我们带入音频队列,方法如下:
//Apple's own code for canonical PCM
    audioDesc.mSampleRate       = 44100.0;
    audioDesc.mFormatID         = kAudioFormatLinearPCM;
    audioDesc.mFormatFlags      = kAudioFormatFlagsAudioUnitCanonical;
    audioDesc.mBytesPerPacket   = 2 * sizeof (AudioUnitSampleType);    // 8
    audioDesc.mFramesPerPacket  = 1;
    audioDesc.mBytesPerFrame    = 1 * sizeof (AudioUnitSampleType);    // 8
    audioDesc.mChannelsPerFrame = 2;
    audioDesc.mBitsPerChannel   = 8 * sizeof (AudioUnitSampleType);    // 32


err = AudioQueueNewOutput(&audioDesc, handler_OSStreamingAudio_queueOutput, self, NULL, NULL, 0, &audioQueue);
    if(err){
#pragma warning  handle error
//never errs, am using breakpoint to check
        return;
    }

我们就这样入队了
while (inNumberBytes)
        {
            size_t bufSpaceRemaining = kAQDefaultBufSize - bytesFilled;
            if (bufSpaceRemaining < inNumberBytes)
            {
                AudioQueueBufferRef fillBuf = audioQueueBuffer[fillBufferIndex];
        fillBuf->mAudioDataByteSize = bytesFilled;
        err = AudioQueueEnqueueBuffer(audioQueue, fillBuf, 0, NULL);
            }


                bufSpaceRemaining = kAQDefaultBufSize - bytesFilled;
                size_t copySize;
                if (bufSpaceRemaining < inNumberBytes)
                {
                    copySize = bufSpaceRemaining;
                }
                else
                {
                    copySize = inNumberBytes;
                }

                if (bytesFilled > packetBufferSize)
                {
                    return;
                }

                AudioQueueBufferRef fillBuf = audioQueueBuffer[fillBufferIndex];
                memcpy((char*)fillBuf->mAudioData + bytesFilled, (const char*)(inInputData + offset), copySize);


                bytesFilled += copySize;
                packetsFilled = 0;
                inNumberBytes -= copySize;
                offset += copySize;
            }
        }

我试图尽可能地将代码包含在内,以使每个人都可以轻松指出我在做白痴。话虽这么说,我感觉我的问题还是出现在轨道阅读器的输出设置声明中,还是出现在AudioQueue的实际声明中(我在这里向队列描述了我将要发送的音频类型)。事实是,我真的在数学上不知道如何实际生成这些数字(每个数据包字节,每个数据包帧,您拥有什么)。对此的解释将不胜感激,并感谢您的提前帮助。

最佳答案

不确定答案是多少,但是会有太多文本和评论链接,希望对您有所帮助(也许可以指导您找到答案)。

首先,我知道在当前项目中调整采样率会影响声音的速度,因此您可以尝试使用这些设置。但是44k是我在大多数默认实现中看到的,包括苹果示例SpeakHere。但是,我会花一些时间将您的代码与该示例进行比较,因为存在很多差异。比如入队前检查。

首先查看此帖子https://stackoverflow.com/a/4299665/530933
它讨论了如何了解音频格式,特别是一帧中有多少字节,以及如何正确投射

也祝你好运。我在这里,苹果论坛和ios论坛(不是官方论坛)上发布了很多问题。响应/帮助很少。为了达到今天的状态(在ulaw中进行音频录制和流式传输),我最终不得不打开Apple Dev Support Ticket。在解决音频之前,我不知道哪个存在(开发支持)。一件好事是,如果您拥有有效的开发者帐户,则可以免费获得2个事件! CoreAudio不好玩。文档很少,而且除了SpeakHere之外,例子很多。我确实发现的一件事是框架标头确实包含一些不错的信息和this book。不幸的是,我只是刚开始读这本书,否则我也许可以为您提供进一步的帮助。

您也可以查看我自己的一些帖子,这些帖子我已尽力回答。
This is my main audio question which I have spent alot of time on to compile all pertinent links and code.

using AQRecorder (audioqueue recorder example) in an objective c class

trying to use AVAssetWriter for ulaw audio(2)

关于objective-c - AVAssetReader到AudioQueueBuffer,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11398997/

10-08 21:07