转:http://blog.csdn.net/ysy441088327/article/details/8164120(余书懿)
音频方面的知识,相对其他编程还是较为复杂的,特别是要搞清楚框架里具体使用的参数和方法,不然写起代码来非常迷茫.
1:播放简短性质的音频,例如按键声音,等可以这样实现.
一:引入框架:
- #import <AudioToolbox/AudioToolbox.h>
二:先声明一个声音源ID
- SystemSoundID _bookSoundID;
三:提供需要播放的音频地址进行声音源的注册.
- NSURL *bookSoundUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"bookSound" ofType:@"wav"]];
- AudioServicesCreateSystemSoundID((__bridge CFURLRef)bookSoundUrl, &_bookSoundID);
四:在需要的时候播放:
- AudioServicesPlaySystemSound(_bookSoundID);
五:不用的声音源记得释放掉
- AudioServicesDisposeSystemSoundID(_bookSoundID);
2: 关于 AVAudioSession
的使用
首先知道 AVAudioSession
是一个单例模式,也就是说,不用开发者自行实例化. 这个类在各种音频环境中起着非常重要的作用
一:首先是设置 AVAudioSession 的 类别
获取输入硬 件 获取输出硬件
与IPOD混合
遵从振铃/静音按键
AVAudioSessionCategoryAmbient
否
是
是
是
AVAudioSessionCategorySoloAmbient
否
是
否
是
AVAudioSessionCategoryPlayback
否
是
否
否
AVAudioSessionCategoryRecord
是
否
否
否
AVAudioSessionCategoryPlayAndRecord
是
是
否
否
根据实际的使用情况来设定具体的类别,设置代码如下:
- AVAudioSession * audioSession = [AVAudioSession sharedInstance];
- [audioSession setDelegate:self];
- [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error: &error];
- [audioSession setActive:YES error: &error];
二:在录制完声音或者播放完声音后,可以将音频会话关闭,来延续后台音乐的播放,代码如下:
- [[AVAudioSession sharedInstance] setActive:NO error: nil];
三:通过音频会话可以强制的设置应用程序使用指定的输出方式,例如:内声道,扬声器,代码如下:
- UInt32 audioRouteOverride = hasHeadset ?kAudioSessionOverrideAudioRoute_None:kAudioSessionOverrideAudioRoute_Speaker;
- AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);
kAudioSessionOverrideAudioRoute_None
内声道,耳机
kAudioSessionOverrideAudioRoute_Speaker 扬声器
四:那么怎么判断用户是否已经插入耳机?代码如下: (参考:http://iandworld.sinaapp.com/?p=184001)
- - (BOOL)hasHeadset {
-
- #if TARGET_IPHONE_SIMULATOR
- #warning *** Simulator mode: audio session code works only on a device
- return NO;
- #else
- CFStringRef route;
- UInt32 propertySize = sizeof(CFStringRef);
- AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &propertySize, &route);
-
- if((route == NULL) || (CFStringGetLength(route) == 0)){
-
- NSLog(@"AudioRoute: SILENT, do nothing!");
- } else {
- NSString* routeStr = (__bridge NSString*)route;
- NSLog(@"AudioRoute: %@", routeStr);
-
-
-
-
-
-
-
-
-
-
-
-
- NSRange headphoneRange = [routeStr rangeOfString : @"Headphone"];
- NSRange headsetRange = [routeStr rangeOfString : @"Headset"];
- if (headphoneRange.location != NSNotFound) {
- return YES;
- } else if(headsetRange.location != NSNotFound) {
- return YES;
- }
- }
- return NO;
- #endif
-
- }
返回YES,表示已经插入耳机,返回NO表示没有插入耳机
五:监听用户拔出插入耳机事件
1:注册监听事件,和回调函数
- AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange,
- audioRouteChangeListenerCallback,
- self);
2:实现回调函数进行相关处理:
- void audioRouteChangeListenerCallback (
- void *inUserData,
- AudioSessionPropertyID inPropertyID,
- UInt32 inPropertyValueSize,
- const void *inPropertyValue
- ) {
-
- if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return;
-
-
- CFDictionaryRef routeChangeDictionary = inPropertyValue;
-
- CFNumberRef routeChangeReasonRef =
- CFDictionaryGetValue (routeChangeDictionary,
- CFSTR (kAudioSession_AudioRouteChangeKey_Reason));
-
- SInt32 routeChangeReason;
-
- CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason);
- NSLog(@" ===================================== RouteChangeReason : %d", routeChangeReason);
- AudioHelper *_self = (AudioHelper *) inUserData;
- if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) {
- [_self resetSettings];
- if (![_self hasHeadset]) {
- [[NSNotificationCenter defaultCenter] postNotificationName:@"ununpluggingHeadse"
- object:nil];
- }
- } else if (routeChangeReason == kAudioSessionRouteChangeReason_NewDeviceAvailable) {
- [_self resetSettings];
- if (![_self hasMicphone]) {
- [[NSNotificationCenter defaultCenter] postNotificationName:@"pluggInMicrophone"
- object:nil];
- }
- } else if (routeChangeReason == kAudioSessionRouteChangeReason_NoSuitableRouteForCategory) {
- [_self resetSettings];
- [[NSNotificationCenter defaultCenter] postNotificationName:@"lostMicroPhone"
- object:nil];
- }
-
-
-
-
- [_self printCurrentCategory];
- }
六:如何保持后台音乐的一直播放呢? (参考:http://blog.csdn.net/yhawaii/article/details/7788340)
1:在Info.plist中,添加"Required background
modes"键,其值设置如下图所示:

2:系统音频服务支持音频播放,并关闭其他正在播放的音频
- AVAudioSession *session = [AVAudioSession sharedInstance];
- [session setActive:YES error:nil];
- [session setCategory:AVAudioSessionCategoryPlayback error:nil];
3:设置app支持接受远程控制事件代码:
- [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
设置app支持接受远程控制事件,其实就是在dock中可以显示应用程序图标,同时点击该图片时,打开app,如下图所示:

4:执行 AVAudioPlayer
七 关于音量
1:由应用主动获取系统音量
- UInt32 dataSize = sizeof(float);
- AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareOutputVolume,
- &dataSize,
- &keyVolume);
获取之前要确保
- AVAudioSession *session = [AVAudioSession sharedInstance];
- [session setActive:YES error:nil];
- [session setCategory:AVAudioSessionCategoryPlayback error:nil];
2:由应用主动设置系统音量 (参考:http://blog.csdn.net/studyrecord/article/details/6452354)
八:关于音频边下载边播放的实现.
请参考:AudioStreamer
https://github.com/mattgallagher/AudioStreamer
如果你只是想简简单单在线播放以下不做任何处理. 那使用AVPlayer 等等
去实现在线播放,也是可以的,但是如果要实现更多更能,还是别折腾这玩意,浪费生命.
AVAudioSession,
原文:http://www.cnblogs.com/guligei/p/3517786.html