ios - 在IOS中重复播放音频会损坏录制

标签 ios iphone audio audio-streaming audio-recording

我的应用程序在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);
    }
}

最佳答案

事实证明,存在一个罕见的错误,几乎可以同时开始多个录音-因此两个录音并行发生,但将音频缓冲区发送到同一回调中,从而使编码录音中的重复缓冲区失真了...

关于ios - 在IOS中重复播放音频会损坏录制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25061583/

相关文章:

iphone - 使用 NSPredicate contains 查找 coredata 实体字段内的字符

ios - Apple 开发者注册过期后,您还可以从 iOS 访问您的应用程序吗?

c# - 如何通过Windows API设置.wav文件的位深度? (C#)

iphone - 如何在IBAction中实现NSArray方法?

IOS 电池容量信息

ios - 与桌面应用程序一样在登录时获取用户 ID 选择屏幕,而不是每次都输入用户 ID

android - 无法从android缓存目录中获取文件

ios - 重叠访问 "result",但修改需要独占访问;考虑复制到 xcode 10 中的局部变量

iphone - NSDateFormatter 在设备和模拟器上给出不同的值?解决办法是什么?

audio - 如何使用 OpenNI 访问 Kinect 音频数据?