语音信号PCM编译码 MATLAB程序

语音信号PCM编译码 MATLAB程序,第1张

% clc

% clear all

% 产生信号

load handel

x=y(1:20000)%取前20000个采样点

sound(x,Fs)

%PCM编码

x1=x/0.8.*2048

yy=pcm_encode(x1)

figure

subplot(2,1,1)

stem(yy(1:80),'.')

title('PCM编码后的波形')

%加噪声

snr=10

sp=mean(yy.^2)

attn=sp./ 10^(snr/10)

attn = sqrt(attn)

noise=randn(1,length(yy)).*attn

np=mean(noise.^2)

snr1=10*log10(sp/np)

data=yy+noise

% data=yy%不加噪声

subplot(2,1,2)

stem(data(1:80),'.r')

title('PCM加噪声后波形')

%译码

demodata=data>0.5

zz=pcm_decode(demodata,0.8)

figure

subplot(2,1,1)

plot(x)

title('原始语音信号')

subplot(2,1,2)

plot(zz)

title('译码后的语音信号')

sound(zz,Fs)

figure

plot(x,'b')

hold on

plot(zz,'r')

legend('编译码前的语音信号','编译码后的语音信号')

title('编,译码前后的语音信号')

function y = pcm_encode( x )

y=zeros(length(x),8) %存储矩阵(全零)

z=sign(x) %判断x的正负

x=abs(x)%取绝对值

%%段落码判断段区间的取值范围为前开后闭区间

for k=1:length(x)

%符号位的判断

if z(k)>0

y(k,1)=1

elseif z(k)<0

y(k,1)=0

end

if x(k)>128 &x(k)<=2048 %在第五段与第八段之间,段位码第一位都为“1”

y(k,2)=1

end

if (x(k)>32 &x(k)<=128) || (x(k)>512 &x(k)<=2048)

y(k,3)=1 %在第三四七八段内,段位码第二位为“1”

end

if (x(k)>16&x(k)<=32)||(x(k)>64&x(k)<=128)||(x(k)>256&x(k)<=512)||(x(k)>1024&x(k)<=2048)

y(k,4)=1 %在二四六八段内,段位码第三位为“1”

end

end

%段内码判断程序

N=zeros(1,length(x))

for k=1:length(x)

N(k)=y(k,2)*4+y(k,3)*2+y(k,4)+1 %找到x位于第几段

end

a=[0,16,32,64,128,256,512,1024] %量化间隔

b=[1,1,2,4,8,16,32,64]%除以16,得到每段的最小量化间隔

for m=1:length(x)

q=ceil((x(m)-a(N(m)))/b(N(m))) %求出在段内的位置

if q==0

y(m,(5:8))=[0,0,0,0] %如果输入为零则输出“0”

else k=num2str(dec2bin(q-1,4)) %编码段内码为二进制

y(m,5)=str2num(k(1))

y(m,6)=str2num(k(2))

y(m,7)=str2num(k(3))

y(m,8)=str2num(k(4))

end

end

%将N行8列矩阵转换为1行8*N列的矩阵

y=y'

y=reshape(y,1,length(x)*8)

end

function x=pcm_decode(y,max)

%将1行8*N列的矩阵转换为N行8列矩阵

y=reshape(y,8,length(y)/8)

y=y'

%PCM译码

n=size(y,1) %求出输入码组的个数

a=[0,16,32,64,128,256,512,1024] %段落起点值

b=[1,1,2,4,8,16,32,64] %每段的最小量化间隔

for k=1:n

t1=y(k,1)%取符号

t2=y(k,2)*4+y(k,3)*2+y(k,4)+1%判断段落位置

t3=y(k,5)*8+y(k,6)*4+y(k,7)*2+y(k,8) %判断段内位置

if t3==0 %段内码为零时

m(k)=(a(t2)+1+0.5*b(t2))/2048*max

else

m(k)=(a(t2)+b(t2)*t3+0.5*b(t2))/2048*max%还原出量化后的电平值

end

%判断符号位

if t1==0

x(k)=-m(k)

else

x(k)=m(k)

end

end

end

脉冲编码调制(Pulse Code Modulation,简称PCM)是一种概念简单、理论完善的编码系统,其最大特征是把连续的输入信号变换成在时间和振幅上都是离散量,然后再变换为代码传输。信息为数字信号,在远距离再生中继传输中不积累噪声,从而提高了通信系统的有效性、可靠性和保密性。利用现场可编程门阵列(FPGA)和VHDL 语言实现了PCM码的解调,这样在不改变硬件电路的情况下,能够适应PCM码传输速率和帧结构变化,从而正确解调数据。

如果你的mac的参数样式和我的是一样的话,那么执行上面的命令,应该就能正常播放了之前录制的pcm,如果不是的话,需要你对照自己的mac参数来进行相关处理

在之前执行ffmpeg的时候,已经安装了SDL,安装目录位于/usr/local/Cellar/sdl2

安装ffmpeg

如果没有安装这个目录,可以执行brew install sdl2

MainWindow::MainWindow(QWidget *parent)

: QMainWindow(parent)

, ui(new Ui::MainWindow)

{

ui->setupUi(this)

}

MainWindow::~MainWindow()

{

delete ui

}

void showVersion() {

SDL_version version

SDL_VERSION(&version)

qDebug() <<version.major <<version.minor <<version.patch

}

void MainWindow::on_playButton_clicked()

{

if (_playThread) { // 停止播放

_playThread->requestInterruption()

_playThread = nullptr

ui->playButton->setText("开始播放")

} else { // 开始播放

_playThread = new PlayThread(this)

_playThread->start()

// 监听线程的结束

connect(_playThread, &PlayThread::finished,

this {

_playThread = nullptr

ui->playButton->setText("开始播放")

})

ui->playButton->setText("停止播放")

}

}

···

然后Run程序,就可以发现成功播放了pcm文件


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7745186.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-09
下一篇 2023-04-09

发表评论

登录后才能评论

评论列表(0条)

保存