播放流后音频队列无法录制音频

Posted

技术标签:

【中文标题】播放流后音频队列无法录制音频【英文标题】:Audio queue cannot record audio after playing a stream 【发布时间】:2012-10-20 14:30:48 【问题描述】:

我正在使用 Mat Gallager 的音频流媒体播放音频流。在程序的另一点(不同的控制器),我正在尝试从设备的麦克风录制一些东西。

这是我的设置:

void SFIdentificator::startRecord()

int i,缓冲区字节大小; UInt32 大小;

try 
    numberOfPackets = 0;

    // specify the recording format
    SetupAudioFormat(kAudioFormatLinearPCM);

    AudioQueueNewInput(  &mRecordFormat,
                       MyInputBufferHandler,
                       this /* userData */,
                       CFRunLoopGetMain() /* run loop */, kCFRunLoopCommonModes /* run loop mode */,
                       0 /* flags */, &mQueue);
    mRecordPacket = 0;

    size = sizeof(mRecordFormat);
    AudioQueueGetProperty(mQueue, kAudioQueueProperty_StreamDescription, &mRecordFormat, &size);

    bufferByteSize = ComputeRecordBufferSize(&mRecordFormat, kBufferDurationSeconds);   // enough bytes for half a second


    size = sizeof(mRecordFormat);
    XThrowIfError(AudioQueueGetProperty(mQueue, kAudioQueueProperty_StreamDescription,
                                        &mRecordFormat, &size), "couldn't get queue's format");

    for (i = 0; i < kNumberRecordBuffers; ++i) 
        XThrowIfError(AudioQueueAllocateBuffer(mQueue, bufferByteSize, &mBuffers[i]), "AudioQueueAllocateBuffer failed");
        XThrowIfError(AudioQueueEnqueueBuffer(mQueue, mBuffers[i], 0, NULL), "AudioQueueEnqueueBuffer failed");
    
    mIsRunning = true;

    XThrowIfError(AudioQueueStart(mQueue, NULL), "AudioQueueStart failed");


 catch (CAXException e) 
    char buf[256];
    fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
catch (...) 
    fprintf(stderr, "An unknown error occurred\n");;

void SFIdentificator::SetupAudioFormat(UInt32 inFormatID)

memset(&mRecordFormat, 0, sizeof(mRecordFormat));

UInt32 size = sizeof(mRecordFormat.mSampleRate);
XThrowIfError(AudiosessionGetProperty(  kAudioSessionProperty_CurrentHardwareSampleRate, &size, &mRecordFormat.mSampleRate), "couldn't get hardware sample rate");

size = sizeof(mRecordFormat.mChannelsPerFrame);
XThrowIfError(AudioSessionGetProperty(  kAudioSessionProperty_CurrentHardwareInputNumberChannels, &size, &mRecordFormat.mChannelsPerFrame), "couldn't get input channel count");

mRecordFormat.mFormatID = inFormatID;
if (inFormatID == kAudioFormatLinearPCM)
    // if we want pcm, default to signed 16-bit little-endian

    mRecordFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
    //      mRecordFormat.mBitsPerChannel = 16;


    mRecordFormat.mBytesPerPacket = mRecordFormat.mBytesPerFrame = (mRecordFormat.mBitsPerChannel / 8) * mRecordFormat.mChannelsPerFrame;
    mRecordFormat.mFramesPerPacket = 1;

    mRecordFormat.mFormatID         = kAudioFormatLinearPCM;
    mRecordFormat.mSampleRate       = 32000.0;
    mRecordFormat.mChannelsPerFrame = 1;
    mRecordFormat.mBitsPerChannel   = 16;
    mRecordFormat.mBytesPerPacket   =  mRecordFormat.mBytesPerFrame = mRecordFormat.mChannelsPerFrame * sizeof (SInt16);
    mRecordFormat.mFramesPerPacket  = 1;

UInt32 SFIdentificator::ComputeRecordBufferSize(const AudioStreamBasicDescription *format, float seconds)
static const int maxBufferSize = 0x50000;

int maxPacketSize = format->mBytesPerPacket;
if (maxPacketSize == 0) 
    UInt32 maxVBRPacketSize = sizeof(maxPacketSize);
    AudioQueueGetProperty (mQueue, kAudioQueueProperty_MaximumOutputPacketSize, &maxPacketSize, &maxVBRPacketSize);


Float64 numBytesForTime = DataFormat().mSampleRate * maxPacketSize * seconds;
//    *outBufferSize = (UInt32)(numBytesForTime < maxBufferSize ? numBytesForTime : maxBufferSize);
return (UInt32)(numBytesForTime < maxBufferSize ? numBytesForTime : maxBufferSize);

似乎如果我先使用 AudioStreamer 类,然后再尝试录制某些内容,则甚至不会调用 Callback。但如果我不先使用 AudioStreamer,一切都很好。

谁能指出我正确的方向?

【问题讨论】:

【参考方案1】:

回答我自己的问题,正确设置 AudioSession 对象的 init() 是个问题。每个会话只应执行一次,再执行一次将导致错误,我已确定无法记录流。但是,即使第二次初始化失败(当然第一次成功),我也可以录制流。

【讨论】:

以上是关于播放流后音频队列无法录制音频的主要内容,如果未能解决你的问题,请参考以下文章

在 iPhone 上使用 AudioQueue 录制/播放

录制音频并保存到文档目录后无法使用 AVAudioPlayer 播放音频文件

ios - 播放视频后录制音频

音频播放录音视频播放拍照视频录制

iOS 无法在扬声器上播放并将音频会话设置为录制

无法播放用 naudio 录制的音频流