質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

4116閲覧

PythonのOverlapLengtなどでの要素数の揃え方

NEK0o0

総合スコア2

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/10/18 10:19

編集2020/10/20 09:03

前提・実現したいこと

Pythonのプログラミングでの質問です
スぺクトログラムの表示などをするプログラムです
下にあるプログラムなのですがどうも配列の数が合わずどうすればいいかご教授願いたいです。
質問するのは初めてなためお手柔らかにお願いします---

発生している問題・エラーメッセージ

ValueError: operands could not be broadcast together with shapes (27200,) (27264,)

修正後のソースコード

Python

1# モジュールのインポート 2import numpy as np 3import matplotlib.pyplot as plt 4import soundfile as sf 5import scipy 6from scipy import signal as sg 7 8# 音声の読み込み 9x, fs = sf.read('speech1.wav') 10 11window_num = 256 # 窓幅のデータ数 12stride_num = 128 # ストライド幅のデータ数 13 14# スペクトログラムの計算 15f, t, X1 = sg.stft(x, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num)) 16 17# 逆STFTによる復号 18_, y = sg.istft(X1, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num)) 19 20# 出力音声の保存 21sf.write('outout.wav', y, fs) 22 23# グラフに表示 24# - 波形 25plt.figure('Original waveform') 26plt.plot(x) 27 28# - 復号した波形 29plt.figure('Decryption waveform') 30plt.plot(y) 31 32# - 信号差の波形(ここが分からない。入力信号xと出力信号yの差信号x−yが求めたい) 33plt.figure('Signal difference waveform') 34plt.plot(x-y) 35

試したこと

質問への回答を受け下記サイトからnperseg、noverlapを用いて要素数をそろえられないかと試した。 https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.istft.html

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

toast-uz

2020/10/19 11:28

それは有償パッケージなのでscipyとは似て非なるものですね。ググると紛らわしいです。そのことについて回答します。
guest

回答1

0

ベストアンサー

質問のエラーについて

stftしてistftすると、元の配列から長さが変わるようです。そのため、長さを揃えて計算しないと、plt.plot(x-y)のところで、ValueError: operands could not be broadcast together with shapes (27200,) (27264,)といったエラーが出ます。これが質問者様の報告されたエラーです。

stftのドキュメントには、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つ余計にウインドウが計算され、変換結果の方が膨らんでしまっていました。

よって、ウインドウがぴったりと切り分けられるように入力配列の後ろを少し削る修正をしました。これでエラーが解消されました。

質問に無いエラーについて

ところが、上記に至るまでに別のエラーで悩まされました。f, t, X1 = sg.stft(x, fs=fs, nperseg=window_num, noverlap=window_num-stride_num)のところで、別のエラーValueError: noverlap must be less than nperseg.が発生するのです。

結論としては、soundfileでの音声ファイルは、モノラルでは1次元、ステレオでは2次元の配列になっていること、および2次元の時の次元の意味がstftの期待とズレていることが原因でした。

実際に、モノラルとステレオ両方のサンプルを提供しているサイトにてwavファイルを取得して、soundfileの取り込み形式を比較して確認しました。shapeを見ると、モノラルだと(8250520,)、ステレオだと(8250624, 2)といった形をしています。時間方向は最初の次元であることに注意してください。

一方、stftのドキュメントには、Axis along which the STFT is computed; the default is over the last axis (i.e. axis=-1).と書かれており、時間方向が最後(-1)の次元がデフォルトです。よってこのギャップが原因で、モノラルだと通るけど、ステレオだとエラーが出る、ということになっていました。デフォルト設定でステレオ音声を入力すると、時間方向の配列の長さが2しか無いことになり、最初かつ唯一のウインドウサイズ(=nperseg)が小さすぎて、設定されたnoverlapと比較して変だよ、というエラーになっていたものと思います。原因がわかるとエラーの意味もわかります。

対策としてaxisオプションでこの動作を変えることも可能ですが、istftも同様の思想なので、**「soundで取り込んだファイルをscipy.signalで分析する場合は、次元を入れ替えてしまったほうが早い」**と思います。よって、scipy.signal処理の時に音声配列を転置(.T)してしまうのが解決策です。これにより、このエラーを解消することができました。なお、質問者様の音声ファイルはモノラルなのでエラーが発生していなかったと思われます。

以上2点の修正を加えたソースです。

Python

1# モジュールのインポート 2import numpy as np 3import matplotlib.pyplot as plt 4import soundfile as sf 5import scipy 6from scipy import signal as sg 7 8# 音声の読み込み 9x, fs = sf.read('speech1.wav') 10 11window_num = 256 # 窓幅のデータ数 12stride_num = 128 # ストライド幅のデータ数 13 14# ★修正 ウインドウがぴったりと切り分けられるように入力配列の後ろを少し削る 15x = x[:-((len(x) - window_num) % stride_num)] 16 17# ★修正 sg計算の前後で転置する。 18# スペクトログラムの計算 19f, t, X1 = sg.stft(x.T, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num)) 20 21# 逆STFTによる復号 22_, y = sg.istft(X1, fs=fs, nperseg=window_num, noverlap=(window_num-stride_num)) 23y = y.T 24 25# 出力音声の保存 26sf.write('outout.wav', y, fs) 27 28# グラフに表示 29# - 波形 30plt.figure('Original waveform') 31plt.plot(x) 32 33# - 復号した波形 34plt.figure('Decryption waveform') 35plt.plot(y) 36 37# - 信号差の波形(ここが分からない。入力信号xと出力信号yの差信号x−yが求めたい) 38plt.figure('Signal difference waveform') 39plt.plot(x-y)

投稿2020/10/19 11:49

編集2020/10/24 03:50
toast-uz

総合スコア3266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NEK0o0

2020/10/20 09:05

丁寧な回答ありがとうございます。再検討し 下記のサイトのnperseg、noverlapを用いて要素数をそろえられないかと試した。のですがやはり、前回と同じエラーが出てしまいます。始めたばかりでわからないことばかりで見当違いな質問をしているかもしれませんがどうか教えていただけると幸いです。https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.istft.html
toast-uz

2020/10/20 11:39

手近なwavファイルで試したみたところ、sg.stftのところで UserWarning: nperseg = 256 is greater than input length = 2, using nperseg = 2 ValueError: noverlap must be less than nperseg. が出て、質問者様の発生しているエラーまでたどり着けません。wavが違うためでしょうか?
NEK0o0

2020/10/21 08:27

再度実行してみたのですが ``` Traceback (most recent call last): File "", line 34, in <module> plt.plot(x-y) ValueError: operands could not be broadcast together with shapes (27200,) (27264,) ``` と出ています
NEK0o0

2020/10/21 08:28

ファイル名は消しているため空白なのはそういうことです
NEK0o0

2020/10/21 13:13

ありがとうございます。 なぜなのでしょうか… 正直、全く持ってやり方が分からない状態なのですが何かいい方法はないでしょうか…
toast-uz

2020/10/21 13:14

すみません。まずは上記のファイルで、私と同じエラーになるのか、確認いただけますか? エラーの出方が異なるのが、ファイルの違いなのか、別要因なのかを切り分けたいです。
NEK0o0

2020/10/21 13:23

提示していただいたファイルであると同じエラーが発生しました
NEK0o0

2020/10/21 13:25

また、使用しているファイルはステレオだと思います
toast-uz

2020/10/21 13:34

ありがとうございます。もう少し考えてみます。
toast-uz

2020/10/24 00:51

できました。
toast-uz

2020/10/24 03:32

やや気持ち悪かった前半部分も、気持ちよく理由と対策がわかりましたので、修正しました。自分としては、会心の回答です。
NEK0o0

2020/10/25 08:56

ここまでの回答をありがとうございます!!! ほんとに助かりました!! 最悪無理やりゼロ行列でも入れるしかない、と思っていたので助かりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問