`
lfp001
  • 浏览: 100593 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

(八)用JAVA编写MP3解码器——解码增益因子

阅读更多

解码一帧Layer3第2步:解码增益因子  -- getScaleFactors_1()和getScaleFactors_2()方法

 

      增益因子(Scale Factor)数据存储在帧内的主信息中。主信息包含增益因子和用哈夫曼编码的主数据(main_data)。增益因子简单讲就是逆量化公式的指数中的一个因子。手册中解码主数据的伪码算法如下,其中MPEG 1.0由ISO/IEC 11172-3给出,MPEG 2.0由ISO/IEC 13818-3给出。官方并没有MPEG2.5这个版本,这个版本是民间版本。

解码主数据的伪码算法

 

      解码MPEG 1.0的增益因子时用到的输入值:

  • slen0[]、slen1[]:从上图中看出增益因子的值为位流中读取0..5位的值,当前究竟应该取几位,由这两个常量表给出。
  • 粒度组信息gri:用于判断块的类型的成员变量block_type、mixed_block_flag值已经在上一步中初始化。
  • scfsi:其值已在上一步初始化,若scfsi[0..3]=1表示增益因子共用。

 

解码MPEG 2.0的增益因子时用到的输入值

  • i_slen2[]:强度立体声(intensity stereo)的增益因子(scalefactor)比特数,变量名中的2表示是MPEG 2.0版。从伪码算法看出解码时需要从位流中读入0..4位,这个常量表的值给出当前应该读多少位
  • n_slen2[]:正常(normal)编码的增益因子(scalefactor,简称sf)比特数,这个常量表的值给出当前应该读多少位
  • 常量表i_slen2[]和n_slen2[]的取值见ISO/IEC 13818-3 subclause 2.4.3.2 slenx x=1..4,这两个常量表已经在Layer3的构造方法内被初始化。
  • nr_of_sfb[3][6][4]:MPEG 2.0的增益因子被分割为4部分,故nr_of_sfb的第3维长度为4;根据块的类型和scalefac_compress值增益因子频带(简称sfb)每部分的个数(number)分为6种情况,6种情况下其个数各不相同,故nr_of_sfb的第2维长度为6;根据帧边信息中block_type和mixed_block_flag这两个成员的值,共分为3种不同的块类型,故nr_of_sfb的第1维长度为3。我把nr_of_sfb设计为这样的结构,是考虑到和逆量化取得增益因子的值顺序一致。

 

解码增益因子得到的值:

 

  • 增益因子用去的比特数保存在part2_bits中,供后续的哈夫曼解码时计算主数据的比特数。
  • 解码得到的增益因子的值,长块的放入scfL[2][23];
  • 得到的增益因子的值,短块(包括纯短块和混合块中的短块)的值保存在scfS[2][3][13]中,得到的这些值供后续的逆量化使用,这些值在数组中的存放顺序要和逆量化时读取的顺序一致,这样效率更高一些。

 

 

  解码MPEG 1.0和MPEG 2.0/2.5增益因子的方法差别很大,这里定义了两个版本的方法。这里涉及到的“纯短块”、“长块”、“混合块”、“窗”概念,在逆量化中再作说明。根据上面对常量及变量值的描述中提及的“共用”、“块的类型”、“窗”就很容易看懂getScaleFactors_x()方法中的if语句和for语句的作用;短块内每个子带分3窗,所以有2重循环。

 

      class Layer3内定义的getScaleFactors_x()方法源码:

	//2.
	//>>>>SCALE FACTORS========================================================
	private static int[][] scfL;		// [2][23];
	private static int[][][] scfS;		// [2][3][13];
	private static int[] i_slen2;		// MPEG 2.0 slen for intensity stereo
	private static int[] n_slen2;		// MPEG 2.0 slen for 'normal' mode
										// slen: 增益因子(scalefactor)比特数
	private static byte[][][] nr_of_sfb;//[3][6][4]

	/*
	 * MPEG 2.0/2.5
	 */
	private void getScaleFactors_2(final int ch, final int gr) {
		byte[] nr;
		int i, bandIdx, win, slen, num, n = 0, scf = 0;
		boolean i_stereo = objHeader.isIStereo();
		GRInfo gri = objSI.ch[ch].gr[gr];
		int[] l = scfL[ch];
		int[][] s = scfS[ch];

		rzero_bandL = 0;
		if ((ch > 0) && i_stereo)
			slen = i_slen2[gri.scalefac_compress >> 1];
		else
			slen = n_slen2[gri.scalefac_compress];

		gri.preflag = (slen >> 15) & 0x1;
		gri.part2_bits = 0;
		if (gri.block_type == 2) {
			n++;
			if ((gri.mixed_block_flag) != 0)
				n++;
			nr = nr_of_sfb[n][(slen >> 12) & 0x7];

			for (i = 0; i < 4; i++) {
				num = slen & 0x7;
				slen >>= 3;
				if (num != 0) {
					for (bandIdx = 0; bandIdx < nr[i]; bandIdx += 3) {
						for (win = 0; win < 3; win++)
							s[win][scf] = bsMainInfo.getBits17(num);
						scf++;
					}
					gri.part2_bits += nr[i] * num;
				} else {
					for (bandIdx = 0; bandIdx < nr[i]; bandIdx += 3) {
						for (win = 0; win < 3; win++)
							s[win][scf] = 0;
						scf++;
					}
				}
			}

			n = (n << 1) + 1;
			for (i = 0; i < n; i += 3) {
				for (win = 0; win < 3; win++)
					s[win][scf] = 0;
				scf++;
			}
		} else {
			nr = nr_of_sfb[n][(slen >> 12) & 0x7];
			for (i = 0; i < 4; i++) {
				num = slen & 0x7;
				slen >>= 3;
				if (num != 0) {
					for (bandIdx = 0; bandIdx < nr[i]; bandIdx++)
						l[scf++] = bsMainInfo.getBits17(num);
					gri.part2_bits += nr[i] * num;
				} else {
					for (bandIdx = 0; bandIdx < nr[i]; bandIdx++)
						l[scf++] = 0;
				}
			}

			n = (n << 1) + 1;
			for (i = 0; i < n; i++)
				l[scf++] = 0;
		}
	}

	/*
	 * MPEG 1.0
	 */
	private static final int slen0[] = { 0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4 };
	private static final int slen1[] = { 0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3 };

	private void getScaleFactors_1(final int ch, final int gr) {
		GRInfo gri = objSI.ch[ch].gr[gr];
		int scale_comp = gri.scalefac_compress;
		int length0 = slen0[scale_comp];
		int length1 = slen1[scale_comp];
		int sfb, win;
		int[] l = scfL[ch];
		int[][] s = scfS[ch];

		gri.part2_bits = 0;

		if (gri.window_switching_flag != 0 && gri.block_type == 2) {
			if (gri.mixed_block_flag != 0) {
				// MIXED block
				gri.part2_bits = 17 * length0 + 18 * length1;
				for (sfb = 0; sfb < 8; sfb++)
					l[sfb] = bsMainInfo.getBits9(length0);

				for (sfb = 3; sfb < 6; sfb++)
					for (win = 0; win < 3; win++)
						s[win][sfb] = bsMainInfo.getBits9(length0);

				for (sfb = 6; sfb < 12; sfb++)
					for (win = 0; win < 3; win++)
						s[win][sfb] = bsMainInfo.getBits9(length1);
			} else {
				// pure SHORT block
				gri.part2_bits = 18 * (length0 + length1);
				for (sfb = 0; sfb < 6; sfb++)
					for (win = 0; win < 3; win++)
						s[win][sfb] = bsMainInfo.getBits9(length0);
				for (sfb = 6; sfb < 12; sfb++)
					for (win = 0; win < 3; win++)
						s[win][sfb] = bsMainInfo.getBits9(length1);
			}
		} else {
			// LONG types 0,1,3
			int[] scfsi = objSI.ch[ch].scfsi;
			if (gr == 0) {
				gri.part2_bits = 10 * (length0 + length1) + length0;
				for (sfb = 0; sfb < 11; sfb++)
					l[sfb] = bsMainInfo.getBits9(length0);
				for (sfb = 11; sfb < 21; sfb++)
					l[sfb] = bsMainInfo.getBits9(length1);
			} else {
				gri.part2_bits = 0;
				if (scfsi[0] == 0) {
					for (sfb = 0; sfb < 6; sfb++)
						l[sfb] = bsMainInfo.getBits9(length0);
					gri.part2_bits += 6 * length0;
				}
				if (scfsi[1] == 0) {
					for (sfb = 6; sfb < 11; sfb++)
						l[sfb] = bsMainInfo.getBits9(length0);
					gri.part2_bits += 5 * length0;
				}
				if (scfsi[2] == 0) {
					for (sfb = 11; sfb < 16; sfb++)
						l[sfb] = bsMainInfo.getBits9(length1);
					gri.part2_bits += 5 * length1;
				}
				if (scfsi[3] == 0) {
					for (sfb = 16; sfb < 21; sfb++)
						l[sfb] = bsMainInfo.getBits9(length1);
					gri.part2_bits += 5 * length1;
				}
			}
		}
	}
	//<<<<SCALE FACTORS========================================================

 

 

上一篇:(七)用JAVA编写MP3解码器——解码帧边信息

下一篇:(九)用JAVA编写MP3解码器——哈夫曼解码

 

【本程序下载地址】http://jmp123.sourceforge.net/

  • 大小: 16 KB
分享到:
评论
2 楼 lfp001 2013-12-06  
逆量化混合块时:前8个频带是长块,用长块公式逆量化;后9个频带是短块。

你从ISO/IEC 11172-3引用过来的说明是指逆量化时如何使用增益因子。解码增益因子时从位流读入增益因子的值,存放到数组内(长块和短块分别存放在各自的数组内),存放的顺序刚好是解码时依次读取的顺序
1 楼 clearstarrysky 2013-12-03  
if block_type is 2 and switch_point is 1:
slen1: length of scalefactors for the scalefactor bands 0 to 7 (long window scalefactor band) and 4 to 5 (short window scalefactor band) Note: Scalefactor bands 0-7 are from the "long window scalefactor band" table, and scalefactor bands 4-11 from the "short window scalefactor band" table. This combination of partitions is contiguous and spans the entire frequency spectrum.
slen2: length of scalefactors for the scalefactor bands 6 to 11
文档里说混合块的短块slen1从4-5,代码里却是从3开始,为什么?
for (sfb = 3; sfb < 6; sfb++) 
for (win = 0; win < 3; win++) 
  s[win][sfb] = bsMainInfo.getBits9(length0);

相关推荐

    matlab开发-完成mp3decoder的实现

    在MATLAB环境中开发一个MP3解码器是一个涉及音频处理和理解MPEG 1音频层3(MP3)编码标准的复杂任务。本项目旨在详细解释如何在MATLAB中实现MP3解码器,以便将压缩的MP3音频数据转换回原始的PCM(脉冲编码调制)音频...

    AAC解码算法原理详解.pdf

    全局增益被编码成一个8位的无符号整数,每个尺度因子与全局增益值差分编码后,使用尺度因子编码表进行哈夫曼编码。 AAC解码算法的实现非常复杂,它涉及音频信号处理的多个高级技术。在iOS开发中,AAC解码器的使用...

    极地码的置信传播位增强解码器

    它们在理论上证明了对于二进制输入离散无记忆信道(Binary-input Discrete Memoryless Channel,BDMC),在使用连续消除(Successive Cancellation,SC)解码器的情况下能够达到信道容量。然而,在有限码长的情况下...

    对Dxva2解码数据进行简单图像处理

    它通常涉及对图像应用一个负的高斯模糊,然后将原图像与模糊图像相减,最后将结果乘以一个增益因子并加上一个阈值,以保留细节并防止过度锐化。 4. **点运算**:点运算是在像素级别上进行的颜色转换或调整,如亮度...

    QPSK解调器原理详解

    3. **FEC单元**:该单元包括Viterbi解码器、去交织器和里德—索罗门解码器。其中Viterbi解码器用于内码解码,支持多种收缩码率;去交织器则用于卷积去交织处理;而里德—索罗门解码器用于进一步纠错。 4. **输出...

    MP3播放器---Matlab_GUI.doc

    - 可以灵活方便地处理音频信号,因此本文档将介绍如何使用MATLAB对MP3文件进行解码,制作一个简易的MP3播放器。 #### 2. MP3音乐文件结构 - **文件组成**: - **TAG_V2 (ID3V2)**:包含作者、作曲、专辑等信息,...

    基于嵌入式uC/OS-II的MP3文件播放系统设计方法

    2. **读取信息**:随后读取通道信息、增益因子等数据。 3. **霍夫曼解码**:进行霍夫曼解码以获取解压后的数据。 4. **频域到时域转换**:解压后的数据仍然处于频域内,需要进一步转换回时域才能播放。 5. **音频...

    实验43 音乐播放器实验.rar_STM32播放wav_STM32的WAV_stm32和wm8978_播放器 STM32_音乐播

    在本实验中,我们将深入探讨如何使用STM32微控制器实现一个基于STM32和WM8978音频编解码器的WAV音乐播放器。STM32是一款广泛使用的ARM Cortex-M系列微处理器,而WM8978是一款高性能、低功耗的音频编解码器,适用于...

    33753146STM32_WM8978.rar

    在STM32中,通常使用定时器和GPIO引脚来模拟I2S总线,实现与外部音频编解码器的通信。WM8978是一款高性能的立体声编解码器,集成了麦克风放大器、模拟混合信号电路和数字信号处理器,支持多种音频格式和采样率。 在...

    gain_table_lbr.rar_Table

    编码器会使用一个预定义的增益表(即这里的“gain_table”),从中选择最佳的增益因子,以适应不同情况下的信号特征。 在 "gain_table_lbr.c" 文件中,我们可以预期找到以下内容: 1. 定义了32个条目的增益表,这些...

    QPSK发送器和接收器.doc

    **在AWGN通道中,有两个可选的延迟类型——斜坡延迟和三角形延迟,用以模拟不同的时序漂移情况,这对评估接收机性能至关重要,特别是对符号同步器的影响。** **接收端的自动增益控制(AGC)用于稳定信号幅度,确保...

    一个控制音量大小的类(16KB)

    在数字音频中,这通常是通过对音频样本进行数学运算来实现的,例如乘以一个特定的增益因子。 1. **C++编程**:C++是一种广泛使用的面向对象的编程语言,非常适合进行底层系统编程和高性能计算。在这个音量控制类中...

    dllAudio-源码.rar

    源码中可能会有相应的解码器和编码器实现,通过特定的压缩算法,如DCT(离散余弦变换)和熵编码,来达到高效存储和传输音频的目的。 在音量控制方面,源码可能包含增益调整、静音、淡入淡出等功能。这通常涉及到对...

    Dalsa采集卡如何与数字相机配合工作.doc

    八、Bayer 解码器 Bayer 解码器可以对 Bayer 滤波彩色面阵相机进行解码和处理。用户可以选择不同的解码模式,例如双线性差值、易保存图像边缘等,并设置相关的参数,例如 γ 校正因子、颜色增益调节等。 Dalsa ...

    CMOS_Image_Sensor.pdf

    CMOS图像传感器的基本架构由像素阵列、解码器和控制器、相关双采样(CDS)、多路复用器以及模数转换器组成,最后通过时钟信号和8位数字输出进行数据读取。 传感器的分辨率: CMOS图像传感器的分辨率可以是CIF、VGA...

    Hi3130V100.pdf

    17. **集成相位锁定环(PLL)**:集成PLL外部连接到晶振,或与解码器和解调器共享同一个时钟源。 18. **集成晶体振荡器电路**:通过外部晶体能够在片上生成系统时钟。 19. **低功耗设计**:在6.9Msymb/s的情况下,...

    matlab_IEEE802.16标准系统的仿真,包括发射机,信道,接收机这个完整的过程

    在仿真中,这通常表示为简单的增益因子。 接下来,我们要考虑的是**信道模型**。在MATLAB中,有多种方法来模拟无线信道,如: - **多径衰落**:可以使用`comm.RayleighChannel`或`comm.LindnerFadingChannel`来...

    音视频SDK功能列表

    12. **加载外部编解码器**:支持加载自定义的音视频编解码器,增强了SDK的兼容性和扩展性。 13. **设备切换**:支持音频输入、输出和视频输入设备的切换,用户可以根据需要选择不同的设备。 14. **WEB浏览器应用**...

Global site tag (gtag.js) - Google Analytics