iOS音频开发

水平有限。。。只是为了方便自己学习写的。。。 这是偶的第一篇博文。。。。

        AVAudioSession类由AVFoundation框架引入。每个IOS应用都有一个音频会话。这个会话可以被AVAudioSession类的sharedInstance类方法访问

        AVAudioSession *audioSession = [AVAudioSession sharedInstance];


        在获得一个AVAudioSession类的实例后,你就能通过调用音频会话对象的setCategory:error:实例方法,来从IOS应用可用的不同类别中作出选择。下面列出了可供使用的音频会话类别:


AVAudioSessionCategorySoloAmbient

这个类别非常像AVAudioSessionCategoryAmbient类别,除了会停止其他程序的音频回放,比如iPad程序。当设备被设置为静音模式,你的音频回放将会停止。


AVAudioSessionCategoryRecord
这会停止其他应用的声音(比如iPod)并让你的应用也不能初始化音频回放(比如AVAudioPlayer)。在这种模式下,你只能进行录音。使用这个 类别,调用AVAudioPlayer的prepareToPlay会返回YES,但是调用play方法将返回NO。主UI界面会照常工作。这时,即使你 的设备屏幕被用户锁定了,应用的录音仍会继续。


AVAudioSessionCategoryPlayback
这个类别会静止其他应用的音频回放(比如iPad应用的音频回放)。你可以使用AVAudioPlayer的prepareToPlay和play方法,在你的应用中播放声音。主UI界面会照常工作。这时,即使屏幕被锁定或者设备为静音模式,音频回放都会继续。


AVAudioSessionCategoryPlayAndRecord
这个类别允许你的应用中同时进行声音的播放和录制。当你的声音录制或播放开始后,其他应用的声音播放将会停止。主UI界面会照常工作。这时,即使屏幕被锁定或者设备为静音模式,音频回放和录制都会继续。


AVAudioSessionCategoryAudioProcessing
这个类别用于应用中进行音频处理的情形,而不是音频回放或录制。设置了这种模式,你在应用中就不能播放和录制任何声音。调用AVAPlayer的prepareToPlay和play方法都将返回NO。其他应用的音频回放,比如iPad,也会在此模式下停止。


AVAudioSessionCategoryAmbient
这个类别不会停止其他应用的声音,相反,它允许你的音频播放于其他应用的声音之上,比如iPod。你的应用的主UI线程会工作正常。调用 AVAPlayer的prepareToPlay和play方法都将返回YES。当用户锁屏时,你的应用将停止所有正在回放的音频。仅当你的应用是唯一播 放该音频文件的应用时,静音模式将停止你程序的音频回放。如果正当iPod播放一手歌时,你开始播放音频,将设备设为静音模式并不能停止你的音频回放。


关于iOS音频开发例子:


一:播放简短性质的音频,例如按键声音等

        1.引入框架

           

 #import <AudioToolbox/AudioToolbox.h>


                2.声明一个声音源ID

                    

SystemSoundID _bookSoundID;


                3.提供需要播放的音频地址进行声音源注册

                   

 NSURL *bookSoundUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"bookSound" ofType:@"wav"]];  
 AudioServicesCreateSystemSoundID((__bridge CFURLRef)bookSoundUrl, &_bookSoundID);

 

               4.在需要的时候执行这个方法

                    

AudioServicesPlaySystemSound(_bookSoundID);


                5.不用的声音源记得释放掉

                   

 
AudioServicesDisposeSystemSoundID(_bookSoundID);

        二: AVAudioSession的使用

            首先知道 AVAudioSession  是一个单例模式,也就是说,不用开发者自行实例化. 这个类在各种音频环境中起着非常重要的作用

            1:    首先是设置 AVAudioSession 的 类别

 

  • AVAudioSession * audioSession = [AVAudioSession sharedInstance]; //得到AVAudioSession单例对象  
    [audioSession setDelegate:self];//设定代理  
    [audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error: &error];//设置类别,表示该应用同时支持播放和录音  
    [audioSession setActive:YES error: &error];//启动音频会话管理,此时会阻断后台音乐的播放.

            2:    在录制完声音或者播放完声音后,可以将音频会话关闭,来延续后台音乐的播放,代码如下:

           

 
[[AVAudioSession sharedInstance] setActive:NO error: nil];


            3:    通过音频会话可以强制的设置应用程序使用指定的输出方式,例如:内声道,扬声器,代码如下:

  • UInt32 audioRouteOverride = hasHeadset ?kAudioSessionOverrideAudioRoute_None:kAudioSessionOverrideAudioRoute_Speaker;  
    AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(audioRouteOverride), &audioRouteOverride);
    kAudioSessionOverrideAudioRoute_None  内声道,耳机
    kAudioSessionOverrideAudioRoute_Speaker 扬声器

            4:    那么怎么判断用户是否已经插入耳机?代码如下:(参考: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)){  
            // Silent Mode  
            NSLog(@"AudioRoute: SILENT, do nothing!");  
        } else {  
            NSString* routeStr = (__bridge NSString*)route;  
            NSLog(@"AudioRoute: %@", routeStr);  
              
            /* Known values of route: 
             * "Headset" 
             * "Headphone" 
             * "Speaker" 
             * "SpeakerAndMicrophone" 
             * "HeadphonesAndMicrophone" 
             * "HeadsetInOut" 
             * "ReceiverAndMicrophone" 
             * "Lineout" 
             */  
              
            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表示没有插入耳机

        5:    监听用户拔出插入耳机事件

                1:注册监听事件,和回调函数

            

  1. AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange,  
                                         audioRouteChangeListenerCallback,  
                                         self);

                    2:实现回调函数进行相关处理:

        

  • void audioRouteChangeListenerCallback (  
                                           void                      *inUserData,  
                                           AudioSessionPropertyID    inPropertyID,  
                                           UInt32                    inPropertyValueSize,  
                                           const void                *inPropertyValue  
                                           ) {  
      
        if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return;  
        // Determines the reason for the route change, to ensure that it is not  
        //      because of a category change.  
        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];  
        }  
        //else if (routeChangeReason == kAudioSessionRouteChangeReason_CategoryChange  ) {  
        //    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];  
        //}  
      
        [_self printCurrentCategory];  
    }

        6:    如何保持后台音乐的一直播放呢? (参考: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 等等 去实现在线播放,也是可以的,但是如果要实现更多更能,还是别折腾这玩意,浪费生命.


你可能感兴趣的:(ios)