UOS Python+Qt5实现声卡回路测试

2024-01-12 13:44

本文主要是介绍UOS Python+Qt5实现声卡回路测试,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.回路治具设计:

2.Ui界面:

3.源代码:

# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'SoundTestWinFrm.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.import json
import configparser
import subprocess
import sys
import os
import logging
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QFrame
from PyQt5.QtWidgets import QApplication, QListWidget, QListWidgetItem
from PyQt5.QtGui import QColor
from datetime import datetime
#from subprocess import Popen
import pyaudio
#import wave
import librosa #pip install pyaudio librosa
import numpy as np
import threading
import glob
from PyQt5.QtCore import QTimer, pyqtSignal
#import pygame #pip install pygame
#import alsaaudio #pip install pyalsaaudio pip install pyalsaaudio
#sudo apt-get install portaudio19-dev
#pip install pyaudio librosa
#import pulsectl #pip install pulsectl
#apt-get install soxclass AnalysisThread(QtCore.QThread):def __init__(self, filename,type, parent=None):super(AnalysisThread, self).__init__(parent)self.filename = filenameself.type=typeself.is_running = Truedef run(self):while self.is_running:# 在这里执行音频分析self.parent().AnalysisSoundFile_Frequency(self.filename,self.type)self.parent().standard_frequency=int(self.parent().AnalysisSound_FrequencySample)#标准的频响self.stop()def stop(self):self.is_running = False # 或者使用更安全的停止逻辑class RecordPlayThread(QtCore.QThread):finished_signal = QtCore.pyqtSignal()  # 添加完成信号set_default_output_device_signal = QtCore.pyqtSignal(str)set_default_input_device_signal = QtCore.pyqtSignal(str)#analysisSoundFile_Frequency_signal=QtCore.pyqtSignal(str)def __init__(self,output_filename,input_filename,duration_seconds,indevice_name,outdevice_name, parent=None):super(RecordPlayThread, self).__init__(parent)self.output_filename=output_filenameself.input_filename=input_filenameself.duration_seconds=duration_secondsself.indevice_name=indevice_nameself.outdevice_name=outdevice_name# 初始化其他变量if parent is not None:self.set_default_output_device_signal.connect(parent.set_default_output_device)self.set_default_input_device_signal.connect(parent.set_default_input_device)#self.analysisSoundFile_Frequency_signal.connect(parent.AnalysisSoundFile_Frequency)self.is_running = Truedef run(self):while self.is_running:# 执行录放音代码,确保在循环中频繁检查 self.is_running#执行设置默认音频设备并同步录放音# 发出信号而不是直接调用方法self.set_default_output_device_signal.emit(self.outdevice_name)self.set_default_input_device_signal.emit(self.indevice_name)# 录音线程record_thread = threading.Thread(target=self.parent().rec_record_audio, args=(self.input_filename, 2))# 播放线程play_thread = threading.Thread(target=self.parent().play_audio_for_duration, args=(self.output_filename, 2))# 启动线程record_thread.start()play_thread.start()# 等待线程完成record_thread.join()play_thread.join()#self.analysisSoundFile_Frequency_signal.emit(self.input_filename,1)self.parent().AnalysisSoundFile_Frequency(self.input_filename,1)#解析声响if self.parent().standard_frequency>=self.parent().AnalysisSound_FrequencySample-1 and \self.parent().standard_frequency<=self.parent().AnalysisSound_FrequencySample+1:self.parent().tempTestPassItem+=2#测试接口两个self.finished_signal.emit()  # 线程完成时发射信号self.stop()def stop(self):self.is_running = False  # 或者使用更安全的停止逻辑class Ui_Form(QWidget):updateTimer = pyqtSignal(bool)  # 定义一个信号def __init__(self):super().__init__()# ... 现有的初始化代码 ...self.analysis_threads = []  # 存储所有的 AnalysisThread 实例self.record_play_threads = []  # 存储所有的 RecordPlayThread 实例# 设置环境变量os.environ["XDG_RUNTIME_DIR"] = "/run/user/{}".format(os.getuid())self.config = configparser.ConfigParser()  # 创建对象self.itemName=''#项目名称self.itemFailSleepExit = 0  # 项目Fail延时退出self.testArgs = []  # 测试参数信息self.soundFile=[]#音频文件self.AnalysisSound_FrequencySample=0#解析的音频频率标准值self.Device_1AnalysisSound_Frequency=0#硬件设备1解析音频频率值self.Device_2AnalysisSound_Frequency=0#硬件设备2解析音频频率值self.output_devices=[]#输出音频设备名称self.input_devices=[]#输入音频设备名称self.in_output_devices=[]#输入输出设备名称self.readTestAudioDevice=[]#读取测试音频设备self.allAudioDeviceTestPass=[]#所有音频测试PASS设备self.front_Device=Falseself.rear_Device=Falseself.currentTestPort='front'#默认为前置self.testPortCount=0#测试端口总数self.ReadPortCount=0#读取的端口数self.standard_frequency=0#标准的频率self.tempTestPassItem=0#临时测试PASS项self.testPassItem=0#最终测试PASS项self.tempDeviceData=[]#临时的硬件信息self.testStandardArgs=''#测试标准参数# 生成日志信息self.logger = logging.getLogger('my_logger')  # 步骤1 创建日志记录器self.logger.setLevel(logging.DEBUG)  # 步骤2 将指定日志级别self.file_handler = logging.FileHandler('./log/log.txt')  # 步骤3 创建文件处理器self.formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')  # 步骤4 创建格式化器self.file_handler.setFormatter(self.formatter)  # 步骤4 将格式化器添加到处理器self.logger.addHandler(self.file_handler)  # 步骤5 将处理器添加到日志记录器# 读取配置self.config.read('./Conf/config.conf', encoding='utf-8')  # 读取配置文件,如果配置文件不存在则创建# 读取测试配置self.itemName = self.config.get('TestItemNameArrays', 'SoundTestName')self.itemFailSleepExit = int(self.config.get('TestItemWinFrmSleepExit', 'SoundTestName'))  # 项目测试Fail延时退出self.testArgs = self.ReadJsonInfo('./Conf/TestArgs.json')  # 读取测试参数信息self.disable_hdmi_audio()  # 禁用HDMI#读取标准值if self.ReadJsonTestArgs(self.itemName)==True:self.ReadPortCount=int(self.testStandardArgs)#读取测试参数#读取音频文件self.soundFile.append('./'+self.config.get('SoundHd','F_L'))#高音左声道self.soundFile.append('./'+self.config.get('SoundHd','F_R'))#高音左声道self.soundFile.append('./'+self.config.get('SoundHd','M_L'))#中音左声道self.soundFile.append('./'+self.config.get('SoundHd','M_R'))#中音右声道self.soundFile.append('./'+self.config.get('SoundHd','S_L'))#低音左声道self.soundFile.append('./'+self.config.get('SoundHd','S_R'))#低音右声道self.soundFile.append('./'+self.config.get('SoundHd', 'Audio'))  # 低音右声道self.setupUi()if self.GetTestPortCount()==True:self.InfoListAddData(f'读取音频:{str(self.testPortCount)}.个端口-实际配置端口:{self.ReadPortCount}', 1)self.lbl_MesInfo.setText('标准音频文件频率解析中...')self.delete_wav_files('.')#删除目录生成的所有音频文件#self.list_audio_devices()#列出所有音频输入设备#self.list_record_devices()#列出所有音频输出设备#解析声响频率self.start_analysis_threads()#读取音频设备#self.list_audio_devices_list()# 获取音频设备名称# 获取音频输出和输入设备名称#self.RecordPlay_analysis_threads()#自动测试音频#解析躁声#self.AnalysisSoundFile_Noise(self.soundFile[6])#self.AnalysisSoundFile_Noise(self.soundFile[3])#self.AnalysisSoundFile_Noise(self.soundFile[2])# 创建一个定时器来检查视频是否播放结束self.timer_1 = QTimer(self)self.timer_1.setInterval(1000)  # 每秒检查一次self.timer_1.timeout.connect(self.check_Test)self.timer_1.start()# 连接信号到槽self.updateTimer.connect(self.handleTimer)else:self.InfoListAddData(f'读取音频:{str(self.testPortCount)}.个端口-实际配置端口:{self.ReadPortCount}', 3)# 定义触发器def handleTimer(self, start):if start:self.timer_1.start()else:self.timer_1.stop()#校验是否完成测试def check_Test(self):try:if self.testPassItem>=int(self.ReadPortCount):#判断是否PASSself.UpdateJsonTestArgs(self.itemName,'PASS')sys.exit(0)else:self.updateTimer.emit(False)  # 发射信号以停止定时器self.RecordPlay_analysis_threads()except Exception as e:self.ShowLog(f"check_Test Err:{e}", False)self.InfoListAddData(f"check_Test Err:{str(e)}",3)return False# 检测当前测试设备并进行判断def DetectsTheCurrentTestDevice(self):try:#运行命令并获取输出process=subprocess.Popen('pactl list cards | grep "available"',stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True, encoding='utf-8')#逐行读取输出self.readTestAudioDevice.clear()#清空列表while True:output=process.stdout.readline()if output=='' and process.poll() is not None:breakif  output not in self.readTestAudioDevice:if 'hdmi' not in output.lower() and 'not available' not in output.lower() and 'input-linein' not in output.lower():portinfo = output.strip()[:output.find(':')]if self.front_Device==True:#前置音频测试PASSif 'front' in portinfo.lower():return Falseelse:self.readTestAudioDevice.append(portinfo)elif self.rear_Device==True:#后置音频测试PASSif 'rear' in portinfo.lower():return Falseelse:self.readTestAudioDevice.append(portinfo)else:self.readTestAudioDevice.append(portinfo)if 'rear' in str(self.readTestAudioDevice) and len(self.readTestAudioDevice)==2:#判断当前为后置接口print('rear',len(self.readTestAudioDevice))self.currentTestPort = 'rear'self.label_2.setStyleSheet('')  # 前置端口背景颜色设置为默认透明self.label_3.setStyleSheet("background-color: lightgreen;")  # 后置端口背景色设置为浅绿色self.lbl_MesInfo.setText('后置音频接口测试')return Trueelif 'front' in str(self.readTestAudioDevice) and len(self.readTestAudioDevice)==2:#判断当前为前置接口print('front', len(self.readTestAudioDevice))self.currentTestPort = 'front'self.label_2.setStyleSheet('background-color: lightgreen;')  # 前置端口背景颜色设置为浅绿色self.label_3.setStyleSheet("")  # 后置端口背景色设置默认透明self.lbl_MesInfo.setText('前置音频接口测试')return Truereturn Falseexcept Exception as e:self.ShowLog(f"DetectsTheCurrentTestDevice Err:{e}", False)self.InfoListAddData(f"DetectsTheCurrentTestDevice Err:{str(e)}",3)return False#获取当前产测试端口测试def GetTestPortCount(self):try:# 运行命令并获取输出process = subprocess.Popen('pactl list cards | grep "available"', stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True, encoding='utf-8')# 逐行读取输出while True:output=process.stdout.readline()if output=='' and process.poll() is not None:breakif  'hdmi' not in output.lower():self.testPortCount+=1#print(self.ReadPortCount,self.testPortCount)if int(self.ReadPortCount)==self.testPortCount:return Trueelse:return Falseexcept Exception as e:self.ShowLog(f"GetTestPortCount Err:{e}", False)self.InfoListAddData(f"GetTestPortCount Err:{str(e)}",3)return False# 启动多线程def RecordPlay_analysis_threads(self):try:self.lbl_MesInfo.setText('音频接口检测中...')# 创建多个线程self.threads = []if self.DetectsTheCurrentTestDevice() == True:#判断当前设置是否接入有效,确认是前置还是后置#if self.get_audio_devices()==True:#获取音频输入输出端口信息self.lbl_MesInfo.setText('获取音频端口信息..')self.AnalysisSound_FrequencySample=0  # 清空高音信息self.evice_1AnalysisSound_Frequency=0  # 清空中音信息self.Device_2AnalysisSound_Frequency=0  # 清空低音信息self.tempTestPassItem=0if self.get_audio_devices() == True:  # 获取音频输入输出端口信息#if self.DetectsTheCurrentTestDevice() == True:x=0y=0if len(self.output_devices)>1:x=1if len(self.input_devices)>1:y=1if self.currentTestPort=='front':#前置测试thread = RecordPlayThread(self.soundFile[6], 'sample_1.wav', 2, self.input_devices[y],self.output_devices[x], self)  # 注意这里传递了 self 作为 parentthread.finished_signal.connect(self.on_thread_finished)  # 连接信号self.threads.append(thread)self.record_play_threads.append(thread)thread.start()elif self.currentTestPort=='rear':#后置测试thread = RecordPlayThread(self.soundFile[6], 'sample_1.wav', 2, self.input_devices[y],self.output_devices[x], self)  # 注意这里传递了 self 作为 parentthread.finished_signal.connect(self.on_thread_finished)  # 连接信号self.threads.append(thread)self.record_play_threads.append(thread)thread.start()else:self.updateTimer.emit(True)  # 启动时钟else:self.updateTimer.emit(True)  # 启动时钟except Exception as e:self.ShowLog(f"RecordPlay_analysis_threads Err:{e}", False)self.InfoListAddData(f"RecordPlay_analysis_threads Err:{str(e)}", 3)return False# 检查所有线程是否完成def on_thread_finished(self):if all(not thread.isRunning() for thread in self.threads):self.handle_all_threads_finished()# 所有线程完成后执行的代码def handle_all_threads_finished(self):if self.currentTestPort == 'front' and self.tempTestPassItem == 2:  # 前置测试self.testPassItem += 2self.front_Device = Trueself.InfoListAddData(f'测试完成的音频接口信息:inputPort-{self.input_devices[0]},outputPort-{self.output_devices[0]}',1)self.InfoListAddData(f'当前测试PASS音频:{self.testPassItem}.个端口', 2)self.lbl_Front_Out_Port.setText('PASS')self.lbl_Front_In_Port.setText('PASS')self.lbl_Front_Out_Port.setStyleSheet('color:green;')self.lbl_Front_In_Port.setStyleSheet('color:green;')elif self.currentTestPort == 'rear' and self.tempTestPassItem >= 2:  # 后置self.testPassItem += 3self.rear_Device = Trueself.InfoListAddData(f'测试完成的音频接口信息:inputPort-{self.input_devices[0]},outputPort-{self.output_devices[0]}', 1)self.InfoListAddData(f'当前测试PASS音频:{self.testPassItem}.个端口', 2)self.lbl_Rear_Out_Port.setText('PASS')self.lbl_Rear_In_Port.setText('PASS')self.lbl_Rear_Out_Port.setStyleSheet('color:green;')self.lbl_Rear_In_Port.setStyleSheet('color:green;')else:if self.currentTestPort == 'front':self.lbl_Front_Out_Port.setText('FAIL')self.lbl_Front_In_Port.setText('FAIL')self.lbl_Front_Out_Port.setStyleSheet('color:red;')self.lbl_Front_In_Port.setStyleSheet('color:red;')else:self.lbl_Rear_Out_Port.setText('FAIL')self.lbl_Rear_In_Port.setText('FAIL')self.lbl_Rear_Out_Port.setStyleSheet('color:red;')self.lbl_Rear_In_Port.setStyleSheet('color:red;')self.updateTimer.emit(True)  # 启动时钟# rec音频录制def rec_record_audio(self,output_filename, duration_seconds):try:# 调用rec命令录制音频# 检查文件是否存在if os.path.exists(output_filename):# 删除文件os.remove(output_filename)self.InfoListAddData(f'音频录入--------------{output_filename}',1)subprocess.run(['rec', output_filename,'trim','0', str(duration_seconds)], check=True)print(f"Audio recorded to {output_filename}")except subprocess.CalledProcessError as e:print(f"Error recording audio: {e}")#play 音频播放def play_audio_for_duration(self,input_filename, duration_seconds):try:# 使用play命令和trim效果播放特定时长的音频self.InfoListAddData(f'音频播放--------------{input_filename}', 1)subprocess.run(['play', input_filename, 'trim', '0', str(duration_seconds)], check=True)print(f"Played {duration_seconds} seconds of {input_filename}")except subprocess.CalledProcessError as e:print(f"Error playing audio: {e}")#获取接入音频装置名称def get_audio_devices(self,exclude_keyword='hdmi'):try:#self.tempDeviceData.clear()#清空临时数据self.input_devices.clear()#清空临时数据self.output_devices.clear()#清空临时数据# 获取输出设备result_sinks = subprocess.run(['pactl', 'list', 'short', 'sinks'], capture_output=True, text=True,check=True)# 获取输入设备result_sources = subprocess.run(['pactl', 'list', 'short', 'sources'], capture_output=True, text=True,check=True)# 解析输出和输入设备名称def parse_device_names(self,output,portType):device_names = []#print(output.split('\n'))for line in output.split('\n'):parts = line.split('\t')if len(parts) > 1:device_name = parts[1]# 排除指定关键词(如HDMI)的设备cle#if device_name not in self.in_output_devices:if exclude_keyword.lower() not in device_name.lower():if 'sources' in portType.lower():#输入if 'input' in device_name.lower():device_names.append(device_name)elif 'sources' not in portType.lower():#输出device_names.append(device_name)return device_namesself.output_devices = parse_device_names(self,result_sinks.stdout,'output')self.input_devices = parse_device_names(self,result_sources.stdout,'input')#判断当前输入设备为前置|后置print('self.currentTestPort=',self.currentTestPort,'\nself.output_devices=',self.output_devices,'\nself.output_devices=',self.input_devices)if self.currentTestPort=='front' and len(self.output_devices)>0 and len(self.input_devices)>0:#判断前置return Trueelif self.currentTestPort=='rear' and len(self.output_devices)>0 and len(self.input_devices)>1:#判断后置return True#self.InfoListAddData(f'音频输出端口信息:{self.output_devices}', 1)#self.InfoListAddData(f'音频输入端口信息:{self.input_devices}', 1)else:return Falseexcept subprocess.CalledProcessError as e:print(f"Error: {e}")return False#禁用HDMI音频输出def disable_hdmi_audio(self):try:# 获取所有 sinks 的列表result = subprocess.run(['pactl', 'list', 'short', 'sinks'], capture_output=True, text=True, check=True)lines = result.stdout.split('\n')# 查找 HDMI 设备hdmi_sink = Nonefor line in lines:if 'hdmi' in line.lower():hdmi_sink = line.split('\t')[1]break# 禁用找到的 HDMI 设备if hdmi_sink:subprocess.run(['pactl', 'set-sink-mute', hdmi_sink, '1'], check=True)print("HDMI audio output has been disabled.")else:print("No HDMI audio output found.")except subprocess.CalledProcessError as e:print(f"Error disabling HDMI audio output: {e}")#启动HDMI音频输出def enable_hdmi_audio(self):try:# 获取所有 sinks 的列表result = subprocess.run(['pactl', 'list', 'short', 'sinks'], capture_output=True, text=True, check=True)lines = result.stdout.split('\n')# 查找 HDMI 设备hdmi_sink = Nonefor line in lines:if 'hdmi' in line.lower():hdmi_sink = line.split('\t')[1]break# 启动找到的 HDMI 设备if hdmi_sink:subprocess.run(['pactl', 'set-sink-mute', hdmi_sink, '0'], check=True)print("HDMI audio output has been enabled.")else:print("No HDMI audio output found.")except subprocess.CalledProcessError as e:print(f"Error disabling HDMI audio output: {e}")#设置为默认output音频设备def set_default_output_device(self,device_name):try:# 设置默认的输出设备subprocess.run(['pactl', 'set-default-sink', device_name], check=True)#设置默认音频接口subprocess.run(['pactl', 'set-sink-volume', device_name, '80%'], check=True)#设置音量print(f"Default output device set to: {device_name}")except subprocess.CalledProcessError as e:print(f"Error setting default output device: {e}")# 设置为默认input音频设备#soxdef set_default_input_device(self,device_name):try:# 设置默认的输入设备subprocess.run(['pactl', 'set-default-source', device_name], check=True)subprocess.run(['pactl', 'set-source-volume', device_name, '80%'], check=True)  # 设置音量print(f"Default input device set to: {device_name}")except subprocess.CalledProcessError as e:print(f"Error setting default input device: {e}")#启动多线程def start_analysis_threads(self):# 创建多个线程self.threads = []#for file in [self.soundFile[6], self.soundFile[3], self.soundFile[2]]:for file in [self.soundFile[6]]:thread = AnalysisThread(file,1, self)thread.start()self.threads.append(thread)self.analysis_threads.append(thread)#删除当前目录下所有*.wav文件def delete_wav_files(self,directory):# 构造当前目录中所有.wav文件的路径模式path_pattern = os.path.join(directory, '*.wav')# 使用glob模块找到所有匹配的文件wav_files = glob.glob(path_pattern)# 遍历所有找到的.wav文件并删除它们for file_path in wav_files:try:os.remove(file_path)print(f"Deleted: {file_path}")except Exception as e:print(f"Error deleting {file_path}: {e}")def synchronized_play_record(self,playback_file, record_duration, record_file, playback_device, record_device):# Create threads for playback and recordingplayback_thread = threading.Thread(target=self.play_audio, args=(playback_file, playback_device))recording_thread = threading.Thread(target=self.record_audio, args=(record_duration, record_file, record_device))# Start both threadsplayback_thread.start()recording_thread.start()# Wait for both threads to completeplayback_thread.join()recording_thread.join()#读取音频设备def list_audio_devices_list(self):try:p = pyaudio.PyAudio()print("Available audio devices:")for index in range(p.get_device_count()):device_info = p.get_device_info_by_index(index)device_name = device_info.get('name')input_channels = device_info.get('maxInputChannels')output_channels = device_info.get('maxOutputChannels')if input_channels > 0:if 'HDMI' not in device_name and 'hdmi' not in device_name:#print(f"Recording Device: {device_name} (Index: {index}, Input Channels: {input_channels})")self.InfoListAddData(f"Recording Device: {device_name} (Index: {index}, Input Channels: {input_channels})",1)self.Playback_deviceIndx.append(index)#音频播放if output_channels > 0:if 'HDMI' not in device_name and 'hdmi' not in device_name:#print(f"Playback Device: {device_name} (Index: {index}, Output Channels: {output_channels})")self.InfoListAddData(f"Recording Device: {device_name} (Index: {index}, Input Channels: {input_channels})", 1)self.Record_deviceIndx.append(index)#音频录音p.terminate()except Exception as e:self.ShowLog("AnalysisSoundFile_Frequency Err:" + str(e), False)self.InfoListAddData(f"AnalysisSoundFile_Frequency Err:{str(e)}",3)def setupUi(self):self.setObjectName("Form")self.resize(1000, 940)icon = QtGui.QIcon()icon.addPixmap(QtGui.QPixmap("IMAGE/Sound.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)self.setWindowIcon(icon)self.gridLayout_2 = QtWidgets.QGridLayout(self)self.gridLayout_2.setObjectName("gridLayout_2")self.gridLayout = QtWidgets.QGridLayout()self.gridLayout.setObjectName("gridLayout")self.horizontalLayout = QtWidgets.QHBoxLayout()self.horizontalLayout.setObjectName("horizontalLayout")self.verticalLayout_4 = QtWidgets.QVBoxLayout()self.verticalLayout_4.setObjectName("verticalLayout_4")self.lbl_logo = QtWidgets.QLabel(self)self.lbl_logo.setText("")self.lbl_logo.setPixmap(QtGui.QPixmap("IMAGE/logo.jpg"))self.lbl_logo.setObjectName("lbl_logo")self.verticalLayout_4.addWidget(self.lbl_logo)font = QtGui.QFont()font.setPointSize(14)font.setBold(False)font.setWeight(50)self.lbl_MesInfo = QtWidgets.QLabel(self)self.lbl_MesInfo.setFont(font)self.lbl_MesInfo.setStyleSheet("background-color: rgb(170, 255, 127);")self.lbl_MesInfo.setAlignment(QtCore.Qt.AlignCenter)self.lbl_MesInfo.setObjectName("lbl_MesInfo")self.verticalLayout_4.addWidget(self.lbl_MesInfo)self.horizontalLayout.addLayout(self.verticalLayout_4)self.verticalLayout_5 = QtWidgets.QVBoxLayout()self.verticalLayout_5.setObjectName("verticalLayout_5")self.label_12 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(16)font.setBold(False)font.setWeight(50)self.label_12.setFont(font)self.label_12.setStyleSheet("background-color: rgb(170, 170, 127);")self.label_12.setText("项目名称")self.label_12.setAlignment(QtCore.Qt.AlignCenter)self.label_12.setObjectName("label_12")self.verticalLayout_5.addWidget(self.label_12)self.verticalLayout_10 = QtWidgets.QVBoxLayout()self.verticalLayout_10.setObjectName("verticalLayout_10")self.label_13 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)font.setBold(False)font.setWeight(50)self.label_13.setFont(font)self.label_13.setStyleSheet("background-color: rgb(255, 170, 127);")self.label_13.setText("端口信息")self.label_13.setAlignment(QtCore.Qt.AlignCenter)self.label_13.setObjectName("label_13")self.verticalLayout_10.addWidget(self.label_13)self.label_14 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)font.setBold(False)font.setWeight(50)self.label_14.setFont(font)self.label_14.setStyleSheet("background-color: rgb(0, 255, 127);")self.label_14.setText("测试结果")self.label_14.setAlignment(QtCore.Qt.AlignCenter)self.label_14.setObjectName("label_14")self.verticalLayout_10.addWidget(self.label_14)self.verticalLayout_5.addLayout(self.verticalLayout_10)self.horizontalLayout.addLayout(self.verticalLayout_5)self.verticalLayout_3 = QtWidgets.QVBoxLayout()self.verticalLayout_3.setObjectName("verticalLayout_3")self.label_2 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setFamily("微软雅黑")font.setPointSize(16)font.setBold(False)font.setWeight(50)self.label_2.setFont(font)self.label_2.setStyleSheet("")self.label_2.setText("前置")self.label_2.setAlignment(QtCore.Qt.AlignCenter)self.label_2.setObjectName("label_2")self.verticalLayout_3.addWidget(self.label_2)self.horizontalLayout_3 = QtWidgets.QHBoxLayout()self.horizontalLayout_3.setObjectName("horizontalLayout_3")self.verticalLayout_6 = QtWidgets.QVBoxLayout()self.verticalLayout_6.setObjectName("verticalLayout_6")self.label_5 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)font.setBold(False)font.setWeight(50)self.label_5.setFont(font)self.label_5.setAlignment(QtCore.Qt.AlignCenter)self.label_5.setObjectName("label_5")self.verticalLayout_6.addWidget(self.label_5)font = QtGui.QFont()font.setPointSize(14)font.setBold(False)font.setWeight(50)self.lbl_Front_Out_Port = QtWidgets.QLabel(self)self.lbl_Front_Out_Port.setFont(font)self.lbl_Front_Out_Port.setAlignment(QtCore.Qt.AlignCenter)self.lbl_Front_Out_Port.setObjectName("lbl_Front_Out_Port")self.verticalLayout_6.addWidget(self.lbl_Front_Out_Port)self.horizontalLayout_3.addLayout(self.verticalLayout_6)self.verticalLayout_7 = QtWidgets.QVBoxLayout()self.verticalLayout_7.setObjectName("verticalLayout_7")self.label_6 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)font.setBold(False)font.setWeight(50)self.label_6.setFont(font)self.label_6.setAlignment(QtCore.Qt.AlignCenter)self.label_6.setObjectName("label_6")self.verticalLayout_7.addWidget(self.label_6)font = QtGui.QFont()font.setPointSize(14)font.setBold(False)font.setWeight(50)self.lbl_Front_In_Port = QtWidgets.QLabel(self)self.lbl_Front_In_Port.setFont(font)self.lbl_Front_In_Port.setAlignment(QtCore.Qt.AlignCenter)self.lbl_Front_In_Port.setObjectName("lbl_Front_In_Port")self.verticalLayout_7.addWidget(self.lbl_Front_In_Port)self.horizontalLayout_3.addLayout(self.verticalLayout_7)self.verticalLayout_3.addLayout(self.horizontalLayout_3)self.horizontalLayout.addLayout(self.verticalLayout_3)self.verticalLayout_2 = QtWidgets.QVBoxLayout()self.verticalLayout_2.setObjectName("verticalLayout_2")self.label_3 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setFamily("微软雅黑")font.setPointSize(16)font.setBold(False)font.setWeight(50)self.label_3.setFont(font)self.label_3.setStyleSheet("")self.label_3.setText("后置")self.label_3.setAlignment(QtCore.Qt.AlignCenter)self.label_3.setObjectName("label_3")self.verticalLayout_2.addWidget(self.label_3)self.horizontalLayout_4 = QtWidgets.QHBoxLayout()self.horizontalLayout_4.setObjectName("horizontalLayout_4")self.verticalLayout_8 = QtWidgets.QVBoxLayout()self.verticalLayout_8.setObjectName("verticalLayout_8")self.label_8 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)font.setBold(False)font.setWeight(50)self.label_8.setFont(font)self.label_8.setAlignment(QtCore.Qt.AlignCenter)self.label_8.setObjectName("label_8")self.verticalLayout_8.addWidget(self.label_8)self.lbl_Rear_Out_Port = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(14)font.setBold(False)font.setWeight(50)self.lbl_Rear_Out_Port.setFont(font)self.lbl_Rear_Out_Port.setAlignment(QtCore.Qt.AlignCenter)self.lbl_Rear_Out_Port.setObjectName("lbl_Rear_Out_Port")self.verticalLayout_8.addWidget(self.lbl_Rear_Out_Port)self.horizontalLayout_4.addLayout(self.verticalLayout_8)self.verticalLayout_9 = QtWidgets.QVBoxLayout()self.verticalLayout_9.setObjectName("verticalLayout_9")self.label_10 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)font.setBold(False)font.setWeight(50)self.label_10.setFont(font)self.label_10.setAlignment(QtCore.Qt.AlignCenter)self.label_10.setObjectName("label_10")self.verticalLayout_9.addWidget(self.label_10)font = QtGui.QFont()font.setPointSize(14)font.setBold(False)font.setWeight(50)self.lbl_Rear_In_Port = QtWidgets.QLabel(self)self.lbl_Rear_In_Port.setFont(font)self.lbl_Rear_In_Port.setAlignment(QtCore.Qt.AlignCenter)self.lbl_Rear_In_Port.setObjectName("lbl_Rear_In_Port")self.verticalLayout_9.addWidget(self.lbl_Rear_In_Port)self.horizontalLayout_4.addLayout(self.verticalLayout_9)self.verticalLayout_2.addLayout(self.horizontalLayout_4)self.horizontalLayout.addLayout(self.verticalLayout_2)self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)self.horizontalLayout_2 = QtWidgets.QHBoxLayout()self.horizontalLayout_2.setObjectName("horizontalLayout_2")self.groupBox = QtWidgets.QGroupBox(self)self.groupBox.setObjectName("groupBox")self.gridLayout_3 = QtWidgets.QGridLayout(self.groupBox)self.gridLayout_3.setObjectName("gridLayout_3")font = QtGui.QFont()font.setPointSize(12)self.ltwgt_Log = QtWidgets.QListWidget(self.groupBox)self.ltwgt_Log.setObjectName("ltwgt_Log")self.ltwgt_Log.setFont(font)self.gridLayout_3.addWidget(self.ltwgt_Log, 0, 0, 1, 1)self.horizontalLayout_2.addWidget(self.groupBox)self.gridLayout.addLayout(self.horizontalLayout_2, 1, 0, 1, 1)self.lbl_Result_Log = QtWidgets.QLabel(self)self.lbl_Result_Log.setStyleSheet("background-color: rgb(0, 0, 0);")self.lbl_Result_Log.setText("")self.lbl_Result_Log.setAlignment(QtCore.Qt.AlignCenter)self.lbl_Result_Log.setObjectName("lbl_Result_Log")self.gridLayout.addWidget(self.lbl_Result_Log, 2, 0, 1, 1)self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)self.retranslateUi()QtCore.QMetaObject.connectSlotsByName(self)self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint | QtCore.Qt.WindowCloseButtonHint)  # 只显示最小化按钮和关闭按钮def retranslateUi(self):_translate = QtCore.QCoreApplication.translateself.setWindowTitle(_translate("Form", "Sound_HD"))self.lbl_MesInfo.setText(_translate("Form", "当前前置Out_Port测试中.."))self.label_5.setText(_translate("Form", "OUT_PORT"))self.lbl_Front_Out_Port.setText(_translate("Form", "N/A"))self.label_6.setText(_translate("Form", "IN_PORT"))self.lbl_Front_In_Port.setText(_translate("Form", "N/A"))self.label_8.setText(_translate("Form", "OUT_PORT"))self.lbl_Rear_Out_Port.setText(_translate("Form", "N/A"))self.label_10.setText(_translate("Form", "IN_PORT"))self.lbl_Rear_In_Port.setText(_translate("Form", "N/A"))#self.groupBox.setTitle(_translate("Form", "-日志"))#列出所有录音设备def list_audio_devices(self):try:#result = subprocess.run(['arecord', '-l'], capture_output=True, text=True)readcmdinfo=subprocess.check_output(['arecord', '-l'], stderr=subprocess.STDOUT)lines = readcmdinfo.decode('utf-8').split('\n')i=0for recordinfo in lines:if 'card' in recordinfo:self.CaptuerHardwareDevices.append(recordinfo)#添加录音设备信息card=recordinfo[recordinfo.find('card')+5:recordinfo.find('card')+6]device=recordinfo[recordinfo.find('device')+7:recordinfo.find('device')+8]self.Recordhw.append('hw:'+card+','+device)if i==0:self.lbl_Front_In_Port.setText('hw:'+card+','+device)elif i==1:self.lbl_Rear_In_Port.setText('hw:'+card+','+device)self.InfoListAddData(recordinfo, 1)i+=1except Exception as e:self.ShowLog("list audio devices Info Err:" + str(e), False)sys.exit(1)#列出所有放音设备def list_record_devices(self):try:#result=subprocess.run(['aplay','-l'], capture_output=True, text=True)readcmdinfo = subprocess.check_output(['aplay','-l'], stderr=subprocess.STDOUT)lines = readcmdinfo.decode('utf-8').split('\n')for playback in lines:if 'card' in playback and 'HDMI' not in playback:self.PlaybackHardwareDevices.append(playback)#添加音频播放设备信息card=playback[playback.find('card')+5:playback.find('card')+6]device=playback[playback.find('device')+7:playback.find('device')+8]self.Playbackhw.append('hw:'+card+','+device)if len(self.Recordhw)>1:self.lbl_Front_Out_Port.setText('hw:'+card+','+device)self.lbl_Rear_Out_Port.setText('hw:'+card+','+device)else:self.lbl_Front_Out_Port.setText('hw:' + card + ',' + device)self.InfoListAddData(playback,1)except Exception as e:self.ShowLog("list record devices Info Err:" + str(e), False)sys.exit(1)#messtr:信息字符串 infoType:信息类型 1=提示信息,2=测试PASS信息,3=测试FAIL信息def InfoListAddData(self,messtr,infoType):try:# 获取当前时间current_time = datetime.now()# 提取年月日时分秒year = current_time.yearmonth = current_time.monthday = current_time.dayhour = current_time.hourminute = current_time.minutesecond = current_time.seconditem = QListWidgetItem(messtr)if infoType==1:item.setForeground(QColor("blue"))elif infoType==2:item.setForeground(QColor("green"))elif infoType==3:item.setForeground(QColor("red"))#self.ltwgt_Log.addItem(year+'-'+month+'-'+day+' '+hour+':'+minute+':'+second+' '+item)self.ltwgt_Log.addItem(item)self.ltwgt_Log.setEnabled(False)#只读# 将光标移动到最底部self.ltwgt_Log.scrollToBottom()except Exception as e:self.ShowLog("InfoListAddData Err:" + str(e), False)sys.exit(1)#窗口关闭def closeEvent(self, event):# 停止所有 AnalysisThread 实例for thread in self.analysis_threads:thread.stop()thread.wait()# 停止所有 RecordPlayThread 实例for thread in self.record_play_threads:thread.stop()thread.wait()self.UpdateJsonTestArgs(self.itemName,'FAIL')self.enable_hdmi_audio()#启动hdmisys.exit(1)# 定义一个函数使得函数窗口居中显示def Center(self):# 获取屏幕尺寸screen_geometry = app.desktop().availableGeometry()# 计算窗口居中位置x = (screen_geometry.width() - self.width()) // 2y = (screen_geometry.height() - self.height()) // 2# 设置窗口位置self.move(x, y)# 读取项目参数信息,itemName:项目名称def ReadJsonTestArgs(self, itemName):try:self.testArgs = self.ReadJsonInfo('./Conf/TestArgs.json')for js in self.testArgs:if itemName in js['ItemName']:self.testStandardArgs = js['Standard']return Trueself.ShowLog('Read TestArgs.json ItemName:' + itemName + ' Info Is Empty!!', False)sys.exit(1)except Exception as e:self.ShowLog("Read TestArgs.json ItemName:" + itemName + " Info Err:" + str(e), False)sys.exit(1)#更新测试参数json,itemName:项目名称,readValue:读取值,testResult:测试结果def UpdateJsonTestArgs(self,itemName,testResult):try:updateTestArgs=[]#更新的测试参数self.testArgs=self.ReadJsonInfo('./Conf/TestArgs.json')for js in self.testArgs:if itemName in js['ItemName']:#js['Read']=readValue#读取的值js['TestResult']=testResult#测试结果updateTestArgs.append(js)else:updateTestArgs.append(js)with open("./Conf/TestArgs.json", "w") as write_file:json.dump(updateTestArgs, write_file)return Trueexcept Exception as e:self.ShowLog("Read TestArgs.json ItemName:"+itemName+" Info Err:" + str(e),False)sys.exit(1)#解析音频文件声响频率 fileName:文件名称,type:类型 1:标准值,2:接口1读取的值 3:接口2读取的值def AnalysisSoundFile_Frequency(self,fileNme,type):try:# 加载音频文件audio_path = fileNmey, sr = librosa.load(audio_path)# 获取频率和时间fft = np.fft.fft(y)magnitude = np.abs(fft)frequency = np.linspace(0, sr, len(magnitude))# 只获取左侧频谱,因为右侧是对称的left_frequency = frequency[:int(len(frequency) / 2)]left_magnitude = magnitude[:int(len(frequency) / 2)]# 找到最大幅度的频率max_magnitude = np.argmax(left_magnitude)peak_freq = left_frequency[max_magnitude]#print(f"{fileNme} Peak Frequency: {peak_freq} Hz")if type==1:self.AnalysisSound_FrequencySample=int(peak_freq)self.InfoListAddData(f"Sample {fileNme} Peak Frequency: {peak_freq} Hz", 1)elif type==2:self.Device_1AnalysisSound_Frequency=int(peak_freq)self.InfoListAddData(f"Recordhw-{self.Recordhw[0]}-Playbackhw:{self.Playbackhw[0]} {fileNme} Peak Frequency: {peak_freq} Hz", 1)elif type==3:self.Device_2AnalysisSound_Frequency=int(peak_freq)self.InfoListAddData(f"Recordhw-{self.Recordhw[0]}-Playbackhw:{self.Playbackhw[0]} {fileNme} Peak Frequency: {peak_freq} Hz",1)except Exception as e:self.ShowLog("AnalysisSoundFile_Frequency Err:" + str(e), False)self.InfoListAddData(f"AnalysisSoundFile_Frequency Err:{str(e)}",3)#sys.exit(1)#解析音频文件分析躁声def AnalysisSoundFile_Noise(self,fileName):try:#加载音频文件:使用librosa加载音频文件。audio_file = fileNamey, sr = librosa.load(audio_file)#特征提取:从音频信号中提取特征,例如梅尔频率倒谱系数(MFCC)mfccs = librosa.feature.mfcc(y=y, sr=sr)print(mfccs)except Exception as e:self.ShowLog("AnalysisSoundFile_Frequency Err:" + str(e), False)sys.exit(1)#读取json信息def ReadJsonInfo(self,fileName):try:if os.path.exists(fileName):f=open(fileName,'r',encoding='utf-8')return json.loads(f.read())except Exception as e:self.ShowLog("Read "+fileName+" Err:" + str(e),False)sys.exit(1)def identify_microphone_position(self,name):# 这里使用假设的命名规则,你需要根据实际情况修改if "front" in name.lower():return "Front Microphone"elif "rear" in name.lower() or "back" in name.lower():return "Rear Microphone"else:return "Unknown Position"#获取音频装置'''def get_audio_devices(self):try:# 运行命令获取音频设备列表result = subprocess.run(['aplay', '-l'], capture_output=True, text=True, check=True)# 打印输出结果print(result.stdout)except subprocess.CalledProcessError as e:print(f"Error: {e}")'''#打印的信息def ShowLog(self,log,isPass):try:if isPass == True:self.lbl_Result_Log.setStyleSheet("color:green;")self.logger.info(str(log))else:self.lbl_Result_Log.setStyleSheet("color:red;")self.logger.error(str(log))self.lbl_Result_Log.setText(str(log))except Exception as e:print("\033[1;31m" + str(e) + " \033[0m")self.logger.error(str(log))sys.exit(1)if __name__=='__main__':app=QApplication(sys.argv)win=Ui_Form()win.Center()  # 居中win.show()sys.exit(app.exec_())

这篇关于UOS Python+Qt5实现声卡回路测试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/598059

相关文章

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount