www.pudn.com > Sound_v1.01.rar > Sound_v1.01.c


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