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,96 @@
1
+ import numpy as np
2
+ import librosa
3
+
4
+ def pre_emphasis(signal, coeff=0.97):
5
+ """预加重"""
6
+ return np.append(signal[0], signal[1:] - coeff * signal[:-1])
7
+
8
+ def framing(signal, frame_size, frame_stride, fs):
9
+ """分帧 + 汉明窗"""
10
+ frame_length = int(round(frame_size * fs))
11
+ frame_step = int(round(frame_stride * fs))
12
+
13
+ # 使用 librosa 进行分帧
14
+ frames = librosa.util.frame(signal, frame_length=frame_length, hop_length=frame_step, axis=0)
15
+
16
+ # 应用汉明窗
17
+ hamming_window = np.hamming(frame_length)
18
+ frames = frames.T * hamming_window
19
+
20
+ return frames
21
+
22
+
23
+ def lpc_analysis(frame, order):
24
+ """对一帧做 LPC 分析"""
25
+ a = librosa.lpc(frame, order=order)
26
+ return a
27
+
28
+ def lpc_to_lsp(a, num_points=512):
29
+ """
30
+ LPC -> LSP 转换(简易近似版,零点搜索法)
31
+ """
32
+ p = len(a) - 1
33
+ a = np.array(a)
34
+ # 构造P(z) Q(z)
35
+ P = np.zeros(p+1)
36
+ Q = np.zeros(p+1)
37
+ for i in range(p+1):
38
+ if i == 0:
39
+ P[i] = 1 + a[i]
40
+ Q[i] = 1 - a[i]
41
+ else:
42
+ P[i] = a[i] + a[p - i]
43
+ Q[i] = a[i] - a[p - i]
44
+ # 频域采样找过零点
45
+ w = np.linspace(0, np.pi, num_points)
46
+ Pw = np.polyval(P[::-1], np.cos(w))
47
+ Qw = np.polyval(Q[::-1], np.cos(w))
48
+
49
+ # 找零点近似位置
50
+ roots_P = w[np.where(np.diff(np.sign(Pw)) != 0)]
51
+ roots_Q = w[np.where(np.diff(np.sign(Qw)) != 0)]
52
+ lsp = np.sort(np.concatenate([roots_P, roots_Q]))
53
+ return lsp
54
+
55
+ def lsp_mse(lsp1, lsp2):
56
+ """计算两个 LSP 向量的均方差"""
57
+ return np.mean((lsp1 - lsp2) ** 2)
58
+
59
+
60
+ def lpc_lsp_distance(ref_wav, test_wav, frame_size=0.025, frame_stride=0.01, order=12):
61
+ """主函数:计算 LPC-LSP 参数失真"""
62
+ ref_sig, fs_r = librosa.load(ref_wav, sr=None)
63
+ test_sig, fs_t = librosa.load(test_wav, sr=None)
64
+
65
+ # 预加重
66
+ ref_sig = pre_emphasis(ref_sig)
67
+ test_sig = pre_emphasis(test_sig)
68
+
69
+ # 分帧
70
+ ref_frames = framing(ref_sig, frame_size, frame_stride, fs_r)
71
+ test_frames = framing(test_sig, frame_size, frame_stride, fs_t)
72
+
73
+ # 对齐帧数(简单切到最短)
74
+ num_frames = min(len(ref_frames), len(test_frames))
75
+ ref_frames = ref_frames[:num_frames]
76
+ test_frames = test_frames[:num_frames]
77
+
78
+ distances = []
79
+ for i in range(num_frames):
80
+ a_ref = lpc_analysis(ref_frames[i], order)
81
+ a_test = lpc_analysis(test_frames[i], order)
82
+ lsp_ref = lpc_to_lsp(a_ref)
83
+ lsp_test = lpc_to_lsp(a_test)
84
+ # 对齐长度(简单裁切)
85
+ min_len = min(len(lsp_ref), len(lsp_test))
86
+ dist = lsp_mse(lsp_ref[:min_len], lsp_test[:min_len])
87
+ distances.append(dist)
88
+
89
+ return np.mean(distances), distances
90
+
91
+ if __name__ == "__main__":
92
+ ref_file = "ref.wav" # 参考语音文件路径
93
+ test_file = "test.wav" # 测试语音文件路径
94
+
95
+ avg_dist, dist_list = lpc_lsp_distance(ref_file, test_file)
96
+ print(f"平均 LSP MSE 失真: {avg_dist}")
@@ -0,0 +1,97 @@
1
+ import numpy as np
2
+ import librosa
3
+ import soundfile as sf
4
+
5
+ def pre_emphasis(signal, coeff=0.97):
6
+ """预加重"""
7
+ return np.append(signal[0], signal[1:] - coeff * signal[:-1])
8
+
9
+ def framing(signal, frame_size, frame_stride, fs):
10
+ """分帧 + 汉明窗"""
11
+ frame_length = int(round(frame_size * fs))
12
+ frame_step = int(round(frame_stride * fs))
13
+
14
+ # 使用 librosa 进行分帧
15
+ frames = librosa.util.frame(signal, frame_length=frame_length, hop_length=frame_step, axis=0)
16
+
17
+ # 应用汉明窗
18
+ hamming_window = np.hamming(frame_length)
19
+ frames = frames.T * hamming_window
20
+
21
+ return frames
22
+
23
+
24
+ def lpc_analysis(frame, order):
25
+ """对一帧做 LPC 分析"""
26
+ a = librosa.lpc(frame, order=order)
27
+ return a
28
+
29
+ def lpc_to_lsp(a, num_points=512):
30
+ """
31
+ LPC -> LSP 转换(简易近似版,零点搜索法)
32
+ """
33
+ p = len(a) - 1
34
+ a = np.array(a)
35
+ # 构造P(z) Q(z)
36
+ P = np.zeros(p+1)
37
+ Q = np.zeros(p+1)
38
+ for i in range(p+1):
39
+ if i == 0:
40
+ P[i] = 1 + a[i]
41
+ Q[i] = 1 - a[i]
42
+ else:
43
+ P[i] = a[i] + a[p - i]
44
+ Q[i] = a[i] - a[p - i]
45
+ # 频域采样找过零点
46
+ w = np.linspace(0, np.pi, num_points)
47
+ Pw = np.polyval(P[::-1], np.cos(w))
48
+ Qw = np.polyval(Q[::-1], np.cos(w))
49
+
50
+ # 找零点近似位置
51
+ roots_P = w[np.where(np.diff(np.sign(Pw)) != 0)]
52
+ roots_Q = w[np.where(np.diff(np.sign(Qw)) != 0)]
53
+ lsp = np.sort(np.concatenate([roots_P, roots_Q]))
54
+ return lsp
55
+
56
+ def lsp_mse(lsp1, lsp2):
57
+ """计算两个 LSP 向量的均方差"""
58
+ return np.mean((lsp1 - lsp2) ** 2)
59
+
60
+
61
+ def lpc_lsp_distance(ref_wav, test_wav, frame_size=0.025, frame_stride=0.01, order=12):
62
+ """主函数:计算 LPC-LSP 参数失真"""
63
+ ref_sig, fs_r = sf.read(ref_wav, dtype='float32')
64
+ test_sig, fs_t = sf.read(test_wav, dtype='float32')
65
+
66
+ # 预加重
67
+ ref_sig = pre_emphasis(ref_sig)
68
+ test_sig = pre_emphasis(test_sig)
69
+
70
+ # 分帧
71
+ ref_frames = framing(ref_sig, frame_size, frame_stride, fs_r)
72
+ test_frames = framing(test_sig, frame_size, frame_stride, fs_t)
73
+
74
+ # 对齐帧数(简单切到最短)
75
+ num_frames = min(len(ref_frames), len(test_frames))
76
+ ref_frames = ref_frames[:num_frames]
77
+ test_frames = test_frames[:num_frames]
78
+
79
+ distances = []
80
+ for i in range(num_frames):
81
+ a_ref = lpc_analysis(ref_frames[i], order)
82
+ a_test = lpc_analysis(test_frames[i], order)
83
+ lsp_ref = lpc_to_lsp(a_ref)
84
+ lsp_test = lpc_to_lsp(a_test)
85
+ # 对齐长度(简单裁切)
86
+ min_len = min(len(lsp_ref), len(lsp_test))
87
+ dist = lsp_mse(lsp_ref[:min_len], lsp_test[:min_len])
88
+ distances.append(dist)
89
+
90
+ return np.mean(distances), distances
91
+
92
+ if __name__ == "__main__":
93
+ ref_file = "ref.wav" # 参考语音文件路径
94
+ test_file = "test.wav" # 测试语音文件路径
95
+
96
+ avg_dist, dist_list = lpc_lsp_distance(ref_file, test_file)
97
+ print(f"平均 LSP MSE 失真: {avg_dist}")
@@ -0,0 +1,104 @@
1
+ '''
2
+ LPC-LSP 参数失真计算
3
+
4
+
5
+
6
+
7
+ '''
8
+ import numpy as np
9
+ import librosa
10
+ import soundfile as sf
11
+
12
+ def pre_emphasis(signal, coeff=0.97):
13
+ """预加重"""
14
+ return np.append(signal[0], signal[1:] - coeff * signal[:-1])
15
+
16
+ def framing(signal, frame_size, frame_stride, fs):
17
+ """分帧 + 汉明窗"""
18
+ frame_length = int(round(frame_size * fs))
19
+ frame_step = int(round(frame_stride * fs))
20
+
21
+ # 使用 librosa 进行分帧
22
+ frames = librosa.util.frame(signal, frame_length=frame_length, hop_length=frame_step, axis=0)
23
+
24
+ # 应用汉明窗
25
+ hamming_window = np.hamming(frame_length)
26
+ frames = frames.T * hamming_window
27
+
28
+ return frames
29
+
30
+
31
+ def lpc_analysis(frame, order):
32
+ """对一帧做 LPC 分析"""
33
+ a = librosa.lpc(frame, order=order)
34
+ return a
35
+
36
+ def lpc_to_lsp(a, num_points=512):
37
+ """
38
+ LPC -> LSP 转换(简易近似版,零点搜索法)
39
+ """
40
+ p = len(a) - 1
41
+ a = np.array(a)
42
+ # 构造P(z) Q(z)
43
+ P = np.zeros(p+1)
44
+ Q = np.zeros(p+1)
45
+ for i in range(p+1):
46
+ if i == 0:
47
+ P[i] = 1 + a[i]
48
+ Q[i] = 1 - a[i]
49
+ else:
50
+ P[i] = a[i] + a[p - i]
51
+ Q[i] = a[i] - a[p - i]
52
+ # 频域采样找过零点
53
+ w = np.linspace(0, np.pi, num_points)
54
+ Pw = np.polyval(P[::-1], np.cos(w))
55
+ Qw = np.polyval(Q[::-1], np.cos(w))
56
+
57
+ # 找零点近似位置
58
+ roots_P = w[np.where(np.diff(np.sign(Pw)) != 0)]
59
+ roots_Q = w[np.where(np.diff(np.sign(Qw)) != 0)]
60
+ lsp = np.sort(np.concatenate([roots_P, roots_Q]))
61
+ return lsp
62
+
63
+ def lsp_mse(lsp1, lsp2):
64
+ """计算两个 LSP 向量的均方差"""
65
+ return np.mean((lsp1 - lsp2) ** 2)
66
+
67
+
68
+ def lpc_lsp_distance(ref_wav, test_wav, frame_size=0.025, frame_stride=0.01, order=12):
69
+ """主函数:计算 LPC-LSP 参数失真"""
70
+ ref_sig, fs_r = sf.read(ref_wav, dtype='float32')
71
+ test_sig, fs_t = sf.read(test_wav, dtype='float32')
72
+
73
+ # 预加重
74
+ ref_sig = pre_emphasis(ref_sig)
75
+ test_sig = pre_emphasis(test_sig)
76
+
77
+ # 分帧
78
+ ref_frames = framing(ref_sig, frame_size, frame_stride, fs_r)
79
+ test_frames = framing(test_sig, frame_size, frame_stride, fs_t)
80
+
81
+ # 对齐帧数(简单切到最短)
82
+ num_frames = min(len(ref_frames), len(test_frames))
83
+ ref_frames = ref_frames[:num_frames]
84
+ test_frames = test_frames[:num_frames]
85
+
86
+ distances = []
87
+ for i in range(num_frames):
88
+ a_ref = lpc_analysis(ref_frames[i], order)
89
+ a_test = lpc_analysis(test_frames[i], order)
90
+ lsp_ref = lpc_to_lsp(a_ref)
91
+ lsp_test = lpc_to_lsp(a_test)
92
+ # 对齐长度(简单裁切)
93
+ min_len = min(len(lsp_ref), len(lsp_test))
94
+ dist = lsp_mse(lsp_ref[:min_len], lsp_test[:min_len])
95
+ distances.append(dist)
96
+
97
+ return np.mean(distances), distances
98
+
99
+ if __name__ == "__main__":
100
+ ref_file = "ref.wav" # 参考语音文件路径
101
+ test_file = "test.wav" # 测试语音文件路径
102
+
103
+ avg_dist, dist_list = lpc_lsp_distance(ref_file, test_file)
104
+ print(f"平均 LSP MSE 失真: {avg_dist}")
@@ -0,0 +1,100 @@
1
+ '''
2
+ LPC-LSP 参数失真计算
3
+ '''
4
+ import numpy as np
5
+ import librosa
6
+ import soundfile as sf
7
+
8
+ def pre_emphasis(signal, coeff=0.97):
9
+ """预加重"""
10
+ return np.append(signal[0], signal[1:] - coeff * signal[:-1])
11
+
12
+ def framing(signal, frame_size, frame_stride, fs):
13
+ """分帧 + 汉明窗"""
14
+ frame_length = int(round(frame_size * fs))
15
+ frame_step = int(round(frame_stride * fs))
16
+
17
+ # 使用 librosa 进行分帧
18
+ frames = librosa.util.frame(signal, frame_length=frame_length, hop_length=frame_step, axis=0)
19
+
20
+ # 应用汉明窗
21
+ hamming_window = np.hamming(frame_length)
22
+ frames = frames.T * hamming_window
23
+
24
+ return frames
25
+
26
+
27
+ def lpc_analysis(frame, order):
28
+ """对一帧做 LPC 分析"""
29
+ a = librosa.lpc(frame, order=order)
30
+ return a
31
+
32
+ def lpc_to_lsp(a, num_points=512):
33
+ """
34
+ LPC -> LSP 转换(简易近似版,零点搜索法)
35
+ """
36
+ p = len(a) - 1
37
+ a = np.array(a)
38
+ # 构造P(z) Q(z)
39
+ P = np.zeros(p+1)
40
+ Q = np.zeros(p+1)
41
+ for i in range(p+1):
42
+ if i == 0:
43
+ P[i] = 1 + a[i]
44
+ Q[i] = 1 - a[i]
45
+ else:
46
+ P[i] = a[i] + a[p - i]
47
+ Q[i] = a[i] - a[p - i]
48
+ # 频域采样找过零点
49
+ w = np.linspace(0, np.pi, num_points)
50
+ Pw = np.polyval(P[::-1], np.cos(w))
51
+ Qw = np.polyval(Q[::-1], np.cos(w))
52
+
53
+ # 找零点近似位置
54
+ roots_P = w[np.where(np.diff(np.sign(Pw)) != 0)]
55
+ roots_Q = w[np.where(np.diff(np.sign(Qw)) != 0)]
56
+ lsp = np.sort(np.concatenate([roots_P, roots_Q]))
57
+ return lsp
58
+
59
+ def lsp_mse(lsp1, lsp2):
60
+ """计算两个 LSP 向量的均方差"""
61
+ return np.mean((lsp1 - lsp2) ** 2)
62
+
63
+
64
+ def lpc_lsp_distance(ref_wav, test_wav, frame_size=0.025, frame_stride=0.01, order=12):
65
+ """主函数:计算 LPC-LSP 参数失真"""
66
+ ref_sig, fs_r = sf.read(ref_wav, dtype='float32')
67
+ test_sig, fs_t = sf.read(test_wav, dtype='float32')
68
+
69
+ # 预加重
70
+ ref_sig = pre_emphasis(ref_sig)
71
+ test_sig = pre_emphasis(test_sig)
72
+
73
+ # 分帧
74
+ ref_frames = framing(ref_sig, frame_size, frame_stride, fs_r)
75
+ test_frames = framing(test_sig, frame_size, frame_stride, fs_t)
76
+
77
+ # 对齐帧数(简单切到最短)
78
+ num_frames = min(len(ref_frames), len(test_frames))
79
+ ref_frames = ref_frames[:num_frames]
80
+ test_frames = test_frames[:num_frames]
81
+
82
+ distances = []
83
+ for i in range(num_frames):
84
+ a_ref = lpc_analysis(ref_frames[i], order)
85
+ a_test = lpc_analysis(test_frames[i], order)
86
+ lsp_ref = lpc_to_lsp(a_ref)
87
+ lsp_test = lpc_to_lsp(a_test)
88
+ # 对齐长度(简单裁切)
89
+ min_len = min(len(lsp_ref), len(lsp_test))
90
+ dist = lsp_mse(lsp_ref[:min_len], lsp_test[:min_len])
91
+ distances.append(dist)
92
+
93
+ return np.mean(distances), distances
94
+
95
+ if __name__ == "__main__":
96
+ ref_file = "ref.wav" # 参考语音文件路径
97
+ test_file = "test.wav" # 测试语音文件路径
98
+
99
+ avg_dist, dist_list = lpc_lsp_distance(ref_file, test_file)
100
+ print(f"平均 LSP MSE 失真: {avg_dist}")
@@ -0,0 +1,128 @@
1
+ '''
2
+ 功能描述
3
+
4
+ 计算参考语音和测试语音之间的线性预测编码-线谱对(LPC-LSP)参
5
+ 数失真度
6
+
7
+ 主要组件
8
+
9
+ 预处理函数:
10
+ - pre_emphasis(): 预加重滤波,增强高频成分
11
+ - framing(): 分帧处理并应用汉明窗
12
+
13
+ LPC分析:
14
+ - lpc_analysis(): 使用librosa.lpc进行线性预测分析
15
+ - lpc_to_lsp(): LPC系数转换为线谱对参数
16
+
17
+ 距离计算:
18
+ - lsp_mse(): 计算LSP向量间的均方误差
19
+ - lpc_lsp_distance(): 主函数,返回平均失真度和逐帧失真列表
20
+
21
+ 技术特点
22
+
23
+ - 使用soundfile读取音频(支持多种格式)
24
+ - librosa进行LPC分析(替代了自定义算法)
25
+ - 基于LSP的频域失真测量,对量化误差敏感度更低
26
+ - 逐帧分析捕捉语音时变特性
27
+
28
+ 应用场景
29
+
30
+ 语音编码器质量评估、语音增强效果测量、语音合成质量分析
31
+ '''
32
+ import numpy as np
33
+ import librosa
34
+ import soundfile as sf
35
+
36
+ def pre_emphasis(signal, coeff=0.97):
37
+ """预加重"""
38
+ return np.append(signal[0], signal[1:] - coeff * signal[:-1])
39
+
40
+ def framing(signal, frame_size, frame_stride, fs):
41
+ """分帧 + 汉明窗"""
42
+ frame_length = int(round(frame_size * fs))
43
+ frame_step = int(round(frame_stride * fs))
44
+
45
+ # 使用 librosa 进行分帧
46
+ frames = librosa.util.frame(signal, frame_length=frame_length, hop_length=frame_step, axis=0)
47
+
48
+ # 应用汉明窗
49
+ hamming_window = np.hamming(frame_length)
50
+ frames = frames.T * hamming_window
51
+
52
+ return frames
53
+
54
+
55
+ def lpc_analysis(frame, order):
56
+ """对一帧做 LPC 分析"""
57
+ a = librosa.lpc(frame, order=order)
58
+ return a
59
+
60
+ def lpc_to_lsp(a, num_points=512):
61
+ """
62
+ LPC -> LSP 转换(简易近似版,零点搜索法)
63
+ """
64
+ p = len(a) - 1
65
+ a = np.array(a)
66
+ # 构造P(z) Q(z)
67
+ P = np.zeros(p+1)
68
+ Q = np.zeros(p+1)
69
+ for i in range(p+1):
70
+ if i == 0:
71
+ P[i] = 1 + a[i]
72
+ Q[i] = 1 - a[i]
73
+ else:
74
+ P[i] = a[i] + a[p - i]
75
+ Q[i] = a[i] - a[p - i]
76
+ # 频域采样找过零点
77
+ w = np.linspace(0, np.pi, num_points)
78
+ Pw = np.polyval(P[::-1], np.cos(w))
79
+ Qw = np.polyval(Q[::-1], np.cos(w))
80
+
81
+ # 找零点近似位置
82
+ roots_P = w[np.where(np.diff(np.sign(Pw)) != 0)]
83
+ roots_Q = w[np.where(np.diff(np.sign(Qw)) != 0)]
84
+ lsp = np.sort(np.concatenate([roots_P, roots_Q]))
85
+ return lsp
86
+
87
+ def lsp_mse(lsp1, lsp2):
88
+ """计算两个 LSP 向量的均方差"""
89
+ return np.mean((lsp1 - lsp2) ** 2)
90
+
91
+
92
+ def lpc_lsp_distance(ref_wav, test_wav, frame_size=0.025, frame_stride=0.01, order=12):
93
+ """主函数:计算 LPC-LSP 参数失真"""
94
+ ref_sig, fs_r = sf.read(ref_wav, dtype='float32')
95
+ test_sig, fs_t = sf.read(test_wav, dtype='float32')
96
+
97
+ # 预加重
98
+ ref_sig = pre_emphasis(ref_sig)
99
+ test_sig = pre_emphasis(test_sig)
100
+
101
+ # 分帧
102
+ ref_frames = framing(ref_sig, frame_size, frame_stride, fs_r)
103
+ test_frames = framing(test_sig, frame_size, frame_stride, fs_t)
104
+
105
+ # 对齐帧数(简单切到最短)
106
+ num_frames = min(len(ref_frames), len(test_frames))
107
+ ref_frames = ref_frames[:num_frames]
108
+ test_frames = test_frames[:num_frames]
109
+
110
+ distances = []
111
+ for i in range(num_frames):
112
+ a_ref = lpc_analysis(ref_frames[i], order)
113
+ a_test = lpc_analysis(test_frames[i], order)
114
+ lsp_ref = lpc_to_lsp(a_ref)
115
+ lsp_test = lpc_to_lsp(a_test)
116
+ # 对齐长度(简单裁切)
117
+ min_len = min(len(lsp_ref), len(lsp_test))
118
+ dist = lsp_mse(lsp_ref[:min_len], lsp_test[:min_len])
119
+ distances.append(dist)
120
+
121
+ return np.mean(distances), distances
122
+
123
+ if __name__ == "__main__":
124
+ ref_file = "ref.wav" # 参考语音文件路径
125
+ test_file = "test.wav" # 测试语音文件路径
126
+
127
+ avg_dist, dist_list = lpc_lsp_distance(ref_file, test_file)
128
+ print(f"平均 LSP MSE 失真: {avg_dist}")
@@ -0,0 +1,177 @@
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
+ return get_snr(speech, noise)
51
+
52
+
53
+ def seg_snr(clean, noisy, frame_length: int, hop_length: int):
54
+ """
55
+ 分帧计算信噪比
56
+ Args:
57
+ clean: 干净音频, numpy array
58
+ noisy: 带噪音频, numpy array
59
+ frame_length: 帧长
60
+ hop_length: 帧移
61
+ Returns:
62
+ snr_mean: 平均信噪比, float
63
+ Raises:
64
+ ValueError: 当输入参数不合法时抛出
65
+ """
66
+ assert clean.shape == noisy.shape, "clean和noisy的维度不一样"
67
+
68
+ # 分帧
69
+ clean_frames = librosa.util.frame(clean, frame_length=frame_length, hop_length=hop_length) # (frame_length, n_frames)
70
+ noisy_frames = librosa.util.frame(noisy, frame_length=frame_length, hop_length=hop_length) # (frame_length, n_frames)
71
+
72
+ # 计算每帧的信噪比
73
+ snr_frames = []
74
+ for i in range(clean_frames.shape[1]):
75
+ clean_frame = clean_frames[:, i]
76
+ noisy_frame = noisy_frames[:, i]
77
+ # 跳过静音帧
78
+ if np.all(np.abs(clean_frame) < 1e-6) or np.all(np.abs(noisy_frame) < 1e-6):
79
+ continue
80
+ snr_frames.append(get_snr(clean_frame, noisy_frame))
81
+
82
+ # 如果所有帧都是静音
83
+ if not snr_frames:
84
+ return float('-inf')
85
+
86
+ return np.mean(snr_frames)
87
+
88
+
89
+ def psnr(clean, noisy, max_val=None):
90
+ """
91
+ 计算峰值信噪比
92
+ Args:
93
+ clean: 干净音频, numpy array
94
+ noisy: 带噪音频, numpy array
95
+ max_val: 信号最大值, 如果为None则使用clean信号的实际最大值
96
+ Returns:
97
+ psnr: 峰值信噪比, 单位dB
98
+ """
99
+ assert clean.shape == noisy.shape, "clean和noisy的维度不一样"
100
+
101
+ # 如果没有指定最大值, 使用clean信号的实际最大值
102
+ if max_val is None:
103
+ max_val = np.abs(clean).max()
104
+
105
+ # 计算均方误差 (MSE)
106
+ mse = np.mean((clean - noisy) ** 2)
107
+
108
+ # 避免除以0
109
+ if mse == 0:
110
+ return float('inf')
111
+
112
+ # 计算PSNR
113
+ psnr = 10 * np.log10(max_val**2 / mse)
114
+ return psnr
115
+
116
+
117
+ def si_sdr(reference, estimate, epsilon=1e-8):
118
+ """
119
+ 计算尺度不变信噪比 (Scale-Invariant Signal-to-Distortion Ratio, SI-SDR)。
120
+
121
+ Args:
122
+ reference (np.ndarray): 原始的、干净的参考信号 (一维数组)。
123
+ estimate (np.ndarray): 模型估计或处理后的信号 (一维数组)。
124
+ epsilon (float): 一个非常小的数值, 用于防止分母为零, 保证数值稳定性。
125
+
126
+ Returns:
127
+ float: SI-SDR 值, 单位为分贝 (dB)。
128
+ """
129
+ assert reference.shape == estimate.shape, "reference和estimate的维度不一样"
130
+
131
+ # 2. 零均值化 (可选但推荐)
132
+ # 移除直流分量, 使计算更关注信号的动态变化
133
+ reference = reference - np.mean(reference)
134
+ estimate = estimate - np.mean(estimate)
135
+
136
+ # 3. 计算目标信号分量 (s_target)
137
+ # s_target 是 estimate 在 reference 上的投影
138
+ # 公式: s_target = (<ŝ, s> / ||s||²) * s
139
+ dot_product = np.dot(estimate, reference) # <ŝ, s> (点积)
140
+ norm_s_squared = np.dot(reference, reference) # ||s||² (s的能量)
141
+
142
+ # 检查参考信号能量, 避免除以零
143
+ if norm_s_squared < epsilon:
144
+ # 如果参考信号几乎是静音, SI-SDR没有意义
145
+ return -np.inf # 返回负无穷或np.nan
146
+
147
+ alpha = dot_product / (norm_s_squared + epsilon) # 最佳缩放因子 α
148
+ s_target = alpha * reference
149
+
150
+ # 4. 计算误差/失真分量 (e_noise)
151
+ e_noise = estimate - s_target
152
+
153
+ # 5. 计算 SI-SDR
154
+ # SI-SDR = 10 * log10 ( ||s_target||² / ||e_noise||² )
155
+ power_s_target = np.sum(s_target**2) # ||s_target||²
156
+ power_e_noise = np.sum(e_noise**2) # ||e_noise||²
157
+
158
+ # 同样加上 epsilon 防止除以零
159
+ if power_e_noise < epsilon:
160
+ # 如果噪声能量极小, 说明匹配得非常好
161
+ return np.inf # 返回正无穷
162
+
163
+ si_sdr_val = 10 * np.log10(power_s_target / (power_e_noise + epsilon))
164
+
165
+ return si_sdr_val
166
+
167
+
168
+ if __name__ == "__main__":
169
+ # 生成测试信号
170
+ speech = np.random.randn(1000)
171
+ noise = np.random.randn(1000) * 0.1 # 较小的噪声
172
+ noisy = speech + noise
173
+
174
+ # 测试各种信噪比计算方法
175
+ print(f"SNR: {get_snr(speech, noise):.2f} dB")
176
+ print(f"Segmental SNR: {seg_snr(speech, noisy, 100, 50):.2f} dB")
177
+ print(f"PSNR: {psnr(speech, noisy):.2f} dB")