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

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

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

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

解決済

Python2.7 バイナリデータ?を整数型に変えたい

slimat
slimat

総合スコア0

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

1回答

0評価

0クリップ

29閲覧

投稿2019/04/03 08:20

編集2022/01/12 10:58

こんにちは。

MacOS Mojave・Python2.7環境でマイクから音を拾って、拾った音をwavファイルに書き込むというプログラムを書こうとしてる途中です。下のコードを実行すると画像のように、dataにはBytes型?のオブジェクトが入っているようなのですけど、その次の行で以下のようなエラーが発生しました。これを適切に整数型に変換してfor文などで要素を一つづつ取り出すなどの処理をしたいのですが、どのように書き直したら上手くいくでしょうか。なお、下記のようにしてpyaudioでは16bitで収録するようにしています。

Python

stream = audio.open(format=pyaudio.paInt16, # 量子化ビット数16bit channels=int(channel), # チャンネル数 rate=int(fs), # サンプリング周波数 input=True, # 録音のときは input=True frames_per_buffer=size, # バッファのサイズを設定 stream_callback = adCallback) # コールバック関数の設定 print data intData = struct.unpack("h", data)

イメージ説明

bash

Traceback (most recent call last): File "5-4.py", line 103, in <module> wavOut(filename) File "5-4.py", line 23, in wavOut intData = struct.unpack("h", data) struct.error: unpack requires a string argument of length 2

下はコード全体です。

Python

#coding: utf-8 import pyaudio as pyaudio import wave import time import numpy as np import matplotlib.pyplot as plt import struct fs = 16000 # サンプリング周波数 [Hz] channel = 1 # チャンネル数 ####### wavファイル保存関数 def wavOut(filename): # 書き出し用オブジェクトの生成(ファイル名の決定) out = wave.Wave_write(filename) out.setnchannels(channel) # チャンネル数を設定 out.setsampwidth(2) # 量子化ビット数16bits(2byte)を設定 out.setframerate(fs) # サンプリング周波数を設定 print data intData = struct.unpack("h", data) for i in intData: if i > 10000: print i if i < 10000: print u"10000未満:" + i # dataを結合してwrite out.writeframes(b''.join(data)) # dataはbytes型 out.close() ####### プロット関数 def plotOut(plot_data): plt.clf() plt.ylim(-1*2**15, 2**15) # 上下15bit分を表示 plt.plot(plot_data) plt.pause(0.01) # plotして0.01秒pause ####### 録音用コーバック関数(別スレッドで動作) def adCallback(in_data, frame_count, time_info, status): # dataに録音バッファ(in_data)を追加 data.append(in_data) # in_dataは何型? # 代入する前にグローバル変数であることを宣言 global buf # 取得した録音バッファ(in_data)をint16に変換 buf = np.frombuffer(in_data, dtype="int16") return (None, pyaudio.paContinue) ####### ここからメイン if __name__ == '__main__': # バッファのサイズ size = 2**10 audio = pyaudio.PyAudio() # オーディオストリームstreamをopen stream = audio.open(format=pyaudio.paInt16, # 量子化ビット数16bit channels=int(channel), # チャンネル数 rate=int(fs), # サンプリング周波数 input=True, # 録音のときは input=True frames_per_buffer=size, # バッファのサイズを設定 stream_callback = adCallback) # コールバック関数の設定 # 初期化 data = [] buf = [] start_time = '' flag = True # 録音の開始 stream.start_stream() # 別スレッドで録音を開始 print ("Recording.") # メインスレッド処理 while flag == True: # プロット plotOut(buf) # プロット # buf中振幅の絶対値が 10000 を超えたら if np.max(np.absolute(buf)) > 10000: start_time = time.time() # 音圧が10000を超えた時刻を取得 print ("Time reset.") # 10000を超えたことをメッセージング flag = False while flag == False: # 音圧が10000を超えたら plotOut(buf) if time.time() - start_time > 2: # 録音を停止する print ("Finished.") stream.close() audio.terminate() flag = True else: # 停止までの残りの秒数をメッセージング print ("Remaining time [s]: " + str(5 - int(time.time() - start_time))) # ファイルに保存 filename = "record.wav" # 保存ファイル名 print ("Write: " + filename) wavOut(filename)

修正したコード(新しいコード)

Python

#coding: utf-8 import pyaudio as pyaudio import wave import time import numpy as np import matplotlib.pyplot as plt import struct fs = 16000 # サンプリング周波数 [Hz] channel = 1 # チャンネル数 ####### wavファイル保存関数 def wavOut(filename): # 書き出し用オブジェクトの生成(ファイル名の決定) out = wave.Wave_write(filename) out.setnchannels(channel) # チャンネル数を設定 out.setsampwidth(2) # 量子化ビット数16bits(2byte)を設定 out.setframerate(fs) # サンプリング周波数を設定 global packed packed = b''.join(data) print u"type(packed): " + str(type(packed)) # str print packed print type() # intData = struct.unpack("h", packed) for i in intData: if i > 10000: print i if i < 10000: print u"10000未満:" + i # dataを結合してwrite out.writeframes(packed) # dataはbytes型 out.close() ####### プロット関数 def plotOut(plot_data): plt.clf() plt.ylim(-1*2**15, 2**15) # 上下15bit分を表示 plt.plot(plot_data) plt.pause(0.01) # plotして0.01秒pause ####### 録音用コーバック関数(別スレッドで動作) def adCallback(in_data, frame_count, time_info, status): # print u"type(in_data): " + str(type(in_data)) # str data.append(in_data) # 文字列のリスト型オブジェクト print data # \xb6\xff\xba\xff\xb6\xff\xb7の形の出力が得られる # 代入する前にグローバル変数であることを宣言 global buf # 取得した録音バッファ(in_data)をint16に変換 # bufはリスト型なので、リストのインデックス0番にndarrayが入るということ? # 4文字の一つの数字に変換していく buf = np.frombuffer(in_data, dtype="int16") # bufはndarrayで、extendsは使えない。 # print u"type(buf): " + str(type(buf)) # 再代入してるからndarrayに変化 return (None, pyaudio.paContinue) ####### ここからメイン if __name__ == '__main__': # バッファのサイズ size = 2**10 audio = pyaudio.PyAudio() # オーディオストリームstreamをopen stream = audio.open(format=pyaudio.paInt16, # 量子化ビット数16bit channels=int(channel), # チャンネル数 rate=int(fs), # サンプリング周波数 input=True, # 録音のときは input=True frames_per_buffer=size, # バッファのサイズを設定 stream_callback = adCallback) # コールバック関数の設定 # 初期化 data = [] packed = 1 buf = False print u"初期化時はtype(buf): " + str(type(buf)) # list start_time = '' flag = True s = 2 # 録音の開始 stream.start_stream() # 別スレッドで録音を開始 print "Recording." # メインスレッド処理 while flag == True: plotOut(buf) # プロット # buf中振幅の絶対値が 10000 を超えたら if np.max(np.absolute(buf)) > 10000: start_time = time.time() # その時刻を取得 flag = False # このwhileループを抜け出し while flag == False: # そして、このループに入る plotOut(buf) # プロット if time.time() - start_time > s: # 検知してからs秒以上経っていたら print "Finished." stream.close() audio.terminate() flag = True # 録音終了 else: # 停止までの残りの秒数をメッセージング print "Remaining time [s]: " + str(5 - int(time.time() - start_time)) # ファイルに保存 filename = "record.wav" # 保存ファイル名 print "Write down wav format: " + filename print u"type(data): " + str(type(data)) # list wavOut(filename)

文字化けした出力の画像
イメージ説明

よろしくお願い致します。

良い質問の評価を上げる

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

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

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

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

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

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

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

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

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

tiitoi
tiitoi

2019/04/03 08:22

バイナリデータをパースするにはバイナリデータがどのようなフォーマットかわからないとできないと思いますよ。
slimat
slimat

2019/04/03 08:27

今、質問文を修正したのですが、この情報だと不足でしょうか。
tiitoi
tiitoi

2019/04/03 08:37 編集

data という変数はどのような変数なのでしょうか?
slimat
slimat

2019/04/03 08:44

コード全体を追記いたしました。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

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

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。