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

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

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

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

Q&A

解決済

2回答

7516閲覧

リアルタイム音声処理に関して

Daichi_Saito

総合スコア7

Python

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

0グッド

0クリップ

投稿2018/05/09 13:44

前提・実現したいこと

リアルタイム音声処理に関して勉強し始めて、とりあえずreverbを実現させたく思い、以下のコードを実行しました。すると、次のようなエラーメッセージが出たのですが、どういうことでしょうか。また、どこを改善すれば良いのでしょうか。pythonです。

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

Traceback (most recent call last):
File "rev.py", line 32, in <module>
input = reverb(input)
File "rev.py", line 27, in reverb
newdata = struct.pack("h"*len(newdata), *newdata)
struct.error: short format requires (-32767 -1) <= number <= 32767

該当のソースコード

python

1import wave 2import struct 3import pyaudio 4from pylab import * 5 6CHUNK = 4096 7RATE = 44100 8p = pyaudio.PyAudio() 9 10stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, frames_per_buffer = CHUNK, input=True, output = True) #inputとoutputを同時に実行 11 12def reverb(input): 13 fs = RATE 14 data = input 15 data = frombuffer(data, dtype="int16") / 32768.0 16 a = 0.7 17 repeat = 3 18 d = 1000 19 newdata = [0.0] * CHUNK 20 for n in range(CHUNK): 21 newdata[n] = data[n] 22 for i in range(1, repeat+1): 23 m = int(n - i * d) 24 if m>=0: 25 newdata[n] += (a ** i) * data[m] 26 newdata = [int(x * 32767.0) for x in newdata] 27 newdata = struct.pack("h"*len(newdata), *newdata) 28 return newdata 29 30while stream.is_active(): 31 input = stream.read(CHUNK) 32 input = reverb(input) 33 output = stream.write(input) 34 35stream.stop_stream() 36stream.close() 37p.terminate() 38 39print("Stop Streaming")

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

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

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

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

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

guest

回答2

0

newdata の要素の値がshortの範囲を超えたために上記のエラーが出ています。

python

1Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit (Intel)] on wi 2n32 3Type "help", "copyright", "credits" or "license" for more information.>>> import struct 4>>> struct.pack("h", 0x7fff) 5'\xff\x7f' 6>>> struct.pack("h", 0x8000) 7Traceback (most recent call last): 8 File "<stdin>", line 1, in <module> 9struct.error: short format requires SHRT_MIN <= number <= SHRT_MAX 10>>> struct.pack("h", -0x8000) 11'\x00\x80' 12>>> struct.pack("h", -0x8001) 13Traceback (most recent call last): 14 File "<stdin>", line 1, in <module> 15struct.error: short format requires SHRT_MIN <= number <= SHRT_MAX

音の合成については詳しくないのですが、for で加算された値が、
-1.0~1.0におさまるようにすれば、
このエラーはでなくなるかと思います。

投稿2018/05/09 16:19

DanDan244

総合スコア57

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

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

0

ベストアンサー

DanDan244さんの回答がエラーの原因ですね。音声の加工はreverbに限らず波形の範囲やダイナミックレンジを気にしないといけないと思います。例えば質問者さんは3段階に渡り一定の遅延後に元の波形の振幅を少しずつ小さくして元波形に加算しようとしておられますが、元の振幅が-1~1だと上記の波形合成を単純にやってしまったのでは最終波形が-1~1の範囲を超えてしまいます。

これを避けるにはいくつか方法があり、ダイナミックレンジを確保するため「音の大小に応じて必要に応じて波形を弱める」ようなコンプレッサー論理などが一番よいと思いますが、少々難しいのでまずは単純に「一定の比率で元の信号を弱める」のがよいと思います。

ご質問のコードでは元の信号に加えて0.2秒強ごとに3回の残響音を0.7倍ずつの大きさで加算してますので元の信号の大きさを1としますと
1 + 0.7 + 0.7**2 + 0.7**3 == 2.533
の大きさになります。よって元信号を1/2.533倍してから加工してやれば信号が範囲内に収まると思います。


コードにはもう一つ大きな問題があります。質問者さんもおわかりであろうかと思いますが、今のコードでは自然なreverbになりません。本来ならchunkの先頭部分も直前のchunkの後半の信号の残響を反映させるべきです。そうするには「一つ前のchunkの波形データを取っておいて次のchunkのreverb処理で参照できるようにするのが単純な解決法になりそうです。

なお、残響の遅延時間は「せまい室内」なら短く「大きなホール」ではより長くなり、極端な話やまびこのようなもののシミュレートだと秒のオーダーの遅延になりますので4096といった短いチャンクサイズに依存した方法はあまり汎用的ではありません。本来はほしい遅延時間に応じた残響音処理用の別バッファーを用意しそこに必要なだけの「過去の波形」を覚えておくのがよいと思います。

残響を長くするためにCHUNKを大きくできれば簡単ですがCHUNKを大きくするということはレイテンシーが大きくなるということです。リアルタイムに録音した音声が実際に再生されるのに1秒とか遅延してしまうと応用としてNGになったりしますのでCHUNKを極端に大きくしないのが普通と思います。今のCHUNKは4096なのでレイテンシーは93ミリ秒で結構大きい印象です。

投稿2018/05/10 11:01

KSwordOfHaste

総合スコア18392

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問