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界面代码

python 复制代码
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格式转换脚本

python 复制代码
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 列表将会是:

python 复制代码
samples = [32767, -32768, 1]

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

相关推荐
喵手3 分钟前
Python爬虫实战:容器化与定时调度实战 - Docker + Cron + 日志轮转 + 失败重试完整方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·容器化·零基础python爬虫教学·csv导出·定时调度
2601_9491465323 分钟前
Python语音通知接口接入教程:开发者快速集成AI语音API的脚本实现
人工智能·python·语音识别
寻梦csdn44 分钟前
pycharm+miniconda兼容问题
ide·python·pycharm·conda
Java面试题总结2 小时前
基于 Java 的 PDF 文本水印实现方案(iText7 示例)
java·python·pdf
不懒不懒2 小时前
【决策树算法实战指南:从原理到Python实现】
python·决策树·id3·c4.5·catr
马猴烧酒.2 小时前
【面试八股|Java集合】Java集合常考面试题详解
java·开发语言·python·面试·八股
天空属于哈夫克32 小时前
Java 版:利用外部群 API 实现自动“技术开课”倒计时提醒
数据库·python·mysql
喵手2 小时前
Python爬虫实战:全站 Sitemap 自动发现 - 解析 sitemap.xml → 自动生成抓取队列的工业级实现!
爬虫·python·爬虫实战·零基础python爬虫教学·sitemap·解析sitemap.xml·自动生成抓取队列实现
luoluoal2 小时前
基于深度学习的web端多格式纠错系统(源码+文档)
python·mysql·django·毕业设计·源码
深蓝海拓2 小时前
PySide6从0开始学习的笔记(二十七) 日志管理
笔记·python·学习·pyqt