AVAssetReader到AudioQueueBuffer

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

我读过这个:( 用AudioQueue播放原始的未压缩声音,没有声音 )和这个:( 如何使用AVAssetReader在iOS上正确读取解码的PCM样本 – 目前不正确的解码 ),

这两者实际上都有所帮助。 在阅读之前,我根本没有听到任何声音。 现在,我听起来很响,但音频播放速度非常快。 这是我第一次涉足音频编程,因此非常感谢任何帮助。

我这样初读了读者:

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 mAudioDataByteSize = bytesFilled; err = AudioQueueEnqueueBuffer(audioQueue, fillBuf, 0, NULL); } bufSpaceRemaining = kAQDefaultBufSize - bytesFilled; size_t copySize; if (bufSpaceRemaining  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 。 但是,我会花一些时间将您的代码与该示例进行比较,因为存在很多差异。 喜欢在入队前检查。

首先看一下这个posthttps://stackoverflow.com/a/4299665/530933它讲述了你如何需要知道音频格式,特别是帧中有多少字节,并适当地进行转换

祝你好运。 我在这里发布了很多问题,苹果论坛和ios论坛(不是官方论坛)。 几乎没有回应/帮助。 为了得到我今天的地方(录音和流媒体在ulaw)我最终不得不打开Apple Dev Support Ticket。 在处理音频之前,我从来不知道存在(开发支持)。 一个好处是,如果你有一个有效的开发帐户,你可以免费获得2个事件! CoreAudio并不好玩。 文档很少,除了SpeakHere之外没有太多的例子。 我发现的一件事是框架标题确实有一些好的信息和本书 。 不幸的是,我只是开始了这本书,否则我可以帮助你。

您还可以查看我自己的一些post,我尽力回答这些post。 这是我的主要音频问题,我花了很多时间来编译所有相关的链接和代码。

在目标c类中使用AQRecorder(audioqueue recorder示例)

试图将AVAssetWriter用于ulaw音频 ( 2 )

出于某种原因,即使我看到使用LPCM的音频队列的每个例子都有

 ASBD.mBitsPerChannel = 8* sizeof (AudioUnitSampleType); 

对我来说,事实certificate我需要

 ASBD.mBitsPerChannel = 2*bytesPerSample; 

有关描述:

 ASBD.mFormatID = kAudioFormatLinearPCM; ASBD.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical; ASBD.mBytesPerPacket = bytesPerSample; ASBD.mBytesPerFrame = bytesPerSample; ASBD.mFramesPerPacket = 1; ASBD.mBitsPerChannel = 2*bytesPerSample; ASBD.mChannelsPerFrame = 2; ASBD.mSampleRate = 48000; 

我不知道为什么会这样,这让我很困扰……但希望我最终可以把它弄清楚。

如果有人能向我解释为什么会这样,我会非常感激。