- 打卡等级:以坛为家III
- 打卡总天数:718
- 最近打卡:2026-07-04 07:01:47
金牌会员
- 积分
- 1087
|
发表于 2026-5-12 15:30:14
|
显示全部楼层
谢谢梁工:已经设置成功。还有一个问题想请教一下。我测试通过CAN发送8点正弦波。非常稳定正常。但是传输实际音频的时候失真很严重,我的音频采集是通过DMA 。转换两次。然后经过A_LOW编码发送。语音采样率8K,每32毫秒采集256字节。通过编码输出128字节。(标准帧32帧)采集和解码都是双缓冲。采集A 发送B 。采集满256字节发送标志==1.在主循环发送32帧。(实际测试接收时间不丢包需要12.5毫秒)。DMA在定时器中断125us触发一次。困惑很久没找到原因。现在真实音频是信号源产生1K正弦波。收到失真抖动。unsigned char ALAW_Encode(int pcm)
{
unsigned char sign, comp, seg;
unsigned int temp;
if (pcm >= 0)
{
sign = 0;
temp = pcm;
}
else
{
sign = 0x80;
temp = -pcm;
}
if (temp > 32635) temp = 32635;
temp += 33;
if (temp >= 16384) seg = 7;
else if (temp >= 8192) seg = 6;
else if (temp >= 4096) seg = 5;
else if (temp >= 2048) seg = 4;
else if (temp >= 1024) seg = 3;
else if (temp >= 512) seg = 2;
else if (temp >= 256) seg = 1;
else seg = 0;
comp = (seg << 4) | ((temp >> (seg + 3)) & 0x0F);
comp ^= 0x55;
return sign | comp;
}
// A-LAW解码实现
int ALAW_Decode(unsigned char alaw)
{
unsigned char sign, seg;
unsigned int temp;
alaw ^= 0x55;
sign = alaw & 0x80;
alaw &= 0x7F;
seg = (alaw >> 4) & 0x07;
temp = (0x80 | (alaw & 0x0F)) << (seg + 3);
temp -= 33;
if (seg != 0)
temp += 4 << seg;
if (sign) return -(int)temp;
else return (int)temp;
}
// A-LAW块编码:256个PCM样本→256字节A-LAW数据
void alaw_encode_block(int *in, unsigned char *out, unsigned int n)
{
unsigned int i;
int sample16;
for (i = 0; i < n; i++)
{
// 原PCM是12bit(-2048~2047),扩展到16bit适配A-LAW
sample16 = in<< 4;
out = ALAW_Encode(sample16);
}
}
// A-LAW块解码:256字节A-LAW→256个PCM样本
void alaw_decode_block(unsigned char *in, int *out, unsigned int n)
{
unsigned int i;
int pcm16;
for (i = 0; i < n; i++)
{
pcm16 = ALAW_Decode(in);
// 还原为12bit PCM
out = pcm16 >> 2;
}
}
void prepare_pwm_buf(int *pcm, unsigned int *pwm, unsigned int n)
{
unsigned int i;
long val;
// unsigned long temp;
for (i = 0; i < n; i++)
{
val = (long)pcm + 2048;
if (val < 10) val = 10;
if (val > 4085) val = 4085;
// temp = (unsigned long)(val - 10) * 255;
// pwm = (unsigned char)(temp / (4085 - 10));
pwm = (val - 10) * 511 / 4075;
}
}
void Timer0_ISR(void) interrupt 1
{
// 输出当前采样点的PWM占空比
PWM_SetDuty(rx_pwm[play_pos]);
// 播放指针+1
play_pos++;
// 播放完一帧256点,回到0重新开始
if(play_pos >= PCM_SAMPLE_NUM)
{
play_pos=0;
silence_cnt++; // 静音计数+1
// 连续多帧没收到新数据 → 填充静音,防止噪音
if(silence_cnt>3)
{
fill_silence(rx_pwm, PCM_SAMPLE_NUM);
silence_cnt=0;
}
}
} 不知道哪里的问题? |
|