浅谈iOS中音频的开发

来源:互联网 发布:js修改微信分享的内容 编辑:程序博客网 时间:2024/06/04 21:16

  我对音频技术不是很精通,最近对这方面比较有兴趣,公司以前的项目用到这方面的技术不多。我只是粗略的涉猎没有深入研究。今天就研究一下写一篇博客。同时希望以后能做一个关于音频的商业项目也期望能接触到音频开发技术的大牛。

  随着移动互联网的发展,智能手机功能越来越丰富。播放音乐、视频、录音、拍照等都是很常用的功能。在iOS中对于多媒体的支持是非常强大的,今天的文章中将会对音频进行介绍。

  在iOS中音频播放从形式上可以分为音效播放和音乐播放。前者主要指的是一些短音频播放,通常作为点缀音频,对于这类音频不需要进行进度、循环等控制。后者指的是一些较长的音频,通常是主音频,对于这些音频的播放通常需要进行精确的控制。在iOS中播放两类音频分别使用AudioToolbox.framework和AVFoundation.framework来完成音效和音乐播放。

  音效

 这里我先介绍我做的一个项目,app名为“叮叮收银”这是一个与收银相关的项目。当时要做的效果是当收银成功有一个“叮”的音效。这样比较人性化,当时产品说会和老板讨论确定这个短音效。我当时就先考虑了短音频的播放。不过后来我发现其实系统声音完全可以。我当时听了好多个系统声音最后确定了一个大家都比较满意的。不过测试声音时要连接真机测试,模拟器是不可以的。

  下面是简单示例:

 1.导入#import <AudioToolbox/AudioToolbox.h>

 2.播放时调用AudioServicesPlaySystemSound(SystemSoundID);

 当参数为 1000-2000 之间数字时就是播放系统声音(我的项目用的是1054音效)

 系统声音对照表:

Sound IDFile name (iPhone)File name (iPod Touch)CategoryNote1000new-mail.cafnew-mail.cafMailReceived 1001mail-sent.cafmail-sent.cafMailSent 1002Voicemail.cafVoicemail.cafVoicemailReceived 1003ReceivedMessage.cafReceivedMessage.cafSMSReceived 1004SentMessage.cafSentMessage.cafSMSSent 1005alarm.cafsq_alarm.cafCalendarAlert 1006low_power.caflow_power.cafLowPower 1007sms-received1.cafsms-received1.cafSMSReceived_Alert 1008sms-received2.cafsms-received2.cafSMSReceived_Alert 1009sms-received3.cafsms-received3.cafSMSReceived_Alert 1010sms-received4.cafsms-received4.cafSMSReceived_Alert 1011--SMSReceived_Vibrate 1012sms-received1.cafsms-received1.cafSMSReceived_Alert 1013sms-received5.cafsms-received5.cafSMSReceived_Alert 1014sms-received6.cafsms-received6.cafSMSReceived_Alert 1015Voicemail.cafVoicemail.caf-Available since 2.11016tweet_sent.caftweet_sent.cafSMSSentAvailable since 5.01020Anticipate.cafAnticipate.cafSMSReceived_AlertAvailable since 4.21021Bloom.cafBloom.cafSMSReceived_AlertAvailable since 4.21022Calypso.cafCalypso.cafSMSReceived_AlertAvailable since 4.21023Choo_Choo.cafChoo_Choo.cafSMSReceived_AlertAvailable since 4.21024Descent.cafDescent.cafSMSReceived_AlertAvailable since 4.21025Fanfare.cafFanfare.cafSMSReceived_AlertAvailable since 4.21026Ladder.cafLadder.cafSMSReceived_AlertAvailable since 4.21027Minuet.cafMinuet.cafSMSReceived_AlertAvailable since 4.21028News_Flash.cafNews_Flash.cafSMSReceived_AlertAvailable since 4.21029Noir.cafNoir.cafSMSReceived_AlertAvailable since 4.21030Sherwood_Forest.cafSherwood_Forest.cafSMSReceived_AlertAvailable since 4.21031Spell.cafSpell.cafSMSReceived_AlertAvailable since 4.21032Suspense.cafSuspense.cafSMSReceived_AlertAvailable since 4.21033Telegraph.cafTelegraph.cafSMSReceived_AlertAvailable since 4.21034Tiptoes.cafTiptoes.cafSMSReceived_AlertAvailable since 4.21035Typewriters.cafTypewriters.cafSMSReceived_AlertAvailable since 4.21036Update.cafUpdate.cafSMSReceived_AlertAvailable since 4.21050ussd.cafussd.cafUSSDAlert 1051SIMToolkitCallDropped.cafSIMToolkitCallDropped.cafSIMToolkitTone 1052SIMToolkitGeneralBeep.cafSIMToolkitGeneralBeep.cafSIMToolkitTone 1053SIMToolkitNegativeACK.cafSIMToolkitNegativeACK.cafSIMToolkitTone 1054SIMToolkitPositiveACK.cafSIMToolkitPositiveACK.cafSIMToolkitTone 1055SIMToolkitSMS.cafSIMToolkitSMS.cafSIMToolkitTone 1057Tink.cafTink.cafPINKeyPressed 1070ct-busy.cafct-busy.cafAudioToneBusyThere was no category for this sound before 4.0.1071ct-congestion.cafct-congestion.cafAudioToneCongestionThere was no category for this sound before 4.0.1072ct-path-ack.cafct-path-ack.cafAudioTonePathAcknowledgeThere was no category for this sound before 4.0.1073ct-error.cafct-error.cafAudioToneErrorThere was no category for this sound before 4.0.1074ct-call-waiting.cafct-call-waiting.cafAudioToneCallWaitingThere was no category for this sound before 4.0.1075ct-keytone2.cafct-keytone2.cafAudioToneKey2There was no category for this sound before 4.0.1100lock.cafsq_lock.cafScreenLocked 1101unlock.cafsq_lock.cafScreenUnlocked 1102--FailedUnlock 1103Tink.cafsq_tock.cafKeyPressed 1104Tock.cafsq_tock.cafKeyPressed 1105Tock.cafsq_tock.cafKeyPressed 1106beep-beep.cafsq_beep-beep.cafConnectedToPower 1107RingerChanged.cafRingerChanged.cafRingerSwitchIndication 1108photoShutter.cafphotoShutter.cafCameraShutter 1109shake.cafshake.cafShakeToShuffleAvailable since 3.01110jbl_begin.cafjbl_begin.cafJBL_BeginAvailable since 3.01111jbl_confirm.cafjbl_confirm.cafJBL_ConfirmAvailable since 3.01112jbl_cancel.cafjbl_cancel.cafJBL_CancelAvailable since 3.01113begin_record.cafbegin_record.cafBeginRecordingAvailable since 3.01114end_record.cafend_record.cafEndRecordingAvailable since 3.01115jbl_ambiguous.cafjbl_ambiguous.cafJBL_AmbiguousAvailable since 3.01116jbl_no_match.cafjbl_no_match.cafJBL_NoMatchAvailable since 3.01117begin_video_record.cafbegin_video_record.cafBeginVideoRecordingAvailable since 3.01118end_video_record.cafend_video_record.cafEndVideoRecordingAvailable since 3.01150vc~invitation-accepted.cafvc~invitation-accepted.cafVCInvitationAcceptedAvailable since 4.01151vc~ringing.cafvc~ringing.cafVCRingingAvailable since 4.01152vc~ended.cafvc~ended.cafVCEndedAvailable since 4.01153ct-call-waiting.cafct-call-waiting.cafVCCallWaitingAvailable since 4.11154vc~ringing.cafvc~ringing.cafVCCallUpgradeAvailable since 4.11200dtmf-0.cafdtmf-0.cafTouchTone 1201dtmf-1.cafdtmf-1.cafTouchTone 1202dtmf-2.cafdtmf-2.cafTouchTone 1203dtmf-3.cafdtmf-3.cafTouchTone 1204dtmf-4.cafdtmf-4.cafTouchTone 1205dtmf-5.cafdtmf-5.cafTouchTone 1206dtmf-6.cafdtmf-6.cafTouchTone 1207dtmf-7.cafdtmf-7.cafTouchTone 1208dtmf-8.cafdtmf-8.cafTouchTone 1209dtmf-9.cafdtmf-9.cafTouchTone 1210dtmf-star.cafdtmf-star.cafTouchTone 1211dtmf-pound.cafdtmf-pound.cafTouchTone 1254long_low_short_high.caflong_low_short_high.cafHeadset_StartCall 1255short_double_high.cafshort_double_high.cafHeadset_Redial 1256short_low_high.cafshort_low_high.cafHeadset_AnswerCall 1257short_double_low.cafshort_double_low.cafHeadset_EndCall 1258short_double_low.cafshort_double_low.cafHeadset_CallWaitingActions 1259middle_9_short_double_low.cafmiddle_9_short_double_low.cafHeadset_TransitionEnd 1300Voicemail.cafVoicemail.cafSystemSoundPreview 1301ReceivedMessage.cafReceivedMessage.cafSystemSoundPreview 1302new-mail.cafnew-mail.cafSystemSoundPreview 1303mail-sent.cafmail-sent.cafSystemSoundPreview 1304alarm.cafsq_alarm.cafSystemSoundPreview 1305lock.cafsq_lock.cafSystemSoundPreview 1306Tock.cafsq_tock.cafKeyPressClickPreviewThe category was SystemSoundPreview before 3.2.1307sms-received1.cafsms-received1.cafSMSReceived_Selection 1308sms-received2.cafsms-received2.cafSMSReceived_Selection 1309sms-received3.cafsms-received3.cafSMSReceived_Selection 1310sms-received4.cafsms-received4.cafSMSReceived_Selection 1311--SMSReceived_Vibrate 1312sms-received1.cafsms-received1.cafSMSReceived_Selection 1313sms-received5.cafsms-received5.cafSMSReceived_Selection 1314sms-received6.cafsms-received6.cafSMSReceived_Selection 1315Voicemail.cafVoicemail.cafSystemSoundPreviewAvailable since 2.11320Anticipate.cafAnticipate.cafSMSReceived_SelectionAvailable since 4.21321Bloom.cafBloom.cafSMSReceived_SelectionAvailable since 4.21322Calypso.cafCalypso.cafSMSReceived_SelectionAvailable since 4.21323Choo_Choo.cafChoo_Choo.cafSMSReceived_SelectionAvailable since 4.21324Descent.cafDescent.cafSMSReceived_SelectionAvailable since 4.21325Fanfare.cafFanfare.cafSMSReceived_SelectionAvailable since 4.21326Ladder.cafLadder.cafSMSReceived_SelectionAvailable since 4.21327Minuet.cafMinuet.cafSMSReceived_SelectionAvailable since 4.21328News_Flash.cafNews_Flash.cafSMSReceived_SelectionAvailable since 4.21329Noir.cafNoir.cafSMSReceived_SelectionAvailable since 4.21330Sherwood_Forest.cafSherwood_Forest.cafSMSReceived_SelectionAvailable since 4.21331Spell.cafSpell.cafSMSReceived_SelectionAvailable since 4.21332Suspense.cafSuspense.cafSMSReceived_SelectionAvailable since 4.21333Telegraph.cafTelegraph.cafSMSReceived_SelectionAvailable since 4.21334Tiptoes.cafTiptoes.cafSMSReceived_SelectionAvailable since 4.21335Typewriters.cafTypewriters.cafSMSReceived_SelectionAvailable since 4.21336Update.cafUpdate.cafSMSReceived_SelectionAvailable since 4.21350--RingerVibeChanged 1351--SilentVibeChanged 4095--VibrateThere was no category for this sound before 2.2.
In the SDK this is the constant kSystemSoundID_Vibrate.

 AudioToolbox.framework是一套基于C语言的框架,使用它来播放音效其本质是将短音频注册到系统声音服务(System Sound Service)。System Sound Service是一种简单、底层的声音播放服务,但是它本身也存在着一些限制:

 1. 音频播放时间不能超过30s     

 2.数据必须是PCM或者IMA4格式    

 3.音频文件必须打包成.caf、.aif、.wav中的一种(注意这是官方文档的说法,实际测试发现一些.mp3也可以播放)

 使用System Sound Service 播放音效的步骤如下:

 1.调用AudioServicesCreateSystemSoundID(   CFURLRef  inFileURL, SystemSoundID*   outSystemSoundID)函数获得系统声音ID。

 2.如果需要监听播放完成操作,则使用AudioServicesAddSystemSoundCompletion(  SystemSoundID inSystemSoundID,CFRunLoopRef  inRunLoop, CFStringRef  inRunLoopMode, AudioServicesSystemSoundCompletionProc  inCompletionRoutine, void*  inClientData)方法注册回调函数。

 3.调用AudioServicesPlaySystemSound(SystemSoundID inSystemSoundID) 或者AudioServicesPlayAlertSound(SystemSoundID inSystemSoundID) 方法播放音效(后者带有震动效果)。】

 下面是简单示例:

 1.导入#import <AudioToolbox/AudioToolbox.h>

 2 .代码

 - (void)viewDidLoad{
    [super viewDidLoad];
    
    [self playSoundEffect:@"feedtip.wav"];
}

/**
 *  播放完成回调函数
 *
 *  @param soundID    系统声音ID
 *  @param clientData 回调时传递的数据
 */
void soundCompleteCallback(SystemSoundID soundID,void * clientData){
    NSLog(@"播放完成...");
}

/**
 *  播放音效文件
 *
 *  @param name 音频文件名称
 */
-(void)playSoundEffect:(NSString *)name{
    NSString *audioFile=[[NSBundle mainBundle] pathForResource:name ofType:nil];
    NSURL *fileUrl=[NSURL fileURLWithPath:audioFile];
    //1.获得系统声音ID
    SystemSoundID soundID = 0;
    /**
     * inFileUrl:音频文件url
     * outSystemSoundID:声音id(此函数会将音效文件加入到系统音频服务中并返回一个长整形ID)
     */
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)(fileUrl), &soundID);
    //如果需要在播放完之后执行某些操作,可以调用如下方法注册一个播放完成回调函数
    AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, soundCompleteCallback, NULL);
    //2.播放音频
    AudioServicesPlaySystemSound(soundID);//播放音效
    //    AudioServicesPlayAlertSound(soundID);//播放音效并震动
}

 音乐

 如果播放较大的音频或者要对音频有精确的控制则System Sound Service可能就很难满足实际需求了,通常这种情况会选择使用AVFoundation.framework中的AVAudioPlayer来实现。AVAudioPlayer可以看成一个播放器,它支持多种音频格式,而且能够进行进度、音量、播放速度等控制。首先简单看一下AVAudioPlayer常用的属性和方法:

属性说明@property(readonly, getter=isPlaying) BOOL playing是否正在播放,只读@property(readonly) NSUInteger numberOfChannels音频声道数,只读@property(readonly) NSTimeInterval duration音频时长@property(readonly) NSURL *url音频文件路径,只读@property(readonly) NSData *data音频数据,只读@property float pan立体声平衡,如果为-1.0则完全左声道,如果0.0则左右声道平衡,如果为1.0则完全为右声道@property float volume音量大小,范围0-1.0@property BOOL enableRate是否允许改变播放速率@property float rate播放速率,范围0.5-2.0,如果为1.0则正常播放,如果要修改播放速率则必须设置enableRate为YES@property NSTimeInterval currentTime当前播放时长@property(readonly) NSTimeInterval deviceCurrentTime输出设备播放音频的时间,注意如果播放中被暂停此时间也会继续累加@property NSInteger numberOfLoops循环播放次数,如果为0则不循环,如果小于0则无限循环,大于0则表示循环次数@property(readonly) NSDictionary *settings音频播放设置信息,只读@property(getter=isMeteringEnabled) BOOL meteringEnabled是否启用音频测量,默认为NO,一旦启用音频测量可以通过updateMeters方法更新测量值对象方法说明- (instancetype)initWithContentsOfURL:(NSURL *)url error:(NSError **)outError使用文件URL初始化播放器,注意这个URL不能是HTTP URL,AVAudioPlayer不支持加载网络媒体流,只能播放本地文件- (instancetype)initWithData:(NSData *)data error:(NSError **)outError使用NSData初始化播放器,注意使用此方法时必须文件格式和文件后缀一致,否则出错,所以相比此方法更推荐使用上述方法或- (instancetype)initWithData:(NSData *)data fileTypeHint:(NSString *)utiString error:(NSError **)outError方法进行初始化- (BOOL)prepareToPlay;加载音频文件到缓冲区,注意即使在播放之前音频文件没有加载到缓冲区程序也会隐式调用此方法。- (BOOL)play;播放音频文件- (BOOL)playAtTime:(NSTimeInterval)time在指定的时间开始播放音频- (void)pause;暂停播放- (void)stop;停止播放- (void)updateMeters更新音频测量值,注意如果要更新音频测量值必须设置meteringEnabled为YES,通过音频测量值可以即时获得音频分贝等信息- (float)peakPowerForChannel:(NSUInteger)channelNumber;获得指定声道的分贝峰值,注意如果要获得分贝峰值必须在此之前调用updateMeters方法- (float)averagePowerForChannel:(NSUInteger)channelNumber获得指定声道的分贝平均值,注意如果要获得分贝平均值必须在此之前调用updateMeters方法@property(nonatomic, copy) NSArray *channelAssignments获得或设置播放声道代理方法说明- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag音频播放完成- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error音频解码发生错误

 AVAudioPlayer的使用比较简单:

  1. 初始化AVAudioPlayer对象,此时通常指定本地文件路径。
  2. 设置播放器属性,例如重复次数、音量大小等。
  3. 调用play方法播放。
 当然由于AVAudioPlayer一次只能播放一个音频文件,所有上一曲、下一曲其实可以通过创建多个播放器对象来完成,这里暂不实现。播放进度的实现主要依靠一个定时器实时计算当前播放时长和音频总时长的比例,另外为了演示委托方法,下面的代码中也实现了播放完成委托方法,通常如果有下一曲功能的话播放完可以触发下一曲音乐播放。下面是主要代码:

 1.导入#import <AVFoundation/AVFoundation.h>
 今天有事先更到这里。

 参考链接:http://www.cnblogs.com/kenshincui/p/4186022.html

0 0
原创粉丝点击