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

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

ただいまの
回答率

90.46%

  • Python 3.x

    10312questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Struts

    199questions

    StrutsはJava向けのWebアプリケーションフレームです。MVCモデルに基づいており、JSPやJavaサーブレットを組み合わせ、アプリケーション構築時に使用する各機能を提供しています。

struct.error: argument for 's' must be a bytes object

受付中

回答 1

投稿

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

TsuhaYuya

score 6

人工知能に関する断創録を参考にボイスチェンジャーを作ろうとしているのですが、エラーが発生してしまい、動いてくれません。。

実装環境
python 3.6.5

# coding: utf-8
import pyaudio
import struct
import subprocess

# SPTKを使った簡単なボイスチェンジャー

CHANNELS = 1
RATE = 16000
CHUNK = 1024


def record(raw_file, record_seconds=5):
    """音声ファイルを録音する
    録音時間は固定。キーボードを押すとループ終わりができなかった・・・"""
    fp = open(raw_file, "wb")
    for _ in range(0, int(RATE / CHUNK * record_seconds)):
        data = stream.read(CHUNK) # ストリームへの書き込み(バイナリ)
        fp.write(struct.pack('s' * CHUNK * 2, *data))
    fp.close()
    stream.stop_stream()
    stream.close()
    p.terminate()


def extract_pitch(raw_file, pitch_file):
    """ピッチパラメータの抽出"""
    cmd = "x2x +sf %s | pitch -a 1 -s 16 -p 80 > %s" % (raw_file, pitch_file)
    subprocess.call(cmd, shell=True)


def extract_mcep(raw_file, mcep_file):
    """メルケプストラムパラメータの抽出"""
    cmd = "x2x +sf %s | frame -p 80 | window | mcep -m 25 -a 0.42 > %s" % (raw_file, mcep_file)
    subprocess.call(cmd, shell=True)


def modify_pitch(m, pitch_file, mcep_file, raw_file):
    """ピッチを変形して再合成
    mが1より大きい => 低い声
    mが1より小さい => 高い声"""
    cmd = "sopr -m %f %s | excite -p 80 | mlsadf -m 25 -a 0.42 -p 80 %s | clip -y -32000 32000 | x2x +fs > %s" % (
    m, pitch_file, mcep_file, raw_file)
    subprocess.call(cmd, shell=True)


def modify_speed(frame_shift, pitch_file, mcep_file, raw_file):
    """話速を変形して再合成
    frame_shiftが小さい => 早口
    frame_shiftが大きい => ゆっくり"""
    cmd = "excite -p %f %s | mlsadf -m 25 -a 0.42 -p %f %s | clip -y -32000 32000 | x2x +fs > %s" % (
    frame_shift, pitch_file, frame_shift, mcep_file, raw_file)
    subprocess.call(cmd, shell=True)


def hoarse_voice(pitch_file, mcep_file, raw_file):
    """ささやき声"""
    modify_pitch(0, pitch_file, mcep_file, raw_file)


def robot_voice(frame_period, record_seconds, mcep_file, raw_file):
    """ロボット声
    frame_periodが小さい => 低い
    frame_periodが大きい => 高い"""
    sequence_length = record_seconds * RATE * frame_period
    cmd = "train -p %d -l %d | mlsadf -m 25 -a 0.42 -p 80 %s | clip -y -32000 32000 | x2x +fs > %s" % (
    frame_period, sequence_length, mcep_file, raw_file)
    subprocess.call(cmd, shell=True)


def child_voice(pitch_file, mcep_file, raw_file):
    """子供声"""
    cmd = "sopr -m 0.4 %s | excite -p 80 | mlsadf -m 25 -a 0.1 -p 80 %s | clip -y -32000 32000 | x2x +fs > %s" % (
    pitch_file, mcep_file, raw_file)
    subprocess.call(cmd, shell=True)


def deep_voice(pitch_file, mcep_file, raw_file):
    """太い声"""
    cmd = "sopr -m 2.0 %s | excite -p 80 | mlsadf -m 25 -a 0.6 -p 80 %s | clip -y -32000 32000 | x2x +fs > %s" % (
    pitch_file, mcep_file, raw_file)
    subprocess.call(cmd, shell=True)


def raw2wav(raw_file, wav_file):
    cmd = "sox -e signed-integer -c %d -b 16 -r %d %s %s" % (CHANNELS, RATE, raw_file, wav_file)
    subprocess.call(cmd, shell=True)


def play(raw_file):
    """rawファイルを再生"""
    p = pyaudio.PyAudio()
    stream = p.open(format=p.get_format_from_width(2), channels=CHANNELS, rate=RATE, output=True)
    f = open(raw_file, "rb")
    data = f.read(CHUNK)
    while data != '':
        stream.write(data)
        data = f.read(CHUNK)
    stream.stop_stream()
    stream.close()
    p.terminate()


if __name__ == "__main__":
    # 録音時間(固定)
    record_seconds = 10

    p = pyaudio.PyAudio()
    stream = p.open(format=pyaudio.paInt16,
                    channels=CHANNELS,
                    rate=RATE,
                    input=True,
                    frames_per_buffer=CHUNK)

    pitch_file = "temp.pitch"
    mcep_file = "temp.mcep"
    raw_file = "temp.raw"
    output_file = "output.raw"

    # オリジナルの音声を録音してrawファイルとして書き出し
    print("*** Now recording ... (%d sec)" % record_seconds)
    record(raw_file, record_seconds)

    # パラメータ抽出
    print("*** extract pitch ...")
    extract_pitch(raw_file, pitch_file)

    print("*** extract mel cepstrum")
    extract_mcep(raw_file, mcep_file)

    # パラメータ変形いろいろ
    print("*** modify parameters ...")

    # どれか一つしか有効にできない
    #    modify_pitch(0.3, pitch_file, mcep_file, output_file)
    #    modify_speed(300, pitch_file, mcep_file, output_file)
    #    hoarse_voice(pitch_file, mcep_file, output_file)
    #    robot_voice(100, record_seconds, mcep_file, output_file)
    #    child_voice(pitch_file, mcep_file, output_file)
    deep_voice(pitch_file, mcep_file, output_file)

    # 変換した音声を再生
    print("*** play!")
    play("output.raw")

エラー内容

Traceback (most recent call last):
 File "voice_changer.py", line 19, in record
    fp.write(struct.pack('s' * CHUNK * 2, *data))
struct.error: argument for 's' must be a bytes object

といった具合です。おそらく、変換する型がよくないのだと思いますが、変換の方法がわかっておりません。
よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

0

元のコードがpython2系のものなので、その絡みでエラーになっているのだと思います。文字列・バイト列周りは仕様が大きく変わっているので、そのままでは動かないのではないでしょうか。

dataの要素が何型になっているのかちょっとわかりませんが、最終的にはpython3のbytesに変換する必要があります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/01/28 15:35

    python2系では動きました。
    3系でも動かしたいのですが、変換の方法がよくわかっていません。
    print(type(data))でdataをプリントすると
    <class 'bytes'>という風に出力されました。

    どこを修正して行く必要がありますでしょうか

    キャンセル

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

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

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

  • Python 3.x

    10312questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Struts

    199questions

    StrutsはJava向けのWebアプリケーションフレームです。MVCモデルに基づいており、JSPやJavaサーブレットを組み合わせ、アプリケーション構築時に使用する各機能を提供しています。