接触iOS开发有些年头了,一直在看博客,从来没有写过啥。开个头吧,记录一下学习的东西,加深点印象。岁数大了,脑袋是真记不住东西。。。忘了哪个名人说的:脑子是个好东西,乱七八糟的东西,记得清清楚楚,想记住的东西,却忘得贼快!好记性,不如烂笔头。
现在音视频的东西火大,就从记录音视频学习开始吧。原理性知识源自《音视频开发进阶指南》,也有部分实践的东西源自袁峥,感谢前辈对于音视频部分知识的分享。
音频编码
音频编码,就是对音频进行压缩。压缩编码的原理实际上是压缩掉冗余信号。冗余不能被人耳感知到的信号,即人耳听觉范围之外的音频信号和被掩蔽掉的音频信号,这些冗余信号不进行编码处理。
补充一点码率的计算:CD的音质,量化格式为16比特,采样率为44100(44.1kHz),声道数为2。CD音质的比特率就是:
16 * 44100 * 2 / 1024 = 1378.125kbps
那么一分钟CD音质的数据占据存储空间就是:
1378.125kbps * 60 / 8 / 1024 = 10.09MB
如果采样率再密集,数据会更大。
1. WAV编码
PCM(脉冲编码调制)是Pulse Code Modulation的缩写。WAV编码就是在PCM数据格式的前面加上44字节,用来表示PCM的采样率、声道数、数据格式等信息(WAV有多种实现方式,都不会进行压缩操作,就是平时听得无损格式的一种)。
特点:音质非常好,大量软件都支持。
适用场合:多媒体开发的中间文件、保存音乐和音素教材。
2.MP3编码
MP3格式,使用LAME编码的中高码率的MP3文件,听感上非常接近WAV文件。
特点:音质再128Kbit/s以上表现好,压缩比比较高,兼容性好。
使用场合:高比特率下对兼容性有要求的音乐欣赏。
3.AAC编码
AAC是新一代的音频有损压缩技术,通过附加的编码结束(PS、SBR等)衍生出LC-AAC、HE-AAC、HE-AACv2三种主要的编码格式。LC-AAC主要应用于高码率场景的编码(≥80Kbit/s);HE-AAC(AAC+SBR)主要应用于中低码率场景的编码(≤80Kbit/s);HE-AACv2(AAC+SB+PS)主要应用于低码率场景的编码(≤48Kbit/s)。
特点:在小于128Kbit/s的码率下表现优异,多用于视频中的音频编码
使用场景:多用于视频中音轨的编码。手机里音视频的部分多数就用的这种。
4.Ogg编码
Ogg编码在各种码率下都表现优秀,可以用更小的码率达到更好的音质!128Kbit/s的Ogg比 192Kbit/s的MP3还要出色!是不是以后可以做一个Ogg编码的播放器~
特点:特点就是高中低码率下表现都好,但是兼容性不好,而且不支持流媒体特性。
使用场景:语音聊天里的音频消息,项目里有语音聊天部分的,应该都不陌生。
分享一下Lame编码MP3文件
Lame库下载链接,下载最新版本多久可以了。编译脚本也有牛牛写好了! 下面是脚本的一些注释
#disable-shared 关闭动态链接库
#disable-frontend 不编译出Lame的可执行文件
#prefix 指定编译好的库放在哪个目录
#CC 指定编译工具
#CFLAGS 指定 编译 过程中的参数 是否开启比特code,App最低版本
#LDFLAGS 指定 链接 过程中的参数 是否开启bitcode,App支持的最低版本
#host 指定最终库要运行的平台
Lame压缩编码的过程大致为:
- 分别设置要转码的文件,生成文件的位置
FILE *pcm = fopen([self.savePath cStringUsingEncoding:1], "rb"); //被转换的音频文件位置
fseek(pcm, 4*1024, SEEK_CUR);//skip file header 跳过 PCM header 能保证录音的开头没有噪音
FILE *mp3 = fopen([self.mp3Path cStringUsingEncoding:1], "wb+"); //输出生成的Mp3文件位置(这里注意打开文件的方式wb 只写方式打开或新建一个二进制文件,只允许写数据。
wb+ 读写方式打开或建立一个二进制文件,允许读和写。)
- 初始化lame_init(),配置一下lame,跟录音的配置差不多
lame_t lame = lame_init();
lame_set_in_samplerate(lame, kSampleRate); 采样率 单位是HZ 通常设置成44100 44.1k
lame_set_num_channels(lame,kChannels); 声道数 通常为双声道 2
lame_set_mode(lame, MONO);//设置最终mp3编码输出的声道模式,如果不设置则和输入声道数一样。参数是枚举,STEREO代表双声道,MONO代表单声道
lame_set_VBR(lame, vbr_default);//设置比特率控制模式,默认是CBR,一般使用VBR
//lame_set_brate(lame, 16);//设置CBR的比特率,只有在CBR模式下才生效。
lame_set_VBR_mean_bitrate_kbps(lame, 16);//设置VBR的比特率,只有在VBR模式下才生效
lame_init_params(lame);

- 然后就是 do {反复读取pcm的FILE,写进MP3的FILE} while(read != 0),读取到最后记得关闭lame,mp3,pcm。
if (kChannels == 1) {
write = lame_encode_buffer(lame, pcm_buffer, nil, read, mp3_buffer, MP3_SIZE);//如果只有一个声道,数据写左声道里去
} else if (kChannels == 2) {
write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
}
lame_mp3_tags_fid(lame, mp3); //这里有坑
lame_close(lame);
fclose(mp3);
fclose(pcm);
在lame_close之前一定要调用lame_mp3_tags_fid()这个方法,不然时间计算不准确。
编码的MP3会预留 VBR tag的空间,如果不插入,会影响计算时间。非VBR模式也会空出 VBR tag。这也是前面文件读写那设置‘wb+‘的原因。 进源码看吧,有详细注释!
最后就可以去指定的MP3路径,把数据播放出来了………