探究音频丢字位置和丢字时间对pesq分数的影响

丢字的本质

丢字的本质是在一段音频中一小段数据变为0

丢字对主观感受的影响

1. 丢字位置

丢字的位置对感知效果有很大影响。如果丢字发生在音频信号的静音部分或低能量部分,感知可能不明显;而如果丢字发生在高能量部分或关键音素上,感知会非常明显。

2. 丢字持续时间

虽然10ms的丢字时间相对较短,但如果丢字发生在关键音素或瞬态(如爆破音、元音等)上,感知会更加明显。

3. 音频内容

不同类型的音频内容对丢字的敏感度不同。例如,语音信号中的丢字可能比音乐信号中的丢字更容易被感知,因为语音信号中有更多的瞬态和关键音素。

4. 人耳的感知能力

人耳对不同频率和时间的变化有不同的敏感度。某些频率范围内的丢字可能更容易被感知,而其他频率范围内的丢字可能不明显。

丢字位置和丢字持续时间的影响

判断丢字的位置在高能量和低能量位置以及丢字时间对pesq分数的影响

选取一段音频,随机在其高能量和低能量位置丢字,丢字时间分别设置为

0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1

单位为s,生成所有丢字的音频,再对丢字音频进行pesq评分,画成折线图输出

脚本代码如下:

复制代码
import numpy as np
from scipy.io import wavfile
from pesq import pesq
from pesq import PesqError
import librosa
import matplotlib.pyplot as plt

def create_single_drop_audio(data, drop_start, drop_duration, sample_rate):
    """在音频信号中指定位置,并将该位置的一小段音频数据设置为零"""
    num_samples = len(data)
    drop_samples = int(drop_duration * sample_rate)
    drop_end = drop_start + drop_samples
    print(drop_start,drop_duration)
    # 创建丢字音频
    dropped_data = np.copy(data)
    dropped_data[drop_start:drop_end] = 0
    
    return dropped_data

# 读取原始音频文件并转换采样率
original_file = 'audio_file.wav'
target_sample_rate = 16000  # 选择8000或16000

# 使用librosa加载音频文件并转换采样率
original_data, original_sample_rate = librosa.load(original_file, sr=target_sample_rate)

# 计算音频信号的能量分布
energy = np.abs(original_data)**2
window_size = int(0.01 * original_sample_rate)  # 10ms窗口
energy = np.convolve(energy, np.ones(window_size), 'same')

# 随机选择一个低能量位置进行丢字
low_energy_indices = np.where(energy < np.percentile(energy, 20))[0]  # 选择能量最低的20%
high_energy_indices = np.where(energy > np.percentile(energy, 80))[0]  # 选择能量最高的20%

# 定义不同的drop_duration值
drop_durations = [0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1]

# 存储PESQ分数
pesq_scores_low_energy = []
pesq_scores_high_energy = []

# 计算原始音频的PESQ分数(与自身比较)
try:
    original_pesq_score = pesq(original_sample_rate, original_data, original_data, 'wb')
    print(f'Original Audio PESQ Score: {original_pesq_score:.2f}')
except PesqError as e:
    print(f'Error calculating PESQ for original audio: {e}')
    original_pesq_score = None

# 对低能量部分进行丢字
drop_start = np.random.choice(low_energy_indices)
for drop_duration in drop_durations:

    dropped_data = create_single_drop_audio(original_data, drop_start, drop_duration, sample_rate=original_sample_rate)
    
    # 保存丢字音频
    output_file = f'low_energy_dropped_audio_{int(drop_duration*1000)}ms.wav'
    wavfile.write(output_file, original_sample_rate, (dropped_data * 32767).astype(np.int16))
    
    try:
        pesq_score = pesq(original_sample_rate, original_data, dropped_data, 'wb')
        pesq_scores_low_energy.append(pesq_score)
        print(f'Low Energy - Drop Duration: {drop_duration:.3f}s, PESQ Score: {pesq_score:.2f}')
    except PesqError as e:
        print(f'Error calculating PESQ for drop_duration {drop_duration} in low energy: {e}')
        pesq_scores_low_energy.append(None)

# 对高能量部分进行丢字
drop_start = np.random.choice(high_energy_indices)
for drop_duration in drop_durations:

    dropped_data = create_single_drop_audio(original_data, drop_start, drop_duration, sample_rate=original_sample_rate)
    
    # 保存丢字音频
    output_file = f'high_energy_dropped_audio_{int(drop_duration*1000)}ms.wav'
    wavfile.write(output_file, original_sample_rate, (dropped_data * 32767).astype(np.int16))
    
    try:
        pesq_score = pesq(original_sample_rate, original_data, dropped_data, 'wb')
        pesq_scores_high_energy.append(pesq_score)
        print(f'High Energy - Drop Duration: {drop_duration:.3f}s, PESQ Score: {pesq_score:.2f}')
    except PesqError as e:
        print(f'Error calculating PESQ for drop_duration {drop_duration} in high energy: {e}')
        pesq_scores_high_energy.append(None)

# 绘制折线图
plt.figure(figsize=(12, 8))
plt.plot([0] + drop_durations, [original_pesq_score] + pesq_scores_low_energy, marker='o', linestyle='-', color='b', label='Low Energy PESQ Score')
plt.plot([0] + drop_durations, [original_pesq_score] + pesq_scores_high_energy, marker='o', linestyle='-', color='r', label='High Energy PESQ Score')
plt.xlabel('Drop Duration (s)')
plt.ylabel('PESQ Score')
plt.title('PESQ Score vs Drop Duration (Low Energy vs High Energy)')
plt.grid(True)
plt.legend()
plt.show()

运行三次,随机选择不同的高能量和低能量部分,生成的折线图

从图表上看,高能部分丢字,只要出现1ms的丢字,mos下降的就很明显,mos下降0.2,主观听感上,就有一个明显的感知"bo"了一声。

但是低能量部分,出现丢字后,有时候mos下降了,有时候没有下降,10ms以内的丢字,mos基本不会下降,但是主观听感上,即使mos下降到3.8,也没有明显的感知

结论

pesq这种评分方式不能很好的评价音频丢字给主观带来的影响

相关推荐
黄啊码5 小时前
【黄啊码】为什么AI写不出阿嬷的情书?
人工智能
rit84324995 小时前
基于POCS的超分辨率重建(Keren配准)MATLAB实现
人工智能·matlab·超分辨率重建
星辰AI5 小时前
AI Agent 记忆系统设计与实现:让 AI 记住一切
人工智能·ai·语言模型
AwakeFantasy5 小时前
聊聊近况和最近做的踩坑项目
人工智能·python·gpt·ocr
路人甲3265 小时前
Moravec‘s Paradox and the Robot Olympics
人工智能·深度学习·计算机视觉·机器人·具身智能
黄啊码5 小时前
【黄啊码】拉勾倒了,但你的简历早就不该在招聘软件上了
人工智能·面试
头歌实践平台5 小时前
头歌 卷积神经网络卷积核和结构设计实验
人工智能·深度学习·cnn
DogDaoDao5 小时前
OpenCV 踩坑全指南
图像处理·人工智能·python·opencv·计算机视觉·matplotlib·rgb
J2虾虾5 小时前
Spring AI Alibaba - 检索增强生成(RAG)
人工智能·spring·原型模式
一切皆是因缘际会5 小时前
底层重构与价值破壁人工智能产业变革
人工智能·安全·重构·系统架构