Multimedia Programming Guide
1,使用Audio(音频)
iOS提供了丰富的工具来操作声音.这些工具被安排的frameworks中,如下所示:
1)MediaPlayer.framework---播放音乐、播放文本、播放iPod库中的podcasts。(addMusic例子实现了播放音乐文件、从iPod(iTunes中)选择音乐并播放,可以播放、暂停)
2) AVFoundation.framework---播放和录制音频(使用Objective-C)(avTouch例子实现了播放.m4a音频,可以控制进度、实时显示音量大小、调整音量、播放、暂停、快进、快退功能)
3)AudioToolbox.framework---同步播放音频,访问传入的音频包,解析音频流,转换音频格式,和录制音频with access to individual packets.(SpearHere例子实现了录音、停止录音、没有暂停录制功能、播放(但是没有开启扬声器)、显示录制音量大小功能)
4)AudioUnit.framework---连接并使用音频处理插件。(需要添加<AudioToolbox/AudioToolbox.h>)
5)OpenAL.framekwork---在游戏或其他应用中提供音频定位回放。iOS支持OpenAL1.1。详细信息请查看OpenAL官网。(oalTouch实现的功能不清楚,不过明确看出来的有同时播放两个音乐,关闭任意的一个声音,暂停和继续播放)
要在你的代码中使用这些特性,需要添加相应的framework到你的代码工程中,并添加一个 #import。例如,要提供访问AV Foundation framework,添加
#import <AVFoundation/AVFoundation.h>
2,Audio Codecs(编码解码器) ,支持的Audio格式,和Audio Sessions
iOS硬件和软件音频编码
你需要选择正确的音频格式和编码类型。在iOS 3.0以后,大多数音频格式可以被软编码(录音)和解码(播放)。软编码支持同时播放多个声音,但是可能会需要显著的CPU开销。
硬件相关的解码提供了极好的性能--但是不支持同时播放多个声音。如果你需要最大化video frame rate,你可以通过使用未压缩的音频或IMA4格式 最小化播放音频的CPU影响,或者使用硬件相关的解码.
iOS设备支持的编码解码器:
AAC(MPEG-4 Advanced Audio Coding) 硬件解码 YES 软件解码 YES
ALAC(Apple Lossless) 硬件解码 YES 软件解码 YES
HE-AAC(MPEG-4 High Efficiency AAC) 硬件解码 YES 软件解码 --
iLBC(internet Low Bitrate Codec) 硬件解码 -- 软件解码 YES
IMA4(IMA/ADPCM) 硬件解码 -- 软件解码 YES
Linear PCM 硬件解码 -- 软件解码 YES
MP3 硬件解码 YES 软件解码 YES
当使用硬件相关解码时,设备在同一时间只能播放一个支持的格式的实例。例如,如果你正在使用硬件解码器播放一个立体MP3声音,第二个MP3声音会使用软解码。相似的,你不能使用硬件同时播放一个AAC和ALAC声音。如果iPod应用在后台正在播放一个AAC或MP3声音,它已经声称了硬件编码/解码;你的应用然后播放AAC,ALAC和MP3音频会使用软解码。
要播放多个音乐而表现良好,或高效地在后台播放声音,使用linear PCM(未压缩)或IMA4(压缩的)音频。
要学习如何检查运行时哪种硬件或软件编码解码器可用,阅读 kAudioFormatProperty_HardwareCodecCapabilities常量in Audio Format Service Reference。
并且阅读Q&A QA1663 “Determining the availability of the AAC hardware encoder at runtime"
总结iOS如何支持音频格式for 单独或多播放:
1)Linear PCM and IMA4 -- 你可以同时播放PCM或IMA4声音
2)AAC,HE-AAC,MP3,and ALAC -- 播放这些声音可以使用高效的硬件相关的解码,但他们共享一个单独的硬件地址。同时只能播放一个声音。
下面列出了iOS设备上可用的录音编码器
1)AAC(MPEG-4 Advanced Audio Coding) 硬件相关编码 YES 软件相关编码 YES
2) ALAC 硬件相关编码 -- 软件相关编码 YES
3) iLBAC 硬件相关编码 -- 软件相关编码 YES
4) IMA4 硬件相关编码 -- 软件相关编码 YES
5) Linear PCM 硬件相关编码 -- 软件相关编码 YES
6) a-law 硬件相关编码 -- 软件相关编码 YES
3,Audio Sessions:
iOS audio session APIs 使你能定义你的应用的general audio behavior and design it to work well within the larger audio context of the device it's running on.这些API在Audio Session Service Reference和AVAudioSession Class Reference中描述。使用这些API,你可以指定下面的行为:
1)你的音频是否被静音--当静音切换时(在iPhone上,这叫做铃音/静音切换)
2)在屏幕锁上时,你的音频是否停止播放
3)在你的音频开始播放时,其他音频是否继续播放还是静音。
audio session还让你对用户动作做出响应,例如耳机插入或拔出,和其他使用设备声音硬件的事件,例如时钟或日历警报和来电。
下面列出了Audio Session的特性:
1)Setting categories:category是标志一组音频行为的Key.有6种categories,在Audio Session Categories中描述。
2)Handling interruptions and route changes:当你的audio被中断时,当中断结束时,当hardware audio route changes时,audio session都会发送消息。这些消息使你能做出响应--例如来电时
3)优化硬件特性:你可以查询audio session 来发现你的设备的characteristics(特色),例如硬件sample rate,硬件channel的数量,是否audio input可用。
有2个interface for working with audio session:
1)A streamlined ,objective-C interface that gives you access to the core audio session features and is described in "AVAudioSession Class Reference”和AVAudioSessionDelegate协议Reference。
2) A C-based interface。 在Audio Session Service Reference中描述。
你可以混合和匹配audio session code from AV Foundation and Audio Session Services
你可以使用默认的audio session行为,然而,除非特定的情况,默认行为是不合适的。
例如,默认情况下,在屏幕自动锁时,你的声音会停止播放。如果你打算继续播放,需要使用下面的代码:
NSError *setCategoryErr = nil;
NSError *activationErr = nil;
[[AVAudioSession sharedInstance]
setCategory: AVAudioSessionCategoryPlayback
error: &setCategoryErr];
[[AVAudioSession sharedInstance]
setActive: YES
error: &activationErr];
AVAudioSessionCategoryPlayback category保证了在屏幕锁时播放继续。激活audio session使特定的cateogry开始起作用。
如何处理打断,基于下面列出的技术:
1)如果你使用AV Foundation framework: The AVAudioPlayer和AVAudioRecorder类提供了代理方法来监听和处理打断开始和结束。
2)如果你使用Audio Queue Services,I/O audio unit:这些技术让你的应用控制中断的处理。你负责保存播放和录音位置,并在打断结束后重新激活你的audio session。实现AVAudioSession的打断代理方法或写一个打断监听器回调函数。
3)如果你使用OpenAL:当使用OpenAL播放时,实现AVAudioSession中断代理方法或写一个中断监听回调函数--就像使用Audio Queue Service时一样。然而,代理或回调函数必须额外地管理OpenAL context。
4)如果你使用System Sound Services:系统声音服务播放的声音在打断开始时会静音。在打断结束时,他们自动重新使用。
每个iOS 应用--除了很少的意外--都应该管理他的audio session。
4,播放音频:
1)通过访问iPod Library播放音频items:
在iOS3.0以后,iPod Library的访问使你能播放一个用户的音乐、audio books和audio podcasts。API的设计使得播放非常简单并支持高级的搜索和播放控制。
如下图所示,你的应用有两个方法来获得media items。Media Item Picker是简单易用、预打包的viewController,内置于iPod应用的音乐选择界面。对于大多数应用来说,这就够了。meida query提供了更多的访问控制,它提供了predicate-based的搜索。
还是如图中右部所示,使用API提供的music player来播放获取的meidia items。
2)播放UI Sound Effects或使用系统声音服务调用震动
要播放用户界面的声音效果(例如点击按钮),或使设备震动,需要使用系统声音服务。这个简洁的interface在System Sound Service Reference中描述。你可以参考Audio UI Sounds(SysSound)例子。这个例子很简单,在这里简单介绍一下:
//制作系统声音文件
NSURL *tapSound = [[NSBundle mainBundle] URLForResource: @"tap" withExtension: @"aif"];
// Store the URL as a CFURLRef instance
self.soundFileURLRef = (CFURLRef) [tapSound retain];
// Create a system sound object representing the sound file.
AudioServicesCreateSystemSoundID (
soundFileURLRef,
&soundFileObject
);
//soundFileObject就是系统声音对象
//播放系统声音
AudioServicesPlaySystemSound (soundFileObject);
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);//只震动
//播放系统声音,如果设备在铃声设置中设置为震动,那么在调用这个函数时设备还会震动
AudioServicesPlayAlertSound (soundFileObject);
限制:
a)不能超过30s
b)需要使用PCM 或 IMA4(IMA/ADPCM)格式
c)打包成.caf、.aif或.wav文件
另外,你在使用AudioServicesPlaySystemSound函数时:
a)声音使用当前系统音量播放,不能使用代码控制。
b)声音立即被播放
c)循环和立体定位是不可用的
d)同时播放是不可用的。
注意:系统提供的警告声音和系统提供的用户界面声音特效对你的应用来说不可用。例如,使用kSystemSoundID_UserPreferredAlert常量作为一个参数给AudioServicesPlayAlertSound函数将不会播放任何东西。
要想使用AudioServicesPlaySystemSound or AudioServicesPlayAlertSound 函数播放音乐,需要首先创建一个sound ID(如上面的例子所示)
一般如果你需要多次播放Sound ID,那么就保留它直到程序退出,如果只使用一次,那么你可以早播放完就立即释放他。
3)使用AVAudioPlayer类来播放声音
AVAudioPlayer提供的是Objective-C interface来播放声音。如果你的应用并不需要立体定位或精确的同步,并且如果你不播放从网络流中捕获的音频,Apple推荐你使用这个类。
使用AVAudioPlayer你可以:
a)播放任意时长的声音。
b)从内存或文件中播放声音。
c)循环播放。
d)同时播放多个声音(虽然不能精确的同步)
e)对于你播放的每个声音 控制其对应的播放level(音量)
f)搜索一个声音文件的特定点,支持快进和快退
g)获得audio power data,你可以用它来处理audio level metering(音量测量)。
AVAudioPlayer可以播放iOS支持的任何格式的音频。
如何配置AVAudioPlayer:
a)指定一个声音文件给audio player
b)[player prepareToPlay];
c)指定一个player代理,处理中断和播放完成事件。
例子:
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource: @"sound" ofType: @"wav"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL error: nil];
[fileURL release];
self.player = newPlayer;
[newPlayer release];
[player prepareToPlay];
[player setDelegate: self];
代理函数:
- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) player successfully: (BOOL) completed {
if (completed == YES) {
[self.button setTitle: @"Play" forState: UIControlStateNormal];
}
}
要播放、暂停或停止一个AVAudioPlayer对象,就调用其播放控制方法。你可以使用playing属性测试播放是否正在播放,如下所示:
if (self.player.playing){
[self.player pause];
} else {
[self.player play];
}
AVAudioPlayer类使用Objective-C的属性方式来管理声音的信息,例如播放位置,音量、循环等:
[self.player setVolume:1.0];//volume从0.0到1.0
4)使用Audio Queue Services播放声音:
Audio Queue Services比AVAudioPlayer功能更加强大。使用Audio Queue Services播放可以让你:
a)精确地安排播放同步。
b)精确地控制音量 on a buffer-by-buffer basis。
c)使用Audio File Stream Services 播放从流中捕获的音频
创建一个Audio Queue Object:
a)创建一个数据结构来管理audio queue需要的信息,例如你想要播放的数据的音频格式。
b)定义一个回调函数来管理audio queue buffers。回调使用Audio File Services来读取你想要播放的文件。
c)实例化playback audio queue,使用AudioQueueNewOutput函数。
下例使用了ANSI C来描述(在你的代码中,你可能需要包括适当的error handling代码)。”SpeakHere“例子在C++程序里显示了这些步骤.
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
);
控制Playback Level(控制播放音量?):
Audio queue objects提供了两个方法来控制playback level。
a)直接设置playback level:使用AudioQueueSetParameter函数,并提供kAudioQueueParam_Volume参数。
Float32 volume=1; //值从0.0到1.0
AudioQueueSetParameter(
myAQstruct.audioQueueObject,
kAudioQueueParam_Volume,
volume
);
b)你还可以通过使用AudioQueueEnqueueBufferWithParameters函数来为audio queue buffer设置播放音量。这些更改在buffers开始播放时生效。
指示播放音量:
你可以通过audio queue对象 获得当前的playback level通过:
i)启用metering:设置其kAudioQueueProperty_EnableLevelMetering属性为true。
ii)查询其kAudioQueueProperty_CurrentLevelMeter属性。
这个属性是一个AudioQueueLevelMeterState结构的array,每个channel一个。AudioQueueLevelMeterState结构为:
typedef struct AudioQueueLevelMeterState{
Float32 mAveragePower;
Float32 mPeakPower;
};
同时播放多个声音:
为每个声音创建单独的playback audio queue object。并为每个audio queue对象同时安排播放的第一个buffer(使用AudioQueueEnqueueBufferWithParameters函数)。
5)通过OpenAL播放立体声音:
在iOS的OpenAL框架中的开源API,提供了一个接口优化在一个立体环境中定位声音。播放,定位,移动声音和在其他平台一样。OpenAL还允许你混合声音。OpenAL使用I/O unit来播放,最省电。
所以,OpenAL是你在游戏中播放声音的最佳选择。然而,OpenAL也是在普通应用中不错的选择。
访问http://openal.org。 例子: oalTouch
14,录音:
iOS支持使用AVAudioRecorder类和Audio Queue Services来录音。这些接口连接硬件,管理内存,并且采用需要的编码解码器。
录音占用系统定义的输入level。系统使用用户选择的audio source的输入--内置的麦克风,或耳机或其他输入源。
15,通过AVAudioRecorder类来录音:
准备录音的步骤:
1)指定一个声音文件URL
2)建立Audio Session
3)配置Audio Recorder的初始化状态
应用加载时是做这些准备步骤的好位置,如下所示:
Listing 1-10 Setting up the audio session and the sound file URL
- (void) viewDidLoad {
[super viewDidLoad];
NSString *tempDir = NSTemporaryDirectory ();
NSString *soundFilePath =
[tempDir stringByAppendingString: @"sound.caf"];
NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
self.soundFileURL = newURL;
[newURL release];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
audioSession.delegate = self;
[audioSession setActive: YES error: nil];
recording = NO;
playing = NO;
}
要处理录音的打断和完成,添加AvAudioSessionDelegate和AVAudioRecorderDelegate协议到接口声明。如果你的应用还播放,那还要曹勇AVAudioPlayerDelegate协议
要实现录音,可参见下面的例子:
Listing 1-11 A record/stop method using the AVAudioRecorder class
- (IBAction) recordOrStop: (id) sender {
if (recording) {
[soundRecorder stop];
recording = NO;
self.soundRecorder = nil;
[recordOrStopButton setTitle: @"Record" forState:
UIControlStateNormal];
[recordOrStopButton setTitle: @"Record" forState:
UIControlStateHighlighted];
[[AVAudioSession sharedInstance] setActive: NO error: nil];
} else {
[[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: soundFileURL
settings: recordSettings
error: nil];
[recordSettings release];
self.soundRecorder = newRecorder;
[newRecorder release];
soundRecorder.delegate = self;
[soundRecorder prepareToRecord];
[soundRecorder record];
[recordOrStopButton setTitle: @"Stop" forState: UIControlStateNormal];
[recordOrStopButton setTitle: @"Stop" forState: UIControlStateHighlighted];
recording = YES;
}
}
6,录制音频:
iOS使用AVAudioRecorder类和Audio Queue Services来支持录音。这些接口连接音频硬件、管理内存,并使用必须的编码。
录音使用用户选择的音频源来录音,如内置的麦克风、或耳机或其他源。
1)使用AVAudioRecorder类来录音:
a)指定一个声音文件URL
b)启动一个audio session
c)配置audio recorder的初始化状态。
应用启动时是启动audio session的一个好时候。如下所示:
- (void) viewDidLoad {
[super viewDidLoad];
NSString *tempDir = NSTemporaryDirectory ();
NSString *soundFilePath =[tempDir stringByAppendingString: @"sound.caf"];
NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
self.soundFileURL = newURL;
[newURL release];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
audioSession.delegate = self;
[audioSession setActive: YES error: nil];
recording = NO;
playing = NO;
}
要处理录音的中断和结束,添加AVAudioSessionDelegate和AVAudioRecorderDelegate协议,如果你的应用还播放声音,你还要采用AVAudioPlayerDelegate协议。
要实现一个record方法,你可以使用下面所示的代码:
- (IBAction) recordOrStop: (id) sender {
if (recording) {
[soundRecorder stop];
recording = NO;
self.soundRecorder = nil;
[recordOrStopButton setTitle: @"Record" forState:UIControlStateNormal];
[recordOrStopButton setTitle: @"Record" forState:UIControlStateHighlighted];
[[AVAudioSession sharedInstance] setActive: NO error: nil];
} else {
[[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: soundFileURL settings: recordSettings error: nil];
[recordSettings release];
self.soundRecorder = newRecorder;
[newRecorder release];
soundRecorder.delegate = self;
[soundRecorder prepareToRecord];
[soundRecorder record];
[recordOrStopButton setTitle: @"Stop" forState: UIControlStateNormal];
[recordOrStopButton setTitle: @"Stop" forState: UIControlStateHighlighted];
recording = YES;
}
}
7、使用Audio Queuqe Services来录音:
要使用Audio Queuqe Services来录音,你要实例化一个recording audio queue对象并提供一个回调函数。回调存储传入的音频数据到内存中。
就像播放时一样,你也可以获得录音的音频音量,通过kAudioQueueProperty_CurrentLevelMeter属性获得。可以在SpeakHere中查看例子。或查看Audio Queue Services Programming Guide中的Recording Audio。
8,转换流化Aduio:
要播放流化的音频内容,例如网络上的,需要使用Audio File Stream Services 与 Audio Queue Services协作.Audio File Stream Service(音频文件流服务)从一个网络比特流中的普通的音频文件中转换音频包和metadata。你还可以使用它从硬盘上的文件来转换packet和metadata。
在iOS中,你可以像在Mac OS X中一样转换音频文件和比特流格式,如下所示:
1)MPEG-1 Audio Layer 3,使用.mp3文件
2)MPEG-2 ADTS,使用 .aac格式
3)AIFC
4)AIFF
5)CAF
6)MPEG-4,使用.m4a .mp4 .3gp文件
7)NeXT
8)WAVE
在检索音频包后,你可以使用iOS支持的任意格式来播放恢复的声音。
要连接一个网络流,使用Core Foundation interface,例如在CFHTTPMessage Reference描述的一样。使用Audio File Stream Services转换网络包到音频包。然后buffer音频包,并将它们发送给一个audio queue object播放。
Audio File Stream Services依赖Aduio File Services interface,例如AudioFramePacketTranslation结构和AudioFilePackeTableInfo结构。他们在Audio File Services Reference中描述。
更多的使用流的信息,请参考Audio File Stream Service Reference。
9、iOS中的Audio Unit Support
iOS提供了一系列处理音频的plug-ins,称为audio units,你可以在任意应用中使用。Audio Unit框架的interface使你能open、connect和使用这些audio units。
要使用Audio Unit框架的特色,需要添加Audio Toolbox框架。
下面列出了iOS提供的audio units:
a)iPod Equalizer unit:iPod EQ unit,kAudioUnitSubType_AUiPodEQ类型,提供了一个简单的、preset-based equalizer(预置的均衡器)。参考例子:iPhoneMixerEQGraphTest(实现了多声道音量控制、混合音量控制、音频风格选择(如R&B,Rock等))
b)3D Mixer unit:kAudioUnitSubType_AU3DMixerEmbedded类型,让你混合多个音频流,指定立体输出panning,管理播放rate,等等。OpenAL建立于这个audio unit之上并提供了一个高级API来适合game apps。
c)Multichannel Mixer unit:kAudioUnitSubType_MultiChannelMixer类型,使你混合多个单声道或立体音频流到一个单独的立体音频流。它还支持左/右 panning 。参考实例:Audio Mixer(MixerHost)(实现了两个声道的混合输出)
d)Remote I/O unit:kAudioUnitSubType_RemoteIO类型,连接到音频输入和输出硬件,并支持实时的I/O。参考aurioTouch例子。(实现了实时的录制音量显示)
e)Voice Processing I/O unit:kAudioUnitSubType_VoiceProcessingIO类型,有I/O unit的特性,并添加了回声抑制和其他关于双向通信的特性。
f)Generic Output unit:kAudioUnitSubType_GenericOutput类型,支持其他格式与转换linear PCM格式的转换;可以用来开始和结构一个段落。
g)Converter unit:kAudioUnitSubType_AUConverter类型,使你转换audio data从一个格式到另一个格式。你一般通过Remote I/O unit来获得这个audio unit的特点,因为它包含了一个Converter Unit。
更多使用system audio unit的信息,请查阅Audio Unit Hosting Guide for iOS。
10、关于iOS Audio的最好的体验:
a)使用适当压缩的音频:如果你打算同时播放多个声音,使用IMA4(压缩的格式)或Linear PCM(未压缩的格式)。
b)转换你需要的data格式和file格式:Mac OS X中的afconvert工具使你能转换很多音频数据格式和文件类型。
c)评估音频内存问题:当你使用Audio Queue Services播放声音时,你可以考虑是完全存放buffer还是只存放足够的buffer就OK了。
d)通过采样率、bit depths和channels来降低音频文件大小:
e)使用合适的技术:
f)低延迟的代码:为了最小的延迟,使用OpenAL或直接使用I/O unit。
在iOS中优先选择的音频格式:
对于未压缩的音频,使用16bit,低位优先,linear PCM音频数据包,在CAF文件中。你可以在Mac OS X中使用afconvert命令行工具转换一个音频文件到这个格式。
/usr/bin/afconvert -f caff -d LEI16 {INPUT} {OUTPUT}
对于压缩的音频,只播放一个声音时,使用AAC格式包,在一个CAF或m4a文件中。
对于同时播放多个声音时,使用更少的内存,使用IMA4(IMA/ADPCM)。IMA4格式也是打包到一个CAF文件中。
11,使用视频:
12,录像和编辑视频:在iOS3.0以后,你可以录像。要显示录像界面,可以创建和push a UIImagePickerController对象。
要录像,你必须首先检查camera source type(UIImagePickerControllerSourceTypeCamera)是否可用,和movie media type(kUTTypeMovie)是否可用for the camera。基于你指定给mediaTypes属性的值,the picker可以直接显示静态照相机或视频照相机,或一个可供用户选择的选择界面。
一点例子:
//为了使用kUTType需要引入下面这个头文件
#import <MobileCoreServices/UTCoreTypes.h>
//声明一个UIImagePickerController
UIImagePickerController *picker =[[[UIImagePickerController alloc] init] autorelease];
//判断sourceType是否可用
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
return;
}
picker.sourceType=UIImagePickerControllerSourceTypeCamera;
//获得当前sourceType可用的MediaTypes:
NSArray *temp_MediaTypes = [UIImagePickerController availableMediaTypesForSourceType:picker.sourceType];
//检测可用的mediaTypes
if ([temp_MediaTypes containsObject:(NSString *)kUTTypeMovie]){
temp_MediaTypes= @[(NSString *)kUTTypeMovie];
}
//设置mediaTypes
picker.mediaTypes = temp_MediaTypes;
[self presentModalViewController:picker animated:YES];
return;
使用UIImagePickerControllerDelegate协议,注册一个代理。代理接收视频录制完成消息, imagePickerController:didFinishPickingMediaWithInfo:方法。
在支持的设备上,你还可以从用户的照片库里选取已经录制好的视频。
在iOS4.0以后,你可以从设备的照相机中录制和显示传入的数据到屏幕上。 你使用AVCaptureSession来管理AVCaptureInput对象代表的输入中的数据流和AVCaptureOutput代表的输出中的数据流。
在iOS4.0以后,你可以编辑,assemble(聚集),and compose(构成,排版) video using assets or with new raw meterials.Assets 使用ASVAsset表示,你可以异步检查它来获得更好的性能。你使用AVMutableCompostion来从一个或多个源组合多媒体,然后 AVAssetExportSession来编码输出。
13,播放视频文件:
iOS支持直接播放视频文件,通过Media Player Framework,查看Media Player Framework Reference。视频播放只有全屏模式,并且可以被游戏开发者使用来播放短的动画或被任何开发者用来播放多媒体文件。当你开始播放视频时,多媒体播放器出现,屏幕变黑,然后视频内容出现。你可以让用户控制或不控制视频的播放。Enabling some or all of these controls 可以使用户改变音量,改变播放位置,或开始和停止视频。如果你不给用户这些控制,视频将会播放到停止。
要初始化视频播放,你必须知道要播放文件的URL。对于你的应用提供的文件来说,这必须是一个文件指针在你的应用程序束内;然而,它也可以是一个远程服务器上的文件指针。使用这个URL来初始化MPMoviePlayerController类的实例。这个类负责视频的播放和管理用户操作。
要开始播放,调用MPMediaPlayback协议中的play方法。
下面显示了一个例子。play方法是一个异步的调用,当movie播放时它返回控制给调用者。movie controller加载movie到一个全屏视图,并且动画movie在应用程序内容之上。当播放完时,movie controller发送通知给application controller对象,它负责释放movie controller,现在它已经不再需要了。
Listing 2-1 Playing full-screen movies
-(void) playMovieAtURL: (NSURL*) theURL {
MPMoviePlayerController* theMovie = [[MPMoviePlayerController alloc] initWithContentURL: theURL];
theMovie.scalingMode = MPMovieScalingModeAspectFill;
theMovie.movieControlMode = MPMovieControlModeHidden;
// Register for the playback finished notification
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(myMovieFinishedCallback:)
name: MPMoviePlayerPlaybackDidFinishNotification
object: theMovie];
// Movie playback is asynchronous, so this method returns immediately.
[theMovie play];
}
// When the movie is done, release the controller.
-(void) myMovieFinishedCallback: (NSNotification*) aNotification
{
MPMoviePlayerController* theMovie = [aNotification object];
[[NSNotificationCenter defaultCenter]
removeObserver: self
name: MPMoviePlayerPlaybackDidFinishNotification
object: theMovie];
// Release the movie instance created in playMovieAtURL:
[theMovie release];
}
在iOS 4.0以后,你可以使用 AVPlayer -- 与 AVPlayerLayer 协同工作 或者 使用一个AVSynchronizedLayer对象 来播放视频。你可以使用AVAudioMix和AVVideoComposition来个性化音频和视频部分。你还可以使用 AVCaptureVideoPreviewLayer 来显示video as it is being captured by an input device。