当前位置: 首页 > article >正文

PyQt实战——将pcm文本数据转换成.pcm的二进制文件

系类往期文章:
PyQt5实战——多脚本集合包,前言与环境配置(一)
PyQt5实战——多脚本集合包,UI以及工程布局(二)
PyQt5实战——多脚本集合包,程序入口QMainWindow(三)
PyQt5实战——操作台打印重定向,主界面以及stacklayout使用(四)
PyQt5实战——UTF-8编码器UI页面设计以及按钮连接(五)
PyQt5实战——UTF-8编码器功能的实现(六)
PyQt5实战——翻译器的UI页面设计以及代码实现(七)
PyQt5实战——翻译的实现,第一次爬取微软翻译经验总结(八)
PyQt5实战——翻译的实现,成功爬取微软翻译(可长期使用)经验总结(九)
PyQt实战——使用python提取JSON数据(十)
PyQt实战——随机涂格子的特色进度条(十一)
PyQt实战——实现编码器与进度条之间的通信,使进度条反映编码进度(十二)
PyQt实战——实现可视化音频播放器(十三)

前言

在我们上两个功能模块中,音频编解码模块与音频播放模块,都在操作音频数据,在音频数据解码后生成的pcm数据以文本格式保存,无法直接给音频播放模块播放,因此在本文中,我们将实现pcm二进制文件生成模块,将pcm数据文本转换成.pcm格式的二进制文件

UI布局展示

非常简单,仅一个文件选择区以及一个处理按钮,选择相应的pcm数据文本,开始执行即可转换为.pcm格式二进制文件

请添加图片描述

代码展示

PcmBUilderClass.py

下面给出UI界面代码

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtSvg import *

from component.btnStyle import *
from component.editStyle import *
from component.getPath import *
from tools.pcmBuilder import *

class WPcmBuilder(QWidget):
    def __init__(self):
        super().__init__()
        self.filePaths = ['']
        self.initUI()
        
    def initUI(self):
        self.pcmBuildlayout = QVBoxLayout()
        self.setLayout(self.pcmBuildlayout)
        # 文件选择
        self.filelayout = QHBoxLayout()
        self.lable = QLabel("请选择文件",self)
        self.filelayout.addWidget(self.lable)
        self.input = QLineEdit(self)
        LineEditStyle(self.input)
        self.filelayout.addWidget(self.input)
        self.choosebtn = QPushButton("选择文件",self)
        btnReleaseStyleA(self.choosebtn)
        self.choosebtn.clicked.connect(self.getpath)
        self.filelayout.addWidget(self.choosebtn)
        self.pcmBuildlayout.addLayout(self.filelayout)
        
        # 开始处理
        self.exebtn = QPushButton("开始处理",self)
        btnReleaseStyleA(self.exebtn)
        self.exebtn.clicked.connect(self.exebtn_press_clicked)
        self.pcmBuildlayout.addWidget(self.exebtn)
        


    def getpath(self):
        get_path(self)
        self.input.setText(self.filePaths[0])
    
    def exebtn_press_clicked(self):
        pcmBuilder(self.filePaths[0])

pcmBuilder.py

下面给出pcm格式转换脚本

import struct

def pcmBuilder(filepath):
    samples = []
    with open(filepath, 'r') as file:
        lines = file.readlines()
        for line in lines:
            samples = samples + [int(data.strip(),16) - 0x10000 if int(data.strip(),16) >= 0x8000 else int(data.strip(),16) for data in line.split()]
            # print(samples)
            
    with open('workspaces/output.pcm', 'wb') as pcm_file:
        for sample in samples:
            pcm_file.write(struct.pack('<h', sample))
    print("转换完成,输出文件为 output.pcm") 

这里我们解释一下:

int(data.strip(),16) - 0x10000 if int(data.strip(),16) >= 0x8000 else int(data.strip(),16) for data in line.split()

这行代码的作用是处理一行十六进制数据,并根据一定的条件将其转换为整数列表。下面我将逐步解析代码。

  • line.split(): 这将字符串 line 按照空格(包括空格、制表符、换行符等)分割成一个字符串列表,每个元素代表一个十六进制数字。
  • data.strip(): 这会去掉每个 data 子字符串的前后空白字符。
  • int(data.strip(), 16): 这会将处理过的 data 字符串从十六进制(基数 16)转换成整数。例如,'FF' 会转换为 255'8000' 会转换为 32768
  • 条件逻辑:
    • if int(data.strip(), 16) >= 0x8000: 这检查该十六进制数(转换成整数后)是否大于等于0x8000(即 32768 十进制)。
      • 如果 ,则会减去 0x10000(即 65536 十进制)。这通常用于将 16 位无符号数转换为有符号数,表示范围从 -3276832767(假设是 16 位二进制补码格式)。
      • 如果 ,则直接使用该整数值。
  • samples = samples + [...]: 这表示将处理后的结果(即这行数据的整数列表)添加到现有的 samples 列表中。
示例

假设 line 是如下的内容:

pythonCopy Codeline = "7FFF 8000 0001"
逐步处理
  1. 第一个元素:'7FFF'
    • data.strip() -> '7FFF'
    • int('7FFF', 16) -> 32767(十进制)
    • 因为 32767 < 32768,没有修改,保持 32767
  2. 第二个元素:'8000'
    • data.strip() -> '8000'
    • int('8000', 16) -> 32768(十进制)
    • 因为32768 >= 32768,需要减去0x10000(65536):
      • 32768 - 65536 -> -32768
  3. 第三个元素:'0001'
    • data.strip() -> '0001'
    • int('0001', 16) -> 1(十进制)
    • 因为 1 < 32768,保持 1
最终列表

经过处理后,samples 列表将会是:

samples = [32767, -32768, 1]

这段代码的作用是读取十六进制数字,并根据需要将其转换为有符号的 16 位整数(如果需要的话)。如果十六进制数大于或等于 0x8000,它会被视为一个负数(通过二进制补码表示)。然后,这些处理后的数字会被添加到 samples 列表中。


http://www.kler.cn/a/463202.html

相关文章:

  • Appium 2.0:移动自动化测试的革新之旅
  • 第二十六天 RNN在NLP中的应用
  • UE5.3 虚幻引擎 Windows插件开发打包(带源码插件打包、无源码插件打包)
  • xilinx的高速接口构成原理和连接结构及ibert工具的使用-以k7 GTX为例
  • Rust 泛型、特征与生命周期详解
  • 原子类及原理和ABA问题解决
  • 关于自回归模型的一份介绍
  • 概率论期末考题类型
  • vue3+TS+vite中Echarts的安装与使用
  • Python视频解码库DeFFcode使用指南
  • 数势科技:解锁数据分析 Agent 的智能密码(14/30)
  • hadoop-common的下载位置分享
  • 【2024年-12月-11日-开源社区openEuler实践记录】深度探秘 libkperf:解锁系统性能剖析的开源宝藏
  • PyTorch快速入门教程【小土堆】之非线性激活
  • LoxodonFramework实现Lua侧绑定UI元素的原理
  • BOSS直聘招聘数据分析的第一步:用Python进行深度清洗
  • 中科汉玉-舆情感知,品牌声誉管理,政企舆情大数据服务平台
  • Django Settings 优化与常用配置指南
  • 安卓入门一 Java基础
  • 7.傅里叶级数练习题
  • ARM公司
  • 二叉树的实现
  • Redis 5设计与源码分析读书笔记
  • 刷机TP TP-Link-WDR5660【持续更新】
  • 常用的公共 NTP(网络时间协议)服务器
  • Java 开发中的指定外部 Jar 路径详解