iOS AudioUnit设置将麦克风输入保存到原始PCM文件

时间:2013-11-19 18:57:22

标签: ios iphone audio audiounit pcm

我目前正在开发iOS的VOIP项目 我使用AudioUnits从麦克风获取数据并播放声音 我的主应用程序是用C#(Xamarin)编写的,它使用C ++库来实现更快的音频和编解码处理。

测试输入/输出结果我正在测试录音和放大器在同一设备上播放
- 将麦克风音频数据存储在recordingCallback中的缓冲区中 - 在playbackCallback

中播放缓冲区中的数据

按预期工作,语音质量很好。

我需要将传入的音频数据从麦克风保存到原始PCM文件。

我已经这样做了,但结果文件只包含一些短的“嘟嘟”信号。

所以我的问题是:

我需要什么音频设置,我可以在生成的原始PCM文件中听到我的声音(真实音频信号)而不是短暂的哔声?
有没有人知道什么可能是错的或我必须做什么,我能够正确地重播生成的PCM文件?

我当前的格式设置是(C#代码):

int framesPerPacket = 1;
int channelsPerFrame = 1;
int bitsPerChannel = 16;
int bytesPerFrame = bitsPerChannel / 8 * channelsPerFrame;
int bytesPerPacket = bytesPerFrame * framesPerPacket;
AudioStreamBasicDescription audioFormat = new AudioStreamBasicDescription ()
{
  SampleRate = 8000,
  Format = AudioFormatType.LinearPCM,
  FormatFlags = AudioFormatFlags.LinearPCMIsSignedInteger | AudioFormatFlags.LinearPCMIsPacked | AudioFormatFlags.LinearPCMIsAlignedHigh,
  BitsPerChannel = bitsPerChannel,
  ChannelsPerFrame = channelsPerFrame,
  BytesPerFrame = bytesPerFrame,
  FramesPerPacket = framesPerPacket,
  BytesPerPacket = bytesPerPacket,
  Reserved = 0
};

其他C#设置(这里简而言之没有错误检查):

AVAudioSession session = AVAudioSession.SharedInstance();
NSError error = null;
session.SetCategory(AVAudioSession.CategoryPlayAndRecord, out error);
session.SetPreferredIOBufferDuration(Config.packetLength, out error);
session.SetPreferredSampleRate(Format.samplingRate,out error);
session.SetActive(true,out error);

我当前的录制回调简称(仅限PCM文件保存)(C ++代码):

OSStatus 
NotSoAmazingAudioEngine::recordingCallback(void *inRefCon,
                              AudioUnitRenderActionFlags *ioActionFlags,
                              const AudioTimeStamp *inTimeStamp,
                              UInt32 inBusNumber,
                              UInt32 inNumberFrames,
                              AudioBufferList *ioData) {
std::pair<BufferData*, int> bufferInfo = _sendBuffer.getNextEmptyBufferList();
AudioBufferList* bufferList = new AudioBufferList();
bufferList->mNumberBuffers = 1;
bufferList->mBuffers[0].mData = NULL;
OSStatus status = AudioUnitRender(_instance->_audioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, bufferList);
if(_instance->checkStatus(status))
{
    if(fout != NULL) //fout is a "FILE*"
    {
        fwrite(bufferList->mBuffers[0].mData, sizeof(short), bufferList->mBuffers[0].mDataByteSize/sizeof(short), fout);
    }
}
delete bufferList;
return noErr;

}

背景信息为什么我需要原始PCM文件:

  

要压缩音频数据,我想使用Opus编解码器   使用编解码器,我遇到的问题是每帧结尾都有一个微小的“勾号”:
  框架大小为60毫秒,我几乎听不到它们,在20毫秒时令人讨厌,在10毫秒帧大小时,我自己的声音因为滴答声而无法听到(对于VOIP应用我尝试获得10毫秒帧)。 / p>      

我不编码&amp;在回调函数中解码(我对用于将音频数据从“micbuffer”传输到“playbuffer”的函数中的数据进行编码/解码)。   每次playbackCallback想要播放一些数据时,我的缓冲区中都有一个帧。

     

我还将我的Opus编码/解码功能作为错误源消除,因为如果我从原始PCM文件中读取PCM数据,则编码&amp;之后将其解码,并将其保存到新的原始PCM文件中,不会出现滴答声(如果我使用“Softe Audio Tools”播放结果文件,则输出文件音频正常)。

     

为了找出导致滴答作响的原因,我想将原始PCM数据从麦克风保存到文件中,以便对该问题进行进一步调查。

1 个答案:

答案 0 :(得分:3)

我自己找到了解决方案:
我的PCM播放器需要44100赫兹立体声,但我的文件只有8000赫兹单声道,因此我保存的文件播放速度太快了10倍。