PCM 脉冲编码调制是Pulse Code Modulation的缩写。脉冲编码调制是数字通信的编码方式之一。销早主要过程是将话音、图像等模拟信号每隔一定时间进行取样,使其离散化,同时将抽样值按分层单位四舍五入取整量化,同时将抽样值按一组二进制码来表示抽样脉冲的幅值。
模拟信号数字化必须经过三个过程,即抽样、量化和编码,以实现话音数字化的脉冲编码调制(PCM,Pulse Coding Modulation)技术。
抽样(Sampling)
抽样是穗斗判把模拟信号以其信号带宽2倍以上的频率提取样值,变为在时间轴上离散的抽样信号的过程。例如,话音信号带宽被限制在0.3~3.4kHz内,用 8kHz的抽样频率(fs),就可获得能取代原来连续话音信号的抽样信号。对一个正弦信号进行抽样获得的抽样信号是一个脉冲幅度调制(PAM)信号,如下图对模拟正弦信号的抽样所示。对抽样信号进行检波和平滑滤波,即可还原出原来的模拟信号。
量化(quantizing)
抽样信号虽然是时间轴上离散的信号,但仍然是模拟信号,其样值在一定的取值范围内,可有无限多个值。显然,对无限个样值一一给出数字码组来对应是不可能的。为了实现以数字码表示样值,必须采用“四舍五入”的方法把样值分级“取整”,使一定取值范围内的样值由无限多个值变为有限个值。这一过程称为量化。
量化后的抽样信号与量化前的抽样信号相比较,当然有所失真,且不再是模拟信号。这种量化失真在接收端还原模拟信号时表现为噪声,并称为量化噪声。量化噪声的大小取决于把样值分级“取整”的方式,分的级数越多,即量化级差或间隔越小,量化噪声也越小。
编码(Coding)
量化后的抽样信号在一定的取值范围内仅有有限个可取的样值,且信号正、负幅度分布的对称性使正、负样值的个数相等,正、负向的量化级对称分布。若将有限个 量化样值的绝对值从小到大依次排列,并对应地依次赋予一个十进制数字代码(例如,赋予样值0的十进制数字代码为0),猜改在码前以“+”、“-”号为前缀,来 区分样值的正、负,则量化后的抽样信号就转化为按抽样时序排列的一串十进制数字码流,即十进制数字信号。简单高效的数据系统是二进制码系统,因此,应将十 进制数字代码变换成二进制编码。根据十进制数字代码的总个数,可以确定所需二进制编码的位数,即字长。这种把量化的抽样信号变换成给定字长的二进制码流的 过程称为编码。
例程:
#include <iostream>using namespace std
int main()
{
const int sect = 8 //number of segement.
const int startingVol[sect+1] = {0,16,32,64,128,256,512,1024,2048}
// the starting value of every segement.
const int quanIntvl[sect] = {1,1,2,4,8,16,32,64}
//quantity interval of every Segments, 1 equeal to 1/2048.
int pcmInd = 0 //pcm code's index.
int pcmCode[sect] = {0,0,0,0,0,0,0,0} // 8 bit of pcm codes.
int sampleValue = 1270
int startPoint //starting point of the segement starting piont
//such as startingVol[startPoint] = 16 or 128 etc.
int finePoint //the starting point of inner segement code.
int quanValue // it's used to store the final quantity value.
int quanError //error caused by quantity.
//the following four variables is used in geting the segmentCode
int low = 0
int high = sect
int mid
int loopInd1 = 0 //loop index to get segment code
int loopInd2 = 0 //loop index to get inner segment codes
//get the first_digit code of polarity
(sampleValue > 0) ? (pcmCode[pcmInd++] = 1) : (pcmCode[pcmInd] = 0)
sampleValue = abs(sampleValue) //make sure the voltage is positive
//get the segment code using modified halve search
while(loopInd1 < 3) //only need 3 loops the segmentCode can be got
{
mid = (low + high)/2
//after 3 loops, sampeValue falls in startingVol[mid] - startingVol[mid] or
//in startingVol[mid-1] - startingVol[mid]
if(sampleValue < startingVol[mid])
{
pcmCode[pcmInd++] = 0
high = mid
startPoint = mid - 1
}
else
{
pcmCode[pcmInd++] = 1
low = mid
startPoint = mid
}
loopInd1++
}//end while
//get the last four bits codes of pcm
low = 0
high = 16 //every segment is split into 16 small segments of the same size
while(loopInd2 < 4)
{
mid = (low + high)/2
//make the compare progress clear using the following two setences.
quanValue = startingVol[startPoint] + mid * quanIntvl[startPoint]
cout<<startingVol[startPoint]<<" + "<<quanIntvl[startPoint]<<" * "<<mid<<" = "
<<quanValue <<" ? "<<sampleValue<<endl
//make the compare progress clear using the above two setences.
if(sampleValue < startingVol[startPoint] + mid * quanIntvl[startPoint])
{
pcmCode[pcmInd++] = 0
high = mid
finePoint = mid -1
}
else
{
pcmCode[pcmInd++] = 1
low = mid
finePoint = mid
}
loopInd2++
}//end while
quanValue = startingVol[startPoint] + finePoint * quanIntvl[startPoint]
quanValue += quanIntvl[startPoint] / 2 //final quantity value.
quanError = abs( sampleValue - quanValue) // error of quantity.
cout<<"Final quantity value is: "<<quanValue<<endl
cout<<"Error of quantity is: "<<quanError<<endl
cout<<"PCM codes are: "
for(int i = 0 i < 8 i++)
{
cout<<pcmCode[i]<<" "
}//end for
cout<<endl
return 0
}
呵宴物呵这个我刚编完,经过老师验收。给你了,用C++写的,你稍做修改就行。#include <iostream>
using namespace std
int main()
{
const int sect = 8 //number of segement.
const int startingVol[sect+1] = {0,16,32,64,128,256,512,1024,2048}
// the starting value of every segement.
const int quanIntvl[sect] = {1,1,2,4,8,16,32,64}
//quantity interval of every Segments, 1 equeal to 1/简乱2048.
int pcmInd = 0//pcm code's index.
int pcmCode[sect] = {0,0,0,0,0,0,0,0} // 8 bit of pcm codes.
int sampleValue = 1270
int startPoint//starting point of the segement starting piont
//such as startingVol[startPoint] = 16 or 128 etc.
int finePoint //the starting point of inner segement code.
int quanValue// it's used to store the final quantity value.
int quanError//error caused by quantity.
//the following four variables is used in geting the segmentCode
int low = 0
int high = sect
int mid
int loopInd1 = 0//loop index to get segment code
int loopInd2 = 0 //loop index to get inner segment codes
//get the first_digit code of polarity
(sampleValue >0) ? (pcmCode[pcmInd++] = 1) : (pcmCode[pcmInd] = 0)
sampleValue = abs(sampleValue) //make sure the voltage is positive
//get the segment code using modified halve search
while(loopInd1 <3) //only need 3 loops the segmentCode can be got
{
mid = (low + high)/拦祥档2
//after 3 loops, sampeValue falls in startingVol[mid] - startingVol[mid] or
//in startingVol[mid-1] - startingVol[mid]
if(sampleValue <startingVol[mid])
{
pcmCode[pcmInd++] = 0
high = mid
startPoint = mid - 1
}
else
{
pcmCode[pcmInd++] = 1
low = mid
startPoint = mid
}
loopInd1++
}//end while
//get the last four bits codes of pcm
low = 0
high = 16 //every segment is split into 16 small segments of the same size
while(loopInd2 <4)
{
mid = (low + high)/2
//make the compare progress clear using the following two setences.
quanValue = startingVol[startPoint] + mid * quanIntvl[startPoint]
cout<<startingVol[startPoint]<<" + "<<quanIntvl[startPoint]<<" * "<<mid<<" = "
<<quanValue <<" ? "<<sampleValue<<endl
//make the compare progress clear using the above two setences.
if(sampleValue <startingVol[startPoint] + mid * quanIntvl[startPoint])
{
pcmCode[pcmInd++] = 0
high = mid
finePoint = mid -1
}
else
{
pcmCode[pcmInd++] = 1
low = mid
finePoint = mid
}
loopInd2++
}//end while
quanValue = startingVol[startPoint] + finePoint * quanIntvl[startPoint]
quanValue += quanIntvl[startPoint] / 2//final quantity value.
quanError = abs( sampleValue - quanValue)// error of quantity.
cout<<"Final quantity value is: "<<quanValue<<endl
cout<<"Error of quantity is: "<<quanError<<endl
cout<<"PCM codes are: "
for(int i = 0i <8i++)
{
cout<<pcmCode[i]<<" "
}//end for
cout<<endl
return 0
}
还有译码你要不要?
这是编码子程序,大概思路是这培源档样的,还需要自己微调。#include<stdio.h>裂斗
#include<math.h>
int main()
{int dataleft=0X0000
scanf("%d",&dataleft)
int b=0 ,lj=0,dl=0,dn=0,pcm=0
if(dataleft<=0)
{dataleft=abs(dataleft)
b=1
}
dataleft>>4
if(dataleft<=15&&dataleft>=0)
{ lj=1
dl=000
dn=(dataleft-0)/lj}
if(dataleft<=31&dataleft>=16)
{ lj=1
dl=001
dn=(dataleft-16)/lj}
if(dataleft<=63&dataleft>=32)
{lj=2
dl=010
dn=(dataleft-32)/lj}
if(dataleft<=127&dataleft>配乱=64)
{ lj=4
dl=011
dn=(dataleft-64)/lj}
if(dataleft<=255&dataleft>=128)
{ lj=8
dl=100
dn=(dataleft-128)/lj}
if(dataleft<=511&dataleft>=256)
{ lj=16
dl=101
dn=(dataleft-256)/lj}
if(dataleft<=1023&dataleft>=512)
{ lj=32
dl=110
dn=(dataleft-512)/lj}
if(dataleft<=2047&dataleft>=1024)
{lj=64
dl=111
dn=(dataleft-1024)/lj}
b=b<<7
dl=dl<<3
pcm=b+dl+dn
printf("%d",pcm)
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)