neverlib 0.2.2__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.
Files changed (236) hide show
  1. neverlib/.history/Docs/audio_aug/test_snr_20250806011311.py +0 -0
  2. neverlib/.history/Docs/audio_aug/test_snr_20250806011331.py +75 -0
  3. neverlib/.history/Docs/audio_aug/test_snr_20250806011342.py +57 -0
  4. neverlib/.history/Docs/audio_aug/test_snr_20250806011352.py +57 -0
  5. neverlib/.history/Docs/audio_aug/test_snr_20250806011403.py +57 -0
  6. neverlib/.history/Docs/audio_aug/test_snr_20250806011413.py +57 -0
  7. neverlib/.history/Docs/audio_aug/test_snr_20250806011435.py +55 -0
  8. neverlib/.history/Docs/vad/1_20250810032405.py +0 -0
  9. neverlib/.history/Docs/vad/1_20250810032417.py +39 -0
  10. neverlib/.history/audio_aug/audio_aug_20250806010451.py +125 -0
  11. neverlib/.history/audio_aug/audio_aug_20250806010750.py +138 -0
  12. neverlib/.history/audio_aug/audio_aug_20250806010759.py +140 -0
  13. neverlib/.history/audio_aug/audio_aug_20250806010803.py +140 -0
  14. neverlib/.history/audio_aug/audio_aug_20250806010809.py +140 -0
  15. neverlib/.history/audio_aug/audio_aug_20250806011108.py +140 -0
  16. neverlib/.history/dataAnalyze/__init___20250805234204.py +87 -0
  17. neverlib/.history/dataAnalyze/__init___20250806204125.py +14 -0
  18. neverlib/.history/dataAnalyze/__init___20250806204139.py +14 -0
  19. neverlib/.history/dataAnalyze/__init___20250806204159.py +14 -0
  20. neverlib/.history/filter/__init___20250820103351.py +70 -0
  21. neverlib/.history/filter/__init___20250821102348.py +70 -0
  22. neverlib/.history/filter/__init___20250821102405.py +14 -0
  23. neverlib/.history/filter/auto_eq/__init___20250819213121.py +36 -0
  24. neverlib/.history/filter/auto_eq/__init___20250821102241.py +36 -0
  25. neverlib/.history/filter/auto_eq/__init___20250821102259.py +36 -0
  26. neverlib/.history/filter/auto_eq/__init___20250821102307.py +36 -0
  27. neverlib/.history/filter/auto_eq/__init___20250821102310.py +36 -0
  28. neverlib/.history/filter/auto_eq/__init___20250821102318.py +36 -0
  29. neverlib/.history/filter/auto_eq/__init___20250821102507.py +36 -0
  30. neverlib/.history/filter/auto_eq/de_eq_20250820103848.py +361 -0
  31. neverlib/.history/filter/auto_eq/de_eq_20250821102422.py +360 -0
  32. neverlib/.history/filter/auto_eq/freq_eq_20250805234206.py +75 -0
  33. neverlib/.history/filter/auto_eq/freq_eq_20250820140732.py +75 -0
  34. neverlib/.history/filter/auto_eq/freq_eq_20250820140745.py +75 -0
  35. neverlib/.history/filter/auto_eq/freq_eq_20250820140816.py +75 -0
  36. neverlib/.history/filter/auto_eq/freq_eq_20250820140938.py +77 -0
  37. neverlib/.history/filter/auto_eq/freq_eq_20250820141003.py +77 -0
  38. neverlib/.history/filter/auto_eq/freq_eq_20250820141006.py +77 -0
  39. neverlib/.history/filter/auto_eq/freq_eq_20250820141019.py +77 -0
  40. neverlib/.history/filter/auto_eq/freq_eq_20250820141049.py +77 -0
  41. neverlib/.history/filter/auto_eq/freq_eq_20250820141211.py +77 -0
  42. neverlib/.history/filter/auto_eq/freq_eq_20250820141227.py +77 -0
  43. neverlib/.history/filter/auto_eq/freq_eq_20250820141311.py +78 -0
  44. neverlib/.history/filter/auto_eq/freq_eq_20250820141340.py +78 -0
  45. neverlib/.history/filter/auto_eq/freq_eq_20250820141712.py +78 -0
  46. neverlib/.history/filter/auto_eq/freq_eq_20250820141733.py +78 -0
  47. neverlib/.history/filter/auto_eq/freq_eq_20250820141755.py +78 -0
  48. neverlib/.history/filter/auto_eq/freq_eq_20250821102434.py +76 -0
  49. neverlib/.history/filter/auto_eq/freq_eq_20250821102500.py +76 -0
  50. neverlib/.history/filter/auto_eq/freq_eq_20250821102502.py +76 -0
  51. neverlib/.history/filter/auto_eq/ga_eq_basic_20250820102957.py +380 -0
  52. neverlib/.history/filter/auto_eq/ga_eq_basic_20250820113054.py +380 -0
  53. neverlib/.history/filter/auto_eq/ga_eq_basic_20250820113150.py +380 -0
  54. neverlib/.history/filter/auto_eq/ga_eq_basic_20250820113520.py +385 -0
  55. neverlib/.history/filter/auto_eq/ga_eq_basic_20250820113525.py +385 -0
  56. neverlib/.history/filter/auto_eq/ga_eq_basic_20250821102212.py +385 -0
  57. neverlib/.history/metrics/dnsmos_20250806001612.py +160 -0
  58. neverlib/.history/metrics/dnsmos_20250815180659.py +160 -0
  59. neverlib/.history/metrics/dnsmos_20250815180701.py +158 -0
  60. neverlib/.history/metrics/dnsmos_20250815181321.py +154 -0
  61. neverlib/.history/metrics/dnsmos_20250815181327.py +154 -0
  62. neverlib/.history/metrics/dnsmos_20250815181331.py +154 -0
  63. neverlib/.history/metrics/dnsmos_20250815181620.py +154 -0
  64. neverlib/.history/metrics/dnsmos_20250815181631.py +154 -0
  65. neverlib/.history/metrics/dnsmos_20250815181742.py +154 -0
  66. neverlib/.history/metrics/dnsmos_20250815181824.py +153 -0
  67. neverlib/.history/metrics/dnsmos_20250815181834.py +153 -0
  68. neverlib/.history/metrics/dnsmos_20250815181922.py +153 -0
  69. neverlib/.history/metrics/dnsmos_20250815182011.py +147 -0
  70. neverlib/.history/metrics/dnsmos_20250815182036.py +144 -0
  71. neverlib/.history/metrics/dnsmos_20250815182936.py +143 -0
  72. neverlib/.history/metrics/dnsmos_20250815182942.py +143 -0
  73. neverlib/.history/metrics/dnsmos_20250815183032.py +137 -0
  74. neverlib/.history/metrics/dnsmos_20250815183101.py +144 -0
  75. neverlib/.history/metrics/dnsmos_20250815183121.py +144 -0
  76. neverlib/.history/metrics/dnsmos_20250815183123.py +143 -0
  77. neverlib/.history/metrics/dnsmos_20250815183214.py +143 -0
  78. neverlib/.history/metrics/dnsmos_20250815183240.py +143 -0
  79. neverlib/.history/metrics/dnsmos_20250815183248.py +144 -0
  80. neverlib/.history/metrics/dnsmos_20250815183407.py +142 -0
  81. neverlib/.history/metrics/dnsmos_20250815183409.py +142 -0
  82. neverlib/.history/metrics/dnsmos_20250815183431.py +142 -0
  83. neverlib/.history/metrics/dnsmos_20250815183507.py +140 -0
  84. neverlib/.history/metrics/dnsmos_20250815183513.py +139 -0
  85. neverlib/.history/metrics/dnsmos_20250815183618.py +139 -0
  86. neverlib/.history/metrics/dnsmos_20250815183709.py +140 -0
  87. neverlib/.history/metrics/dnsmos_20250815183756.py +137 -0
  88. neverlib/.history/metrics/dnsmos_20250815183815.py +128 -0
  89. neverlib/.history/metrics/dnsmos_20250815183827.py +129 -0
  90. neverlib/.history/metrics/dnsmos_20250815183913.py +117 -0
  91. neverlib/.history/metrics/dnsmos_20250815183914.py +117 -0
  92. neverlib/.history/metrics/dnsmos_20250815184003.py +118 -0
  93. neverlib/.history/metrics/dnsmos_20250815184040.py +118 -0
  94. neverlib/.history/metrics/dnsmos_20250815184049.py +118 -0
  95. neverlib/.history/metrics/dnsmos_20250815184104.py +117 -0
  96. neverlib/.history/metrics/dnsmos_20250815184200.py +117 -0
  97. neverlib/.history/metrics/lpc_lsp_metric_20250816015944.py +128 -0
  98. neverlib/.history/metrics/lpc_lsp_metric_20250816020142.py +128 -0
  99. neverlib/.history/metrics/lpc_lsp_metric_20250816020156.py +128 -0
  100. neverlib/.history/metrics/lpc_lsp_metric_20250816020554.py +130 -0
  101. neverlib/.history/metrics/lpc_lsp_metric_20250816020600.py +125 -0
  102. neverlib/.history/metrics/lpc_lsp_metric_20250816020631.py +120 -0
  103. neverlib/.history/metrics/lpc_lsp_metric_20250816020746.py +118 -0
  104. neverlib/.history/metrics/lpc_me_20250816013111.py +0 -0
  105. neverlib/.history/metrics/lpc_me_20250816013129.py +121 -0
  106. neverlib/.history/metrics/lpc_me_20250816015430.py +103 -0
  107. neverlib/.history/metrics/lpc_me_20250816015535.py +96 -0
  108. neverlib/.history/metrics/lpc_me_20250816015542.py +96 -0
  109. neverlib/.history/metrics/lpc_me_20250816015636.py +97 -0
  110. neverlib/.history/metrics/lpc_me_20250816015658.py +104 -0
  111. neverlib/.history/metrics/lpc_me_20250816015703.py +100 -0
  112. neverlib/.history/metrics/lpc_me_20250816015945.py +128 -0
  113. neverlib/.history/metrics/snr_20250806010538.py +177 -0
  114. neverlib/.history/metrics/snr_20250806211634.py +184 -0
  115. neverlib/.history/metrics/spec_20250805234209.py +45 -0
  116. neverlib/.history/metrics/spec_20250816135530.py +11 -0
  117. neverlib/.history/metrics/spec_20250816135654.py +16 -0
  118. neverlib/.history/metrics/spec_20250816135736.py +68 -0
  119. neverlib/.history/metrics/spec_20250816135904.py +75 -0
  120. neverlib/.history/metrics/spec_20250816135921.py +82 -0
  121. neverlib/.history/metrics/spec_20250816140111.py +82 -0
  122. neverlib/.history/metrics/spec_20250816140543.py +136 -0
  123. neverlib/.history/metrics/spec_20250816140559.py +172 -0
  124. neverlib/.history/metrics/spec_20250816140602.py +172 -0
  125. neverlib/.history/metrics/spec_20250816140608.py +172 -0
  126. neverlib/.history/metrics/spec_20250816140654.py +148 -0
  127. neverlib/.history/metrics/spec_20250816140705.py +144 -0
  128. neverlib/.history/metrics/spec_20250816140755.py +138 -0
  129. neverlib/.history/metrics/spec_20250816140823.py +170 -0
  130. neverlib/.history/metrics/spec_20250816140832.py +170 -0
  131. neverlib/.history/metrics/spec_20250816140833.py +170 -0
  132. neverlib/.history/metrics/spec_20250816140922.py +147 -0
  133. neverlib/.history/metrics/spec_20250816141148.py +107 -0
  134. neverlib/.history/metrics/spec_20250816141219.py +123 -0
  135. neverlib/.history/metrics/spec_20250816141732.py +178 -0
  136. neverlib/.history/metrics/spec_20250816141740.py +178 -0
  137. neverlib/.history/metrics/spec_20250816142030.py +178 -0
  138. neverlib/.history/metrics/spec_20250816142107.py +135 -0
  139. neverlib/.history/metrics/spec_20250816142126.py +135 -0
  140. neverlib/.history/metrics/spec_20250816142410.py +135 -0
  141. neverlib/.history/metrics/spec_20250816142415.py +136 -0
  142. neverlib/.history/metrics/spec_metric_20250816135156.py +0 -0
  143. neverlib/.history/metrics/spec_metric_20250816135226.py +5 -0
  144. neverlib/.history/metrics/spec_metric_20250816135227.py +10 -0
  145. neverlib/.history/metrics/spec_metric_20250816135306.py +15 -0
  146. neverlib/.history/metrics/spec_metric_20250816135442.py +31 -0
  147. neverlib/.history/metrics/spec_metric_20250816135448.py +31 -0
  148. neverlib/.history/metrics/spec_metric_20250816135520.py +29 -0
  149. neverlib/.history/metrics/spec_metric_20250816135537.py +63 -0
  150. neverlib/.history/metrics/spec_metric_20250816135653.py +65 -0
  151. neverlib/.history/vad/PreProcess_20250805234211.py +63 -0
  152. neverlib/.history/vad/PreProcess_20250809232455.py +63 -0
  153. neverlib/.history/vad/PreProcess_20250816020725.py +66 -0
  154. neverlib/.history/vad/VAD_Silero_20250805234211.py +50 -0
  155. neverlib/.history/vad/VAD_Silero_20250809232456.py +50 -0
  156. neverlib/.history/vad/VAD_WebRTC_20250805234211.py +61 -0
  157. neverlib/.history/vad/VAD_WebRTC_20250809232456.py +61 -0
  158. neverlib/.history/vad/VAD_funasr_20250805234211.py +54 -0
  159. neverlib/.history/vad/VAD_funasr_20250809232456.py +54 -0
  160. neverlib/.history/vad/VAD_vadlib_20250805234211.py +70 -0
  161. neverlib/.history/vad/VAD_vadlib_20250809232455.py +70 -0
  162. neverlib/.history/vad/VAD_whisper_20250805234211.py +55 -0
  163. neverlib/.history/vad/VAD_whisper_20250809232456.py +55 -0
  164. neverlib/.specstory/.what-is-this.md +69 -0
  165. 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
  166. neverlib/Docs/audio_aug/test_snr.py +55 -0
  167. neverlib/__init__.py +2 -2
  168. neverlib/audio_aug/HarmonicDistortion.py +79 -0
  169. neverlib/audio_aug/TFDrop.py +41 -0
  170. neverlib/audio_aug/TFMask.py +56 -0
  171. neverlib/audio_aug/__init__.py +1 -1
  172. neverlib/audio_aug/audio_aug.py +19 -5
  173. neverlib/audio_aug/clip_aug.py +41 -0
  174. neverlib/audio_aug/coder_aug.py +209 -0
  175. neverlib/audio_aug/coder_aug2.py +118 -0
  176. neverlib/audio_aug/loss_packet_aug.py +103 -0
  177. neverlib/audio_aug/quant_aug.py +78 -0
  178. neverlib/data_analyze/README.md +234 -0
  179. neverlib/data_analyze/__init__.py +14 -0
  180. neverlib/data_analyze/dataset_analyzer.py +590 -0
  181. neverlib/data_analyze/quality_metrics.py +364 -0
  182. neverlib/data_analyze/rms_distrubution.py +62 -0
  183. neverlib/data_analyze/spectral_analysis.py +218 -0
  184. neverlib/data_analyze/statistics.py +406 -0
  185. neverlib/data_analyze/temporal_features.py +126 -0
  186. neverlib/data_analyze/visualization.py +468 -0
  187. neverlib/filter/README.md +101 -0
  188. neverlib/filter/__init__.py +7 -0
  189. neverlib/filter/auto_eq/README.md +165 -0
  190. neverlib/filter/auto_eq/__init__.py +36 -0
  191. neverlib/filter/auto_eq/de_eq.py +360 -0
  192. neverlib/filter/auto_eq/freq_eq.py +76 -0
  193. neverlib/filter/auto_eq/ga_eq_advanced.py +577 -0
  194. neverlib/filter/auto_eq/ga_eq_basic.py +385 -0
  195. neverlib/filter/biquad.py +45 -0
  196. neverlib/filter/common.py +5 -6
  197. neverlib/filter/core.py +339 -0
  198. neverlib/metrics/dnsmos.py +117 -0
  199. neverlib/metrics/lpc_lsp.py +118 -0
  200. neverlib/metrics/snr.py +184 -0
  201. neverlib/metrics/spec.py +136 -0
  202. neverlib/metrics/test_pesq.py +35 -0
  203. neverlib/metrics/time.py +68 -0
  204. neverlib/tests/test_vad.py +21 -0
  205. neverlib/utils/audio_split.py +2 -1
  206. neverlib/utils/message.py +4 -4
  207. neverlib/utils/utils.py +36 -16
  208. neverlib/vad/PreProcess.py +6 -3
  209. neverlib/vad/README.md +10 -10
  210. neverlib/vad/VAD_Energy.py +1 -1
  211. neverlib/vad/VAD_Silero.py +2 -2
  212. neverlib/vad/VAD_WebRTC.py +2 -2
  213. neverlib/vad/VAD_funasr.py +2 -2
  214. neverlib/vad/VAD_statistics.py +3 -3
  215. neverlib/vad/VAD_vadlib.py +3 -3
  216. neverlib/vad/VAD_whisper.py +2 -2
  217. neverlib/vad/__init__.py +1 -1
  218. neverlib/vad/class_get_speech.py +4 -4
  219. neverlib/vad/class_vad.py +1 -1
  220. neverlib/vad/utils.py +47 -5
  221. {neverlib-0.2.2.dist-info → neverlib-0.2.4.dist-info}/METADATA +120 -120
  222. neverlib-0.2.4.dist-info/RECORD +229 -0
  223. {neverlib-0.2.2.dist-info → neverlib-0.2.4.dist-info}/WHEEL +1 -1
  224. neverlib/Documents/vad/VAD_Energy.ipynb +0 -159
  225. neverlib/Documents/vad/VAD_Silero.ipynb +0 -305
  226. neverlib/Documents/vad/VAD_WebRTC.ipynb +0 -183
  227. neverlib/Documents/vad/VAD_funasr.ipynb +0 -179
  228. neverlib/Documents/vad/VAD_ppasr.ipynb +0 -175
  229. neverlib/Documents/vad/VAD_statistics.ipynb +0 -522
  230. neverlib/Documents/vad/VAD_vadlib.ipynb +0 -184
  231. neverlib/Documents/vad/VAD_whisper.ipynb +0 -430
  232. neverlib/utils/waveform_analyzer.py +0 -51
  233. neverlib/wav_data/000_short.wav +0 -0
  234. neverlib-0.2.2.dist-info/RECORD +0 -40
  235. {neverlib-0.2.2.dist-info → neverlib-0.2.4.dist-info}/licenses/LICENSE +0 -0
  236. {neverlib-0.2.2.dist-info → neverlib-0.2.4.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,184 @@
1
+ import sys
2
+ sys.path.append("../")
3
+ import librosa
4
+ import numpy as np
5
+ from neverlib.vad.utils import vad2nad
6
+
7
+
8
+ def get_snr(speech, noise):
9
+ """计算信噪比
10
+ Args:
11
+ speech: 语音音频
12
+ noise: 噪声音频
13
+ Returns:
14
+ snr: 信噪比
15
+ """
16
+ assert speech.ndim == noise.ndim, "speech和noise的维度不一样"
17
+
18
+ power_speech = np.mean(speech**2)
19
+ power_noise = max(np.mean(noise**2), 1e-10)
20
+
21
+ snr = 10 * np.log10(power_speech / power_noise)
22
+ return snr
23
+
24
+
25
+ def get_snr_from_noisy(noisy, speech_vad=None):
26
+ """根据带噪音频计算信噪比
27
+ Args:
28
+ noisy: 带噪音频
29
+ speech_vad: [{start:xxx, end:xxx}, ...]
30
+ Returns:
31
+ snr: 信噪比
32
+ """
33
+ assert speech_vad is not None, "speech_vad不能为空"
34
+
35
+ # 提取语音段
36
+ speech_segments = []
37
+ for segment in speech_vad:
38
+ start = segment['start']
39
+ end = segment['end']
40
+ speech_segments.append(noisy[start:end])
41
+ speech = np.concatenate(speech_segments, axis=0)
42
+
43
+ # 提取非语音段
44
+ noise_segments = []
45
+ noise_point_list = vad2nad(speech_vad, len(noisy))
46
+ for noise_point in noise_point_list:
47
+ noise_segments.append(noisy[noise_point['start']:noise_point['end']])
48
+ noise = np.concatenate(noise_segments, axis=0)
49
+
50
+ P_speech_noise = np.mean(speech ** 2) # 语音+噪声功率
51
+ P_noise = max(np.mean(noise ** 2), EPS) # 纯噪声功率
52
+
53
+ # 计算净语音功率
54
+ P_speech = max(P_speech_noise - P_noise, EPS)
55
+ snr = 10 * np.log10(P_speech / P_noise)
56
+
57
+ return snr
58
+
59
+
60
+ def seg_snr(clean, noisy, frame_length: int, hop_length: int):
61
+ """
62
+ 分帧计算信噪比
63
+ Args:
64
+ clean: 干净音频, numpy array
65
+ noisy: 带噪音频, numpy array
66
+ frame_length: 帧长
67
+ hop_length: 帧移
68
+ Returns:
69
+ snr_mean: 平均信噪比, float
70
+ Raises:
71
+ ValueError: 当输入参数不合法时抛出
72
+ """
73
+ assert clean.shape == noisy.shape, "clean和noisy的维度不一样"
74
+
75
+ # 分帧
76
+ clean_frames = librosa.util.frame(clean, frame_length=frame_length, hop_length=hop_length) # (frame_length, n_frames)
77
+ noisy_frames = librosa.util.frame(noisy, frame_length=frame_length, hop_length=hop_length) # (frame_length, n_frames)
78
+
79
+ # 计算每帧的信噪比
80
+ snr_frames = []
81
+ for i in range(clean_frames.shape[1]):
82
+ clean_frame = clean_frames[:, i]
83
+ noisy_frame = noisy_frames[:, i]
84
+ # 跳过静音帧
85
+ if np.all(np.abs(clean_frame) < 1e-6) or np.all(np.abs(noisy_frame) < 1e-6):
86
+ continue
87
+ snr_frames.append(get_snr(clean_frame, noisy_frame))
88
+
89
+ # 如果所有帧都是静音
90
+ if not snr_frames:
91
+ return float('-inf')
92
+
93
+ return np.mean(snr_frames)
94
+
95
+
96
+ def psnr(clean, noisy, max_val=None):
97
+ """
98
+ 计算峰值信噪比
99
+ Args:
100
+ clean: 干净音频, numpy array
101
+ noisy: 带噪音频, numpy array
102
+ max_val: 信号最大值, 如果为None则使用clean信号的实际最大值
103
+ Returns:
104
+ psnr: 峰值信噪比, 单位dB
105
+ """
106
+ assert clean.shape == noisy.shape, "clean和noisy的维度不一样"
107
+
108
+ # 如果没有指定最大值, 使用clean信号的实际最大值
109
+ if max_val is None:
110
+ max_val = np.abs(clean).max()
111
+
112
+ # 计算均方误差 (MSE)
113
+ mse = np.mean((clean - noisy) ** 2)
114
+
115
+ # 避免除以0
116
+ if mse == 0:
117
+ return float('inf')
118
+
119
+ # 计算PSNR
120
+ psnr = 10 * np.log10(max_val**2 / mse)
121
+ return psnr
122
+
123
+
124
+ def si_sdr(reference, estimate, epsilon=1e-8):
125
+ """
126
+ 计算尺度不变信噪比 (Scale-Invariant Signal-to-Distortion Ratio, SI-SDR)。
127
+
128
+ Args:
129
+ reference (np.ndarray): 原始的、干净的参考信号 (一维数组)。
130
+ estimate (np.ndarray): 模型估计或处理后的信号 (一维数组)。
131
+ epsilon (float): 一个非常小的数值, 用于防止分母为零, 保证数值稳定性。
132
+
133
+ Returns:
134
+ float: SI-SDR 值, 单位为分贝 (dB)。
135
+ """
136
+ assert reference.shape == estimate.shape, "reference和estimate的维度不一样"
137
+
138
+ # 2. 零均值化 (可选但推荐)
139
+ # 移除直流分量, 使计算更关注信号的动态变化
140
+ reference = reference - np.mean(reference)
141
+ estimate = estimate - np.mean(estimate)
142
+
143
+ # 3. 计算目标信号分量 (s_target)
144
+ # s_target 是 estimate 在 reference 上的投影
145
+ # 公式: s_target = (<ŝ, s> / ||s||²) * s
146
+ dot_product = np.dot(estimate, reference) # <ŝ, s> (点积)
147
+ norm_s_squared = np.dot(reference, reference) # ||s||² (s的能量)
148
+
149
+ # 检查参考信号能量, 避免除以零
150
+ if norm_s_squared < epsilon:
151
+ # 如果参考信号几乎是静音, SI-SDR没有意义
152
+ return -np.inf # 返回负无穷或np.nan
153
+
154
+ alpha = dot_product / (norm_s_squared + epsilon) # 最佳缩放因子 α
155
+ s_target = alpha * reference
156
+
157
+ # 4. 计算误差/失真分量 (e_noise)
158
+ e_noise = estimate - s_target
159
+
160
+ # 5. 计算 SI-SDR
161
+ # SI-SDR = 10 * log10 ( ||s_target||² / ||e_noise||² )
162
+ power_s_target = np.sum(s_target**2) # ||s_target||²
163
+ power_e_noise = np.sum(e_noise**2) # ||e_noise||²
164
+
165
+ # 同样加上 epsilon 防止除以零
166
+ if power_e_noise < epsilon:
167
+ # 如果噪声能量极小, 说明匹配得非常好
168
+ return np.inf # 返回正无穷
169
+
170
+ si_sdr_val = 10 * np.log10(power_s_target / (power_e_noise + epsilon))
171
+
172
+ return si_sdr_val
173
+
174
+
175
+ if __name__ == "__main__":
176
+ # 生成测试信号
177
+ speech = np.random.randn(1000)
178
+ noise = np.random.randn(1000) * 0.1 # 较小的噪声
179
+ noisy = speech + noise
180
+
181
+ # 测试各种信噪比计算方法
182
+ print(f"SNR: {get_snr(speech, noise):.2f} dB")
183
+ print(f"Segmental SNR: {seg_snr(speech, noisy, 100, 50):.2f} dB")
184
+ print(f"PSNR: {psnr(speech, noisy):.2f} dB")
@@ -0,0 +1,45 @@
1
+ """
2
+ 频域的客观评价指标
3
+ LSD: 对数谱距离
4
+ """
5
+ import sys
6
+ sys.path.append("..")
7
+ import numpy as np
8
+ import librosa
9
+ from utils import EPS
10
+
11
+
12
+ def lsd(reference, estimate, n_fft=2048, hop_length=512, win_length=None):
13
+ """
14
+ 计算两个一维音频信号之间的对数谱距离 (Log-Spectral Distance, LSD)。
15
+ 该实现遵循标准的LSD定义: 整体均方根误差。
16
+
17
+ Args:
18
+ reference (np.ndarray): 原始的、干净的参考信号 (一维数组)。
19
+ estimate (np.ndarray): 模型估计或处理后的信号 (一维数组)。
20
+ n_fft (int): FFT点数, 决定了频率分辨率。
21
+ hop_length (int): 帧移, 决定了时间分辨率。
22
+ win_length (int, optional): 窗长。如果为None, 则默认为n_fft。
23
+ epsilon (float): 一个非常小的数值, 用于防止对零取对数, 保证数值稳定性。
24
+
25
+ Returns:
26
+ float: 对数谱距离值, 单位为分贝 (dB)。
27
+ """
28
+ assert reference.ndim == 1 and estimate.ndim == 1, "输入信号必须是一维数组。"
29
+
30
+ if win_length is None:
31
+ win_length = n_fft
32
+
33
+ reference_stft = librosa.stft(reference, n_fft=n_fft, hop_length=hop_length, win_length=win_length) # (F,T)
34
+ estimate_stft = librosa.stft(estimate, n_fft=n_fft, hop_length=hop_length, win_length=win_length) # (F,T)
35
+
36
+ reference_power_spec = np.abs(reference_stft) ** 2 # (F,T)
37
+ estimate_power_spec = np.abs(estimate_stft) ** 2 # (F,T)
38
+
39
+ reference_log_power_spec = 10 * np.log10(reference_power_spec + EPS)
40
+ estimate_log_power_spec = 10 * np.log10(estimate_power_spec + EPS)
41
+
42
+ squared_error = (reference_log_power_spec - estimate_log_power_spec) ** 2
43
+ lsd_val = np.sqrt(np.mean(squared_error))
44
+
45
+ return lsd_val
@@ -0,0 +1,11 @@
1
+ """
2
+ 频域的客观评价指标
3
+ LSD: 对数谱距离
4
+ """
5
+ import sys
6
+ sys.path.append("..")
7
+ import numpy as np
8
+ import librosa
9
+ from utils import EPS
10
+
11
+
@@ -0,0 +1,16 @@
1
+ '''
2
+ Author: 凌逆战 | Never
3
+ Date: 2025-08-05 23:42:10
4
+ Description:
5
+ '''
6
+ """
7
+ 频域的客观评价指标
8
+ LSD: 对数谱距离
9
+ """
10
+ import sys
11
+ sys.path.append("..")
12
+ import numpy as np
13
+ import librosa
14
+ from utils import EPS
15
+
16
+
@@ -0,0 +1,68 @@
1
+ '''
2
+ Author: 凌逆战 | Never
3
+ Date: 2025-08-16 13:51:57
4
+ Description: 频域客观度量指标
5
+ '''
6
+
7
+ import librosa
8
+ import numpy as np
9
+ import soundfile as sf
10
+ from neverlib.utils import EPS
11
+
12
+
13
+
14
+
15
+
16
+ def lsd(ref_wav, test_wav, n_fft=2048, hop_length=512, win_length=None):
17
+ """
18
+ 计算两个一维音频信号之间的对数谱距离 (Log-Spectral Distance, LSD)。
19
+ 该实现遵循标准的LSD定义: 整体均方根误差。
20
+
21
+ Args:
22
+ ref_wav (np.ndarray): 原始的、干净的参考信号 (一维数组)。
23
+ test_wav (np.ndarray): 模型估计或处理后的信号 (一维数组)。
24
+ n_fft (int): FFT点数, 决定了频率分辨率。
25
+ hop_length (int): 帧移, 决定了时间分辨率。
26
+ win_length (int, optional): 窗长。如果为None, 则默认为n_fft。
27
+ epsilon (float): 一个非常小的数值, 用于防止对零取对数, 保证数值稳定性。
28
+
29
+ Returns:
30
+ float: 对数谱距离值, 单位为分贝 (dB)。
31
+ """
32
+ assert ref_wav.ndim == 1 and test_wav.ndim == 1, "输入信号必须是一维数组。"
33
+
34
+ if win_length is None:
35
+ win_length = n_fft
36
+
37
+ ref_stft = librosa.stft(ref_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length) # (F,T)
38
+ test_stft = librosa.stft(test_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length) # (F,T)
39
+
40
+ ref_power_spec = np.abs(ref_stft) ** 2 # (F,T)
41
+ test_power_spec = np.abs(test_stft) ** 2 # (F,T)
42
+
43
+ ref_log_power_spec = 10 * np.log10(ref_power_spec + EPS)
44
+ test_log_power_spec = 10 * np.log10(test_power_spec + EPS)
45
+
46
+ squared_error = (ref_log_power_spec - test_log_power_spec) ** 2
47
+ lsd_val = np.sqrt(np.mean(squared_error))
48
+
49
+ return lsd_val
50
+
51
+ def mcd(ref_wav, test_wav, sr=16000):
52
+ """
53
+ 梅尔倒谱距离 Mel-Cepstral Distance
54
+ ref_spec: 参考频谱
55
+ test_spec: 测试频谱
56
+ """
57
+ ref_wav, ref_sr = sf.read(ref_wav)
58
+ test_wav, test_sr = sf.read(test_wav)
59
+ assert ref_sr == test_sr == sr, "采样率必须为16000Hz"
60
+ assert len(ref_wav) == len(test_wav), "音频长度必须相同"
61
+
62
+ ref_mfcc = librosa.feature.mfcc(y=ref_wav, sr=sr)
63
+ test_mfcc = librosa.feature.mfcc(y=test_wav, sr=sr)
64
+
65
+ # 计算 MCD (跳过 0 阶)
66
+ diff = ref_mfcc[1:] - test_mfcc[1:]
67
+ mcd = (10.0 / np.log(10)) * np.sqrt(2 * np.mean(np.sum(diff ** 2, axis=0)))
68
+ return mcd
@@ -0,0 +1,75 @@
1
+ '''
2
+ Author: 凌逆战 | Never
3
+ Date: 2025-08-16 13:51:57
4
+ Description: 频域客观度量指标
5
+ '''
6
+
7
+ import librosa
8
+ import numpy as np
9
+ import soundfile as sf
10
+ from neverlib.utils import EPS
11
+
12
+
13
+ def sd(ref_wav, test_wav, n_fft=2048, hop_length=512, win_length=None):
14
+ """
15
+ 频谱距离
16
+ """
17
+ ref_spec = librosa.stft(ref_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length)
18
+ test_spec = librosa.stft(test_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length)
19
+ return np.sqrt(np.mean((ref_spec - test_spec) ** 2))
20
+
21
+
22
+
23
+ def lsd(ref_wav, test_wav, n_fft=2048, hop_length=512, win_length=None):
24
+ """
25
+ 计算两个一维音频信号之间的对数谱距离 (Log-Spectral Distance, LSD)。
26
+ 该实现遵循标准的LSD定义: 整体均方根误差。
27
+
28
+ Args:
29
+ ref_wav (np.ndarray): 原始的、干净的参考信号 (一维数组)。
30
+ test_wav (np.ndarray): 模型估计或处理后的信号 (一维数组)。
31
+ n_fft (int): FFT点数, 决定了频率分辨率。
32
+ hop_length (int): 帧移, 决定了时间分辨率。
33
+ win_length (int, optional): 窗长。如果为None, 则默认为n_fft。
34
+ epsilon (float): 一个非常小的数值, 用于防止对零取对数, 保证数值稳定性。
35
+
36
+ Returns:
37
+ float: 对数谱距离值, 单位为分贝 (dB)。
38
+ """
39
+ assert ref_wav.ndim == 1 and test_wav.ndim == 1, "输入信号必须是一维数组。"
40
+
41
+ if win_length is None:
42
+ win_length = n_fft
43
+
44
+ ref_stft = librosa.stft(ref_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length) # (F,T)
45
+ test_stft = librosa.stft(test_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length) # (F,T)
46
+
47
+ ref_power_spec = np.abs(ref_stft) ** 2 # (F,T)
48
+ test_power_spec = np.abs(test_stft) ** 2 # (F,T)
49
+
50
+ ref_log_power_spec = 10 * np.log10(ref_power_spec + EPS)
51
+ test_log_power_spec = 10 * np.log10(test_power_spec + EPS)
52
+
53
+ squared_error = (ref_log_power_spec - test_log_power_spec) ** 2
54
+ lsd_val = np.sqrt(np.mean(squared_error))
55
+
56
+ return lsd_val
57
+
58
+ def mcd(ref_wav, test_wav, sr=16000):
59
+ """
60
+ 梅尔倒谱距离 Mel-Cepstral Distance
61
+ ref_spec: 参考频谱
62
+ test_spec: 测试频谱
63
+ """
64
+ ref_wav, ref_sr = sf.read(ref_wav)
65
+ test_wav, test_sr = sf.read(test_wav)
66
+ assert ref_sr == test_sr == sr, "采样率必须为16000Hz"
67
+ assert len(ref_wav) == len(test_wav), "音频长度必须相同"
68
+
69
+ ref_mfcc = librosa.feature.mfcc(y=ref_wav, sr=sr)
70
+ test_mfcc = librosa.feature.mfcc(y=test_wav, sr=sr)
71
+
72
+ # 计算 MCD (跳过 0 阶)
73
+ diff = ref_mfcc[1:] - test_mfcc[1:]
74
+ mcd = (10.0 / np.log(10)) * np.sqrt(2 * np.mean(np.sum(diff ** 2, axis=0)))
75
+ return mcd
@@ -0,0 +1,82 @@
1
+ '''
2
+ Author: 凌逆战 | Never
3
+ Date: 2025-08-16 13:51:57
4
+ Description: 频域客观度量指标
5
+ '''
6
+
7
+ import librosa
8
+ import numpy as np
9
+ import soundfile as sf
10
+ from neverlib.utils import EPS
11
+
12
+
13
+ def sd(ref_wav, test_wav, n_fft=2048, hop_length=512, win_length=None):
14
+ """
15
+ 频谱距离
16
+ """
17
+ ref_spec = librosa.stft(ref_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length)
18
+ test_spec = librosa.stft(test_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length)
19
+ return np.sqrt(np.mean((ref_spec - test_spec) ** 2))
20
+
21
+
22
+
23
+ def lsd(ref_wav, test_wav, n_fft=2048, hop_length=512, win_length=None):
24
+ """
25
+ 计算两个一维音频信号之间的对数谱距离 (Log-Spectral Distance, LSD)。
26
+ 该实现遵循标准的LSD定义: 整体均方根误差。
27
+
28
+ Args:
29
+ ref_wav (np.ndarray): 原始的、干净的参考信号 (一维数组)。
30
+ test_wav (np.ndarray): 模型估计或处理后的信号 (一维数组)。
31
+ n_fft (int): FFT点数, 决定了频率分辨率。
32
+ hop_length (int): 帧移, 决定了时间分辨率。
33
+ win_length (int, optional): 窗长。如果为None, 则默认为n_fft。
34
+ epsilon (float): 一个非常小的数值, 用于防止对零取对数, 保证数值稳定性。
35
+
36
+ Returns:
37
+ float: 对数谱距离值, 单位为分贝 (dB)。
38
+ """
39
+ assert ref_wav.ndim == 1 and test_wav.ndim == 1, "输入信号必须是一维数组。"
40
+
41
+ if win_length is None:
42
+ win_length = n_fft
43
+
44
+ ref_stft = librosa.stft(ref_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length) # (F,T)
45
+ test_stft = librosa.stft(test_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length) # (F,T)
46
+
47
+ ref_power_spec = np.abs(ref_stft) ** 2 # (F,T)
48
+ test_power_spec = np.abs(test_stft) ** 2 # (F,T)
49
+
50
+ ref_log_power_spec = 10 * np.log10(ref_power_spec + EPS)
51
+ test_log_power_spec = 10 * np.log10(test_power_spec + EPS)
52
+
53
+ squared_error = (ref_log_power_spec - test_log_power_spec) ** 2
54
+ lsd_val = np.sqrt(np.mean(squared_error))
55
+
56
+ return lsd_val
57
+
58
+ def mcd(ref_wav, test_wav, sr=16000):
59
+ """
60
+ 梅尔倒谱距离 Mel-Cepstral Distance
61
+ ref_spec: 参考频谱
62
+ test_spec: 测试频谱
63
+ """
64
+ ref_wav, ref_sr = sf.read(ref_wav)
65
+ test_wav, test_sr = sf.read(test_wav)
66
+ assert ref_sr == test_sr == sr, "采样率必须为16000Hz"
67
+ assert len(ref_wav) == len(test_wav), "音频长度必须相同"
68
+
69
+ ref_mfcc = librosa.feature.mfcc(y=ref_wav, sr=sr)
70
+ test_mfcc = librosa.feature.mfcc(y=test_wav, sr=sr)
71
+
72
+ # 计算 MCD (跳过 0 阶)
73
+ diff = ref_mfcc[1:] - test_mfcc[1:]
74
+ mcd = (10.0 / np.log(10)) * np.sqrt(2 * np.mean(np.sum(diff ** 2, axis=0)))
75
+ return mcd
76
+
77
+ if __name__ == "__main__":
78
+ ref_file = "../data/vad_example.wav" # 参考语音文件路径
79
+ test_file = "../data/vad_example.wav" # 测试语音文件路径
80
+
81
+ avg_dist, dist_list = lpc_lsp_distance(ref_file, test_file)
82
+ print(f"平均 LSP MSE 失真: {avg_dist}")
@@ -0,0 +1,82 @@
1
+ '''
2
+ Author: 凌逆战 | Never
3
+ Date: 2025-08-16 13:51:57
4
+ Description: 频域客观度量指标
5
+ '''
6
+
7
+ import librosa
8
+ import numpy as np
9
+ import soundfile as sf
10
+ from neverlib.utils import EPS
11
+
12
+
13
+ def sd(ref_wav, test_wav, n_fft=2048, hop_length=512, win_length=None):
14
+ """
15
+ 频谱距离
16
+ """
17
+ ref_spec = librosa.stft(ref_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length)
18
+ test_spec = librosa.stft(test_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length)
19
+ return np.sqrt(np.mean((ref_spec - test_spec) ** 2))
20
+
21
+
22
+
23
+ def lsd(ref_wav, test_wav, n_fft=2048, hop_length=512, win_length=None):
24
+ """
25
+ 计算两个一维音频信号之间的对数谱距离 (Log-Spectral Distance, LSD)。
26
+ 该实现遵循标准的LSD定义: 整体均方根误差。
27
+
28
+ Args:
29
+ ref_wav (np.ndarray): 原始的、干净的参考信号 (一维数组)。
30
+ test_wav (np.ndarray): 模型估计或处理后的信号 (一维数组)。
31
+ n_fft (int): FFT点数, 决定了频率分辨率。
32
+ hop_length (int): 帧移, 决定了时间分辨率。
33
+ win_length (int, optional): 窗长。如果为None, 则默认为n_fft。
34
+ epsilon (float): 一个非常小的数值, 用于防止对零取对数, 保证数值稳定性。
35
+
36
+ Returns:
37
+ float: 对数谱距离值, 单位为分贝 (dB)。
38
+ """
39
+ assert ref_wav.ndim == 1 and test_wav.ndim == 1, "输入信号必须是一维数组。"
40
+
41
+ if win_length is None:
42
+ win_length = n_fft
43
+
44
+ ref_stft = librosa.stft(ref_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length) # (F,T)
45
+ test_stft = librosa.stft(test_wav, n_fft=n_fft, hop_length=hop_length, win_length=win_length) # (F,T)
46
+
47
+ ref_power_spec = np.abs(ref_stft) ** 2 # (F,T)
48
+ test_power_spec = np.abs(test_stft) ** 2 # (F,T)
49
+
50
+ ref_log_power_spec = 10 * np.log10(ref_power_spec + EPS)
51
+ test_log_power_spec = 10 * np.log10(test_power_spec + EPS)
52
+
53
+ squared_error = (ref_log_power_spec - test_log_power_spec) ** 2
54
+ lsd_val = np.sqrt(np.mean(squared_error))
55
+
56
+ return lsd_val
57
+
58
+ def mcd(ref_wav, test_wav, sr=16000):
59
+ """
60
+ 梅尔倒谱距离 Mel-Cepstral Distance
61
+ ref_spec: 参考频谱
62
+ test_spec: 测试频谱
63
+ """
64
+ ref_wav, ref_sr = sf.read(ref_wav)
65
+ test_wav, test_sr = sf.read(test_wav)
66
+ assert ref_sr == test_sr == sr, "采样率必须为16000Hz"
67
+ assert len(ref_wav) == len(test_wav), "音频长度必须相同"
68
+
69
+ ref_mfcc = librosa.feature.mfcc(y=ref_wav, sr=sr)
70
+ test_mfcc = librosa.feature.mfcc(y=test_wav, sr=sr)
71
+
72
+ # 计算 MCD (跳过 0 阶)
73
+ diff = ref_mfcc[1:] - test_mfcc[1:]
74
+ mcd = (10.0 / np.log(10)) * np.sqrt(2 * np.mean(np.sum(diff ** 2, axis=0)))
75
+ return mcd
76
+
77
+ if __name__ == "__main__":
78
+ ref_file = "../data/000_short_enhance.wav" # 参考语音文件路径
79
+ test_file = "../data/vad_example.wav" # 测试语音文件路径
80
+
81
+ avg_dist, dist_list = lpc_lsp_distance(ref_file, test_file)
82
+ print(f"平均 LSP MSE 失真: {avg_dist}")