0

サイトから取得した例を使用して、コンピューターのマイク (2 チャネル) を介して記録されたデータからバイトのバッファーを読み取りますpyaudio

import pyaudio
import wave

CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"

p = pyaudio.PyAudio()

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

print("* recording")

frames = []

for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
    data = stream.read(CHUNK)
    frames.append(data)

print("* done recording")

print frames

frames次のようになります。

['\x00\xfd\xff\xff.....\xfc\xff\xff', '\xff\xfc\xff\xff......\xfc\xff\xff', ... ]

または私が変更した場合CHUNK = 1

['\x00\xfd\xff\xff', '\xff\xfc\xff\xff', '\x00\xfd\xcc\xcf']

もちろんもっと長いですが。バイトはチャネルごとにインターリーブされていると思われるので、2 つずつペアに分割する必要があると思います。

私が欲しいのは、次のような配列です。

np.array([
  [123, 43],
  [3, 433],
  [43, 66]
])

ここで、最初の列は最初のチャネルの値で、2 番目の列は 2 番目のチャネルの値です。これらのエンコードされた値を解釈するにはどうすればよいですか ( CHUNK1024 のような妥当な値に設定)。


アップデート:

私はかなり混乱しています。以下を使用して、format文字列のリストをスペースで区切られた16進値の単一の文字列に変更しましたが、それらの数が奇数であるように見えます...これは、チャネルごとに1つずつ、2つの値がある場合には起こりません(偶数になります):

fms = ''.join(frames)
fms_string = ''.join( [ "%02X " % ord( x ) for x in fms ] ).strip()
fms_list = fms_string.split(" ")
print len(fms_list) # this prints an ODD number...

更新 2:

より簡単なルートを試して、これを試しました:

import array
fstring = ''.join(frames)
wave_nums = array.array('h', fstring) # this correctly returns list of ints!
print len(wave_nums) 

さまざまな録音時間でこれを試したところ、次の結果が得られました (混乱する結果)。

RECORD_SECONDS = 2 ---> len(wave_nums) is 132300 (132300 / 44100 = 3 seconds of frames)
RECORD_SECONDS = 4 ---> len(wave_nums) is 308700 (308700 / 44100 = 7 seconds of frames)
RECORD_SECONDS = 5 ---> len(wave_nums) is 396900 (396900 / 44100 = 9 seconds of frames)

これは、秒数と一致するフレーム数を取得していることを意味し2*(number of seconds recording) - 1ます...これはどのように可能ですか?

4

2 に答える 2

1

portaudio ソースをざっと見てみると、実際にはチャネルがインターリーブされているように見えます

結合を使用してリストを平坦化し、左右の値を計算して (それらを 16 ビット長に設定)、リストをそれ自体で圧縮できます。

joined = ''.join(frames).encode('latin-1')

left = map(lambda m, l: (m << 8) + l, joined[0::4], joined[1::4])
right = map(lambda m, l: (m << 8) + l, joined[2::4], joined[3::4])

zipped = zip(left, right)

Python 2.x では、encode latin1 トリックは機能しないため、次のようにする必要があります。

joined = ''.join(frames)
joined = map(ord, joined)

left = map(lambda m, l: (m << 8) + l, joined[0::4], joined[1::4])
right = map(lambda m, l: (m << 8) + l, joined[2::4], joined[3::4])

zipped = zip(left, right)

これは、Python 2.x の ascii 文字列と unicode の優先順位と関係があります。

アップデート:

バイト数が奇数の場合、read先に読み込もうとしたバイト数が多すぎて黙って失敗し、その時点で持っていたものだけが返された可能性があります。通常の状態では常​​に複数の CHUNK バイトを read から受け取る必要があるため、結合関数にエラーがない限り、最後に何か問題があります。私と一緒に試してみて、何が起こるか見てください。

于 2013-08-29T04:38:06.163 に答える