发布网友 发布时间:2024-10-24 11:24
共2个回答
热心网友 时间:2024-10-26 10:17
这是我写的一个C++实现方案,希望对你有帮助
#include <iostream>
#include <cmath>
using namespace std;
int main(){
const int sect = 8; //将输入输出的范围分为8段.
const int startingVol[sect+1] = {0,16,32,,128,256,512,1024,2048};
// 每段的起始值
const int quanIntvl[sect] = {1,1,2,4,8,16,32,};
//将每大段内为16个小段后,依次对应的每个小段之间的间隔
//如与32之间的大段分为16段,每小段之间的间隔为2
int pcmCode[sect] = {0,0,0,0,0,0,0,0}; // 8位的PCM编码。
int startPoint; //计算量化后的值时使用到的每大段起始值数组的下标
int finePoint; //计算量化后的值时使用到的每小段间隔数组的下标
const double pi=3.141592653579;
int quanValue; // 最后量化出来得到的值
int quanError; //量化引起的误差
for(double j=0;j<=20;j++) {
int sampleValue = 300*sin((j/10)*pi)+500*sin((j/3)*pi)-400*sin((j/8)*pi); //几个sin函数叠加产生一个虚拟的波形
int pcmInd = 0; //表示第几位编码
int low = 0;
int high = sect;
int mid;
int loopInd1 = 0; //编码第二到第三位所使用的循环次数
int loopInd2 = 0; //编码第四到第八位所使用的循环次数
(sampleValue >= 0) ? (pcmCode[pcmInd] = 0) : (pcmCode[pcmInd] = 1); //获取PCM编码的第一位,即采样值的符号
sampleValue = abs(sampleValue); //将采样值取为其绝对值,以保证后面程序的顺利运行
//其余位编码的获取采用二分搜索
//首先编码第2到第4位
while(loopInd1 < 3) //因为知道输入分为8段,所以设定二分搜索的循环次数为3次即可将第2到第4位编码完成
{
mid = (low + high)/2;
if(sampleValue < startingVol[mid])
{
pcmCode[++pcmInd] = 0;
high = mid;
startPoint = mid - 1 ;
}
else
{
pcmCode[++pcmInd] = 1;
low = mid;
startPoint = mid;
}
loopInd1++;
}
//编码剩下的4位
low = 0;
high = 16; //每段内平均分为16个小段
//仍然使用二分搜索
while(loopInd2 < 4)
{
mid = (low + high)/2;
//在程序运行中显示下列语句来使得编码过程更加直观
quanValue = startingVol[startPoint] + mid * quanIntvl[startPoint];
cout<<startingVol[startPoint]<<" + "<<quanIntvl[startPoint]<<" * "<<mid<<" = "
<<quanValue <<" ? "<<sampleValue<<endl;
if(sampleValue < startingVol[startPoint] + mid * quanIntvl[startPoint])
{
pcmCode[++pcmInd] = 0;
high = mid;
finePoint = mid -1;
}
else if(sampleValue > startingVol[startPoint] + mid * quanIntvl[startPoint])
{
pcmCode[++pcmInd] = 1;
low = mid;
finePoint = mid;
}
else
{
finePoint = mid;
break;
}
loopInd2++;
}
quanValue = startingVol[startPoint] + finePoint * quanIntvl[startPoint];
if((sampleValue-quanValue)>=quanIntvl[startPoint] / 2)
{
quanValue += quanIntvl[startPoint] / 2;
}
else if((quanValue-sampleValue)>=quanIntvl[startPoint] / 2)
{
quanValue -= quanIntvl[startPoint] / 2;
}
//对量化结果进行最后的调整以更加靠近采样值
quanError = abs( sampleValue - quanValue);
cout<<"采样值: "<<sampleValue<<endl;
cout<<"最终值: "<<quanValue<<endl;
cout<<"实际误差: "<<quanError<<endl;
cout<<"PCM编码为: ";
for(int i = 0; i < 8; i++)
{
cout<<pcmCode[i]<<" ";
}
cout<<endl;
}
return 0;
}
热心网友 时间:2024-10-26 10:11
?