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));
}