sound_v1.01.c

来自「A律和U律压缩源程序(DSP课程设计的源代码」· C语言 代码 · 共 348 行

C
348
字号

/*****************程序描述********************************************/
/*
硬件资源:AD转换器AD50,多通道缓冲串口McBSP
编序原理:使用基于CCITT721的A律压缩标准和U率压缩标准对输入的语音信号进行压缩和解压
功能描述:(1)开机亮灯三次,表示系统正常工作
          (2)LED0亮表示输入、压缩语音信号
          (3)利用定时器延时10S
          (4)LED0灭,LED1亮表示解压、输出语音信号
          (5)LED0灭,LED1灭一次压缩、回放过程结束
作者:舒光华 刘霖
编程日期:2007年1月9号
版本号:V1.01
*********************************************************************/                 


//包含头文件
#include <type.h>     //数据类型头文件
#include <board.h>    //DSK板头文件
#include <codec.h>    //AD50C头文件
#include <mcbsp54.h>  //多通道缓冲串口头文件
#include <timer.h>    //定时器头文件

//宏定义
#define	SIGN_BIT	0x80		/*  A律压缩后数据的符号位 */
#define	QUANT_MASK  0x0f		/* 段内码权重因子 */
#define	NSEGS		 8		    /* A律压缩的段数 */
#define	SEG_SHIFT	 4		    /* 段码左移的位数*/
#define	SEG_MASK	0x70		/* 段码权重因子*/
#define TIME0        0          /*定时器0*/
#define N           32000       /*缓冲区大小*/
//子函数声明
void delay(s16 period);
void led(s16 cnt);
void initCodec(void);
void flashEnable(void);
unsigned char linear2alaw(s16 pcm_val);
int alaw2linear(unsigned char	a_val);
static int search(int val,short	*table,int size);
unsigned char linear2ulaw(int	pcm_val);//u率压缩
int ulaw2linear(unsigned char u_val);//u率解压
void initTimer0(void);//定时器初始化
//全局变量定义
HANDLE hHandset;//McBSP句柄
s16 data;//存放一次压缩后的数据
s16 data1;//存放一次解压后的数据
u16 i=0;
u16 j=0;
u16 k,l=0;//计数器
u16 flag=0;//查询定时器的标志
u16 temp1;
u8 temp2;//中间变量
u16 buffer[N];//数据缓冲区
static short seg_end[8]={0x1F,0x3F,0x7F,0xFF,0x1FF,0x3FF,0x7FF,0xFFF};


//主函数
void main()
{
    if (brd_init(100))    return;//初始化失败则返回
    led(2);                  //闪灯两次
    initCodec();             //初始化codec
    flashEnable();           //选择片外FLASH为片外存储器
 
/*       
    delay(100);
    brd_led_toggle(BRD_LED0);
     for(i=0x9000;i<0xefff;i++)
     {     
      REG_WRITE(i,*(volatile u16*)DRR1_ADDR(HANDSET_CODEC));
     delay(20);
     }
     brd_led_toggle(BRD_LED1);
     delay(200);
     for(i=0x9000;i<0xefff;i++)
     {
     *(volatile u16*)DXR1_ADDR(HANDSET_CODEC)=REG_READ(i);
     delay(20);
     }
     brd_led_toggle(BRD_LED2);
 */ 

   while (1)
    {
       brd_led_enable(BRD_LED0);      //点亮数码管0 表示录音结束
       while (!MCBSP_RRDY(HANDSET_CODEC)) {};       //等待接收handset处的采样
       data = *(volatile u16*)DRR1_ADDR(HANDSET_CODEC);  //从handset处读取采样
       temp1=linear2alaw(data);                            //对采样进行a律压缩
       //temp1=linear2ulaw(data);                            //对采样进行u律压缩
     //保存压缩后的数据 把低地址数据放在高八位 高地址数据放在第八位                     
         
       i=i+1;          
	   if(i%2==1)
	   		{
				buffer[j]=(temp1<<=8);       
				/*奇数数据左移8位  temp1=abcdefgh00000000
				buffer[j]=temp1*/
	   		}
	   else
    		{
 		    	buffer[j]=(buffer[j]|temp1);  
		    	/*偶数数据与temp1取或 组成新的数据
                                                  buffer[j]=abcdefghiabcdefghi*/
       			j++;   //j加1
       		}
       		
       if(i>=(2*N)) 
       		{
				i=0;
	   		}
	   		
	   if(j>=N)
	   		{
	   			j=0;
	   			brd_led_disable(BRD_LED0);      //熄灭数码管0 表示录音结束
	   			
	   			//启动定时器与查询方式相结合,实现10S延时
	   			initTimer0();
                while(flag<100)
                {
                   if(IFR&0x0008)              //查询Timer0的中断标志位
                   {
                       IFR |= 0x0008;
                       flag++;                 //查询标志自加
                   }
                }
                flag=0;
                TIMER_HALT(TIME0);//定时结束,查询标志清零且定时器停止工作
                
                // 播放录音	
		   		brd_led_enable(BRD_LED1);     //点亮二极管1 表示放音开始
	   			for(k=0;k<(2*N);k++)
	   			{
	   				if(k%2==0)
	   				{
	   					temp2=(buffer[l]>>8)&0x0ff;
	   				}
	   				else
	   				{
	   					temp2=buffer[l]&0x0ff;
	   					l++;
	   				}
				if(l>=N)
	   					l=0;
	   					
	   			//解压、采样输出		
	   			data1=alaw2linear(temp2);
	   			//data1=ulaw2linear(temp2);
	   			while (!MCBSP_XRDY(HANDSET_CODEC)) {};    
	   			*(volatile u16*)DXR1_ADDR(HANDSET_CODEC) = data1;
	   	   		}
                  
	   	   	   if(k==(2*N))
	   	   	   {
	   	   	     brd_led_disable(BRD_LED1); //熄灭二极管1 表示放音结束    
                 brd_led_disable(BRD_LED0); //熄灭二极管0 表示程序结束
	   	   	   }
      	    }
    }       
 
}                                               


                                                                   
/**************子函数定义**************************/

/*******延时子程序******/
void delay(s16 period)
{
    int i, j;
    
    for(i=0; i<period; i++)
    {
        for(j=0; j<period>>1; j++);
    }
}

/*******闪灯******/
void led(s16 cnt)
{

	while ( cnt-- )
	{
		brd_led_toggle(BRD_LED0);
		delay(1000);
		brd_led_toggle(BRD_LED1);
		delay(1000);
		brd_led_toggle(BRD_LED2);
		delay(1000);
	}
}

/*****初始化codec**/
void initCodec(void)
{
    /* Open Handset Codec */
    hHandset = codec_open(HANDSET_CODEC);             // Acquire handle to codec 
    /* Set codec parameters */
    codec_dac_mode(hHandset, CODEC_DAC_15BIT);             // DAC in 15-bit mode 
    codec_adc_mode(hHandset, CODEC_ADC_15BIT);             // ADC in 15-bit mode 
    codec_ain_gain(hHandset, CODEC_AIN_6dB);  // 6dB gain on analog input to ADC 
    codec_aout_gain(hHandset, CODEC_AOUT_MINUS_6dB);    
                                          // -6dB gain on analog output from DAC 
    codec_sample_rate(hHandset,SR_16000);                 // 16KHz sampling rate 
}
/********初始化定时器(10ms)******************/
void initTimer0(void)
{
   TIMER_HALT(TIME0);      //停止定时器工作
   PRD(TIME0)=64299;       //设置PRD寄存器的值
   TCR(TIME0)=0x0c0f;      //设置TCR寄存器的值
}

/*****设置flash****/
void flashEnable(void)
{
CPLD_CTRL2_REG|=0x0010;
CPLD_DMCTRL_REG|=0x0040;
}

/*****a律压缩******/
unsigned char linear2alaw(s16 pcm_val)	     
{
	int		mask;
	int		seg;
	unsigned char	aval;

	if (pcm_val >= 0) 
	{
		mask = 0xD5;		                   // 标记 (7th) bit = 1
	} 
	else 
	{
		mask = 0x55;		                         // 标记 bit = 0 
		pcm_val = -pcm_val;
	}
		// Convert the scaled magnitude to segment number. 
	seg = search(pcm_val, seg_end, 8);           

        // Combine the sign, segment, and quantization bits. 
    if (seg >= 8)	                            // out of range, 返回最大数. 
		return (0x7F ^ mask);
	else 
	{
		aval = seg << SEG_SHIFT;
		if (seg < 2)
			aval |= (pcm_val >> 1) & QUANT_MASK;
		else
			aval |= (pcm_val >>seg) & QUANT_MASK;

		return (aval ^ mask);
	}
}

/****alaw的子程序**/
static int search(int val,short	*table,int size)
{
	int		i;

	for (i = 0; i < size; i++) 
	{
		if (val <= *table++)
		return (i);
	}
	return (size);
}

/*****a律解压******/
int alaw2linear(unsigned char	a_val)
{
	int		t;
	int		seg;

	a_val ^= 0x55;
    t = (a_val & QUANT_MASK) << 4;
	seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
	if(seg==0) 
	{
	 	t += 8;
	 	t=(t>>3);
	}
	if((seg<4)&&(seg>0)) 
	{
	 	t +=0x108;
	 	t=(t>>(4-seg));
	}
	if(seg>3)
	{
		t+=0x108;
		t=(t<<=(seg-4));
	}
return ((a_val & SIGN_BIT) ? t : -t);
}

#define	BIAS		(0x84)		/* Bias for linear code. */
/******************u律压缩*****************************/
unsigned char linear2ulaw(int	pcm_val)	/* 2's complement (16-bit range) */
{
	int		mask;
	int		seg;
	unsigned char	uval;

	/* Get the sign and the magnitude of the value. */
	if (pcm_val < 0)
	 {
		pcm_val = BIAS - pcm_val;
		mask = 0x7F;
	 }
	 else 
	 {
		pcm_val += BIAS;
		mask = 0xFF;
   	 }

	/* Convert the scaled magnitude to segment number. */
	seg = search(pcm_val, seg_end, 8);//seg_end的地址传给形参table

	/*
	 * Combine the sign, segment, quantization bits;
	 * and complement the code word.
	 */
	if (seg >= 8)		/* out of range, return maximum value. */
		return (0x7F ^ mask);
	else 
	{
		uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
		return (uval ^ mask);
	}

}
/*****u律解压******/
int ulaw2linear(unsigned char u_val)
{
	int		t;

	/* Complement to obtain normal u-law value. */
	u_val = ~u_val;

	/*
	 * Extract and bias the quantization bits. Then
	 * shift up by the segment number and subtract out the bias.
	 */
	t = ((u_val & QUANT_MASK) << 3) + BIAS;
	t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;

	return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?