Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
377 views
in Technique[技术] by (71.8m points)

audiounit - Apple's Voice Processing Audio Unit ( kAudioUnitSubType_VoiceProcessingIO ) broken on iOS 5.1

I'm writing a VOIP app for iPad (currently targeting 2&3).

I originally wrote the audio code using the Audio Unit API, with a kAudioUnitSubtype_RemoteIO unit. This worked well, but unsurprisingly echo was a problem. I tried to use the built-in echo-suppression by switching to using a kAudioUnitSubType_VoiceProcessingIO unit. This works really well on iOS 6 (iPad 3), but the same code on iOS 5.1 (iPad 2) produces white noise on the microphone input.

The documentation just mentions that it should be available in iOS 3.0 and later

The iOS version seems to be the important difference here. I tried running the app on two iPhone 4Ss, one with iOS 6 which sounded fine and one with iOS 5.1 which sounded like white noise.

My ASBD looks like this:

typedef int16_t sample_t;
#define AUDIO_BUFFER_SAMPLE_RATE 48000
#define FORMAT_FLAGS (kAudioFormatFlagsIsSignedInteger | kAudioFormatFlagsIsNonInterleaved)
#define CHANNELS_PER_FRAME 1

...

const size_t bytes_per_sample = sizeof(sample_t);
const int eight_bits_per_byte = 8;
AudioStreamBasicDescription streamFormat;
streamFormat.mFormatID = kAudioFormatLinearPCM;
streamFormat.mSampleRate = AUDIO_BUFFER_SAMPLE_RATE;
streamFormat.mFormatFlags = FORMAT_FLAGS;

streamFormat.mChannelsPerFrame = CHANNELS_PER_FRAME;
streamFormat.mBytesPerFrame = bytes_per_sample * CHANNELS_PER_FRAME;
streamFormat.mBitsPerChannel = bytes_per_sample * eight_bits_per_byte;

streamFormat.mFramesPerPacket = 1;
streamFormat.mBytesPerPacket = streamFormat.mBytesPerFrame * streamFormat.mFramesPerPacket;
streamFormat.mReserved = 0;

Has anyone ever got kAudioUnitSubType_VoiceProcessingIO to work on iOS 5.1?

Does anyone know of any serious documentation for this IO?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

TL;DR add kAudioFormatFlagsIsPacked to FORMAT_FLAGS

I discovered this via a bit of a convoluted route. None of this seems to be well documentated anywhere, but I came across this SO post talking about using the IO on a Mac. One of the things mentioned was using "FlagsCononical". I tried setting:

#define FORMAT_FLAGS kAudioFormatFlagsAudioUnitCanonical

which didn't work, and the call to AudioUnitInitialize failed with a return code of 29759. I couldn't find any documentation about what this meant, but when I tried:

#define FORMAT_FLAGS kAudioFormatFlagsCanonical

everything worked! Success!

The definition of kAudioFormatFlagsCanonical in CoreAudioTypes.h if you are building for an iPad (and therefore have CA_PREFER_FIXED_POINT defined as 1) is:

kAudioFormatFlagsCanonical = kAudioFormatFlagsIsSignedInteger
                           | kAudioFormatFlagsNativeEndian
                           | kAudioFormatFlagIsPacked;

After adding kAudioFormatFlagIsPacked to my original code it worked. I added kAudioFormatFlagsNativeEndian for good measure. I removed kAudioFormatFlagsIsNonInterleaved as it was unnecessary for single channel audio anyway. What I was left with is identical to kAudioFormatFlagsCanonical.

So my set-up, which worked on an iPad 2 (iOs 5.1) and an iPad 3 (iOS 6.0) was the following:

  • Sample rate of 48000
  • 1 channel
  • kAudioFormatFlagsCanonical
  • int16_t samples
  • Linear PCM

I'm still keen on documentation for this IO if anyone has any, and of course if this helped you don't forget to upvote :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...