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

Python + Qt PCM十三折线编码_第1张图片

代码+UI

链接:https://pan.baidu.com/s/17GtG9b5OEtczVnoR0s1SHA 
提取码:65np 

你可能感兴趣的:(PCM,PCM,Python,Qt)