分类:
2012-12-07 17:36:08
原文地址:MP3解码算法分析(7)——L1帧解码器分析 作者:gliethttp
:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://kware.blogbus.com/logs/30741651.html
1. L1帧解码 LayerIDecoder.java
public void decodeFrame() {
num_subbands = header.number_of_subbands();
subbands = new Subband[32]; // Layer I 有 32 个子带
mode = header.mode();
createSubbands(); // 创建子带
readAllocation(); //
readScaleFactorSelection(); // L1 层没有比例系数选择
if ((crc != null) || header.checksum_ok()) { //
readScaleFactors(); //
readSampleData(); // 读取解样数据
}
}
2. 读取分配 LayerIDecoder.java,
protected void readAllocation() { // 开始读取音频数据
for (int i = 0; i < num_subbands; ++i) // 对 32 个子带依次读取“分配”
subbands[i].read_allocation(stream, header, crc);
}
class SubbandLayer1 { // L1 子带
protect int allocation, samplelength; // 注:Subband 类属性
protected float factor, offset;
...
public void read_allocation(Bitstream stream, Header header, Crc16 crc) {
if ((allocation=stream.get_bits(4))==15); // 警告:流中包含一个非法分配,MPEG 流已被破坏!
if (crc!=null) crc.add_bits(allocation, 4);// 加入校验
if (allocation != 0) {
samplelength = allocation + 1; // 计算采样长度
factor = table_factor[allocation]; // 系数
offset = table_offset[allocation]; // 偏移
}
}
}
3. 校验和检查 Header class:
// 比较计算的 checksum 和流 checksum,返回成功与否
// 校验参与部分有:Header 和 32个4字节 Allocaltion
public boolean checksum_ok () { return (checksum == crc.checksum()); }
4. 读取比例系数 LayerIDecoder class:
protected void readScaleFactors() {
for (int i=0; i
}
class SubbandLayer1 { // L1子带类的比例系数读取
public void read_scalefactor(Bitstream stream, Header header) {
if (allocation != 0) scalefactor =
scalefactors[stream.get_bits(6)]; // 每个子带有 6bits 的比例系数位
}
}
5. 读取样本数据并写入解样数据 LayerIDecoder class:
protected void readSampleData() {
boolean read_ready = false;
boolean write_ready = false;
int i, mode = header.mode();
do {
for (i = 0; i < num_subbands; ++i) // 对 32 个子带依次读取“样本数据”
read_ready = subbands[i].read_sampledata(stream);
do {
for (i = 0; i < num_subbands; ++i) // 对 32 个子带解样数据依次写入样本缓冲
write_ready = subbands[i].put_next_sample(which_channels, filter1, filter2);
filter1.calculate_pcm_samples(buffer); // 计算施加过滤器 1
if ((which_channels==OutputChannels.BOTH_CHANNELS) && (mode!=Header.SINGLE_CHANNEL))
filter2.calculate_pcm_samples(buffer); // 计算施加过滤器 2
} while (!write_ready);
} while (!read_ready);
}
class SubbandLayer1 {
public boolean read_sampledata(Bitstream stream) {
if (allocation != 0) sample = (float)
(stream.get_bits(samplelength)); // 读取样本数据,长度=samplelength=allocation+1
if (++samplenumber == 12) { // 读取的样本数类计,超过 12 复位
samplenumber = 0;
return true; // 样本读取结束 32|12 = 96?
}
return false;
}
...
}
class SynthesisFilter { // 计算 32 PCM 采样并放进输出缓冲区 Obuffer 对象
public void calculate_pcm_samples(Obuffer buffer) {
compute_new_v();
compute_pcm_samples(buffer);
actual_write_pos = (actual_write_pos + 1) & 0xf;
actual_v = (actual_v == v1) ? v2 : v1;
for (int p=0; p<32; p++) samples[p] = 0.0f;
}
// Compute new values via a fast cosine transform.
private void compute_new_v() { ... }
private void compute_pcm_samples(Obuffer buffer) {
switch (actual_write_pos) {
case 0:
compute_pcm_samples0(buffer);
break;
case 1:
...
}
if (buffer!=null)
buffer.appendSamples(channel, _tmpOut);
// MDM: I was considering putting in quality control for
// low-spec CPUs, but the performance gain (about 10-15%)
// did not justify the considerable drop in audio quality.
switch (inc) {
case 16:
buffer.appendSamples(channel, tmpOut);
break;
case 32:
for (int i=0; i<16; i++) {
buffer.append(channel, (short)tmpOut[i]);
buffer.append(channel, (short)tmpOut[i]);
}
break;
case 64:
for (int i=0; i<8; i++) {
buffer.append(channel, (short)tmpOut[i]);
buffer.append(channel, (short)tmpOut[i]);
buffer.append(channel, (short)tmpOut[i]);
buffer.append(channel, (short)tmpOut[i]);
}
break;
}
}
private void compute_pcm_samples0(Obuffer buffer) {
final float[] vp = actual_v;
// int inc = v_inc;
final float[] tmpOut = _tmpOut;
int dvp =0;
// fat chance of having this loop unroll
for ( int i=0; i<32; i++) {
float pcm_sample;
final float[] dp = d16[i];
pcm_sample = (float)(
( (vp[0 + dvp] * dp[0]) + (vp[15 + dvp] * dp[1])
+ (vp[14 + dvp] * dp[2]) + (vp[13 + dvp] * dp[3])
+ (vp[12 + dvp] * dp[4]) + (vp[11 + dvp] * dp[5])
+ (vp[10 + dvp] * dp[6]) + (vp[ 9 + dvp] * dp[7])
+ (vp[ 8 + dvp] * dp[8]) + (vp[ 7 + dvp] * dp[9])
+ (vp[6 + dvp] * dp[10]) + (vp[5 + dvp] * dp[11])
+ (vp[4 + dvp] * dp[12]) + (vp[3 + dvp] * dp[13])
+ (vp[2 + dvp] * dp[14]) + (vp[1 + dvp] * dp[15])
) * scalefactor
);
tmpOut[i] = pcm_sample;
dvp += 16;
}
}
}