neverlib 0.2.3__py3-none-any.whl → 0.2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- neverlib/.history/Docs/audio_aug/test_snr_20250806011311.py +0 -0
- neverlib/.history/Docs/audio_aug/test_snr_20250806011331.py +75 -0
- neverlib/.history/Docs/audio_aug/test_snr_20250806011342.py +57 -0
- neverlib/.history/Docs/audio_aug/test_snr_20250806011352.py +57 -0
- neverlib/.history/Docs/audio_aug/test_snr_20250806011403.py +57 -0
- neverlib/.history/Docs/audio_aug/test_snr_20250806011413.py +57 -0
- neverlib/.history/Docs/audio_aug/test_snr_20250806011435.py +55 -0
- neverlib/.history/Docs/vad/1_20250810032405.py +0 -0
- neverlib/.history/Docs/vad/1_20250810032417.py +39 -0
- neverlib/.history/audio_aug/audio_aug_20250806010451.py +125 -0
- neverlib/.history/audio_aug/audio_aug_20250806010750.py +138 -0
- neverlib/.history/audio_aug/audio_aug_20250806010759.py +140 -0
- neverlib/.history/audio_aug/audio_aug_20250806010803.py +140 -0
- neverlib/.history/audio_aug/audio_aug_20250806010809.py +140 -0
- neverlib/.history/audio_aug/audio_aug_20250806011108.py +140 -0
- neverlib/.history/dataAnalyze/__init___20250806204125.py +14 -0
- neverlib/.history/dataAnalyze/__init___20250806204139.py +14 -0
- neverlib/.history/dataAnalyze/__init___20250806204159.py +14 -0
- neverlib/.history/filter/__init___20250820103351.py +70 -0
- neverlib/.history/filter/__init___20250821102348.py +70 -0
- neverlib/.history/filter/__init___20250821102405.py +14 -0
- neverlib/.history/filter/auto_eq/__init___20250819213121.py +36 -0
- neverlib/.history/filter/auto_eq/__init___20250821102241.py +36 -0
- neverlib/.history/filter/auto_eq/__init___20250821102259.py +36 -0
- neverlib/.history/filter/auto_eq/__init___20250821102307.py +36 -0
- neverlib/.history/filter/auto_eq/__init___20250821102310.py +36 -0
- neverlib/.history/filter/auto_eq/__init___20250821102318.py +36 -0
- neverlib/.history/filter/auto_eq/__init___20250821102507.py +36 -0
- neverlib/{filter/AudoEQ/auto_eq_de.py → .history/filter/auto_eq/de_eq_20250820103848.py} +1 -1
- neverlib/.history/filter/auto_eq/de_eq_20250821102422.py +360 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820140732.py +75 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820140745.py +75 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820140816.py +75 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820140938.py +77 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820141003.py +77 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820141006.py +77 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820141019.py +77 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820141049.py +77 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820141211.py +77 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820141227.py +77 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820141311.py +78 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820141340.py +78 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820141712.py +78 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820141733.py +78 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250820141755.py +78 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250821102434.py +76 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250821102500.py +76 -0
- neverlib/.history/filter/auto_eq/freq_eq_20250821102502.py +76 -0
- neverlib/{filter/AudoEQ/auto_eq_ga_basic.py → .history/filter/auto_eq/ga_eq_basic_20250820102957.py} +1 -1
- neverlib/.history/filter/auto_eq/ga_eq_basic_20250820113054.py +380 -0
- neverlib/.history/filter/auto_eq/ga_eq_basic_20250820113150.py +380 -0
- neverlib/.history/filter/auto_eq/ga_eq_basic_20250820113520.py +385 -0
- neverlib/.history/filter/auto_eq/ga_eq_basic_20250820113525.py +385 -0
- neverlib/.history/filter/auto_eq/ga_eq_basic_20250821102212.py +385 -0
- neverlib/.history/metrics/dnsmos_20250806001612.py +160 -0
- neverlib/.history/metrics/dnsmos_20250815180659.py +160 -0
- neverlib/.history/metrics/dnsmos_20250815180701.py +158 -0
- neverlib/.history/metrics/dnsmos_20250815181321.py +154 -0
- neverlib/.history/metrics/dnsmos_20250815181327.py +154 -0
- neverlib/.history/metrics/dnsmos_20250815181331.py +154 -0
- neverlib/.history/metrics/dnsmos_20250815181620.py +154 -0
- neverlib/.history/metrics/dnsmos_20250815181631.py +154 -0
- neverlib/.history/metrics/dnsmos_20250815181742.py +154 -0
- neverlib/.history/metrics/dnsmos_20250815181824.py +153 -0
- neverlib/.history/metrics/dnsmos_20250815181834.py +153 -0
- neverlib/.history/metrics/dnsmos_20250815181922.py +153 -0
- neverlib/.history/metrics/dnsmos_20250815182011.py +147 -0
- neverlib/.history/metrics/dnsmos_20250815182036.py +144 -0
- neverlib/.history/metrics/dnsmos_20250815182936.py +143 -0
- neverlib/.history/metrics/dnsmos_20250815182942.py +143 -0
- neverlib/.history/metrics/dnsmos_20250815183032.py +137 -0
- neverlib/.history/metrics/dnsmos_20250815183101.py +144 -0
- neverlib/.history/metrics/dnsmos_20250815183121.py +144 -0
- neverlib/.history/metrics/dnsmos_20250815183123.py +143 -0
- neverlib/.history/metrics/dnsmos_20250815183214.py +143 -0
- neverlib/.history/metrics/dnsmos_20250815183240.py +143 -0
- neverlib/.history/metrics/dnsmos_20250815183248.py +144 -0
- neverlib/.history/metrics/dnsmos_20250815183407.py +142 -0
- neverlib/.history/metrics/dnsmos_20250815183409.py +142 -0
- neverlib/.history/metrics/dnsmos_20250815183431.py +142 -0
- neverlib/.history/metrics/dnsmos_20250815183507.py +140 -0
- neverlib/.history/metrics/dnsmos_20250815183513.py +139 -0
- neverlib/.history/metrics/dnsmos_20250815183618.py +139 -0
- neverlib/.history/metrics/dnsmos_20250815183709.py +140 -0
- neverlib/.history/metrics/dnsmos_20250815183756.py +137 -0
- neverlib/.history/metrics/dnsmos_20250815183815.py +128 -0
- neverlib/.history/metrics/dnsmos_20250815183827.py +129 -0
- neverlib/.history/metrics/dnsmos_20250815183913.py +117 -0
- neverlib/.history/metrics/dnsmos_20250815183914.py +117 -0
- neverlib/.history/metrics/dnsmos_20250815184003.py +118 -0
- neverlib/.history/metrics/dnsmos_20250815184040.py +118 -0
- neverlib/.history/metrics/dnsmos_20250815184049.py +118 -0
- neverlib/.history/metrics/dnsmos_20250815184104.py +117 -0
- neverlib/.history/metrics/dnsmos_20250815184200.py +117 -0
- neverlib/.history/metrics/lpc_lsp_metric_20250816015944.py +128 -0
- neverlib/.history/metrics/lpc_lsp_metric_20250816020142.py +128 -0
- neverlib/.history/metrics/lpc_lsp_metric_20250816020156.py +128 -0
- neverlib/.history/metrics/lpc_lsp_metric_20250816020554.py +130 -0
- neverlib/.history/metrics/lpc_lsp_metric_20250816020600.py +125 -0
- neverlib/.history/metrics/lpc_lsp_metric_20250816020631.py +120 -0
- neverlib/.history/metrics/lpc_lsp_metric_20250816020746.py +118 -0
- neverlib/.history/metrics/lpc_me_20250816013111.py +0 -0
- neverlib/.history/metrics/lpc_me_20250816013129.py +121 -0
- neverlib/.history/metrics/lpc_me_20250816015430.py +103 -0
- neverlib/.history/metrics/lpc_me_20250816015535.py +96 -0
- neverlib/.history/metrics/lpc_me_20250816015542.py +96 -0
- neverlib/.history/metrics/lpc_me_20250816015636.py +97 -0
- neverlib/.history/metrics/lpc_me_20250816015658.py +104 -0
- neverlib/.history/metrics/lpc_me_20250816015703.py +100 -0
- neverlib/.history/metrics/lpc_me_20250816015945.py +128 -0
- neverlib/.history/metrics/snr_20250806010538.py +177 -0
- neverlib/.history/metrics/snr_20250806211634.py +184 -0
- neverlib/.history/metrics/spec_20250805234209.py +45 -0
- neverlib/.history/metrics/spec_20250816135530.py +11 -0
- neverlib/.history/metrics/spec_20250816135654.py +16 -0
- neverlib/.history/metrics/spec_20250816135736.py +68 -0
- neverlib/.history/metrics/spec_20250816135904.py +75 -0
- neverlib/.history/metrics/spec_20250816135921.py +82 -0
- neverlib/.history/metrics/spec_20250816140111.py +82 -0
- neverlib/.history/metrics/spec_20250816140543.py +136 -0
- neverlib/.history/metrics/spec_20250816140559.py +172 -0
- neverlib/.history/metrics/spec_20250816140602.py +172 -0
- neverlib/.history/metrics/spec_20250816140608.py +172 -0
- neverlib/.history/metrics/spec_20250816140654.py +148 -0
- neverlib/.history/metrics/spec_20250816140705.py +144 -0
- neverlib/.history/metrics/spec_20250816140755.py +138 -0
- neverlib/.history/metrics/spec_20250816140823.py +170 -0
- neverlib/.history/metrics/spec_20250816140832.py +170 -0
- neverlib/.history/metrics/spec_20250816140833.py +170 -0
- neverlib/.history/metrics/spec_20250816140922.py +147 -0
- neverlib/.history/metrics/spec_20250816141148.py +107 -0
- neverlib/.history/metrics/spec_20250816141219.py +123 -0
- neverlib/.history/metrics/spec_20250816141732.py +178 -0
- neverlib/.history/metrics/spec_20250816141740.py +178 -0
- neverlib/.history/metrics/spec_20250816142030.py +178 -0
- neverlib/.history/metrics/spec_20250816142107.py +135 -0
- neverlib/.history/metrics/spec_20250816142126.py +135 -0
- neverlib/.history/metrics/spec_20250816142410.py +135 -0
- neverlib/.history/metrics/spec_20250816142415.py +136 -0
- neverlib/.history/metrics/spec_metric_20250816135156.py +0 -0
- neverlib/.history/metrics/spec_metric_20250816135226.py +5 -0
- neverlib/.history/metrics/spec_metric_20250816135227.py +10 -0
- neverlib/.history/metrics/spec_metric_20250816135306.py +15 -0
- neverlib/.history/metrics/spec_metric_20250816135442.py +31 -0
- neverlib/.history/metrics/spec_metric_20250816135448.py +31 -0
- neverlib/.history/metrics/spec_metric_20250816135520.py +29 -0
- neverlib/.history/metrics/spec_metric_20250816135537.py +63 -0
- neverlib/.history/metrics/spec_metric_20250816135653.py +65 -0
- neverlib/.history/vad/PreProcess_20250805234211.py +63 -0
- neverlib/.history/vad/PreProcess_20250809232455.py +63 -0
- neverlib/.history/vad/PreProcess_20250816020725.py +66 -0
- neverlib/.history/vad/VAD_Silero_20250805234211.py +50 -0
- neverlib/.history/vad/VAD_Silero_20250809232456.py +50 -0
- neverlib/.history/vad/VAD_WebRTC_20250805234211.py +61 -0
- neverlib/.history/vad/VAD_WebRTC_20250809232456.py +61 -0
- neverlib/.history/vad/VAD_funasr_20250805234211.py +54 -0
- neverlib/.history/vad/VAD_funasr_20250809232456.py +54 -0
- neverlib/.history/vad/VAD_vadlib_20250805234211.py +70 -0
- neverlib/.history/vad/VAD_vadlib_20250809232455.py +70 -0
- neverlib/.history/vad/VAD_whisper_20250805234211.py +55 -0
- neverlib/.history/vad/VAD_whisper_20250809232456.py +55 -0
- neverlib/.specstory/.what-is-this.md +69 -0
- neverlib/.specstory/history/2025-08-05_17-06Z-/350/277/231/344/270/200/346/255/245/347/232/204/347/233/256/347/232/204/346/230/257/344/273/200/344/271/210.md +424 -0
- neverlib/Docs/audio_aug/test_snr.py +55 -0
- neverlib/audio_aug/HarmonicDistortion.py +79 -0
- neverlib/audio_aug/TFDrop.py +41 -0
- neverlib/audio_aug/TFMask.py +56 -0
- neverlib/audio_aug/audio_aug.py +16 -1
- neverlib/audio_aug/clip_aug.py +41 -0
- neverlib/audio_aug/coder_aug.py +209 -0
- neverlib/audio_aug/coder_aug2.py +118 -0
- neverlib/audio_aug/loss_packet_aug.py +103 -0
- neverlib/audio_aug/quant_aug.py +78 -0
- neverlib/data_analyze/__init__.py +14 -0
- neverlib/filter/auto_eq/__init__.py +36 -0
- neverlib/filter/auto_eq/de_eq.py +360 -0
- neverlib/filter/auto_eq/freq_eq.py +76 -0
- neverlib/filter/{AudoEQ/auto_eq_ga_advanced.py → auto_eq/ga_eq_advanced.py} +1 -1
- neverlib/filter/auto_eq/ga_eq_basic.py +385 -0
- neverlib/metrics/dnsmos.py +58 -101
- neverlib/metrics/lpc_lsp.py +118 -0
- neverlib/metrics/snr.py +11 -4
- neverlib/metrics/spec.py +136 -45
- neverlib/utils/utils.py +17 -14
- neverlib/vad/PreProcess.py +5 -2
- neverlib/vad/VAD_Silero.py +1 -1
- neverlib/vad/VAD_WebRTC.py +1 -1
- neverlib/vad/VAD_funasr.py +1 -1
- neverlib/vad/VAD_vadlib.py +1 -1
- neverlib/vad/VAD_whisper.py +1 -1
- {neverlib-0.2.3.dist-info → neverlib-0.2.4.dist-info}/METADATA +1 -1
- neverlib-0.2.4.dist-info/RECORD +229 -0
- neverlib-0.2.3.dist-info/RECORD +0 -53
- /neverlib/{dataAnalyze/__init__.py → .history/dataAnalyze/__init___20250805234204.py} +0 -0
- /neverlib/{filter/AudoEQ/auto_eq_spectral_direct.py → .history/filter/auto_eq/freq_eq_20250805234206.py} +0 -0
- /neverlib/{dataAnalyze → data_analyze}/README.md +0 -0
- /neverlib/{dataAnalyze → data_analyze}/dataset_analyzer.py +0 -0
- /neverlib/{dataAnalyze → data_analyze}/quality_metrics.py +0 -0
- /neverlib/{dataAnalyze → data_analyze}/rms_distrubution.py +0 -0
- /neverlib/{dataAnalyze → data_analyze}/spectral_analysis.py +0 -0
- /neverlib/{dataAnalyze → data_analyze}/statistics.py +0 -0
- /neverlib/{dataAnalyze → data_analyze}/temporal_features.py +0 -0
- /neverlib/{dataAnalyze → data_analyze}/visualization.py +0 -0
- /neverlib/filter/{AudoEQ → auto_eq}/README.md +0 -0
- {neverlib-0.2.3.dist-info → neverlib-0.2.4.dist-info}/WHEEL +0 -0
- {neverlib-0.2.3.dist-info → neverlib-0.2.4.dist-info}/licenses/LICENSE +0 -0
- {neverlib-0.2.3.dist-info → neverlib-0.2.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# -*- coding:utf-8 -*-
|
|
2
|
+
# Author:凌逆战 | Never
|
|
3
|
+
# Date: 2024/9/27
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
import random
|
|
8
|
+
import numpy as np
|
|
9
|
+
import soundfile as sf
|
|
10
|
+
from scipy import signal
|
|
11
|
+
from neverlib.utils import EPS
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def volume_norm(wav):
|
|
15
|
+
"""
|
|
16
|
+
音量归一化
|
|
17
|
+
:param wav: (T,)
|
|
18
|
+
:return: (T,)
|
|
19
|
+
"""
|
|
20
|
+
wav = wav / (np.max(np.abs(wav)) + 1e-8)
|
|
21
|
+
return wav
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def add_reverb(wav, rir, ratio=1, mode="same"):
|
|
25
|
+
"""添加混响,
|
|
26
|
+
Args:
|
|
27
|
+
wav: [T, channel]
|
|
28
|
+
rir: [T, channel]
|
|
29
|
+
ratio: 0-1
|
|
30
|
+
mode: "same" for SE or "full" for kws
|
|
31
|
+
"""
|
|
32
|
+
if random.random() < ratio:
|
|
33
|
+
wav = signal.fftconvolve(wav, rir, mode=mode) # (28671, 3)
|
|
34
|
+
# note: 建议过完添加混响后再进行归一化, 否则可能会出现溢出
|
|
35
|
+
# wav = volume_norm(wav)
|
|
36
|
+
return wav
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def snr_aug_changeNoise(clean, noise, snr):
|
|
40
|
+
"""
|
|
41
|
+
保持语音不变, 改变噪声的幅度
|
|
42
|
+
snr = 10 * log10(signal_power / k*noise_power)
|
|
43
|
+
"""
|
|
44
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
45
|
+
clean_power = np.mean(clean ** 2) # 纯净语音功率
|
|
46
|
+
noise_power = np.mean(noise ** 2) # 噪声功率
|
|
47
|
+
noise_scale = np.sqrt(clean_power / (noise_power * 10 ** (snr / 10) + EPS))
|
|
48
|
+
noisy = clean + noise_scale * noise
|
|
49
|
+
return noisy, noise_scale
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def snr_aug_changeNoise(clean, noise, snr):
|
|
53
|
+
"""
|
|
54
|
+
保持语音不变, 改变噪声的幅度
|
|
55
|
+
snr = 10 * log10(signal_power / k*noise_power)
|
|
56
|
+
"""
|
|
57
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
58
|
+
clean_power = np.mean(clean ** 2) # 纯净语音功率
|
|
59
|
+
noise_power = np.mean(noise ** 2) # 噪声功率
|
|
60
|
+
snr_in = 10 * np.log10(clean_power / (noise_power + EPS) + EPS)
|
|
61
|
+
snr_gain = snr_in - snr
|
|
62
|
+
gain = 10 ** (snr_gain / 20)
|
|
63
|
+
noisy = clean + gain * noise
|
|
64
|
+
return noisy
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def snr_aug_changeClean(clean, noise, snr):
|
|
68
|
+
"""
|
|
69
|
+
保持噪声不变, 改变语音的幅度
|
|
70
|
+
snr = 10 * log10(k*signal_power/ noise_power)
|
|
71
|
+
"""
|
|
72
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
73
|
+
clean_power = np.mean(clean ** 2)
|
|
74
|
+
noise_power = np.mean(noise ** 2)
|
|
75
|
+
clean_scale = np.sqrt(noise_power * 10 ** (snr / 10) / (clean_power + 1e-8))
|
|
76
|
+
noisy = clean * clean_scale + noise
|
|
77
|
+
|
|
78
|
+
return noisy, clean_scale
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def snr_aug_Interpolation(clean, noise, snr):
|
|
82
|
+
"""
|
|
83
|
+
在已知clean_len<=noise_len的情况下
|
|
84
|
+
将clean插入到noise中的snr aug方法
|
|
85
|
+
Args:
|
|
86
|
+
clean: 语音
|
|
87
|
+
noise: 噪声
|
|
88
|
+
snr: snr=random.uniform(*snr_range)
|
|
89
|
+
"""
|
|
90
|
+
clean_len, noise_len = clean.shape[0], noise.shape[0]
|
|
91
|
+
assert clean_len <= noise_len, f"clean_len must be less than noise_len."
|
|
92
|
+
noisy = noise.copy()
|
|
93
|
+
index = random.randint(0, noise_len - clean_len)
|
|
94
|
+
noise = noise[index:index + clean_len, :]
|
|
95
|
+
noisy_tmp, _ = snr_aug_changeClean(clean, noise, snr)
|
|
96
|
+
noisy[index:index + clean_len, :] = noisy_tmp
|
|
97
|
+
return noisy
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_audio_segments(wav_len, audio_path_list, sr=16000):
|
|
101
|
+
"""
|
|
102
|
+
从音频列表中随机拼接指定长度音频
|
|
103
|
+
Args:
|
|
104
|
+
wav_len: 需要返回的音频长度
|
|
105
|
+
audio_path_list: 音频路径列表
|
|
106
|
+
sr: 采样率
|
|
107
|
+
Returns:返回指定长度的音频
|
|
108
|
+
"""
|
|
109
|
+
audio_len = 0
|
|
110
|
+
wav_list = []
|
|
111
|
+
while audio_len < wav_len:
|
|
112
|
+
audio_path = random.choice(audio_path_list)
|
|
113
|
+
wav, wav_sr = sf.read(audio_path, always_2d=True, dtype='float32')
|
|
114
|
+
assert wav_sr == sr, f"音频采样率是{wav_sr}, 期望{sr}"
|
|
115
|
+
audio_len += len(wav)
|
|
116
|
+
wav_list.append(wav)
|
|
117
|
+
wav = np.concatenate(wav_list, axis=0)
|
|
118
|
+
if len(wav) > wav_len:
|
|
119
|
+
# 随机截取clean_len
|
|
120
|
+
start = random.randint(0, len(wav) - wav_len)
|
|
121
|
+
wav = wav[start:start + wav_len, :]
|
|
122
|
+
return wav
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def volume_aug(wav, range, rate, method="linmax"):
|
|
126
|
+
"""音量增强 """
|
|
127
|
+
if random.random() < rate:
|
|
128
|
+
target_level = random.uniform(range[0], range[1])
|
|
129
|
+
if method == "dbrms":
|
|
130
|
+
wav_rms = (wav ** 2).mean() ** 0.5
|
|
131
|
+
scalar = 10 ** (target_level / 20) / (np.max(wav_rms) + EPS)
|
|
132
|
+
elif method == "linmax":
|
|
133
|
+
ipt_max = np.max(np.abs(wav))
|
|
134
|
+
# wav/wav_max*target_level=target_level_wav
|
|
135
|
+
# 处理后音频的 最大值就是target_level
|
|
136
|
+
scalar = target_level / (ipt_max + EPS)
|
|
137
|
+
else:
|
|
138
|
+
raise ValueError("method must be 'dbrms' or 'linmax'")
|
|
139
|
+
wav *= scalar
|
|
140
|
+
return wav
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# -*- coding:utf-8 -*-
|
|
2
|
+
# Author:凌逆战 | Never
|
|
3
|
+
# Date: 2024/9/27
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
import random
|
|
8
|
+
import numpy as np
|
|
9
|
+
import soundfile as sf
|
|
10
|
+
from scipy import signal
|
|
11
|
+
from neverlib.utils import EPS
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def volume_norm(wav):
|
|
15
|
+
"""
|
|
16
|
+
音量归一化
|
|
17
|
+
:param wav: (T,)
|
|
18
|
+
:return: (T,)
|
|
19
|
+
"""
|
|
20
|
+
wav = wav / (np.max(np.abs(wav)) + 1e-8)
|
|
21
|
+
return wav
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def add_reverb(wav, rir, ratio=1, mode="same"):
|
|
25
|
+
"""添加混响,
|
|
26
|
+
Args:
|
|
27
|
+
wav: [T, channel]
|
|
28
|
+
rir: [T, channel]
|
|
29
|
+
ratio: 0-1
|
|
30
|
+
mode: "same" for SE or "full" for kws
|
|
31
|
+
"""
|
|
32
|
+
if random.random() < ratio:
|
|
33
|
+
wav = signal.fftconvolve(wav, rir, mode=mode) # (28671, 3)
|
|
34
|
+
# note: 建议过完添加混响后再进行归一化, 否则可能会出现溢出
|
|
35
|
+
# wav = volume_norm(wav)
|
|
36
|
+
return wav
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def snr_aug_changeNoise(clean, noise, snr):
|
|
40
|
+
"""
|
|
41
|
+
保持语音不变, 改变噪声的幅度
|
|
42
|
+
snr = 10 * log10(signal_power / k*noise_power)
|
|
43
|
+
"""
|
|
44
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
45
|
+
clean_power = np.mean(clean ** 2) # 纯净语音功率
|
|
46
|
+
noise_power = np.mean(noise ** 2) # 噪声功率
|
|
47
|
+
noise_scale = np.sqrt(clean_power / (noise_power * 10 ** (snr / 10) + EPS))
|
|
48
|
+
noisy = clean + noise_scale * noise
|
|
49
|
+
return noisy, noise_scale
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def snr_aug_changeNoise(clean, noise, snr):
|
|
53
|
+
"""
|
|
54
|
+
保持语音不变, 改变噪声的幅度
|
|
55
|
+
snr = 10 * log10(signal_power / k*noise_power)
|
|
56
|
+
"""
|
|
57
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
58
|
+
clean_power = np.mean(clean ** 2) # 纯净语音功率
|
|
59
|
+
noise_power = np.mean(noise ** 2) # 噪声功率
|
|
60
|
+
snr_in = 10 * np.log10(clean_power / (noise_power + EPS) + EPS)
|
|
61
|
+
snr_gain = snr_in - snr
|
|
62
|
+
gain = 10 ** (snr_gain / 20)
|
|
63
|
+
noisy = clean + gain * noise
|
|
64
|
+
return noisy
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def snr_aug_changeClean(clean, noise, snr):
|
|
68
|
+
"""
|
|
69
|
+
保持噪声不变, 改变语音的幅度
|
|
70
|
+
snr = 10 * log10(k*signal_power/ noise_power)
|
|
71
|
+
"""
|
|
72
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
73
|
+
clean_power = np.mean(clean ** 2)
|
|
74
|
+
noise_power = np.mean(noise ** 2)
|
|
75
|
+
clean_scale = np.sqrt(noise_power * 10 ** (snr / 10) / (clean_power + 1e-8))
|
|
76
|
+
noisy = clean * clean_scale + noise
|
|
77
|
+
|
|
78
|
+
return noisy, clean_scale
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def snr_aug_Interpolation(clean, noise, snr):
|
|
82
|
+
"""
|
|
83
|
+
在已知clean_len<=noise_len的情况下
|
|
84
|
+
将clean插入到noise中的snr aug方法
|
|
85
|
+
Args:
|
|
86
|
+
clean: 语音
|
|
87
|
+
noise: 噪声
|
|
88
|
+
snr: snr=random.uniform(*snr_range)
|
|
89
|
+
"""
|
|
90
|
+
clean_len, noise_len = clean.shape[0], noise.shape[0]
|
|
91
|
+
assert clean_len <= noise_len, f"clean_len must be less than noise_len."
|
|
92
|
+
noisy = noise.copy()
|
|
93
|
+
index = random.randint(0, noise_len - clean_len)
|
|
94
|
+
noise = noise[index:index + clean_len, :]
|
|
95
|
+
noisy_tmp, _ = snr_aug_changeClean(clean, noise, snr)
|
|
96
|
+
noisy[index:index + clean_len, :] = noisy_tmp
|
|
97
|
+
return noisy
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_audio_segments(wav_len, audio_path_list, sr=16000):
|
|
101
|
+
"""
|
|
102
|
+
从音频列表中随机拼接指定长度音频
|
|
103
|
+
Args:
|
|
104
|
+
wav_len: 需要返回的音频长度
|
|
105
|
+
audio_path_list: 音频路径列表
|
|
106
|
+
sr: 采样率
|
|
107
|
+
Returns:返回指定长度的音频
|
|
108
|
+
"""
|
|
109
|
+
audio_len = 0
|
|
110
|
+
wav_list = []
|
|
111
|
+
while audio_len < wav_len:
|
|
112
|
+
audio_path = random.choice(audio_path_list)
|
|
113
|
+
wav, wav_sr = sf.read(audio_path, always_2d=True, dtype='float32')
|
|
114
|
+
assert wav_sr == sr, f"音频采样率是{wav_sr}, 期望{sr}"
|
|
115
|
+
audio_len += len(wav)
|
|
116
|
+
wav_list.append(wav)
|
|
117
|
+
wav = np.concatenate(wav_list, axis=0)
|
|
118
|
+
if len(wav) > wav_len:
|
|
119
|
+
# 随机截取clean_len
|
|
120
|
+
start = random.randint(0, len(wav) - wav_len)
|
|
121
|
+
wav = wav[start:start + wav_len, :]
|
|
122
|
+
return wav
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def volume_aug(wav, range, rate, method="linmax"):
|
|
126
|
+
"""音量增强 """
|
|
127
|
+
if random.random() < rate:
|
|
128
|
+
target_level = random.uniform(range[0], range[1])
|
|
129
|
+
if method == "dbrms":
|
|
130
|
+
wav_rms = (wav ** 2).mean() ** 0.5
|
|
131
|
+
scalar = 10 ** (target_level / 20) / (np.max(wav_rms) + EPS)
|
|
132
|
+
elif method == "linmax":
|
|
133
|
+
ipt_max = np.max(np.abs(wav))
|
|
134
|
+
# wav/wav_max*target_level=target_level_wav
|
|
135
|
+
# 处理后音频的 最大值就是target_level
|
|
136
|
+
scalar = target_level / (ipt_max + EPS)
|
|
137
|
+
else:
|
|
138
|
+
raise ValueError("method must be 'dbrms' or 'linmax'")
|
|
139
|
+
wav *= scalar
|
|
140
|
+
return wav
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# -*- coding:utf-8 -*-
|
|
2
|
+
# Author:凌逆战 | Never
|
|
3
|
+
# Date: 2024/9/27
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
import random
|
|
8
|
+
import numpy as np
|
|
9
|
+
import soundfile as sf
|
|
10
|
+
from scipy import signal
|
|
11
|
+
from neverlib.utils import EPS
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def volume_norm(wav):
|
|
15
|
+
"""
|
|
16
|
+
音量归一化
|
|
17
|
+
:param wav: (T,)
|
|
18
|
+
:return: (T,)
|
|
19
|
+
"""
|
|
20
|
+
wav = wav / (np.max(np.abs(wav)) + 1e-8)
|
|
21
|
+
return wav
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def add_reverb(wav, rir, ratio=1, mode="same"):
|
|
25
|
+
"""添加混响,
|
|
26
|
+
Args:
|
|
27
|
+
wav: [T, channel]
|
|
28
|
+
rir: [T, channel]
|
|
29
|
+
ratio: 0-1
|
|
30
|
+
mode: "same" for SE or "full" for kws
|
|
31
|
+
"""
|
|
32
|
+
if random.random() < ratio:
|
|
33
|
+
wav = signal.fftconvolve(wav, rir, mode=mode) # (28671, 3)
|
|
34
|
+
# note: 建议过完添加混响后再进行归一化, 否则可能会出现溢出
|
|
35
|
+
# wav = volume_norm(wav)
|
|
36
|
+
return wav
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def snr_aug_changeNoise(clean, noise, snr):
|
|
40
|
+
"""
|
|
41
|
+
保持语音不变, 改变噪声的幅度
|
|
42
|
+
snr = 10 * log10(signal_power / k*noise_power)
|
|
43
|
+
"""
|
|
44
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
45
|
+
clean_power = np.mean(clean ** 2) # 纯净语音功率
|
|
46
|
+
noise_power = np.mean(noise ** 2) # 噪声功率
|
|
47
|
+
noise_scale = np.sqrt(clean_power / (noise_power * 10 ** (snr / 10) + EPS))
|
|
48
|
+
noisy = clean + noise_scale * noise
|
|
49
|
+
return noisy, noise_scale
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def snr_aug_changeNoise_v2(clean, noise, snr):
|
|
53
|
+
"""
|
|
54
|
+
保持语音不变, 改变噪声的幅度
|
|
55
|
+
snr = 10 * log10(signal_power / k*noise_power)
|
|
56
|
+
"""
|
|
57
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
58
|
+
clean_power = np.mean(clean ** 2) # 纯净语音功率
|
|
59
|
+
noise_power = np.mean(noise ** 2) # 噪声功率
|
|
60
|
+
snr_in = 10 * np.log10(clean_power / (noise_power + EPS) + EPS)
|
|
61
|
+
snr_gain = snr_in - snr
|
|
62
|
+
gain = 10 ** (snr_gain / 20)
|
|
63
|
+
noisy = clean + gain * noise
|
|
64
|
+
return noisy
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def snr_aug_changeClean(clean, noise, snr):
|
|
68
|
+
"""
|
|
69
|
+
保持噪声不变, 改变语音的幅度
|
|
70
|
+
snr = 10 * log10(k*signal_power/ noise_power)
|
|
71
|
+
"""
|
|
72
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
73
|
+
clean_power = np.mean(clean ** 2)
|
|
74
|
+
noise_power = np.mean(noise ** 2)
|
|
75
|
+
clean_scale = np.sqrt(noise_power * 10 ** (snr / 10) / (clean_power + 1e-8))
|
|
76
|
+
noisy = clean * clean_scale + noise
|
|
77
|
+
|
|
78
|
+
return noisy, clean_scale
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def snr_aug_Interpolation(clean, noise, snr):
|
|
82
|
+
"""
|
|
83
|
+
在已知clean_len<=noise_len的情况下
|
|
84
|
+
将clean插入到noise中的snr aug方法
|
|
85
|
+
Args:
|
|
86
|
+
clean: 语音
|
|
87
|
+
noise: 噪声
|
|
88
|
+
snr: snr=random.uniform(*snr_range)
|
|
89
|
+
"""
|
|
90
|
+
clean_len, noise_len = clean.shape[0], noise.shape[0]
|
|
91
|
+
assert clean_len <= noise_len, f"clean_len must be less than noise_len."
|
|
92
|
+
noisy = noise.copy()
|
|
93
|
+
index = random.randint(0, noise_len - clean_len)
|
|
94
|
+
noise = noise[index:index + clean_len, :]
|
|
95
|
+
noisy_tmp, _ = snr_aug_changeClean(clean, noise, snr)
|
|
96
|
+
noisy[index:index + clean_len, :] = noisy_tmp
|
|
97
|
+
return noisy
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_audio_segments(wav_len, audio_path_list, sr=16000):
|
|
101
|
+
"""
|
|
102
|
+
从音频列表中随机拼接指定长度音频
|
|
103
|
+
Args:
|
|
104
|
+
wav_len: 需要返回的音频长度
|
|
105
|
+
audio_path_list: 音频路径列表
|
|
106
|
+
sr: 采样率
|
|
107
|
+
Returns:返回指定长度的音频
|
|
108
|
+
"""
|
|
109
|
+
audio_len = 0
|
|
110
|
+
wav_list = []
|
|
111
|
+
while audio_len < wav_len:
|
|
112
|
+
audio_path = random.choice(audio_path_list)
|
|
113
|
+
wav, wav_sr = sf.read(audio_path, always_2d=True, dtype='float32')
|
|
114
|
+
assert wav_sr == sr, f"音频采样率是{wav_sr}, 期望{sr}"
|
|
115
|
+
audio_len += len(wav)
|
|
116
|
+
wav_list.append(wav)
|
|
117
|
+
wav = np.concatenate(wav_list, axis=0)
|
|
118
|
+
if len(wav) > wav_len:
|
|
119
|
+
# 随机截取clean_len
|
|
120
|
+
start = random.randint(0, len(wav) - wav_len)
|
|
121
|
+
wav = wav[start:start + wav_len, :]
|
|
122
|
+
return wav
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def volume_aug(wav, range, rate, method="linmax"):
|
|
126
|
+
"""音量增强 """
|
|
127
|
+
if random.random() < rate:
|
|
128
|
+
target_level = random.uniform(range[0], range[1])
|
|
129
|
+
if method == "dbrms":
|
|
130
|
+
wav_rms = (wav ** 2).mean() ** 0.5
|
|
131
|
+
scalar = 10 ** (target_level / 20) / (np.max(wav_rms) + EPS)
|
|
132
|
+
elif method == "linmax":
|
|
133
|
+
ipt_max = np.max(np.abs(wav))
|
|
134
|
+
# wav/wav_max*target_level=target_level_wav
|
|
135
|
+
# 处理后音频的 最大值就是target_level
|
|
136
|
+
scalar = target_level / (ipt_max + EPS)
|
|
137
|
+
else:
|
|
138
|
+
raise ValueError("method must be 'dbrms' or 'linmax'")
|
|
139
|
+
wav *= scalar
|
|
140
|
+
return wav
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# -*- coding:utf-8 -*-
|
|
2
|
+
# Author:凌逆战 | Never
|
|
3
|
+
# Date: 2024/9/27
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
import random
|
|
8
|
+
import numpy as np
|
|
9
|
+
import soundfile as sf
|
|
10
|
+
from scipy import signal
|
|
11
|
+
from neverlib.utils import EPS
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def volume_norm(wav):
|
|
15
|
+
"""
|
|
16
|
+
音量归一化
|
|
17
|
+
:param wav: (T,)
|
|
18
|
+
:return: (T,)
|
|
19
|
+
"""
|
|
20
|
+
wav = wav / (np.max(np.abs(wav)) + 1e-8)
|
|
21
|
+
return wav
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def add_reverb(wav, rir, ratio=1, mode="same"):
|
|
25
|
+
"""添加混响,
|
|
26
|
+
Args:
|
|
27
|
+
wav: [T, channel]
|
|
28
|
+
rir: [T, channel]
|
|
29
|
+
ratio: 0-1
|
|
30
|
+
mode: "same" for SE or "full" for kws
|
|
31
|
+
"""
|
|
32
|
+
if random.random() < ratio:
|
|
33
|
+
wav = signal.fftconvolve(wav, rir, mode=mode) # (28671, 3)
|
|
34
|
+
# note: 建议过完添加混响后再进行归一化, 否则可能会出现溢出
|
|
35
|
+
# wav = volume_norm(wav)
|
|
36
|
+
return wav
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def snr_aug_changeNoise(clean, noise, snr):
|
|
40
|
+
"""
|
|
41
|
+
保持语音不变, 改变噪声的幅度
|
|
42
|
+
snr = 10 * log10(signal_power / k*noise_power)
|
|
43
|
+
"""
|
|
44
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
45
|
+
clean_power = np.mean(clean ** 2) # 纯净语音功率
|
|
46
|
+
noise_power = np.mean(noise ** 2) # 噪声功率
|
|
47
|
+
noise_scale = np.sqrt(clean_power / (noise_power * 10 ** (snr / 10) + EPS))
|
|
48
|
+
noisy = clean + noise_scale * noise
|
|
49
|
+
return noisy, noise_scale
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def snr_aug_changeNoise_v2(clean, noise, snr):
|
|
53
|
+
"""
|
|
54
|
+
保持语音不变, 改变噪声的幅度
|
|
55
|
+
snr = 10 * log10(signal_power / k*noise_power)
|
|
56
|
+
"""
|
|
57
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
58
|
+
clean_power = np.mean(clean ** 2) # 纯净语音功率
|
|
59
|
+
noise_power = np.mean(noise ** 2) # 噪声功率
|
|
60
|
+
snr_in = 10 * np.log10(clean_power / (noise_power + EPS) + EPS)
|
|
61
|
+
snr_gain = snr_in - snr
|
|
62
|
+
gain = 10 ** (snr_gain / 20)
|
|
63
|
+
noisy = clean + gain * noise
|
|
64
|
+
return noisy, gain
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def snr_aug_changeClean(clean, noise, snr):
|
|
68
|
+
"""
|
|
69
|
+
保持噪声不变, 改变语音的幅度
|
|
70
|
+
snr = 10 * log10(k*signal_power/ noise_power)
|
|
71
|
+
"""
|
|
72
|
+
assert clean.shape == noise.shape, "clean and noise must have the same shape"
|
|
73
|
+
clean_power = np.mean(clean ** 2)
|
|
74
|
+
noise_power = np.mean(noise ** 2)
|
|
75
|
+
clean_scale = np.sqrt(noise_power * 10 ** (snr / 10) / (clean_power + 1e-8))
|
|
76
|
+
noisy = clean * clean_scale + noise
|
|
77
|
+
|
|
78
|
+
return noisy, clean_scale
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def snr_aug_Interpolation(clean, noise, snr):
|
|
82
|
+
"""
|
|
83
|
+
在已知clean_len<=noise_len的情况下
|
|
84
|
+
将clean插入到noise中的snr aug方法
|
|
85
|
+
Args:
|
|
86
|
+
clean: 语音
|
|
87
|
+
noise: 噪声
|
|
88
|
+
snr: snr=random.uniform(*snr_range)
|
|
89
|
+
"""
|
|
90
|
+
clean_len, noise_len = clean.shape[0], noise.shape[0]
|
|
91
|
+
assert clean_len <= noise_len, f"clean_len must be less than noise_len."
|
|
92
|
+
noisy = noise.copy()
|
|
93
|
+
index = random.randint(0, noise_len - clean_len)
|
|
94
|
+
noise = noise[index:index + clean_len, :]
|
|
95
|
+
noisy_tmp, _ = snr_aug_changeClean(clean, noise, snr)
|
|
96
|
+
noisy[index:index + clean_len, :] = noisy_tmp
|
|
97
|
+
return noisy
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def get_audio_segments(wav_len, audio_path_list, sr=16000):
|
|
101
|
+
"""
|
|
102
|
+
从音频列表中随机拼接指定长度音频
|
|
103
|
+
Args:
|
|
104
|
+
wav_len: 需要返回的音频长度
|
|
105
|
+
audio_path_list: 音频路径列表
|
|
106
|
+
sr: 采样率
|
|
107
|
+
Returns:返回指定长度的音频
|
|
108
|
+
"""
|
|
109
|
+
audio_len = 0
|
|
110
|
+
wav_list = []
|
|
111
|
+
while audio_len < wav_len:
|
|
112
|
+
audio_path = random.choice(audio_path_list)
|
|
113
|
+
wav, wav_sr = sf.read(audio_path, always_2d=True, dtype='float32')
|
|
114
|
+
assert wav_sr == sr, f"音频采样率是{wav_sr}, 期望{sr}"
|
|
115
|
+
audio_len += len(wav)
|
|
116
|
+
wav_list.append(wav)
|
|
117
|
+
wav = np.concatenate(wav_list, axis=0)
|
|
118
|
+
if len(wav) > wav_len:
|
|
119
|
+
# 随机截取clean_len
|
|
120
|
+
start = random.randint(0, len(wav) - wav_len)
|
|
121
|
+
wav = wav[start:start + wav_len, :]
|
|
122
|
+
return wav
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def volume_aug(wav, range, rate, method="linmax"):
|
|
126
|
+
"""音量增强 """
|
|
127
|
+
if random.random() < rate:
|
|
128
|
+
target_level = random.uniform(range[0], range[1])
|
|
129
|
+
if method == "dbrms":
|
|
130
|
+
wav_rms = (wav ** 2).mean() ** 0.5
|
|
131
|
+
scalar = 10 ** (target_level / 20) / (np.max(wav_rms) + EPS)
|
|
132
|
+
elif method == "linmax":
|
|
133
|
+
ipt_max = np.max(np.abs(wav))
|
|
134
|
+
# wav/wav_max*target_level=target_level_wav
|
|
135
|
+
# 处理后音频的 最大值就是target_level
|
|
136
|
+
scalar = target_level / (ipt_max + EPS)
|
|
137
|
+
else:
|
|
138
|
+
raise ValueError("method must be 'dbrms' or 'linmax'")
|
|
139
|
+
wav *= scalar
|
|
140
|
+
return wav
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Author: 凌逆战 | Never
|
|
3
|
+
Date: 2025-08-06 00:56:39
|
|
4
|
+
Description:
|
|
5
|
+
'''
|
|
6
|
+
"""
|
|
7
|
+
音频数据分析模块
|
|
8
|
+
Audio Data Analysis Module
|
|
9
|
+
|
|
10
|
+
提供完整的音频数据分析功能, 包括特征提取、质量评估、统计分析和可视化等。
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# 基础工具
|
|
14
|
+
from neverlib.dataAnalyze.temporal_features import dB, peak_amplitude, rms_amplitude
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Author: 凌逆战 | Never
|
|
3
|
+
Date: 2025-08-06 00:56:39
|
|
4
|
+
Description:
|
|
5
|
+
'''
|
|
6
|
+
"""
|
|
7
|
+
音频数据分析模块
|
|
8
|
+
Audio Data Analysis Module
|
|
9
|
+
|
|
10
|
+
提供完整的音频数据分析功能, 包括特征提取、质量评估、统计分析和可视化等。
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# 基础工具
|
|
14
|
+
from .dataAnalyze.temporal_features import dB, peak_amplitude, rms_amplitude
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Author: 凌逆战 | Never
|
|
3
|
+
Date: 2025-08-06 00:56:39
|
|
4
|
+
Description:
|
|
5
|
+
'''
|
|
6
|
+
"""
|
|
7
|
+
音频数据分析模块
|
|
8
|
+
Audio Data Analysis Module
|
|
9
|
+
|
|
10
|
+
提供完整的音频数据分析功能, 包括特征提取、质量评估、统计分析和可视化等。
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# 基础工具
|
|
14
|
+
from neverlib.dataAnalyze.temporal_features import dB, peak_amplitude, rms_amplitude
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Author: 凌逆战 | Never
|
|
3
|
+
Date: 2025-03-17 19:23:33
|
|
4
|
+
Description:
|
|
5
|
+
'''
|
|
6
|
+
"""
|
|
7
|
+
节省路径
|
|
8
|
+
from neverlib.filter import common
|
|
9
|
+
如果没有用户必须完整路径
|
|
10
|
+
from neverlib.filter.common import *
|
|
11
|
+
"""
|
|
12
|
+
from .common import *
|
|
13
|
+
from .core import *
|
|
14
|
+
from .biquad import *
|
|
15
|
+
|
|
16
|
+
def __getattr__(name):
|
|
17
|
+
"""延迟导入机制 - 只在用户实际使用时才导入需要额外依赖的模块"""
|
|
18
|
+
if name in ['compute_frequency_eq']:
|
|
19
|
+
# 需要 librosa 库的频谱直接补偿方法
|
|
20
|
+
try:
|
|
21
|
+
from .AudoEQ.auto_eq_spectral_direct import compute_frequency_eq
|
|
22
|
+
return compute_frequency_eq
|
|
23
|
+
except ImportError as e:
|
|
24
|
+
raise ImportError(f"使用 {name} 需要安装 librosa: pip install librosa") from e
|
|
25
|
+
|
|
26
|
+
elif name in ['get_filter_function', 'match_frequency_response', 'plot_spectra_comparison']:
|
|
27
|
+
# 差分进化优化方法
|
|
28
|
+
try:
|
|
29
|
+
from .AudoEQ.auto_eq_de import get_filter_function, match_frequency_response, plot_spectra_comparison
|
|
30
|
+
if name == 'get_filter_function':
|
|
31
|
+
return get_filter_function
|
|
32
|
+
elif name == 'match_frequency_response':
|
|
33
|
+
return match_frequency_response
|
|
34
|
+
elif name == 'plot_spectra_comparison':
|
|
35
|
+
return plot_spectra_comparison
|
|
36
|
+
except ImportError as e:
|
|
37
|
+
raise ImportError(f"使用 {name} 需要安装相应依赖,详见 AudoEQ/README.md") from e
|
|
38
|
+
|
|
39
|
+
elif name in ['individual_creator', 'get_magnitude_spectrum_db', 'get_single_filter_freq_response_db_from_coeffs',
|
|
40
|
+
'get_combined_eq_response_db', 'evaluate_individual', 'custom_mutate']:
|
|
41
|
+
# 需要 deap 库的遗传算法基础版
|
|
42
|
+
try:
|
|
43
|
+
from .AudoEQ.auto_eq_ga_basic import (
|
|
44
|
+
individual_creator, get_magnitude_spectrum_db, get_single_filter_freq_response_db_from_coeffs,
|
|
45
|
+
get_combined_eq_response_db, evaluate_individual, custom_mutate
|
|
46
|
+
)
|
|
47
|
+
if name == 'individual_creator':
|
|
48
|
+
return individual_creator
|
|
49
|
+
elif name == 'get_magnitude_spectrum_db':
|
|
50
|
+
return get_magnitude_spectrum_db
|
|
51
|
+
elif name == 'get_single_filter_freq_response_db_from_coeffs':
|
|
52
|
+
return get_single_filter_freq_response_db_from_coeffs
|
|
53
|
+
elif name == 'get_combined_eq_response_db':
|
|
54
|
+
return get_combined_eq_response_db
|
|
55
|
+
elif name == 'evaluate_individual':
|
|
56
|
+
return evaluate_individual
|
|
57
|
+
elif name == 'custom_mutate':
|
|
58
|
+
return custom_mutate
|
|
59
|
+
except ImportError as e:
|
|
60
|
+
raise ImportError(f"使用 {name} 需要安装 deap: pip install deap") from e
|
|
61
|
+
|
|
62
|
+
elif name == 'EQOptimizer':
|
|
63
|
+
# 需要 deap 库的遗传算法高级版
|
|
64
|
+
try:
|
|
65
|
+
from .AudoEQ.auto_eq_ga_advanced import EQOptimizer
|
|
66
|
+
return EQOptimizer
|
|
67
|
+
except ImportError as e:
|
|
68
|
+
raise ImportError(f"使用 {name} 需要安装 deap: pip install deap") from e
|
|
69
|
+
|
|
70
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|