teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

6

文法の修正

2020/10/24 03:50

投稿

toast-uz
toast-uz

スコア3266

answer CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  [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つ余計にウインドウが計算され、変換結果の方が膨らんでしまっていました。
6
6
 
7
- よって、**ウインドウがぴったりと切りれるように入力配列の後ろを少し切り取る**修正をしました。これでエラーが解消されました。
7
+ よって、**ウインドウがぴったりと切り分けられるように入力配列の後ろを少しる**修正をしました。これでエラーが解消されました。
8
8
 
9
9
  **質問に無いエラーについて**
10
10
 
@@ -34,7 +34,7 @@
34
34
  window_num = 256 # 窓幅のデータ数
35
35
  stride_num = 128 # ストライド幅のデータ数
36
36
 
37
- # ★修正 ウインドウがぴったりと切りれるように入力配列の後ろを少し切り取
37
+ # ★修正 ウインドウがぴったりと切り分けられるように入力配列の後ろを少し
38
38
  x = x[:-((len(x) - window_num) % stride_num)]
39
39
 
40
40
  # ★修正 sg計算の前後で転置する。

5

補足追記

2020/10/24 03:50

投稿

toast-uz
toast-uz

スコア3266

answer CHANGED
@@ -14,9 +14,9 @@
14
14
 
15
15
  実際に、[モノラルとステレオ両方のサンプルを提供しているサイト](https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/audio-samples.html)にてwavファイルを取得して、soundfileの取り込み形式を比較して確認しました。shapeを見ると、モノラルだと(8250520,)、ステレオだと(8250624, 2)といった形をしています。時間方向は最初の次元であることに注意してください。
16
16
 
17
- 一方、[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で分析る場合は次元を入替えてしまっが早」**と思います。
17
+ 一方、[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と比較して変だよ、といエラーになってたものと思います。原因がわかるとエラーの意味もわかります。
18
18
 
19
- よって、scipy.signal処理の時に音声配列を転置(.T)してしまうのが解決策です。これにより、このエラーを解消することができました。なお、質問者様の音声ファイルはモノラルなのでエラーが発生していなかったと思われます。
19
+ 対策としてaxisオプションでこの動作を変えることも可能ですが、istftも同様の思想なので、**「soundで取り込んだファイルをscipy.signalで分析する場合は、次元を入れ替えてしまったほうが早い」**と思います。よって、scipy.signal処理の時に音声配列を転置(.T)してしまうのが解決策です。これにより、このエラーを解消することができました。なお、質問者様の音声ファイルはモノラルなのでエラーが発生していなかったと思われます。
20
20
 
21
21
  以上2点の修正を加えたソースです。
22
22
 

4

文法の修正

2020/10/24 03:47

投稿

toast-uz
toast-uz

スコア3266

answer CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  stftしてistftすると、元の配列から長さが変わるようです。そのため、長さを揃えて計算しないと、`plt.plot(x-y)`のところで、`ValueError: operands could not be broadcast together with shapes (27200,) (27264,)`といったエラーが出ます。これが質問者様の報告されたエラーです。
4
4
 
5
- [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のデフォルトオプションによって、余りが補完されて、変換結果の方が膨らんでしまっていま
5
+ [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つ余計にウインドウが計算され、変換結果の方が膨らんでしまっていました
6
6
 
7
- よって、**ウインドウがぴったりと切り取れるように入力配列の後ろを少し切り取る**こ、このエラーが解消されま
7
+ よって、**ウインドウがぴったりと切り取れるように入力配列の後ろを少し切り取る**修正をしました。でエラーが解消されました
8
8
 
9
9
  **質問に無いエラーについて**
10
10
 

3

より正確な記載に修正

2020/10/24 03:35

投稿

toast-uz
toast-uz

スコア3266

answer CHANGED
@@ -2,8 +2,10 @@
2
2
 
3
3
  stftしてistftすると、元の配列から長さが変わるようです。そのため、長さを揃えて計算しないと、`plt.plot(x-y)`のところで、`ValueError: operands could not be broadcast together with shapes (27200,) (27264,)`といったエラーが出ます。これが質問者様の報告されたエラーです。
4
4
 
5
- ょっれ、stft istft同じ長さに戻オプの付方とかあるのかもれませんが、未確認です。
5
+ [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のデフォルトオプションによって、余り補完されて変換結果の方が膨らんしまっています。
6
6
 
7
+ よって、**ウインドウがぴったりと切り取れるように入力配列の後ろを少し切り取る**ことで、このエラーが解消されます。
8
+
7
9
  **質問に無いエラーについて**
8
10
 
9
11
  ところが、上記に至るまでに別のエラーで悩まされました。`f, t, X1 = sg.stft(x, fs=fs, nperseg=window_num, noverlap=window_num-stride_num)`のところで、別のエラー`ValueError: noverlap must be less than nperseg.`が発生するのです。
@@ -12,7 +14,7 @@
12
14
 
13
15
  実際に、[モノラルとステレオ両方のサンプルを提供しているサイト](https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/audio-samples.html)にてwavファイルを取得して、soundfileの取り込み形式を比較して確認しました。shapeを見ると、モノラルだと(8250520,)、ステレオだと(8250624, 2)といった形をしています。時間方向は最初の次元であることに注意してください。
14
16
 
15
- 一方、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で分析する場合は、次元を入れ替えてしまったほうが早い」**と思います。
17
+ 一方、[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で分析する場合は、次元を入れ替えてしまったほうが早い」**と思います。
16
18
 
17
19
  よって、scipy.signal処理の時に音声配列を転置(.T)してしまうのが解決策です。これにより、このエラーを解消することができました。なお、質問者様の音声ファイルはモノラルなのでエラーが発生していなかったと思われます。
18
20
 
@@ -32,6 +34,9 @@
32
34
  window_num = 256 # 窓幅のデータ数
33
35
  stride_num = 128 # ストライド幅のデータ数
34
36
 
37
+ # ★修正 ウインドウがぴったりと切り取れるように入力配列の後ろを少し切り取る。
38
+ x = x[:-((len(x) - window_num) % stride_num)]
39
+
35
40
  # ★修正 sg計算の前後で転置する。
36
41
  # スペクトログラムの計算
37
42
  f, t, X1 = sg.stft(x.T, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num))
@@ -54,7 +59,5 @@
54
59
 
55
60
  # - 信号差の波形(ここが分からない。入力信号xと出力信号yの差信号x−yが求めたい)
56
61
  plt.figure('Signal difference waveform')
57
- # ★修正 配列の長さを揃える
58
- min_len = min(len(x), len(y))
59
- plt.plot(x[:min_len]-y[:min_len])
62
+ plt.plot(x-y)
60
63
  ```

2

一部修正

2020/10/24 03:29

投稿

toast-uz
toast-uz

スコア3266

answer CHANGED
@@ -1,15 +1,21 @@
1
- 質問のエラーについて
1
+ **質問のエラーについて**
2
2
 
3
3
  stftしてistftすると、元の配列から長さが変わるようです。そのため、長さを揃えて計算しないと、`plt.plot(x-y)`のところで、`ValueError: operands could not be broadcast together with shapes (27200,) (27264,)`といったエラーが出ます。これが質問者様の報告されたエラーです。
4
4
 
5
- 質問無いエラーについて
5
+ ちょっとこれ、stft → istftで同じ長さ戻すオプションの付け方とかあるのかもしれませんが、未確認です。
6
6
 
7
- ところが、上記至るまでに別のエラーで悩まされました。`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に悪影響を与えてることを関連付けました。
7
+ **質問無いエラーにて**
8
8
 
9
- 結論してはsoundfileでの音声ファイルは、モノは1次元、ステレオでは2次元の配列になっていることが原因でした。実際に、[モノラルとステレオ両方のサンプルを提供しているサイト](https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/audio-samples.html)にてwavファイルを取得して、soundfile取り込み形式を比較して確認しました。一方、stftは1次元配列を前提しています。
9
+ ころが上記に至るまに別悩まされました。`f, t, X1 = sg.stft(x, fs=fs, nperseg=window_num, noverlap=window_num-stride_num)`のところで、別のエラー`ValueError: noverlap must be less than nperseg.`が発生るのです
10
10
 
11
- そのため、soundfileの入力がモノラルかステレオかを区別して、ステレオの際に、片側の音声のみ1次元配列とし取り出す対処をす必要があります。れによりエラーを解消することができました。なお、質問者様の音声ファイルはモノラルなのでエラーが発生していなかったと思われます。
11
+ 結論としては、soundfile音声ファイルは、モノラルでは1次元、ステレオ2次元配列になっるこおよび2次元時の次元の意味がstftの期待とズレていることが原因でした。
12
12
 
13
+ 実際に、[モノラルとステレオ両方のサンプルを提供しているサイト](https://docs.espressif.com/projects/esp-adf/en/latest/design-guide/audio-samples.html)にてwavファイルを取得して、soundfileの取り込み形式を比較して確認しました。shapeを見ると、モノラルだと(8250520,)、ステレオだと(8250624, 2)といった形をしています。時間方向は最初の次元であることに注意してください。
14
+
15
+ 一方、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で分析する場合は、次元を入れ替えてしまったほうが早い」**と思います。
16
+
17
+ よって、scipy.signal処理の時に音声配列を転置(.T)してしまうのが解決策です。これにより、このエラーを解消することができました。なお、質問者様の音声ファイルはモノラルなのでエラーが発生していなかったと思われます。
18
+
13
19
  以上2点の修正を加えたソースです。
14
20
 
15
21
  ```Python
@@ -26,15 +32,13 @@
26
32
  window_num = 256 # 窓幅のデータ数
27
33
  stride_num = 128 # ストライド幅のデータ数
28
34
 
29
- # ★修正 マルチチャネルなら最初きチャネルみを取り出
35
+ # ★修正 sg計算前後で転置る。
30
- if x.ndim > 1:
31
- x = x[:,0]
32
-
33
36
  # スペクトログラムの計算
34
- f, t, X1 = sg.stft(x, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num))
37
+ f, t, X1 = sg.stft(x.T, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num))
35
38
 
36
39
  # 逆STFTによる復号
37
40
  _, y = sg.istft(X1, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num))
41
+ y = y.T
38
42
 
39
43
  # 出力音声の保存
40
44
  sf.write('outout.wav', y, fs)

1

質問修正に伴う回答修正

2020/10/24 01:43

投稿

toast-uz
toast-uz

スコア3266

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