IOS中重复音频的损坏录音

Posted

技术标签:

【中文标题】IOS中重复音频的损坏录音【英文标题】:Corrupt recording with repeating audio in IOS 【发布时间】:2014-07-31 14:31:33 【问题描述】:

我的应用程序在 iPhone 上录制流式音频。我的问题是一小部分(~2%)的录音被破坏了。他们似乎有一些重复的音频缓冲区。

例如收听this file。


编辑:令人惊讶的是,使用 Audacity 仔细查看数据会发现重复部分非常相似但并不完全相同。由于 FLAC(我用于编码音频的格式)是一种无损压缩,我想这不是流/编码中的错误,而是问题源于来自麦克风的数据!


下面是我用来设置音频录制流的代码 - 有什么问题吗?

// see functions implementation below
- (void)startRecording

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
               , ^
        [self setUpRecordQueue];
        [self setUpRecordQueueBuffers];
        [self primeRecordQueueBuffers];
        AudioQueueStart(recordQueue, NULL);
    );




// this is called only once before any recording takes place
- (void)setUpAudioFormat

    AudiosessionInitialize(
                           NULL,
                           NULL,
                           nil,
                           (__bridge  void *)(self)
                           );

        UInt32 sessionCategory = kAudioSessionCategory_PlayAndRecord;
        AudioSessionSetProperty(
                            kAudioSessionProperty_AudioCategory,
                            sizeof(sessionCategory),
                            &sessionCategory
                            );

        AudioSessionSetActive(true);

    audioFormat.mFormatID         = kAudioFormatLinearPCM;
    audioFormat.mSampleRate       = SAMPLE_RATE;//16000.0;
    audioFormat.mChannelsPerFrame = CHANNELS;//1;
    audioFormat.mBitsPerChannel   = 16;
    audioFormat.mFramesPerPacket  = 1;
    audioFormat.mBytesPerFrame    = audioFormat.mChannelsPerFrame * sizeof(SInt16);
    audioFormat.mBytesPerPacket   = audioFormat.mBytesPerFrame * audioFormat.mFramesPerPacket;
    audioFormat.mFormatFlags      = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;

    bufferNumPackets = 2048;  // must be power of 2 for FFT!
    bufferByteSize = [self byteSizeForNumPackets:bufferNumPackets];


// I suspect the duplicate buffers arrive here:
static void recordCallback(
                       void* inUserData,
                       AudioQueueRef inAudioQueue,
                       AudioQueueBufferRef inBuffer,
                       const AudioTimeStamp* inStartTime,
                       UInt32 inNumPackets,
                       const AudioStreamPacketDescription* inPacketDesc)

     Recorder* recorder = (__bridge Recorder*) inUserData;
    if (inNumPackets > 0)
    
        // append the buffer to FLAC encoder
        [recorder recordedBuffer:inBuffer->mAudioData byteSize:inBuffer->mAudioDataByteSize packetsNum:inNumPackets];
    

    AudioQueueEnqueueBuffer(inAudioQueue, inBuffer, 0, NULL);




- (void)setUpRecordQueue

     OSStatus errorStatus = AudioQueueNewInput(
                   &audioFormat,
                   recordCallback,
                   (__bridge void *)(self),                // userData
                   CFRunLoopGetMain(),  // run loop
                   NULL,                // run loop mode
                   0,                   // flags
                   &recordQueue);
       UInt32 trueValue = true;
      AudioQueueSetProperty(recordQueue,kAudioQueueProperty_EnableLevelMetering,&trueValue,sizeof (UInt32));


- (void)setUpRecordQueueBuffers

    for (int t = 0; t < NUMBER_AUDIO_DATA_BUFFERS; ++t)
    
         OSStatus errorStatus = AudioQueueAllocateBuffer(
                             recordQueue,
                             bufferByteSize,
                             &recordQueueBuffers[t]);
    


- (void)primeRecordQueueBuffers

    for (int t = 0; t < NUMBER_AUDIO_DATA_BUFFERS; ++t)
    
        OSStatus errorStatus = AudioQueueEnqueueBuffer(
                            recordQueue,
                            recordQueueBuffers[t],
                            0,
                            NULL);
    

【问题讨论】:

【参考方案1】:

原来有一个罕见的错误允许多个录音几乎同时开始 - 所以两个录音并行发生,但将音频缓冲区发送到同一个回调,使编码录音中的重复缓冲区失真......

【讨论】:

以上是关于IOS中重复音频的损坏录音的主要内容,如果未能解决你的问题,请参考以下文章

iOS开发之音频播放录音

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

在iOS中绘制录音音频波形图

iOS开发系列--音频播放录音视频播放拍照视频录制

为啥我的 iOS 录音回调中的音频缓冲区未满?

Swift实现iOS录音与播放音频功能