iOS开发之音频解析第三方框架介绍

最近在做iOS音频相关的App,在做之前选择了三种解决方案。第一种方案是使用苹果自带的音频解析类AVPlayer,虽然AVPlayer也可以播放音频。但是要做类似于QQ音乐这样的App,使用AVPlayer就显得无能为力了。第二种解决方案使用第三方音频解析框架AudioStreamer,这是一个老外写的音频解析框架。其中包括本地和网络的音频数据解析。核心文件
AudioPlayer.h 和 AudioPlayer.m。这套框架使用的是CFNetwork和CoreAudio封装的。其集成了进度拖动,断点续传等功能。使用这个框架做类似于QQ音乐,酷狗音乐等音频类App完全可以胜任。第三种解决方案使用第三方音频解析框架FreeStream,这个也是老外写的一个音频解析框架。对于这个框架而言,它是使用C++进行音频的解析。虽然是C++的Objc调用,却没有额外的性能消耗。这款音频解析框架主要特点是性能优越,内存占用小,是一个不错的选择。但由于这个框架要想做更多功能就要开发者自己去修改这个框架来满足自己的项目需求。下载地址:http://code4app.com/ios/FreeStreamer/52afca18cb7e84eb788b4690
    所以我综上对比选择了第二种解决方案,使用了AudioStreamer。AudioStreamer虽然作者自己把网络数据解析和本地数据解析封装好了,但我们实际上并不需要。我们可以根据自己的需求写自己的网络数据解析。关于AudioStream源码的分析,由于个人能力有限,并不能完全看懂。有兴趣的读者可以去研究一下源码。AudioStreamer下载地址:http://code4app.com/ios/Audjusta
... c55cb7e8450688b5158

    下面根据我自己的经验说一下这个框架在项目中该如何使用。也许我们并非一开始就去研究框架源码。这样是不明智的,就这个框架来说,它涉及到了CoreAudio的知识。首先你要非常了解苹果的音频队列服务,对CFNetwork也要很了解。
    一般来说我们使用第三方框架都会看.h中给我们所提供的接口。能满足需求就无需修改,不能满足则在进行扩展。下面我们一起看看AudioPlayer.h中给我们提供了哪些接口。
AudioPlayer.h
1.缓冲设置
缓冲数据的大小设置  此处设置的是2M,在iPhone4上测试会发出内存溢出的警告, 故这个值不宜设置的太大,一般是1 * 1024 或者 2 * 1024。设置这个缓冲大小,可以实现音频的断点续传的功能。

#define AudioPlayerDefaultNumberOfAudioQueueBuffers (2 * 1024)

2.播放网络状态
typedef enum
{
    AudioPlayerInternalStateInitialised = 0, 
    AudioPlayerInternalStateRunning = 1, 
    AudioPlayerInternalStatePlaying = (1 << 1) | AudioPlayerInternalStateRunning, // 数据加载成功,进入音频播放状态
    AudioPlayerInternalStateStartingThread = (1 << 2) | AudioPlayerInternalStateRunning,   // 开始进行音频的播放
    AudioPlayerInternalStateWaitingForData = (1 << 3) | AudioPlayerInternalStateRunning, // 等待数据的加载,缓冲数据中
    AudioPlayerInternalStateWaitingForQueueToStart = (1 << 4) | AudioPlayerInternalStateRunning, // 等待音频队列开始播放
    AudioPlayerInternalStatePaused = (1 << 5) | AudioPlayerInternalStateRunning, //  暂停音频的播放,数据停止加载
    AudioPlayerInternalStateRebuffering = (1 << 6) | AudioPlayerInternalStateRunning, // 开始数据的重新加载
    AudioPlayerInternalStateStopping = (1 << 7), // 一个音频数据加载完毕,停止播放。
    AudioPlayerInternalStateStopped = (1 << 8), // 数据加载完成,播放状态为停止状态
    AudioPlayerInternalStateDisposed = (1 << 9), // 数据加载失败,一般是无效数据
    AudioPlayerInternalStateError = (1 << 10)    //   数据加载出错,一般是网络错误。
}
AudioPlayerInternalState;

3. 播放器的播放状态
typedef enum
{
    AudioPlayerStateReady, // 播放器已经准备好
    AudioPlayerStateRunning = 1, // 播放器正在运行中
    AudioPlayerStatePlaying = (1 << 1) | AudioPlayerStateRunning, // 播放器开始播放音频
    AudioPlayerStatePaused = (1 << 2) | AudioPlayerStateRunning,
    AudioPlayerStateStopped = (1 << 3), // 暂停播放和停止播放
    AudioPlayerStateError = (1 << 4), // 播放音频错误,一般是网络数据错误
    AudioPlayerStateDisposed = (1 << 5) // 播放错误,一般是由无效数据导致的错误
}
AudioPlayerState;

4. 监听播放器播放停止的原因
typedef enum
{
    AudioPlayerStopReasonNoStop = 0, // 未知原因停止
    AudioPlayerStopReasonEof, // 播放到文件末尾导致的停止
    AudioPlayerStopReasonUserAction,// 用户操作导致的停止
    AudioPlayerStopReasonUserActionFlushStop // 用户刷新播放导致的停止
}
AudioPlayerStopReason;

5. 播放状态码
typedef enum
{
    AudioPlayerErrorNone = 0, // 一般错误
    AudioPlayerErrorDataSource, // 数据错误
    AudioPlayerErrorStreamParseBytesFailed, // 解析数据流失败
    AudioPlayerErrorDataNotFound, // 数据没有找到
    AudioPlayerErrorQueueStartFailed, // 音频队列准备失败
    AudioPlayerErrorQueuePauseFailed, // 音频队列暂停失败
    AudioPlayerErrorUnknownBuffer,    // 不知名的数据缓冲
    AudioPlayerErrorQueueStopFailed,  // 音频队列停止失败
    AudioPlayerErrorOther       // 其他错误
}
AudioPlayerErrorCode;

@class AudioPlayer;

// 播放代理
@protocol AudioPlayerDelegate <NSObject>
// 播放状态f发生变化的调用
-(void) audioPlayer:(AudioPlayer*)audioPlayer stateChanged:(AudioPlayerState)state;
// 播放出错的调用
-(void) audioPlayer:(AudioPlayer*)audioPlayer didEncounterError:(AudioPlayerErrorCode)errorCode;
// 开始播放 得到itemId
-(void) audioPlayer:(AudioPlayer*)audioPlayer didStartPlayingQueueItemId:(NSObject*)queueItemId;
// 缓冲完成的调用
-(void) audioPlayer:(AudioPlayer*)audioPlayer didFinishBufferingSourceWithQueueItemId:(NSObject*)queueItemId;
// 已经播放结束的回调
-(void) audioPlayer:(AudioPlayer*)audioPlayer didFinishPlayingQueueItemId:(NSObject*)queueItemId withReason:(AudioPlayerStopReason)stopReason andProgress:(double)progress
andDuration:(double)duration;

@optional

-(void) audioPlayer:(AudioPlayer*)audioPlayer logInfo:(NSString*)line;
// 播放网络变化的回调
-(void) audioPlayer:(AudioPlayer*)audioPlayer internalStateChanged:(AudioPlayerInternalState)state;

// 取消播放
-(void) audioPlayer:(AudioPlayer*)audioPlayer didCancelQueuedItems:(NSArray*)queuedItems;
@end

@class QueueEntry;

typedef struct
{
    AudioQueueBufferRef ref; // 音频队列缓冲引用
    int bufferIndex;
}
AudioQueueBufferRefLookupEntry;

@interface AudioPlayer : NSObject<DataSourceDelegate>
{
@private
    UInt8* readBuffer;
    int readBufferSize;
    
    NSOperationQueue* fastApiQueue;
    
    QueueEntry* currentlyPlayingEntry;
    QueueEntry* currentlyReadingEntry;
    
    NSMutableArray* upcomingQueue;
    NSMutableArray* bufferingQueue;
    
    AudioQueueBufferRef* audioQueueBuffer;
    AudioQueueBufferRefLookupEntry* audioQueueBufferLookup;
    unsigned int audioQueueBufferRefLookupCount;
    unsigned int audioQueueBufferCount;
    AudioStreamPacketDescription* packetDescs;
    bool* bufferUsed;
    int numberOfBuffersUsed;
    
    AudioQueueRef audioQueue;
    AudioStreamBasicDescription currentAudioStreamBasicDescription;
    
    NSThread* playbackThread;
    NSRunLoop* playbackThreadRunLoop;
    NSConditionLock* threadFinishedCondLock;
    
    AudioFileStreamID audioFileStream;
    
    BOOL discontinuous;
    
    int bytesFilled;
    int packetsFilled;
    
    int fillBufferIndex;
    
    UIBackgroundTaskIdentifier backgroundTaskId;
    
    AudioPlayerErrorCode errorCode;
    AudioPlayerStopReason stopReason;
    
    int currentlyPlayingLock;
    pthread_mutex_t playerMutex;
    pthread_mutex_t queueBuffersMutex;
    pthread_cond_t queueBufferReadyCondition;
    
    volatile BOOL waiting;
    volatile BOOL disposeWasRequested;
    volatile BOOL seekToTimeWasRequested;
    volatile BOOL newFileToPlay;
    volatile double requestedSeekTime;
    volatile BOOL audioQueueFlushing;
    volatile SInt64 audioPacketsReadCount;
    volatile SInt64 audioPacketsPlayedCount;
    
    BOOL meteringEnabled;
    AudioQueueLevelMeterState* levelMeterState;
    NSInteger numberOfChannels;
}

// 音频的总时间  这个时间是由播放器自己计算出来的。
@property (readonly) double duration;
// 音频当前播放的进度
@property (readonly) double progress;
// 播放器的状态
@property (readwrite) AudioPlayerState state;
// 停止播放时的原因
@property (readonly) AudioPlayerStopReason stopReason;
@property (readwrite, unsafe_unretained) id<AudioPlayerDelegate> delegate;
@property (readwrite) BOOL meteringEnabled;

// 对外接口
-(id) init;

-(id) initWithNumberOfAudioQueueBuffers:(int)numberOfAudioQueueBuffers andReadBufferSize:(int)readBufferSizeIn;

// 从URL地址获取数据源
-(DataSource*) dataSourceFromURL:(NSURL*)url;

// 播放指定URL的资源
-(void) play:(NSURL*)url;

-(void) queueDataSource:(DataSource*)dataSource withQueueItemId:(NSObject*)queueItemId;
// 设置数据源
-(void) setDataSource:(DataSource*)dataSourceIn withQueueItemId:(NSObject*)queueItemId;
// 设置播放进度
-(void) seekToTime:(double)value;

// 暂停播放
-(void) pause;
// 唤醒播放
-(void) resume;
// 停止播放
-(void) stop;
// 刷新停止
-(void) flushStop;

-(void) mute;
-(void) unmute;
-(void) dispose;
// 得到当前播放id
-(NSObject*) currentlyPlayingQueueItemId;
// 刷新
-(void) updateMeters;
-(float) peakPowerInDecibelsForChannel:(NSUInteger)channelNumber;
-(float) averagePowerInDecibelsForChannel:(NSUInteger)channelNumber;

@end

今天先写到这,以后有时间可以研究一下AudioPlayer.m中的具体实现。

时间: 2024-09-14 20:23:40

iOS开发之音频解析第三方框架介绍的相关文章

iOS开发网络篇—使用ASI框架进行文件下载

iOS开发网络篇-使用ASI框架进行文件下载 说明:本文介绍iOS网络编程中经常用到的框架ASI,如何使用该框架进行文件的下载. 一.简单介绍 代码示例: 1 #import "YYViewController.h" 2 #import "ASIHTTPRequest.h" 3 4 @interface YYViewController () 5 6 7 @end 8 9 @implementation YYViewController 10 11 - (void)

iOS开发系列—Objective-C之Foundation框架

概述 我们前面的章节中就一直新建Cocoa Class,那么Cocoa到底是什么,它和我们前面以及后面要讲的内容到底有什么关系呢?Objective-C开发中经常用到NSObject,那么这个对象到底是谁?它为什么又出现在Objective-C中间呢?今天我们将揭开这层面纱,重点分析在IOS开发中一个重要的框架Foundation,今天的主要内容有: Foundation概述 常用结构体 日期 字符串 数组 字典 装箱和拆箱 反射 拷贝 文件操作 归档 Foundation概述 为什么前面说的内

iOS开发系列--音频播放、录音、视频播放、拍照、视频录制

概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操作都提供了多套API.在今天的文章中将会对这些内容进行一一介绍: 音频 音效 音乐 音频会话 录音 音频队列服务 视频 MPMoviePlayerController MPMoviePlayerViewController AVPlayer 摄像头 UIImagePickerControlle

iOS开发使用XML解析网络数据_IOS

前言:本篇随笔介绍的是XML解析. 正文: 1.XML解析方式有2两种: DOM:一次性将整个XML数据加载进内存进行解析,比较适合解析小文件SAX:从根元素开始,按顺序一个元素一个元素往下解析,比较适合解析大文件 2.IOS中XML解析方案有很多种: 2-1.第三方框架: libxml2:纯C语言,默认包含在iOS SDK中,同时支持DOM和SAX解析 GDataXML:DOM方式解析,由Google开发,基于libxml2 2-2.苹果原生 NSXMLParser:SAX方式解析,使用简单

iOS开发实现音频播放功能_IOS

音频播放 1.介绍  - 功能介绍  用于播放比较长的音频.说明.音乐 ,使用到的是AVFoundation  - 框架介绍  * AVAudioPlayer  * 初始化:  注意 : (3)必须声明全局变量的音乐播放对象.或者是属性的音乐播放对象  才可以播放 (4)在退出播放页面的时候 一定要把播放对象置空  同时把delegate置空 导入框架:#import <AVFoundation/AVFoundation.h> 声明全局变量 @interface ViewController

iOS开发入门:OCUnit测试框架

使用OCUnit测试框架iOS单元测试框架 原则上,是否使用测试框架都不会影响单元测试结果,但是"工欲善其事,必先利其器"使用单元测试框架更便于我们测试和分析结果. 主要的iOS单元测试框架有: OCUnit,是开源测试框架,与Xcode工具集成在一起使用非常方便,测试报告以文本形式输出到输出窗口: GHUnit,是开源测试框架,它可以将测试报告以应用形式可视化输出到设备或模拟器上,也可以以文本形式输出到输出窗口:GHUnit可以测试OCUnit编写的测试用例: OCMock,是开源测

iOS开发UI篇—常见的项目文件介绍

一.项目文件结构示意图 二.文件介绍 1.products文件夹:主要用于mac电脑开发的可执行文件,ios开发用不到这个文件 2.frameworks文件夹主要用来放依赖的框架 3.test文件夹是用来做单元测试的 4.常用的文件夹(项目名称文件夹) (1)XXXinfo.plist文件(在该项目中为 01-常见文件-Info.plist) 1)简单说明 是配置文件,该文件对工程做一些运行期的配置,非常重要,不能删除. 在旧版本xcode创建的工程中,这个配置文件的名字就叫做info.plis

IOS开发之音频--录音

前言:本篇介绍录音.   关于录音,这里提供更为详细的讲解网址:http://www.cnblogs.com/kenshincui/p/4186022.html#audioRecord  ,并且该博客有更完整的详述和代码实现哦.   内容大纲: 1.录音应用场景. 2.录音功能实现. 3.概念补充. 4.开发经验.   正文:   1.录音应用场景 ① 语言聊天:在即时通讯APP中,例如即时通讯APP中,例如微信.QQ等等,都有语音发送功能. ②语音备忘录:录一段音频,来记录某件事情.   2.

iOS开发那些事--OCUnit测试框架

使用OCUnit测试框架iOS单元测试框架 原则上,是否使用测试框架都不会影响单元测试结果,但是"工欲善其事,必先利其器"使用单元测试框架更便于我们测试和分析结果. 主要的iOS单元测试框架有: OCUnit,是开源测试框架,与Xcode工具集成在一起使用非常方便,测试报告以文本形式输出到输出窗口: GHUnit,是开源测试框架,它可以将测试报告以应用形式可视化输出到设备或模拟器上,也可以以文本形式输出到输出窗口:GHUnit可以测试OCUnit编写的测试用例: OCMock,是开源测