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

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

ただいまの
回答率

90.76%

  • Python

    6915questions

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

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

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 292

Daichi_Saito

score 1

 前提・実現したいこと

リアルタイム音声処理に関して勉強し始めて、とりあえず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

 該当のソースコード

import wave
import struct
import pyaudio
from pylab import *

CHUNK = 4096
RATE = 44100
p = pyaudio.PyAudio()

stream = p.open(format=pyaudio.paInt16, channels=1, rate=RATE, frames_per_buffer = CHUNK, input=True, output = True) #inputとoutputを同時に実行

def reverb(input):
    fs = RATE
    data = input
    data = frombuffer(data, dtype="int16") / 32768.0
    a = 0.7
    repeat = 3
    d = 1000
    newdata = [0.0] * CHUNK
    for n in range(CHUNK):
        newdata[n] = data[n]
        for i in range(1, repeat+1):
            m = int(n - i * d)
            if m>=0:
                newdata[n] += (a ** i) * data[m]
    newdata = [int(x * 32767.0) for x in newdata]
    newdata = struct.pack("h"*len(newdata), *newdata)
    return newdata

while stream.is_active():
    input = stream.read(CHUNK)
    input = reverb(input)
    output = stream.write(input)

stream.stop_stream()
stream.close()
p.terminate()

print("Stop Streaming")
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

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ミリ秒で結構大きい印象です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.76%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python

    6915questions

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