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



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

为了测试输入/输出结果,我目前正在测试录音&在同一设备上播放
-将麦克风音频数据存储在录制中的缓冲区Callback
-播放回放中缓冲区的数据回调

工作如预期,音质良好。

我需要将麦克风传入的音频数据保存到原始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毫秒的帧数)。

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

我还消除了我的Opus编码/解码功能作为错误源,因为如果我从原始PCM文件中读取PCM数据,请编码&之后对其进行解码,并将其保存到一个新的原始PCM文件中,不会出现勾选(如果我用"Softe Audio Tools"播放结果文件,则输出文件音频正常)。

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

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

最新更新