如何计算一个granule所占的average available bits 及我所提出的疑问
所谓available bits也就是真实的有用的音频数据, 最后会被解码的数据, 或者也可以说它是main_data数据, 是由big_value和count1组成的. 罗嗦一堆就是说明available bits是真正的被解码的数据, 是不包括side_info的. 计算方式为
The average number of bits per granule is calculated from the frame size.
The bitrate 64 kb/second is used as an example. At bitrate 64 kb/second
at 48000 samples per second
对于MP3来说, 一个Frame播放0.24(到底是0.24还是0.26我还不敢肯定, 也许是0.26吧)秒? 计算一个granule占用的位元数(平均的!)
(64000*0.24 bits perframe)/ (2 granules per frame) = 768 bits per granule
mean_bits是指一个granule有意义的位元(平均而言). 除去head以外的真正的语音数据(main_data).
config.mpeg.bits_per_frame描述一个frame有多少个bits(不是平均的, 这里一定要注意,一定要深入的注意,我在这里差点被骗了, 竟然认为是平均的, 够笨。 FU*K! )
sideinfo_len描述了除main_data以外的数据长度
因为一个frame有两个granule, 因此要除以2.
mean_bits = (config.mpeg.bits_per_frame - sideinfo_len) >> 1;
这里有一个疑问, 那么sideinfo_len到底是描述的什么?
/*
* 通道数(单声道为1, 双声道为2)
* 这里的 sideinfo_len 并不是指side_info结构的大小, 而是指
* FrameHeader + CRC + SideInfo 的大小.
* 其中CRC部分不存在, 也就是说没有校验.
*
* Frame结构
* FrameHeader(32bits), CRC校验(16/0bits), 旁资讯(17/32bytes), MAIN_DATA, -- 音讯资料
*
* 136怎么来? 17bytes * 8 == 136 bits -- 单声道
* 256怎么来? 32bytes * 8 == 256 bits -- 立体声
*
* 请参考<<专题组员:B09002003陈健峰.PDF>> Page12
*/
sideinfo_len = 32; // FrameHeader所占位元数.
sideinfo_len += ( config.wave.channels==1 ? 136 : 256 );
由此可见, sideinfo_len并不是单指旁资讯的长度. 单声道时旁资讯是17个byte, 立体声时是32个byte.
那么接下来需要对mean_bits在追究下去
一个granule里头是有2个声道的(我们假设是双声道的音频)
那么
// 每个声道所包含的main_data位元数(平均的)
// max_bits描述的是一个声道所包含的main_data位元数(平均的)
max_bits = mean_bits / config.wave.channels;
在继续研究shine的过程中, 我发现每压缩一个frame 的时候, max_bits都是一样的. 第一个frame的max_bits和第N个frame的max_bits全是一样的. 我实在是不敢相信.
我觉得好奇怪, 怎么会是一样的,按道理说不应该啊,
接着要看max_bits的来源, 它是由mean_bits确定的, 因为我一直默认channels是2的.
找到mean_bits,
mean_bits = (config.mpeg.bits_per_frame - sideinfo_len) >> 1;
发现mean_bits是由config.mpeg.bits_per_frame和sideinfo_len确定的, 但是我们知道所有的frame中sideinfo_len也是一样的, 请注意看前面提到的sideinfo_len究竟是什么东西(它不是仅仅表示side_info部分的长度的, 切切要注意啊!)
那么就是要拿
config.mpeg.bits_per_frame同志开刀了.
OK,
config.mpeg.bits_per_frame
= 8 * (whole_slots_per_frame + config.mpeg.padding);
这个混蛋找到了,
但是还没没有完, 另外2个家伙(whole_slots_per_frame和config.mpeg.padding也不是省油的灯啊!)被牵扯近来了。