我目前正在为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倍。