概述
基础知识-音频编解码,音频格式,音频会话(session)
- ios软硬件音频编解码器
- 音频会话(Audio Sessions)
播放音频
- 使用iPod库访问播放音频项目
- 使用系统声音服务播放UI声音效果或者调用震动
- 使用AVAudioPlayer 播放音乐更轻松
- 使用音频队列服务播放控制声音
- 使用OpenAL播放定位声音
音频录制
- 使用AVAudioRecorder 类录制音频
- 使用Audio Queue Services 录制
解析流式音频
ios中的音频单元支持
ios音频最佳实战
- 使用音频提示
- ios的首先音频格式
今天学习开源框架LFLiveKit,看到音频录制的部分,该部分是采用的AVFoundation.frame中AVAudio.framework框架来完成的。以前没有接触过这部分,因此这里摘录出来仔细研究学习。
首先想学习框架,肯定官网是最佳的场所,我搜寻了下官方文档,找到这一点相关知识multimedia Programming guide。一点点学习嘛,先学会这块再说。
概述
基础知识-音频编解码,音频格式,音频会话(session)
ios的音频开发,了解下ios设备的硬件和软件架构的有关知识是很必要的。
ios软硬件音频编解码器
为确保音频的最佳性能和质量,我们需要选择正确的音频格式和音频编解码器类型。从ios3.0开始,大多数音频格式可以使用软件编码和解码(录制和播放)。软件编码器支持多个声音的同时播放,但是需要大量的cpu开销。
硬件辅助解码可以提供很好的性能,但是就不能支持同时播放多个声音了。如果我们需要在应用程序中最大化视频帧速率,最小的cpu音频开销,那么我们需要使用未压缩的音频或者IMA4格式,也可以使用硬件帮助解码压缩的音频。
下表是ios设备上可用的播放音频编解码器。
Audio decoder/playback format | Hardware-assisted decoding | Software-based decoding |
---|---|---|
AAC (MPEG-4 Advanced Audio Coding) | Yes | Yes, starting in iOS 3.0 |
ALAC (Apple Lossless) | Yes | Yes, starting in iOS 3.0 |
HE-AAC (MPEG-4 High Efficiency AAC) | Yes | - |
iLBC (internet Low Bitrate Codec, another format for speech) | - | Yes |
IMA4 (IMA/ADPCM) | - | Yes |
Linear PCM (uncompressed, linear pulse-code modulation) | - | Yes |
MP3 (MPEG-1 audio layer 3) | Yes | Yes, starting in iOS 3.0 |
µ-law and a-law | - | Yes |
通过上面的表格,我们知道同时支持硬编码和软编码的格式有aac alac 和 mp3.
使用硬件辅助编码时,设备一次只能播放一种支持格式的单个实例。例如,如果我们使用硬件编解码器播放立体声mp3音乐,那么第二个同步mp3声音将使用软件编码(硬件只能编码一个,)。同样,我们无法使用硬件同时编码aac和alac格式音乐。
要是要要播放多种声音,或者在ipod在后台播放音乐,我们应该使用线型PCM(未压缩)或者IMA4(压缩)音频。
要了解运行时设备上可用的硬件和软件编解码器。我们可以看kAudioFormatProperty_HardwareCodecCapabilities常量来了解。
如何确定在运行时aac硬件编码器的可用性。
ios4.0以及更高版本支持使用扩展音频文件和音频转换器api进行硬件脱机编码。这就是硬编码
注意 ios3.1 只支持扩展音频文件api。
要检查acc硬件编码器的可用性,使用下列代码
Boolean IsAACHardwareEncoderAvailable(void)
{
Boolean isAvailable = false;
OSStatus error;
// get an array of AudioClassDescriptions for all installed encoders for the given format
// the specifier is the format that we are interested in - this is 'aac ' in our case
UInt32 encoderSpecifier = kAudioFormatMPEG4AAC;
UInt32 size;
error = AudioFormatGetPropertyInfo(kAudioFormatProperty_Encoders, sizeof(encoderSpecifier),
&encoderSpecifier, &size);
if (error) {
printf("AudioFormatGetPropertyInfo kAudioFormatProperty_Encoders error %lu %4.4s\n", error, (char*)&error);
return false;
}
UInt32 numEncoders = size / sizeof(AudioClassDescription);
AudioClassDescription encoderDescriptions[numEncoders];
error = AudioFormatGetProperty(kAudioFormatProperty_Encoders, sizeof(encoderSpecifier), &encoderSpecifier, &size, encoderDescriptions);
if (error) {
printf("AudioFormatGetProperty kAudioFormatProperty_Encoders error %lu %4.4s\n", error, (char*)&error); return false; }
for (UInt32 i=0; i < numEncoders; ++i) {
if (encoderDescriptions[i].mSubType == kAudioFormatMPEG4AAC &&
encoderDescriptions[i].mManufacturer == kAppleHardwareAudioCodecManufacturer) isAvailable = true;
}
return isAvailable;
}
总结下ios如何支持单个或者多个播放音频格式
- 线型PCM 和IMA4(IMA/ADPCM) 我们可以在ios中同时播放多个线型的PCM或者IMA4 音乐,而不会产生cpu 性能问题。对于ILBC语音质量格式以及 µ-law 和 a-law 压缩格式也是一样的,当用压缩格式,需要检查音质以确保满足需求。
- AAC,HE-AAC,MP3和ALAC(Apple Lossless) 对AAC,HE-AAC,MP3和ALAC(Apple Lossless)的播放可以在设备上使用高效的硬件辅助编码,但这些编码都共享一条硬件路径。因此,硬件编码只能播放这些格式之一的单个实例。
AAC,HE-AAC,MP3和ALAC播放的单一硬件路径对“播放”风格应用程序(如虚拟钢琴)有影响。如果用户正在ipod的应用程序中播放这三种格式之一的歌曲,那么我们的应用程序将通过软编码进行编码。
下表记录在ios设备上可用的录制音频编解码器
Audio encoder/recording format | Hardware-assisted encoding | Software-based encoding |
---|---|---|
AAC (MPEG-4 Advanced Audio Coding) | Yes, starting in iOS 3.1 for iPhone 3GS and iPod touch (2nd generation) Yes, starting in iOS 3.2 for iPad | Yes, starting in iOS 4.0 for iPhone 3GS and iPod touch (2nd generation) |
ALAC (Apple Lossless) | - | Yes |
iLBC (internet Low Bitrate Codec, for speech) | - | Yes |
IMA4 (IMA/ADPCM) | - | Yes |
Linear PCM (uncompressed, linear pulse-code modulation) | - | Yes |
µ-law and a-law | - | Yes |
通过上表,我们知道了录制音频,同时支持硬件和软件编码的之后aac格式编码
音频会话(Audio Sessions)
ios音频会话api允许我们定义应用程序的一般音频行为。相关api在 Audio Session Services Reference and AVAudioSession Class Reference。这些使用这些api,可以完成下列对音频的操作:
- 设备静音
- 音频是否在屏幕锁定时停止
- 当音频开始的时候,其他音频是否应该继续播放或者静音。
音频会话api还会响应用户操作,例如插入或者播出耳机,以及使用设备声音硬件的事件,例如时钟和日历闹钟以及来电。
音频会话的三个编程功能如下表
音频会话功能 | 描述 |
---|---|
设置categories | category是标示应用程序的一组音频行为的key。通过设置category,我们可以向ios表明我们的音频意图,例如屏幕锁定时我们的音频是否应该继续。响应中断中描述的六个类别。我们也可以微调某些category的行为,例如可以看 Use Modes to Specialize the Category. |
处理中断和路由更改 | 当音频中断,中断结束以及硬件音频路由发生变化时,音频会话会发布通知。通过这些通知,我们可以优雅的响应较大音频环境中的更改-例如由于来电而导致的中断。更多细节可以看处理音频硬件路由改变 和Audio Guidelines By App Type. |
优化硬件性能 | 我们可以查询音频会话以发现运行的应用程序的设备的特征,例如硬件采样率,硬件通道数以及音频输入是否可用有关详细细节可看Optimizing for Device Hardware. |
有两个用于处理音频会话的接口:
- 一个简化的oc接口,可以让我们访问核心音频会话特性。具体可参看 AVAudioSession Class Reference和AVAudioSessionDelegate Protocol Reference。
- 一个基于c的接口,通过对所有基本和高级音频会话特性的全面访问。具体可参考 Audio Session Services Reference
我们可以混合和匹配AVFoundation和audio sessionServices中的音频会话代码-他们两个是相互兼容的。
音频会话带有一些默认行为,我们可以使用这些开始开发。
例如,使用默认音频会话时,当自动锁定时间超时且屏幕锁定时,应用程序中的音频将停止。 如果要确保在屏幕锁定的情况下继续播放,请在应用程序的初始化代码中包含以下行:
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance]
setCategory: AVAudioSessionCategoryPlayback
error: &setCategoryErr];
[[AVAudioSession sharedInstance]
setActive: YES
error: &activationErr];
AVAudioSessionCategoryPlayback category 确保当屏幕锁屏的时候可以继续播放音频。
如何处理来电或者时钟以及日历闹钟导致的中断取决于我们使用的音频技术。见下表
Audio technology | How interruptions work |
---|---|
AV Foundation framework | AVAudioPlayer和AVAudioRecorder类为中断开始和结束提供委托方法。实现这些方法来更新用户界面,并且我们可以在中断后,回复暂停的播放。系统在中断时会自动的暂停播放和录制,并在恢复播放或者录制时候重新激活音频会话。如果要在应用程序启动时保存和恢复播放位置,请在中断和应用程序退出时保存播放位置。 |
Audio Queue Services, I/O audio unit | 我们可以通过该技术处理中断。我们需要保存播放盒录制位置,并且中断结束后重新激活音频会话。实现AVAudioSession中断的委托代理方法或者编写监听回调函数-通知 |
OpenAL | 使用openAL 进行播放,需要实现AVAudioSession中断委托方法或编写中断回调函数-与使用音频队列服务时一样的。这里需要注意的时,委托或者回调必须重新管理openAL上下文 |
System Sound Services | 用系统声音服务播放的音乐在终端开始时保持静音。如果终端结束,他们可以自动的再次使用。应用程序不能影响使用此播放技术的声音的中断行为 |
每个ios应用程序(极少数例外)都应该主动管理其音频会话。有关如何执行此操作的完整说明,可以看这里Audio Session Programming Guide
播放音频
本节主要介绍如何播放在 iPod library access, System Sound Services, Audio Queue Services, t AV Foundation framework和OpenAL.中声音。
使用iPod库访问播放音频项目
在ios3.0开始,ipad 库访问可以应用程序播放用户的歌曲,有声读物或者音频播客。api设计使用基本播放非常简单,同时还支持高级搜索和播放控制。
下图展示应用程序有两种方法来检索媒体项目。左侧显示的媒体项目选择器是一个易于使用的预打包视图控制器,其行为类似于内置ipod应用程序的音乐选择界面。对于许多应用来说,这已经足够了。如果选择器不能满足我们的需求,那么就可以选择右边的medai query。他支持来自ipod库的基于谓词的项目规范。
如何将媒体项目添加到应用程序的完成实例,可以参考 *iPod Library Access Programming Guide。例子可以参考 AddMusic工程
使用系统声音服务播放UI声音效果或者调用震动
想要播放用户界面声音效果(如按钮点击),或在支持他的设备上调用振动,请使用系统服务声音服务。详细讲解在System Sound Services Reference。我们可以在 iOS Dev Center中找到简单的代码。
注意:使用声音系统服务播放的声音不受使用音频会话的配置限制。因此,我们无法使system sound services 音频的行为和应用程序中的其他音频行为保持一致。这是避免将system sound services用于除预期用途之外的任何音频的最重要原因。
AudioServicesPlaySystemSound 函数能让我们可以非常简单的播放简短的声音文件。简单必定带来一些限制。我们的声音文件必须是满足下列要求:
- 持续时间不能超过30s
- 采用pcm 或者IMA4(IMA/ADPCM)格式
- 打包在.caf .aif 或者 .wav文件中
此外,我们可以使用AudioServicesPlaySystemSound函数时:
- 声音播放使用当前系统音量,没有可用的编程音量控制
- 声音立刻播放
- 无法进行循环和立体声定位
- 同时不放不可用:我们一次只能播放一种声音
有个类似的AudioServicesPlayAlertSound函数,可以用来播放短声音作为警报。如果用户已将其设备配置为在“震动设置”中的震动,那么调用此功能除了播放声音文件之外还会调用振动。
注意:应用程序无法使用系统提供的警报声和系统提供的用户界面声音效果。例如,使用kSystemSoundID_UserPreferredAlert常量作为AudioServicesPlayAlertSound函数的参数将不会播放任何内容。
举例如下:
// Get the main bundle for the app
CFBundleRef mainBundle = CFBundleGetMainBundle ();
// Get the URL to the sound file to play. The file in this case
// is "tap.aif"
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle,CFSTR ("2"),CFSTR ("caf"),NULL);
SystemSoundID soundFileObject =0 ;
AudioServicesCreateSystemSoundID (soundFileURLRef,
&soundFileObject);
self.soundFileObject = soundFileObject;
播放音乐
AudioServicesPlaySystemSound (self.soundFileObject);
如何获取.caf 文件呢?
通过终端命令,将简单的mp3文件转换,命令如下
afconvert /Users/Mina/Desktop/1.mp3 /Users/Mina/Desktop/2.caf -d ima4 -f caff -v
在典型的使用中,包含偶尔或者重复播放音乐,我们需要保留声音的ID对象,知道应用程序退出释放对象。如果我们知道只使用一次,那我们可以播放声音后里面销毁对象,释放内存。
在支持振动的ios设备上运行的app可以使用 system sound services 触发该共功能。使用kSystemSoundID_Vibrate标识符指定vibrate(振动) 选项。要触发她,使用AudioServicesPlaySystemSound函数。
#import <AudioToolbox/AudioToolbox.h>
#import <UIKit/UIKit.h>
- (void) vibratePhone {
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
}
iPod touch不支持此功能。
使用AVAudioPlayer 播放音乐更轻松
AVAudioPlayer 类提供了一个简单的oc接口,用于播放声音。如果我们的app不需要立体声定位或者精确同步,并且不需要播放从网络流捕获的音频。我们可以使用此类播放。
该类可以完成下列功能:
- 播放任何持续时间的声音
- 播放文件或内存缓存区的声音
- 循环声音
- 同时播放多个声音(没有精确同步)
- 控制正在播放的每个声音的相对播放水平
- 寻找声音文件中的特定点,该文件吃吃快进和快退等功能
- 获取音频的电源数据,该数据可以用来音频水平的测量。
AVAudioPlayer 类允许我们在ios中使用可用的任何音频格式播放音乐。具体可以参考 AVAudioPlayer Class Reference
如何配置音频播放器
- 1.指定一个音乐文件给音频播放器
- 2.准备播放音频播放器,获取所需的硬件资源
- 3.指定音频播放器委托对象,该对象处理中断以及播放完成的事件。
具体可看下面例子
-(void)avplay{
NSString *soundFilePath =
[[NSBundle mainBundle] pathForResource: @"1"
ofType: @"mp3"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
AVAudioPlayer *newPlayer =
[[AVAudioPlayer alloc] initWithContentsOfURL: fileURL
error: nil];
self.player = newPlayer;
[self.player prepareToPlay];
[self.player setDelegate: self];
}
-(void)buttonEvent:(id)button{
[self.player play];
}
我们可以设置音量
[self.player setVolume: 1.0]; // available range is 0.0 through 1.0
对于更多信息,可以看AVAudioPlayer Class Reference
使用音频队列服务播放控制声音
音频队列服务增加了AVAudioPlayer的可用的播放功能。使用音频队列服务进行播放可以实现下来功能:
- 精确的安排播放音乐,允许同步
- 在煮个缓冲区的基础上精确的控制音量
- 使用音频文件流服务播放您从六中捕获的音频。
音频队列服务允许我们播放任何可用的音频格式音乐。该技术不仅可以播放,也可以用来录制。
对于更多细节,可以看 Audio Queue Services Programming Guide和Audio Queue Services Reference。 简单代码可以看SpeakHere
创建音频队列对象
创建音频队列对象进行播放音乐,用一下几步:
- 1.创建数据结构以管理音频对象所需的信息,例如我们需要播放的数据的音频格式。
- 2.定义用于管理音频队列缓冲区的回调函数。回调使用音频文件服务来读取我们需要播放的文件。
- 3.使用AudioQueueNewOutput函数实例化播放音频队列
代码如下:
static const int kNumberBuffers = 3;
// Create a data structure to manage information needed by the audio queue
struct myAQStruct {
AudioFileID mAudioFile;
CAStreamBasicDescription mDataFormat;
AudioQueueRef mQueue;
AudioQueueBufferRef mBuffers[kNumberBuffers];
SInt64 mCurrentPacket;
UInt32 mNumPacketsToRead;
AudioStreamPacketDescription *mPacketDescs;
bool mDone;
};
// Define a playback audio queue callback function
static void AQTestBufferCallback(
void *inUserData,
AudioQueueRef inAQ,
AudioQueueBufferRef inCompleteAQBuffer
) {
myAQStruct *myInfo = (myAQStruct *)inUserData;
if (myInfo->mDone) return;
UInt32 numBytes;
UInt32 nPackets = myInfo->mNumPacketsToRead;
AudioFileReadPackets (
myInfo->mAudioFile,
false,
&numBytes,
myInfo->mPacketDescs,
myInfo->mCurrentPacket,
&nPackets,
inCompleteAQBuffer->mAudioData
);
if (nPackets > 0) {
inCompleteAQBuffer->mAudioDataByteSize = numBytes;
AudioQueueEnqueueBuffer (
inAQ,
inCompleteAQBuffer,
(myInfo->mPacketDescs ? nPackets : 0),
myInfo->mPacketDescs
);
myInfo->mCurrentPacket += nPackets;
} else {
AudioQueueStop (
myInfo->mQueue,
false
);
myInfo->mDone = true;
}
}
// Instantiate an audio queue object
AudioQueueNewOutput (
&myInfo.mDataFormat,
AQTestBufferCallback,
&myInfo,
CFRunLoopGetCurrent(),
kCFRunLoopCommonModes,
0,
&myInfo.mQueue
);
这段代码直接复制到工程中会发生错误的.想要详细了如何使用应该看SpeakHere,改工程中包含以上代码。
因为这篇文章只是讲解音频知识的大概。所以不会过多设计技术细节。
控制播放水平
音频队列对象为我们提供了两种控制播放级别的方法。
最直接的方式是用下列代码
Float32 volume = 1; // linear scale, range from 0.0 through 1.0
AudioQueueSetParameter (
myAQstruct.audioQueueObject,
kAudioQueueParam_Volume,
volume
);
这里说的播放水平就是音量大小啦。
我们还可以使用AudioQueueEnqueueBufferWithParameters函数设置音频队列缓冲区的播放级别。这可以让我们指定音频队列来设置,产生的效果是,改队列携带了这次操作,当该队列进行播放是,该设置才能生效。
以上两种方式更改音频队列将一直有效。
提高播放水平
我们可以通过下列方式获取当前播放水平:
- 通过将kAudioQueueProperty_EnableLevelMetering属性设置为true来启用音频队列对象的计量
- 查询音频队列对象的kAudioQueueProperty_CurrentLevelMeter
此属性的值是AudioQueueLevelMeterState结构的数组,每个通道一个。
typedef struct AudioQueueLevelMeterState {
Float32 mAveragePower;
Float32 mPeakPower;
}; AudioQueueLevelMeterState;
播放多个音乐
要同时播放多个声音,我们需要为每个声音创建一个播放音频队列对象。对于每个音频队列,使用AudioQueueEnqueueBufferWithParameters函数安排第一个音频缓冲区同时启动。
从iOS 3.0开始,几乎所有支持的音频格式都可用于同步播放 - 即所有可以使用软件解码播放的格式,如表1-1所示。 对于处理器效率最高的多重播放,请使用线性PCM(未压缩)或IMA4(压缩)音频。
使用OpenAL播放定位声音
OpenAL框架中的ios中的提供的开源openAL 音频api提供了一个优化的界面,用于在播放期间定位立体生成中的声音。播放,定位和移动声音就想其他的平台上一样。openAL 还可以让你混合声音。openAL使用I / O单元进行播放,从而实现最低延迟。
出于以上原因,openAL是基于ios的设备上播放游戏应用程序中的声音的最佳选择。但是,openAL也是一般ios应用程序音频播放需求的不错的选择。
对于更多的使用,我们可以看OpenAL FAQ for iPhone OS。demo 可以看oalTouch
音频录制
ios 可以使用AVAudioRecorder类和Audio Queue Services 进行音频录制。这些接口可以根据需要连接音频硬件,管理内存和使用编解码器。录制音频的格式见上面的表。
录制音频可以在系统定义的输入水平进行。系统可以从用户选择的音频源来获取输入信息-例如内置的麦克风,或者如果耳机连接,那么输入源也可以是耳机麦克风或者其他输入源。
使用AVAudioRecorder 类录制音频
在ios 中录制声音的最简单的方式是使用AVAudioRecorder类。该类提供了一个高度简化的oc接口,可以轻松的提供诸如暂停恢复录制和处理音频中断等复杂操作。同时,我们也可以控制录音的格式。
准备录音需要以下步骤:
- 1.指定一个声音文件地址
- 2.设置音频会话
- 3.配置音频录制的初始化的状态
app在启动的时候就对此部分进行配置是很好的时机。如下
- (void) audioRecorder {
NSString *tempDir = NSTemporaryDirectory ();
NSString *soundFilePath =
[tempDir stringByAppendingString: @"sound.caf"];
NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
self.soundFileURL = newURL;
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
audioSession.delegate = self;
[audioSession setActive: YES error: nil];
}
要处理中断和录制完成,我们需要增加AVAudioSessionDelegate和AVAudioRecorderDelegate协议的实现。如果我们的应用程序也需要播放,我们需要参考AVAudioPlayerDelegate Protocol Reference
开启录制代码如下
- (IBAction) recordOrStop: (id) sender {
[[AVAudioSession sharedInstance]
setCategory: AVAudioSessionCategoryRecord
error: nil];
NSDictionary *recordSettings =
[[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax],
AVEncoderAudioQualityKey,
nil];
AVAudioRecorder *newRecorder =
[[AVAudioRecorder alloc] initWithURL: self.soundFileURL settings: recordSettings
error: nil];
self.soundRecorder = newRecorder;
self.soundRecorder.delegate = self;
[self.soundRecorder prepareToRecord];
[self.soundRecorder record];
}
想要了解更多AVAudioRecorder信息可以看AVAudioRecorder Class Reference
使用Audio Queue Services 录制
用Audio Queue Services录制音频,首先我们需要实例化一个录制音频队列对象,提供一个回调函数。回调将传入的音频数据存储在内存中以供立即使用,或者将其写入文件以进行长期存储。
与回放功能一样,我们可以通过查询其kAudioQueueProperty_CurrentLevelMeter属性从音频队列对象获取当前录制音频级别。
对于更多细节如何使用Audio Queue Services录制音频,可以参考Recording Audio inAudio Queue Services Programming Guide
解析流式音频
要播放流式音频内容,例如来说网络的内容,我们需要用Audio Queue Services中的音频文件流服务。音频文件流服务从网络比特流中的公共音频文件容器格式解析音频数据包和元数据。我们也可以使用他来解析磁盘文件中的数据包和元数据。
在ios中,我们可以解析的音频文件和比特流数据形式如下
- MPEG-1 Audio Layer 3, used for .mp3 files
- MPEG-2 ADTS, used for the .aac audio data format
- AIFC
- AIFF
- CAF
- MPEG-4, used for .m4a, .mp4, and .3gp files
- NeXT
- WAVE
检索到音频数据包后,我们可以播放ios中支持的任何格式的恢复声音。
想了解更多流信息,参考Audio File Stream Services Reference
ios中的音频单元支持
ios提供了一组音频处理插件,称为音频单元,可以在任何的应用程序中使用。Audio Unit框架中的接口允许我们打开,连接和使用这些音频单元。
使用audio unit框架的功能,我们需要将audio toolbox 框架添加到xocde工程中。 #import <AudioToolbox/AudioToolbox.h>
下列表就是在ios提供的 audio units
Audio unit | Description |
---|---|
iPod Equalizer unit | iPod EQ单元的类型是kAudioUnitSubType_AUiPodEQ,它提供一个简单的,基于预设的均衡器,可以在app中使用。有关如何使用此音频单元,参考Mixer iPodEQ AUGraph Test |
3D Mixer unit | 3D混音器单元的类型是kAudioUnitSubType_AU3DMixerEmbedded,可以让我们混合多个音频流,指定立体声输出平移,操作播放速率等。OpenAL构建于此音频单元之上,提供更适合游戏应用程序的更高级API |
Multichannel Mixer unit | 多通道混音器单元,类型是kAudioUnitSubType_MultiChannelMixer,允许将多个单声道或者立体声音频流混合到单个立体声中。他还支持每个输入的左/右平移。 |
Remote I/O unit | 远程I/O单元,类型是kAudioUnitSubType_RemoteIO,连接到音频输入和输出硬件,并支持实时I.O. aurioTouch |
Voice Processing I/O unit | 语音处理I/O,单元类型是kAudioUnitSubType_VoiceProcessingIO,具有I/O一单元的特性,并为双向通信添加了回声抑制和其他功能 |
Generic Output unit | 通用输出单元,类型是kAudioUnitSubType_GenericOutput,支持转换为线型PCM格式和从线型PCM格式的转换。;可以用于启动和停止 graph |
Converter unit | 转换器单元的类型是kAudioUnitSubType_AUConverter,允许我们将音频数据从一种格式转换成领一种格式。通常使用包含转换器单元的远程I/O单元获得此音频单元的功能 |
更多细节参考 Audio Unit Hosting Guide for iOS
简单demo aurioTouch
ios音频最佳实战
使用音频提示
Tip | Action |
---|---|
适当使用压缩视频 | 对于aac,mp3,alac音频,可以使用硬件辅助编码器进行解码。虽然有效,但一次仅限一个音频流。如果需要同时播放多个声音,请使用IMA4(压缩)或者线型PCM(未压缩)格式存储这些声音 |
转换为我们需要的数据格式和文件 | Mac OS X中的afconvert工具允许我们转换为各种音频数据格式和文件类型。 具体用法可以用man afconvert 或者 Preferred Audio Formats in iOS |
评估音频内存问题 | 使用音频队列服务播放声音时,我们需要编写一个回调,将短段音频数据发送到音频队列的缓冲区。在默写情况下,最好将整个声音文件加载到内存中进行播放,从而最大限度的减少磁盘访问。在其他情况下,一次加载足够的数据以保持缓冲区满是最好的。 |
通过限制采样率,位深度和通道来减小音频文件大小 | 采样率和每个采样的位数会直接影响音频文件的大小。如果您需要播放许多此类声音或者长时间声音,需要考虑减少这些值以减少音频数据的内存占用。例如,我们可以使用32KHZ或者更低的采样率,而不是使用44.2KHZ的采样率来获取合理的音质效果。使用单声道音频而不是立体声(双声道)可减少文件大小。对于每个声音asset,需要考虑单声道是否可以满足需求 |
选择合适的技术 | 如果需要方便的高阶界面来定位立体声场中的声音或者低延迟播放时,可以使用openAL。要解析文件或网络流总的音频数据包,请使用 Audio File Stream Services。要简单播放单个或者多个声音,请使用AVAudioRecorder类。对于音频聊天,可以使用语音处理I/O单元。要播放从用户的iTunes资料库同步的音频资源,使用iPod Library Access。当我们需要音频播放警报和用户界面音效时,我们使用Core Audio’s System Sound Services。对于其他音频应用程序,包含流式音频的播放,精确同步以及对传入音频数据包的访问,使用Audio Queue Services. |
低延迟的代码 | 要获得尽可能低的播放延迟,使用openAL或者直接使用I/O单元 |
ios的首先音频格式
对于未压缩(最高质量的)音频,请使用导报在caf文件中的16位小端线型PCM 音频格式。我们可以使用afconvert 命令行工具来mac os x中将音频文件转换为此格式
/usr/bin/afconvert -f caff -d LEI16 {INPUT} {OUTPUT}
afconvert 工具允许我们转换为各种音频数据格式和文件类型。我们可以用 man afconvert 查看其功能。或者afconvert -h 查看
man afconvert
对于一次播放一个声音的压缩音频,以及当不需要与ipod应用程序同时播放音频时,可以使用CAF或者m4a文件中打包成aac格式。
当需要同时播放多个声音时候,为了减少内存使用量,使用IMA4(IMA/ADPCM)压缩。这样可以减少文件大小,但在解压缩过程中对CPU的影响最小。与线型PCM数据一样,在caf 文件中打包IMA4 数据。
网友评论