Java中AudioFileStream_AudioFileStream学习
AudioFileStream介绍
AudioFileStreamer是用来读取采样率、码率、时长等基本信息以及分离音频帧。
AudioFileStreamer用在流播放中,当然不仅限于网络流,本地文件同样可以用它来读取信息和分离音频帧。
AudioFileStreamer的主要数据是文件数据,支持的文件格式有:
MPEG-1 Audio Layer 3, used for .mp3 files
MPEG-2 ADTS, used for the .aac audio data format
AIFC
AIFF
CAF
MPEG-4, used for .m4a, .mp4, and .3gp files
NeXT
WAVE
AudioFileStreamOpen
初始化AudioFileStream,创建一个音频流解析器,生成一个AudioFileStream示例。
函数示例
extern OSStatus
AudioFileStreamOpen (
void * __nullable inClientData,
AudioFileStream_PropertyListenerProc inPropertyListenerProc,
AudioFileStream_PacketsProc inPacketsProc,
AudioFileTypeID inFileTypeHint,
AudioFileStreamID __nullable * __nonnull outAudioFileStream)
__OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
参数列表:
inClientData 上下文对象
AudioFileStream_PropertyListenerProc 歌曲信息解析的回调,每次解析出一个歌曲信息,都会执行一次回调。
AudioFileStream_PacketsProc 分离帧的回调,每解析出一部分帧就会进行一次回调
AudioFileTypeID 是文件类型的提示,创建指定文件格式的音频流解析器。AudioFileTypeID对应的枚举
enum {
kAudioFileAIFFType = 'AIFF',
kAudioFileAIFCType = 'AIFC',
kAudioFileWAVEType = 'WAVE',
kAudioFileSoundDesigner2Type = 'Sd2f',
kAudioFileNextType = 'NeXT',
kAudioFileMP3Type = 'MPG3', // mpeg layer 3
kAudioFileMP2Type = 'MPG2', // mpeg layer 2
kAudioFileMP1Type = 'MPG1', // mpeg layer 1
kAudioFileAC3Type = 'ac-3',
kAudioFileAAC_ADTSType = 'adts',
kAudioFileMPEG4Type = 'mp4f',
kAudioFileM4AType = 'm4af',
kAudioFileM4BType = 'm4bf',
kAudioFileCAFType = 'caff',
kAudioFile3GPType = '3gpp',
kAudioFile3GP2Type = '3gp2',
kAudioFileAMRType = 'amrf'
};
outAudioFileStream AudioFileStream实例对应的AudioFileStreamID,AudioFileStream其他函数需要使用。
返回值
返回值用来判断是否成功初始化(OSSStatus == noErr)
AudioFileStreamParseBytes
解析数据,在初始化完成之后,调用该方法解析文件数据。
函数示例
extern OSStatus AudioFileStreamParseBytes(AudioFileStreamID inAudioFileStream,
UInt32 inDataByteSize,
const void* inData,
UInt32 inFlags);
参数列表
inAudioFileStream 初始化成功后返回的 AudioFileStreamID
inDataByteSize 本次解析的文件长度
inData 本次解析的数据
inFlags 标志位,标识本次的解析和上一次解析是否是连续的关系,默认0表示连续,否则传入kAudioFileStreamParseFlag_Discontinuity。
返回值
OSStatus的值不是noErr则表示解析不成功,对应的错误码:
enum
{
kAudioFileStreamError_UnsupportedFileType = 'typ?',
kAudioFileStreamError_UnsupportedDataFormat = 'fmt?',
kAudioFileStreamError_UnsupportedProperty = 'pty?',
kAudioFileStreamError_BadPropertySize = '!siz',
kAudioFileStreamError_NotOptimized = 'optm',
kAudioFileStreamError_InvalidPacketOffset = 'pck?',
kAudioFileStreamError_InvalidFile = 'dta?',
kAudioFileStreamError_ValueUnknown = 'unk?',
kAudioFileStreamError_DataUnavailable = 'more',
kAudioFileStreamError_IllegalOperation = 'nope',
kAudioFileStreamError_UnspecifiedError = 'wht?',
kAudioFileStreamError_DiscontinuityCantRecover = 'dsc!'
};
每次调用成功后应该注意返回值,一旦出现错误就不必要进行后续的解析。
AudioFileStream_PropertyListenerProc
解析文件格式信息的回调,在调用AudioFileStreamParseBytes方法进行解析时会首先读取格式信息,并同步的进入AudioFileStream_PropertyListenerProc回调方法。
函数示例
typedef void (*AudioFileStream_PropertyListenerProc)(
void * inClientData,
AudioFileStreamID inAudioFileStream,
AudioFileStreamPropertyID inPropertyID,
AudioFileStreamPropertyFlags * ioFlags);
参数列表
inClientData 得到上下文
inAudioFileStream 表示当前的FileStream的AudioFileStreamID
inPropertyID 表示此次回调解析的AudioFileStreamPropertyID,
支持的AudioFileStreamPropertyID枚举:
enum
{
kAudioFileStreamProperty_ReadyToProducePackets = 'redy',
kAudioFileStreamProperty_FileFormat = 'ffmt',
kAudioFileStreamProperty_DataFormat = 'dfmt',
kAudioFileStreamProperty_FormatList = 'flst',
kAudioFileStreamProperty_MagicCookieData = 'mgic',
kAudioFileStreamProperty_AudioDataByteCount = 'bcnt',
kAudioFileStreamProperty_AudioDataPacketCount = 'pcnt',
kAudioFileStreamProperty_MaximumPacketSize = 'psze',
kAudioFileStreamProperty_DataOffset = 'doff',
kAudioFileStreamProperty_ChannelLayout = 'cmap',
kAudioFileStreamProperty_PacketToFrame = 'pkfr',
kAudioFileStreamProperty_FrameToPacket = 'frpk',
kAudioFileStreamProperty_PacketToByte = 'pkby',
kAudioFileStreamProperty_ByteToPacket = 'bypk',
kAudioFileStreamProperty_PacketTableInfo = 'pnfo',
kAudioFileStreamProperty_PacketSizeUpperBound = 'pkub',
kAudioFileStreamProperty_AverageBytesPerPacket = 'abpp',
kAudioFileStreamProperty_BitRate = 'brat',
kAudioFileStreamProperty_InfoDictionary = 'info'
};
当前PropertyID对应的信息已经解析完成信息,可以通过AudioFileStreamGetProperty接口获取PropertyID对应的值或者数据结构;
extern OSStatus AudioFileStreamGetProperty(AudioFileStreamID inAudioFileStream,
AudioFileStreamPropertyID inPropertyID,
UInt32 * ioPropertyDataSize,
void * outPropertyData);
ioFlags 表示这个property是否需要被缓存。
AudioFileStreamPropertyID解析
kAudioFileStreamProperty_BitRate 音频数据的码率,通过码率可以计算音视频的总时长
kAudioFileStreamProperty_DataOffset 表示音频数据在整个音频文件中的offset
因为大多数音频文件都会有一个文件头之后才使真正的音频数据),这个值在seek时会发挥比较大的作用,音频的seek并不是直接seek文件位置而seek时间(比如seek到2分10秒的位置),seek时会根据时间计算出音频数据的字节offset然后需要再加上音频数据的offset才能得到在文件中的真正offset
kAudioFileStreamProperty_DataFormat 表示音频文件结构信息,是一个AudioStreamBasicDescription的结构
kAudioFileStreamProperty_FormatList 作用和kAudioFileStreamProperty_DataFormat是一样的,区别在于用这个PropertyID获取到是一个AudioStreamBasicDescription的数组
kAudioFileStreamProperty_AudioDataByteCount 音频文件中音频数据的总量。这个Property的作用一是用来计算音频的总时长,二是可以在seek时用来计算时间对应的字节offset
kAudioFileStreamProperty_ReadyToProducePackets 一旦回调中这个PropertyID出现就代表解析完成,接下来可以对音频数据进行帧分离了
计算时长Duration
double duration = (audioDataByteCount * 8) / bitRate
音频数据的字节总量audioDataByteCount可以通过kAudioFileStreamProperty_AudioDataByteCount获取,
码率bitRate可以通过kAudioFileStreamProperty_BitRate获取
AudioFileStream_PacketsProc
分离音频帧回调,读取格式信息完成之后,继续调用AudioFileStreamParseBytes方法可以对帧进行分离,并同步的进入AudioFileStream_PacketsProc回调方法
函数示例
typedef void (*AudioFileStream_PacketsProc)(
void * inClientData,
UInt32 inNumberBytes,
UInt32 inNumberPackets,
const void * inInputData,
AudioStreamPacketDescription *inPacketDescriptions);
参数列表
inClientData 得到上下文
inNumberBytes 表示本次处理的数据大小
inNumberPackets 本次总共处理了多少帧AudioFileStreamPropertyID
inInputData 本次处理的所有数据
AudioStreamPacketDescription AudioStreamPacketDescription数组,存储了每一帧数据是从第几个字节开始的,这一帧总共多少字节。
AudioFileStreamSeek
seek操作
AudioFileStreamClose
AudioFileStream使用完毕后需要调用AudioFileStreamClose进行关闭
函数示例
extern OSStatus AudioFileStreamClose(AudioFileStreamID inAudioFileStream);
参数:inAudioFileStream 初始化时生成的AudioFileStreamID
参考资料:
Java中AudioFileStream_AudioFileStream学习相关推荐
- Java中注解学习系列教程-2
简介 在上一篇文章中,我们讲解了:Java中注解的定义.JDK中内置注解.第三方注解.本文是注解系列教程中的第二篇.来看看今天主要内容:1:注解的分类2:元注解说明3:自定义注解声明一:注解的分类注解 ...
- Java中注解学习系列教程-1
前言: 我们为什么要学习注解? 注解是我们的编程更简洁明了.spring boot的流行也带动了注解.spring boot中就使用了大量的注解来减少配置.我们在使用spring boot开发时候,感 ...
- java中xpath_java-xpath学习
/** 使用xpath技术取得xml文件中任意级别下的内容 基于dom4j的xpath技术 1)能够在xml文件中,快速定位需要元素,无需从根元素一个一个的导航到需要的子元素 Document.sel ...
- java中接口学习总结
1.什么是接口? 接口是一种对事物的公用特征进行的抽象,抽象出来的特征放在接口中进行描述,类似类,和类的区别是比类更特别,接口中的内容也有限制,不像类中可以有属性,方法,代码块等等.接口中的成员只能是 ...
- java中泛型学习总结
为什么需要使用泛型: 1):存储任意类型的数据在集合中 ,但是取出来都是Object类型的,此时就得强转. List list = new ArrayList();list.add(1); //Int ...
- java excel 注解_Java中注解学习系列教程-5 excel导出优化初级阶段
在上一篇文章中,我们实现了使用自定义注解导出Excel的小案例.但是有问题的.我们发现,如果对象属性中包含了date类型或者使用了枚举类.这个时候就会出问题.我们来看看问题所在: 是不是已经看到了结果 ...
- Java中有关Null的9件事
对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者都承认这是他的一项巨大失误.Java为什么要保留null呢?null出现有一段时间了,并且我认 ...
- @excel 注解_Java中注解学习系列教程-3
本文是<Java中注解学习系列教程>第三篇文章 在前两篇中我们学习了注解的定义.JDK内置注解.注解分类及自定义注解的写法. 本文咱们将学习: 1:自定义注解一些说明 2:自定义注解怎 ...
- excel导出多重表头utils_Java中注解学习系列教程-4 使用自定义注解实现excel导出...
本文是<Java中注解学习系列教程>第四篇文章也是小案例文章. 自定义注解小案例是:使用自定义注解实现excel导出. Excel导出分析: 有表头.数据值.一般第一行是表头,从第二行 ...
最新文章
- js调用php函数兵每秒刷新,深入理解JavaScript立即调用函数表达式(IIFE)
- 在HTML5网页中写法正确的是,跟永哥学HTML5(4):正确使用HTML5的header、hgroup和section...
- 三级计算机等级2021年9月考试准考证下载步骤
- 山东大学软件学院计算机组成原理课程设计实验一
- python都被我用来爬美女图片了
- onselect与onselectstart 禁止选中
- 大数据在高校的应用场景_大数据在高校教育信息化的应用
- 【DeepLearning-Note】Implementation of Convolutiona Netural Network
- python九九乘法表矩形_python九九乘法表和打印图形程序
- idea快速搭建ssm框架
- 小白也可以看懂的Numpy实操演示教程
- BIM模型导入SuperMap
- 西方经济学的十大原理
- Postman如何携带token——Bearer Token和Headers
- 【Maven】私服搭建与使用:nexus,repository,mirror,distributionManagement
- java爬虫教程 百度云_java视频教程java爬虫实战项目httpclient hbase springmvc solr
- PMP BAC完工预算
- python+vue+django旅游景点酒店线路套餐管理系统
- Vue Already included file name XXX differs from file name XXX only in casing.
- Python 读取Excel, 隔行取数据, 保存Excel