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

Boa*_*ish 5 iphone audio pcm audiounit ios

我目前正在开发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
};
Run Code Online (Sandbox Code Playgroud)

额外的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);
Run Code Online (Sandbox Code Playgroud)

我目前的录音回调简称(仅限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;
Run Code Online (Sandbox Code Playgroud)

}

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

要压缩音频数据,我想使用Opus编解码器.
使用编解码器,我遇到的问题是每帧结尾都有一个微小的"滴答声":
帧大小为60毫秒我几乎听不到它们,20毫秒令人讨厌,10毫秒帧大小我自己的声音可以因为滴答声而被聆听(对于VOIP应用程序,我试图获得10ms帧).

我不在回调函数中编码和解码(我在用于将音频数据从"micbuffer"传输到"playbuffer"的函数中编码/解码数据).每次playbackCallback想要播放一些数据时,我的缓冲区中都有一个帧.

我还将我的Opus编码/解码功能作为错误源消除,因为如果我从原始PCM文件中读取PCM数据,然后对其进行编码和解码,并将其保存到新的原始PCM文件中,则不会出现滴答声(如果我播放的话)结果文件带"Softe Audio Tools",输出文件音频正常).

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

Boa*_*ish 4

我自己找到了解决方案:
我的 PCM 播放器期望 44100 Hz 立体声,但我的文件只有 8000 Hz 单声道,因此我保存的文件播放速度快了大约 10 倍。