Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS AudioUnit settings to save mic input to raw PCM file

I'm currently working on a VOIP project for iOS.
I use AudioUnits to get data from the mic and play sounds.
My main app is written in C# (Xamarin) and uses a C++ library for faster audio and codec processing.

To test the input/output result I'm currently testing recording & playback on the same device
- store the mic audio data in a buffer in the recordingCallback
- play the data from the buffer in the playbackCallback

That works as expected, the voice quality is good.

I need to save the incoming audio data from the mic to a raw PCM file.

I have done that, but the resulting file only contains some short "beep" signals.

So my question is:

What Audio settings do I need, that I can hear my voice (real audio signals) in the resulting raw PCM file instead of short beep sounds?
Has anyone an idea what could be wrong or what I have to do that I'm able to replay the resulting PCM file correctly?

My current format settings are (C# code):

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
};

Additional C# settings (here in short without error checking):

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);

My current recording callback in short (only for PCM file saving) (C++ code):

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;

}

Background info why I need a raw PCM file:

To compress the audio data I'd like to use the Opus codec.
With the codec I have the problem that there is a tiny "tick" at the end of each frame:
With a frame size of 60ms I nearly can't hear them, at 20ms its annoying, at 10 ms frame sizes my own voice can't be heared because of the ticking (for the VOIP application I try to get 10ms frames).

I don't encode & decode in the callback functions (I encode/decode the data in the functions which I use to transfer audio data from the "micbuffer" to the "playbuffer"). And everytime the playbackCallback wants to play some data, there is a frame in my buffer.

I also eliminate my Opus encoding/decoding functions as error source, because if I read PCM data from a raw PCM file, encode & decode it afterwards, and save it to a new raw PCM file, the ticking does not appear (if I play the result file with "Softe Audio Tools", the output file audio is OK).

To find out what causes the ticking, I'd like to save the raw PCM data from the mic to a file to make further investigations on that issue.

like image 691
Boardwish Avatar asked Nov 19 '13 18:11

Boardwish


1 Answers

I found the solution myself:
My PCM player expected 44100 Hz stereo, but my file only had 8000 Hz mono and therefore my saved file was played about 10x too fast.

like image 77
Boardwish Avatar answered Nov 06 '22 10:11

Boardwish