IOS 音频开发文件大小计算
- 音频基础知识
- 音频文件计算大小
- 音频转码
标签(空格分隔): 调查 IOS音频
https://developer.apple.com/library/ios/documentation/MusicAudio/Conceptual/CoreAudioOverview/SupportedAudioFormatsMacOSX/SupportedAudioFormatsMacOSX.html
音频基础知识
组成
音频文件的组成:文件格式(或者音频容器) + 数据格式(或者音频编码)。
文件格式(或音频容器)是用于形容文件本身的格式。
我们可以通过多种不同的方法为真正的音频数据编码。例如CAF文件便是一种文件格式,它能够包含MP3格式,线性PCM以及其它数据格式的音频。
数据格式(或音频编码)
我们将从音频编码开始阐述(而不是文件格式),因为编码是最重要的环节。
线性PCM:
这是表示线性脉冲编码调制,主要是描写用于将模拟声音数据转换成数字格式的技术。简单地说也就是未压缩的数据。因为数据是未压缩的,所以我们便可以最快速地播放出音频,而如果空间不是问题的话这便是iPhone音频的优先代码选择。
音频文件计算大小
声卡对声音的处理质量可以用三个基本参数来衡量,即采样频率、采样位数和声道数。
采样频率:
是指单位时间内的采样次数。采样频率越大,采样点之间的间隔就越小,数字化后得到的声音就越逼真,但相应的数据量就越大。声卡一般提供11.025kHz、22.05kHz和44.1kHz等不同的采样频率。
采样位数:
是记录每次采样值数值大小的位数。采样位数通常有8bits或16bits两种,采样位数越大,所能记录声音的变化度就越细腻,相应的数据量就越大。
声道数
是指处理的声音是单声道还是立体声。单声道在声音处理过程中只有单数据流,而立体声则需要左、右声道的两个数据流。显然,立体声的效果要好,但相应的数据量要比单声道的数据量加倍。
声音数据量的计算公式为:
数据量(字节/秒)= (采样频率(Hz)× 采样位数(bit) × 声道数)/ 8
单声道的声道数为1,立体声的声道数为2。
【例1】请计算对于5分钟双声道、16位采样位数、44.1kHz采样频率声音的不压缩数据量是多少?
根据公式:数据量=(采样频率×采样位数×声道数×时间)/8
得,数据量(MB)=[44.1×1000×16×2×(5×60)] /(8×1024×1024)=50.47MB
计算时要注意几个单位的换算细节:
时间单位换算:1分=60秒
采样频率单位换算:1kHz=1000Hz
数据量单位换算:1MB=1024×1024=1048576B
【例2】请计算对于双声道立体声、采样频率为44.1kHz、采样位数为16位的激光唱盘(CD-A),用一个650MB的CD-ROM可存放多长时间的音乐?
已知音频文件大小的计算公式如下:
文件的字节数/每秒=采样频率(Hz)X采样位数(位)X声道数/8
根据上面的公式计算一秒钟时间内的不压缩数据量:(44.1×1000×16×2)/8=0.168MB/s
那么,一个650MB的CD-ROM可存放的时间为:(650/0.168)/(60×60)=1.07小时。
IOS 音频转码
音频转码使用的框架为:AudioToolBox
内存转码:
使用函数: AudioConverterFillComplexBuffer
- (void)handleAudioPackets:(const void *)inputData
numberOfBytes:(UInt32)numberOfBytes
numberOfPackets:(UInt32)numberOfPackets
packetDescriptions:(AudioStreamPacketDescription *)packetDescriptions
{
if (!_audioFileStream || !_parseAudioHeader || !_decodeConverterRef) return;
AudioConvertInfo convertInfo = (AudioConvertInfo){
.done = NO,
.numberOfPackets = numberOfPackets,
.packetDescriptions = packetDescriptions,
.audioBuffer = (AudioBuffer){
.mData = (void *)inputData,
.mDataByteSize = numberOfBytes,
.mNumberChannels = _sourceAsbd.mChannelsPerFrame
}
};
AudioBufferList decodedData;
decodedData.mNumberBuffers = 1;
decodedData.mBuffers[0].mNumberChannels = _canonicalAsbd.mChannelsPerFrame;
decodedData.mBuffers[0].mDataByteSize = _decodeBufferSize;
decodedData.mBuffers[0].mData = _decodeBuffer;
UInt32 ioOutputDataPackets1, ioOutputDataPackets2;
OSStatus decodingStatus, encodingStatus;
while (1)
{
ioOutputDataPackets1 = numberOfPackets;
decodingStatus = AudioConverterFillComplexBuffer(_decodeConverterRef, AudioConverterCallback, (void*)&convertInfo, &ioOutputDataPackets1, &decodedData, NULL);
if (decodingStatus == OS_STATUS_DONE || decodingStatus == 0)
{
if (ioOutputDataPackets1 > 0)
{
// Start encoding
AudioConvertInfo encodeConvertInfo = (AudioConvertInfo){
.done = NO,
.numberOfPackets = ioOutputDataPackets1,
.packetDescriptions = NULL,
.audioBuffer = (AudioBuffer){
.mData = decodedData.mBuffers[0].mData,
.mDataByteSize = decodedData.mBuffers[0].mDataByteSize,
.mNumberChannels = _canonicalAsbd.mChannelsPerFrame
}
};
AudioBufferList encodedData;
encodedData.mNumberBuffers = 1;
encodedData.mBuffers[0].mNumberChannels = _destinationAsbd.mChannelsPerFrame;
encodedData.mBuffers[0].mDataByteSize = _encodeBufferSize;
encodedData.mBuffers[0].mData = _encodeBuffer;
while (1)
{
ioOutputDataPackets2 = _encodePacketsPerBuffer;
encodingStatus = AudioConverterFillComplexBuffer(_encodeConverterRef, AudioConverterCallback, (void*)&encodeConvertInfo, &ioOutputDataPackets2, &encodedData, _encodePacketDescriptions);
if (encodingStatus == OS_STATUS_DONE || encodingStatus == 0)
{
//一个buffer 转码成功
}
else
{
[self failureOccurred];
return;
}
if (encodingStatus == OS_STATUS_DONE)
{
break;
}
}
// End encoding
}
}
else
{
[self failureOccurred];
return;
}
if (decodingStatus == OS_STATUS_DONE)
{
break;
}
}
}
文件转码:
使用函数 ExtAudioFileRead
void startConvert(ExtAudioConverterSettings* settings){
//Determine the proper buffer size and calculate number of packets per buffer
//for CBR and VBR format
UInt32 sizePerBuffer = 32*1024;//32KB is a good starting point
UInt32 framesPerBuffer = sizePerBuffer/sizeof(SInt16);
// allocate destination buffer
SInt16 *outputBuffer = (SInt16 *)malloc(sizeof(SInt16) * sizePerBuffer);
while (1) {
AudioBufferList outputBufferList;
outputBufferList.mNumberBuffers = 1;
outputBufferList.mBuffers[0].mNumberChannels = settings->outputFormat.mChannelsPerFrame;
outputBufferList.mBuffers[0].mDataByteSize = sizePerBuffer;
outputBufferList.mBuffers[0].mData = outputBuffer;
UInt32 framesCount = framesPerBuffer;
CheckError(ExtAudioFileRead(settings->inputFile,
&framesCount,
&outputBufferList),
"ExtAudioFileRead failed");
if (framesCount==0) {
printf("Done reading from input file\n");
return;
}
CheckError(ExtAudioFileWrite(settings->outputFile,
framesCount,
&outputBufferList),
"ExtAudioFileWrite failed");
}
}
代码下载 http://download.csdn.net/download/qihongru1227/9326777
原文链接:http://www.jianshu.com/p/5e5428471f48
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
IOS 音频开发文件大小计算的更多相关文章
- iOS 音频开发
音频基础知识 组成 音频文件的组成:文件格式(或者音频容器) + 数据格式(或者音频编码). 文件格式(或音频容器)是用于形容文件本身的格式. 我们可以通过多种不同的方法为真正的音频数据编码.例如 ...
- iOS音频开发系列-概述篇
概述 iOS中对于音频的处理,苹果提供了两个库. AVFoundation AudioToolbox 在iOS系统中apple对上述的流程进行了封装并提供了不同层次的接口
- iOS 音频开发之CoreAudio
转自:http://www.cnblogs.com/javawebsoa/archive/2013/05/20/3089511.html 接 触过IOS音频开发的同学都知道,Core Audio 是I ...
- 一篇对iOS音频比较完善的文章
转自:http://www.cnblogs.com/iOS-mt/p/4268532.html 感谢作者:梦想通 前言 从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改我也 ...
- IOS 音频播放
iOS音频播放 (一):概述 前言 从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改我也因此对于iOS下的音频播放实现有了一定的研究.写这个系列的博客目的一方面希望能够抛砖 ...
- iOS多线程开发
概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操 ...
- iOS音频播放(一):概述
(本文转自码农人生) 前言 从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改,我也因此对于iOS下的音频播放实现有了一定的研究.写这个 系列的博客目的一方面希望能够抛砖引玉 ...
- ios新手开发——toast提示和旋转图片加载框
不知不觉自学ios已经四个月了,从OC语法到app开发,过程虽然枯燥无味,但是结果还是挺有成就感的,在此分享我的ios开发之路中的小小心得~废话不多说,先上我们今天要实现的效果图: 有过一点做APP经 ...
- iOS企业级开发初级课程-表视图(13集)
首先了解了表视图的组成.表视图类的构成.表视图的分类以及表视图的两个重要协议(委托协议和数据源协议),对表视图有了一个整体上的认识.接下来我们掌握了如何实现简单表视图和分节表视图,以及表视图中索引.搜 ...
随机推荐
- PHP不到100行代码实现SSO单点登录
1.点击登录跳转到SSO登录页面并带上当前应用的callback地址2.登录成功后生成COOKIE并将COOKIE传给callback地址3.callback地址接收SSO的COOKIE并设置在当前域 ...
- 一些Demo链接
youtube下载神器:https://github.com/rg3/youtube-dl我擦咧vim插件:https://github.com/Valloric/YouCompleteMevim插件 ...
- IntelliJ IDEA 自动导入包 快捷方式
idea可以自动优化导入包,但是有多个同名的类调用不同的包,必须自己手动Alt+Enter设置 设置idea导入包 勾选标注 1 选项,IntelliJ IDEA 将在我们书写代码的时候自动帮我们优化 ...
- [PCL]4 PCL中图像匹配的几个类图
IterativeClosestPoint () { reg_name_ = "IterativeClosestPoint"; ransac_iterations_ = ; tra ...
- UIKit结构图
- spring 定时任务标注
使用spring框架,需要定时任务只需要在方法上加@Component 就可以了 package hello; import java.text.SimpleDateFormat; import ja ...
- The Struts dispatcher cannot be found. This is usually caused by using Strut
The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the assoc ...
- docker summary
http://blog.tankywoo.com/docker/2014/05/08/docker-4-summary.html 总结的很好 ----------------------------- ...
- C++Primer 第一章
/* 1.main函数的标准写法就只有两种,一种是带命令行的,一种是不带命令行的.其返回类型必须是int. 2.如果main函数最后没有return语句,则编译器会自动加上一句 return 0; * ...
- fzu 2111 Min Number
http://acm.fzu.edu.cn/problem.php?pid=2111 Problem 2111 Min Number Accept: 572 Submit: 1106Tim ...