c语言十三折线法的实现报告,Python + Qt PCM十三折线编码

C语言地址:https://blog.csdn.net/qq_36407771/article/details/88798839

from PCM_Ui import *

from PyQt5.QtWidgets import *

from PyQt5.QtCore import *

from PyQt5.QtGui import *

import sys

import matplotlib.pyplot as plt

import numpy as np

import os

import math

TEMP_PATH = "temp.jpg" #缓冲图像

TIMES = 10 #周期10

SAVE_FILE_NAME = "PCM_Code.txt" #保存文件名字

class PCM(QDialog):

def __init__(self,ui,parent = None):

super().__init__(parent)

self._Qimg = QPixmap() #用于显示图片

self._old_Data = None #原波形

self._new_Data = None #采集得到的波形

self._old_time_s = 0 #周期

self._new_time_s = 0 #周期

self.HZ = 0 #原波形采集频率

self.Signal_HZ = 0 #原波形信号频率

self.process_HZ = 0 #新采集频率

self.__ui = ui #ui界面

self.code = None #PCM编码

self.__scaledImg = None #防止图片过大,缩放后的图片

self.__ui.setupUi(self) #给界面上控件

self.__ui.ImgLabel.setAlignment(Qt.AlignCenter) #设置对其方式:居中对齐

self.__ui.save_btn.setEnabled(False) #设置没有编码不能按保存编码

self.__ui.o_process_btn.clicked.connect(self._o_process) #产生原波形(Sin)

self.__ui.p_process_btn.clicked.connect(self._p_process) #根据采集频率得到新波形

self.__ui.PCM_btn.clicked.connect(self.PCM_Code) #计算新波形的PCM编码

self.__ui.save_btn.clicked.connect(self.saveCode) #保存编码

def _update(self): #更新界面(刷新图片)

self.__showGraph() #对图片的处理

if os.path.exists(TEMP_PATH): #缓存图片

self._Qimg.load(TEMP_PATH) #加载图片

if self._Qimg.size().width() > self.__ui.ImgLabel.size().width() and \

self._Qimg.size().height() > self.__ui.ImgLabel.size().height(): #图片过大则缩放图片

self.__scaledImg = self._Qimg.scaled(self.__ui.ImgLabel.size)

elif self._Qimg.size().width() > self.__ui.ImgLabel.size().width(): #根据宽缩放

self.__scaledImg = self._Qimg.scaledToWidth(self.__ui.ImgLabel.size().width())

elif self._Qimg.size().height() > self.__ui.ImgLabel.size().height(): #根据高缩放

self.__scaledImg = self._Qimg.scaledToHeight(self.__ui.ImgLabel.size().height())

else:

self.__scaledImg = self._Qimg.copy() #复制该图片信息

self.__ui.ImgLabel.setPixmap(self.__scaledImg) #给Label贴上图片

super().update() #调用父类的update函数

def _o_process(self):

try: #判断是否输入的是数字

self.HZ = int(self.__ui.o_setHz.text()) #得到采集频率

self.Signal_HZ = int(self.__ui.o_setSignalHz.text()) #得到信号频率

self._old_time_s = TIMES #周期

self._old_Data = np.sin(np.linspace(0, self.Signal_HZ * self._old_time_s * 2 * np.pi , self.HZ * self._old_time_s)) #产生正弦波

self._update() #刷新显示

except ValueError:

QMessageBox(QMessageBox.Critical,"error type!","Please input with number").exec_() #提醒需要输入数字

return

def _p_process(self):

try:

self.process_HZ = int(self.__ui.p_setHZ.text()) #得到采集频率

if self.process_HZ > self.HZ: #最大只能为该频率

self.process_HZ = self.HZ

self._new_time_s = TIMES #周期

self.__scanWave() #根据原音频信息得到新信息

self._update() #刷新显示

except ValueError:

QMessageBox(QMessageBox.Critical,"error type!","Please input with number").exec_() #提醒需要输入数字

return

def __showGraph(self): #显示波形信息图

plt.clf() #清除原图像

Graphnum = 3 if self._old_time_s != 0 and self._new_time_s != 0 \

else 1 #设置显示图的个数

if self._new_time_s != 0: #得到对应采集频率的横坐标点集合

new_time = np.arange(0,self.process_HZ * self._new_time_s)*(1.0 / self.process_HZ)

if self._old_time_s != 0: #得到对应采集频率的横坐标点集合

old_time = np.arange(0,self.HZ * self._old_time_s)*(1.0 / self.HZ)

if self._old_time_s != 0:

plt.subplot(Graphnum,1,1) #设置图片个数,排版方式

plt.plot(old_time,self._old_Data) #根据两个x,y集合,显示对应的数据

plt.xlabel("Time(s)") #x轴注释

plt.ylabel("Amplitude") #y轴注释

plt.title("original wavedata") #图像注释

if self._new_time_s != 0: #如果存在被采集,显示采集点

plt.scatter(new_time,self._new_Data,color= "black")

plt.grid('on') #标尺,on:有,off:无。

if self._new_time_s != 0:

plt.subplot(Graphnum,1,3) #设置图片个数,排版方式

plt.plot(new_time,self._new_Data) #根据两个x,y集合,显示对应的数据

plt.xlabel("Time(s)") #x轴注释

plt.ylabel("Amplitude") #y轴注释

plt.title("sampled wavedata") #图像注释

plt.grid('on') #标尺,on:有,off:无。

plt.savefig(TEMP_PATH)

def __scanWave(self):

K = self.HZ / self.process_HZ #频率比例

newframes = int(self._old_Data.shape[0] / K) #新采集点个数

self._new_Data = np.zeros((newframes,)) #创建对应的集合

for x in range(newframes):

self._new_Data[x] = self._old_Data[int(x * K)] #在对应的波形数据上获取采集的数据

def saveCode(self):

path = QFileDialog().getSaveFileName(self, "Save File", SAVE_FILE_NAME, "TEXT (*.txt)") #打开保存文件对话框

if len(path[0]) != 0:

f = open(path[0],'w') #打开文件

for x in self.code:

f.write(str(x.tostring())) #按行写入文件(字节)

f.close() #关闭文件

def PCM_Code(self):

if self._new_time_s == 0: #如果没有采集,提示采集

QMessageBox(QMessageBox.Information,"no data","Please sample the original waveform!").exec_()

return

self.changeCode() #十三折线换算

self.toPCM_Code() #转换为PCM编码

self.__ui.save_btn.setEnabled(True)

def changeCode(self):

self.code = np.zeros((self._new_Data.shape[0],))

for i,x in enumerate(self._new_Data):

f = 1 if x>= 0 else -1

d = abs(x)

y = 0

""" 十三折线换算法"""

if d>=0 and d<0.015625:

y=16*d

elif d>=0.015625 and d<0.03125:

y=d*8+0.125

elif d>=0.03125 and d<0.0625:

y=4*d+0.25

elif d>=0.0625 and d<0.125:

y=2*d+0.375

elif d>=0.125 and d<0.25:

y=d+0.5

elif d>=0.25 and d<0.5:

y=0.5*d+5/8.00

elif d>=0.5 and d<=1:

y=0.25*d+3/4.00

self.code[i] = y * f #存储换算后的值

def toPCM_Code(self):

z = [0,16,32,64,128,256,512,1024] #对应量化区间

y = [1,1,2,4,8,16,32,64] #每个量化区间按16等分后的每一小段量化等级

code_list = [] #存储PCM编码

for i,x in enumerate(self._new_Data):

g = x * 2048 #2048个量化等级

e = math.floor(g) #低位取整

code = np.zeros((8,),dtype=int) #存储编码

if e < 0: #符号位判断,小于0第一位码为0,大于0第一位码为1

code[0] = 0

e = abs(e)

else:

code[0] = 1

if e > 128: #段落码第一位判断

code[1] = 1

if e <= 32 or (e>=128 and e<= 512): #段落码第二位判断

code[2] = 0

else:

code[2] = 1

if (e>=16 and e<32) or (e>=64 and e< 128) or(e>=256 and e<=512) or e>=1024:

code[3] = 1 #段落码第三位判断

h = code[1] * 4 + code[2] * 2 + code[3] #根据段落码算出在第几段

k = int((e - z[h]) / y[h]) #算出在段内第几段

if k == 0: #输入为0,输出也为0

code[4],code[5],code[6],code[7] = 0,0,0,0

else:

num = 7 #从高位开始编码

while(k>0):

code[num] = k%2 #取余编码

num -= 1

k = int(k/2) #0

9d396d309894cfbc16ba3508de30c811.png

代码+UI

链接:https://pan.baidu.com/s/17GtG9b5OEtczVnoR0s1SHA

提取码:65np

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值