回答編集履歴

6

文法の修正

2020/10/24 03:50

投稿

toast-uz
toast-uz

スコア3266

test CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
 
13
- よって、**ウインドウがぴったりと切りれるように入力配列の後ろを少し切り取る**修正をしました。これでエラーが解消されました。
13
+ よって、**ウインドウがぴったりと切り分けられるように入力配列の後ろを少しる**修正をしました。これでエラーが解消されました。
14
14
 
15
15
 
16
16
 
@@ -70,7 +70,7 @@
70
70
 
71
71
 
72
72
 
73
- # ★修正 ウインドウがぴったりと切りれるように入力配列の後ろを少し切り取
73
+ # ★修正 ウインドウがぴったりと切り分けられるように入力配列の後ろを少し
74
74
 
75
75
  x = x[:-((len(x) - window_num) % stride_num)]
76
76
 

5

補足追記

2020/10/24 03:50

投稿

toast-uz
toast-uz

スコア3266

test CHANGED
@@ -30,11 +30,11 @@
30
30
 
31
31
 
32
32
 
33
- 一方、[stftのドキュメント](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.stft.html)には、Axis along which the STFT is computed; the default is over the last axis (i.e. axis=-1).と書かれており、時間方向が最後(-1)の次元がデフォルトです。よってこのギャップが原因で、モノラルだと通るけど、ステレオだとエラーが出る、ということになっていました。axisプションでこの動作変えも可能ですがistftも同様思想なので、**「soundで取り込んだファイルをscipy.signalで分析る場合は次元を入替えしまったほうが早い」**と思います。
33
+ 一方、[stftのドキュメント](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.stft.html)には、Axis along which the STFT is computed; the default is over the last axis (i.e. axis=-1).と書かれており、時間方向が最後(-1)の次元がデフォルトです。よってこのギャップが原因で、モノラルだと通るけど、ステレオだとエラーが出る、ということになっていました。デフォルト設定でステレ音声入力すると、時間方向配列の長さが2しか無いことにり、最初かつ唯一ウインドウサイズ(=nperseg)が小さぎて設定さたnoverlapと比較し変だよ、というエラーになていものと思います。原因がわかるとエラーの意味もわかります。
34
34
 
35
35
 
36
36
 
37
- よって、scipy.signal処理の時に音声配列を転置(.T)してしまうのが解決策です。これにより、このエラーを解消することができました。なお、質問者様の音声ファイルはモノラルなのでエラーが発生していなかったと思われます。
37
+ 対策としてaxisオプションでこの動作を変えることも可能ですが、istftも同様の思想なので、**「soundで取り込んだファイルをscipy.signalで分析する場合は、次元を入れ替えてしまったほうが早い」**と思います。よって、scipy.signal処理の時に音声配列を転置(.T)してしまうのが解決策です。これにより、このエラーを解消することができました。なお、質問者様の音声ファイルはモノラルなのでエラーが発生していなかったと思われます。
38
38
 
39
39
 
40
40
 

4

文法の修正

2020/10/24 03:47

投稿

toast-uz
toast-uz

スコア3266

test CHANGED
@@ -6,11 +6,11 @@
6
6
 
7
7
 
8
8
 
9
- [stftのドキュメント](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.stft.html)には、Notesに、In order to enable inversion of an STFT via the inverse STFT in istft, the signal windowing must obey the constraint of “Nonzero OverLap Add” (NOLA), and the input signal must have complete windowing coverage (i.e. (x.shape[axis] - nperseg) % (nperseg-noverlap) == 0).と記載されており、ちゃんとistftしたいのであれば、入力シグナルがぴったりとウインドウに切り分けられるように(x.shape[axis] - nperseg) % (nperseg-noverlap) == 0 であること、という記載があります。すなわち、入力シグナルがウインドウで切り分けた余りがあることが、エラーの原因でした。実際には、paddedのデフォルトオプションによって、余りが補完されて、変換結果の方が膨らんでしまっていま
9
+ [stftのドキュメント](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.stft.html)には、Notesに、In order to enable inversion of an STFT via the inverse STFT in istft, the signal windowing must obey the constraint of “Nonzero OverLap Add” (NOLA), and the input signal must have complete windowing coverage (i.e. (x.shape[axis] - nperseg) % (nperseg-noverlap) == 0).と記載されています。ちゃんとistftしたいのであれば、入力シグナルがぴったりとウインドウに切り分けられるように(x.shape[axis] - nperseg) % (nperseg-noverlap) == 0 であること、という意味です。すなわち、入力シグナルがウインドウで切り分けた余りがあることが、エラーの原因でした。実際には、paddedのデフォルトオプションによって、余りが自動補完されて1つ余計にウインドウが計算され、変換結果の方が膨らんでしまっていました
10
10
 
11
11
 
12
12
 
13
- よって、**ウインドウがぴったりと切り取れるように入力配列の後ろを少し切り取る**こ、このエラーが解消されま
13
+ よって、**ウインドウがぴったりと切り取れるように入力配列の後ろを少し切り取る**修正をしました。でエラーが解消されました
14
14
 
15
15
 
16
16
 

3

より正確な記載に修正

2020/10/24 03:35

投稿

toast-uz
toast-uz

スコア3266

test CHANGED
@@ -6,7 +6,11 @@
6
6
 
7
7
 
8
8
 
9
- ちょっとこれ、stft istftで同じ長さオプの付方とかあるのかもしれませが、未確認です。
9
+ [stftのドキュメント](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.stft.html)にはNotesに、In order to enable inversion of an STFT via the inverse STFT in istft, the signal windowing must obey the constraint of “Nonzero OverLap Add” (NOLA), and the input signal must have complete windowing coverage (i.e. (x.shape[axis] - nperseg) % (nperseg-noverlap) == 0).と記載されており、ちゃんとistftしたいのあれば、入力シグナルがぴったりとウインドウ切り分けられるように(x.shape[axis] - nperseg) % (nperseg-noverlap) == 0 であること、という記載がありま。すなわち、入力グナルがウイドウで切り分た余りがあることが、エラー原因でた。実際には、paddedのデフォルトオプションによって、余りが補完さて、変換結果の方が膨らんでしまっています。
10
+
11
+
12
+
13
+ よって、**ウインドウがぴったりと切り取れるように入力配列の後ろを少し切り取る**ことで、このエラーが解消されます。
10
14
 
11
15
 
12
16
 
@@ -26,7 +30,7 @@
26
30
 
27
31
 
28
32
 
29
- 一方、stftのは、Axis along which the STFT is computed; the default is over the last axis (i.e. axis=-1).と書かれており、時間方向が最後(-1)の次元がデフォルトです。よってこのギャップが原因で、モノラルだと通るけど、ステレオだとエラーが出る、ということになっていました。axisオプションでこの動作を変えることも可能ですが、istftも同様の思想なので、**「soundで取り込んだファイルをscipy.signalで分析する場合は、次元を入れ替えてしまったほうが早い」**と思います。
33
+ 一方、[stftのドキュメント](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.stft.html)には、Axis along which the STFT is computed; the default is over the last axis (i.e. axis=-1).と書かれており、時間方向が最後(-1)の次元がデフォルトです。よってこのギャップが原因で、モノラルだと通るけど、ステレオだとエラーが出る、ということになっていました。axisオプションでこの動作を変えることも可能ですが、istftも同様の思想なので、**「soundで取り込んだファイルをscipy.signalで分析する場合は、次元を入れ替えてしまったほうが早い」**と思います。
30
34
 
31
35
 
32
36
 
@@ -63,6 +67,12 @@
63
67
  window_num = 256 # 窓幅のデータ数
64
68
 
65
69
  stride_num = 128 # ストライド幅のデータ数
70
+
71
+
72
+
73
+ # ★修正 ウインドウがぴったりと切り取れるように入力配列の後ろを少し切り取る。
74
+
75
+ x = x[:-((len(x) - window_num) % stride_num)]
66
76
 
67
77
 
68
78
 
@@ -110,10 +120,6 @@
110
120
 
111
121
  plt.figure('Signal difference waveform')
112
122
 
113
- # ★修正 配列の長さを揃える
114
-
115
- min_len = min(len(x), len(y))
116
-
117
- plt.plot(x[:min_len]-y[:min_len])
123
+ plt.plot(x-y)
118
124
 
119
125
  ```

2

一部修正

2020/10/24 03:29

投稿

toast-uz
toast-uz

スコア3266

test CHANGED
@@ -1,4 +1,4 @@
1
- 質問のエラーについて
1
+ **質問のエラーについて**
2
2
 
3
3
 
4
4
 
@@ -6,19 +6,31 @@
6
6
 
7
7
 
8
8
 
9
- 質問無いエラーについて
9
+ ちょっとこれ、stft → istftで同じ長さ戻すオプションの付け方とかあるのかもしれませんが、未確認です。
10
10
 
11
11
 
12
12
 
13
- ところが、上記至るまでに別のエラーで悩まされました。`f, t, X1 = sg.stft(x, fs=fs, nperseg=window_num, noverlap=window_num-stride_num)`のところで、別のエラー`ValueError: noverlap must be less than nperseg.`が発生するのです。soundfileで音声を取り込んでstftをする例がネット無く、waveによる取り込みが主でした。よっ、waveによる取り込みとsoundfileによる取り込みを比較して、ステレオ時にsoundfileで取り込む形式が、その後のstftに悪影響を与えていることを関連付けました。
13
+ **質問無いエラーについ**
14
14
 
15
15
 
16
16
 
17
- 結論してはsoundfileでの音声ファイルは、モノは1次元、ステレオでは2次元の配列になっていることが原因でした。実際に、[モノラルとステレオ両方のサンプルを提供しているサイト](https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/audio-samples.html)にてwavファイルを取得して、soundfileの取り込み形式を比較して確認しました。一方、stftは1次元配列を前提としています。
17
+ ころが上記に至るまに別悩まされました。`f, t, X1 = sg.stft(x, fs=fs, nperseg=window_num, noverlap=window_num-stride_num)`のところで、別のエラー`ValueError: noverlap must be less than nperseg.`が発生るのです
18
18
 
19
19
 
20
20
 
21
- そのため、soundfileの入力がモノラルかステレオかを区別して、ステレオの際に、片側の音声のみ1次元配列とし取り出す対処をす必要があります。れにり、こエラーを解消することができました。なお、質問者様の音声ファイルはモノラルなのでエラーが発生していなかったと思われます。
21
+ 結論としては、soundfile音声ファイルは、モノラルでは1次元、ステレオ2次元配列になっること、おび2次元時の次元の意味がstftの期待とズレていることが原因でした。
22
+
23
+
24
+
25
+ 実際に、[モノラルとステレオ両方のサンプルを提供しているサイト](https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/audio-samples.html)にてwavファイルを取得して、soundfileの取り込み形式を比較して確認しました。shapeを見ると、モノラルだと(8250520,)、ステレオだと(8250624, 2)といった形をしています。時間方向は最初の次元であることに注意してください。
26
+
27
+
28
+
29
+ 一方、stftの方は、Axis along which the STFT is computed; the default is over the last axis (i.e. axis=-1).と書かれており、時間方向が最後(-1)の次元がデフォルトです。よってこのギャップが原因で、モノラルだと通るけど、ステレオだとエラーが出る、ということになっていました。axisオプションでこの動作を変えることも可能ですが、istftも同様の思想なので、**「soundで取り込んだファイルをscipy.signalで分析する場合は、次元を入れ替えてしまったほうが早い」**と思います。
30
+
31
+
32
+
33
+ よって、scipy.signal処理の時に音声配列を転置(.T)してしまうのが解決策です。これにより、このエラーを解消することができました。なお、質問者様の音声ファイルはモノラルなのでエラーが発生していなかったと思われます。
22
34
 
23
35
 
24
36
 
@@ -54,23 +66,19 @@
54
66
 
55
67
 
56
68
 
57
- # ★修正 マルチチャネルなら最初きチャネルみを取り出
69
+ # ★修正 sg計算前後で転置る。
58
-
59
- if x.ndim > 1:
60
-
61
- x = x[:,0]
62
-
63
-
64
70
 
65
71
  # スペクトログラムの計算
66
72
 
67
- f, t, X1 = sg.stft(x, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num))
73
+ f, t, X1 = sg.stft(x.T, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num))
68
74
 
69
75
 
70
76
 
71
77
  # 逆STFTによる復号
72
78
 
73
79
  _, y = sg.istft(X1, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num))
80
+
81
+ y = y.T
74
82
 
75
83
 
76
84
 

1

質問修正に伴う回答修正

2020/10/24 01:43

投稿

toast-uz
toast-uz

スコア3266

test CHANGED
@@ -1,13 +1,111 @@
1
- 質問者様使われたOverlapLengthは、有償プログミング言語であるMATLABのオプションです。MATLABはそもそもPythonとは別物ですし、Pythonのライブラリとも似非なるものです。Pythonのライブラリ群がMATLABを真似たものと思います。
1
+ 質問のーについ
2
2
 
3
3
 
4
4
 
5
- 現状コードOverlapLengthの箇所以外でも、エラーやワーニング各所にてしいます。
5
+ stftしてistftすると、元配列から長さが変わるようす。そのため長さを揃えて計算しないと、`plt.plot(x-y)`のところで、`ValueError: operands could not be broadcast together with shapes (27200,) (27264,)`といったエラーが出ます。これが質問者様の報告されたエラーです。
6
-
7
- よって、Pythonとそのライブラリ群を前提に、コードを再度検討いただき、改めてご質問ください。
8
6
 
9
7
 
10
8
 
11
- [ウィキペティアMATLAB](https://ja.wikipedia.org/wiki/MATLAB)
9
+ 質問に無いエラーについて
12
10
 
13
- [MATLAB に慣れた人が Python を始めるときの11の注意点](https://datachemeng.com/matlab_to_python/)
11
+
12
+
13
+ ところが、上記に至るまでに別のエラーで悩まされました。`f, t, X1 = sg.stft(x, fs=fs, nperseg=window_num, noverlap=window_num-stride_num)`のところで、別のエラー`ValueError: noverlap must be less than nperseg.`が発生するのです。soundfileで音声を取り込んでstftをする例がネットに無く、waveによる取り込みが主でした。よって、waveによる取り込みとsoundfileによる取り込みを比較して、ステレオ時にsoundfileで取り込む形式が、その後のstftに悪影響を与えていることを関連付けました。
14
+
15
+
16
+
17
+ 結論としては、soundfileでの音声ファイルは、モノラルでは1次元、ステレオでは2次元の配列になっていることが原因でした。実際に、[モノラルとステレオ両方のサンプルを提供しているサイト](https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/audio-samples.html)にてwavファイルを取得して、soundfileの取り込み形式を比較して確認しました。一方、stftは1次元配列を前提としています。
18
+
19
+
20
+
21
+ そのため、soundfileの入力がモノラルかステレオかを区別して、ステレオの際には、片側の音声のみ1次元配列として取り出す対処をする必要があります。これにより、このエラーを解消することができました。なお、質問者様の音声ファイルはモノラルなのでエラーが発生していなかったと思われます。
22
+
23
+
24
+
25
+ 以上2点の修正を加えたソースです。
26
+
27
+
28
+
29
+ ```Python
30
+
31
+ # モジュールのインポート
32
+
33
+ import numpy as np
34
+
35
+ import matplotlib.pyplot as plt
36
+
37
+ import soundfile as sf
38
+
39
+ import scipy
40
+
41
+ from scipy import signal as sg
42
+
43
+
44
+
45
+ # 音声の読み込み
46
+
47
+ x, fs = sf.read('speech1.wav')
48
+
49
+
50
+
51
+ window_num = 256 # 窓幅のデータ数
52
+
53
+ stride_num = 128 # ストライド幅のデータ数
54
+
55
+
56
+
57
+ # ★修正 マルチチャネルなら最初きチャネルのみを取り出す
58
+
59
+ if x.ndim > 1:
60
+
61
+ x = x[:,0]
62
+
63
+
64
+
65
+ # スペクトログラムの計算
66
+
67
+ f, t, X1 = sg.stft(x, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num))
68
+
69
+
70
+
71
+ # 逆STFTによる復号
72
+
73
+ _, y = sg.istft(X1, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num))
74
+
75
+
76
+
77
+ # 出力音声の保存
78
+
79
+ sf.write('outout.wav', y, fs)
80
+
81
+
82
+
83
+ # グラフに表示
84
+
85
+ # - 波形
86
+
87
+ plt.figure('Original waveform')
88
+
89
+ plt.plot(x)
90
+
91
+
92
+
93
+ # - 復号した波形
94
+
95
+ plt.figure('Decryption waveform')
96
+
97
+ plt.plot(y)
98
+
99
+
100
+
101
+ # - 信号差の波形(ここが分からない。入力信号xと出力信号yの差信号x−yが求めたい)
102
+
103
+ plt.figure('Signal difference waveform')
104
+
105
+ # ★修正 配列の長さを揃える
106
+
107
+ min_len = min(len(x), len(y))
108
+
109
+ plt.plot(x[:min_len]-y[:min_len])
110
+
111
+ ```