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

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

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

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

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

Q&A

解決済

2回答

2504閲覧

wavファイル(4ch,24bit)の波形データの可視化がしたい

mas_555

総合スコア13

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

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

2グッド

3クリップ

投稿2020/01/08 12:38

編集2020/01/08 12:42

実現したいこと

音波測定機器から吐き出した.wav形式の波形データをpythonで開き、波形のグラフを得たいです。

やったこと

下記リンク「waveモジュールで24bitの音声ファイルを読みたい」項を参考にしながら、ファイルを開いてデータの形式を確認するところまではいきました。
参考リンク
測定データの形式
・チャンネル数:4ch(4つのセンサーから波形データを同時に測定している)
・サンプル幅:3(つまり24bitデータ?)
・フレームレート:51200
・データ数:任意

教えていただきたいこと

4ch 24bitのデータから、4つの波形データのグラフを得たいのですが、データの構造がよくわからなく、下記の部分で手が止まっております。

■ いろいろ調べてみましたが下記の文章がよく理解できませんでした。おそらくバイナリファイル?機械語?のような話を理解していた方がよいのでしょうか?素人にもわかるような説明もしくは参考文献などご教示いただけますでしょうか。(「特に3byteずつ読み込む 0を詰める」の意味がわからない)

24bit音源の場合はfrombufferで24bitが指定できないため自力で読む必要があります。ここでは下記のコードのようにstructモジュールのunpackを用いて3byteずつ読み込みつつ、0を詰めてint32としてunpackすることで24bit音源の読み込みを実現しています。

■ その他コード中のわからなかった部分をコメントで記述しました。質問要旨がまとまっておらず申し訳ありませんが、
教えていただけますと幸いです。

python

1buf = fp.readframes(nframe * nchan) # ←なぜチャンネル数をかけているのでしょうか? 2 fp.close() 3 4 read_sec = 40 5 read_sample = read_sec * nchan * fs # ←なぜチャンネル数をかけているのでしょうか? 6 print("read {0} second (= {1} frame)...".format(read_sec, 7 read_sample)) 8 unpacked_buf = [unpack("<i", 9 bytearray([0]) + buf[nbyte * i:nbyte * (i + 1)])[0] 10 for i in range(read_sample)] 11 12 # ndarray化 13 ndarr_buf = np.array(unpacked_buf) 14 15 # -1.0〜1.0に正規化 ←正規化とは何のためにするのでしょうか? 16 float_buf = np.where(ndarr_buf > 0, 17 ndarr_buf / (2.0 ** 31 - 1), 18 ndarr_buf / (2.0 ** 31)) 19 20 # interleaveを解く(ステレオ音源の場合) 21 wav_l = float_buf[::2] # ステレオ(2ch)なので2つデータを取得しているのは理解しました。しかしなぜ一つのデータからステップでスライスしているのでしょうか? 22 wav_r = float_buf[1::2] # どのようなデータ構造をしているか、4chの場合はどのようにすべきか教えていただけますでしょうか 23 time = np.arange(np.alen(wav_l)) / fs

質問の要旨がまとまっておらず申し訳ありません。
素人質問で申し訳ありませんが、教えていただけると嬉しいです。

set0gut1👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

wavファイルのデータ部のバイト構造は

1バイト目1チャンネルの1つ目のデータの下位バイト
2バイト目1チャンネルの1つ目のデータの中間バイト
3バイト目1チャンネルの1つ目のデータの上位バイト
4バイト目2チャンネルの1つ目のデータの下位バイト
5バイト目2チャンネルの1つ目のデータの中間バイト
6バイト目2チャンネルの1つ目のデータの上位バイト
7バイト目3チャンネルの1つ目のデータの下位バイト
8バイト目3チャンネルの1つ目のデータの中間バイト
9バイト目3チャンネルの1つ目のデータの上位バイト
10バイト目4チャンネルの1つ目のデータの下位バイト
11バイト目4チャンネルの1つ目のデータの中間バイト
12バイト目4チャンネルの1つ目のデータの上位バイト
13バイト目1チャンネルの2つ目のデータの下位バイト
14バイト目1チャンネルの2つ目のデータの中間バイト
15バイト目1チャンネルの2つ目のデータの上位バイト
16バイト目2チャンネルの2つ目のデータの下位バイト
17バイト目2チャンネルの2つ目のデータの中間バイト
18バイト目2チャンネルの2つ目のデータの上位バイト
...

このデータより3バイトずつバイナリーデータを数値データに変換して

11チャンネルの1つ目の数値データ
22チャンネルの1つ目の数値データ
33チャンネルの1つ目の数値データ
44チャンネルの1つ目の数値データ
51チャンネルの2つ目の数値データ
62チャンネルの2つ目の数値データ
...

のような配列を作成するのですが、バイトデータを数値データに変換するunpack()関数は残念ながら1バイト、2バイト、4バイト、8バイトのバイナリーデータには対応しているのですが、3バイトのデータには対応しておりません。

そこで3バイトを読み込んだ後に最下位に 0x00 データを埋めて

上位バイト中間バイト下位バイト00000000

を4バイトデータとして数値に変換する処理(unpack)を行っているということです。

実際の処理としては、バイナリーデータは下位バイトが先頭にくる"リトルエンディアン"という並びになっておりますので、バイトデータの先頭に0x00を付加したのちに unpack() を行う処理をおこなっております。

その他

正規化とは何のためにするのでしょうか?

上記のように24bitのデータ(実際は0埋めされて32bitデータ)から数値に変換すると-2147483648 〜 2147483647 の値が得られますので、これを -1 ~ 1 の振幅のデータに変換を行っております。

interleaveを解く(ステレオ音源の場合)の箇所

数値データの配列は、4チャンネルのデータが交互に構成されておりますので、これをチャンネル毎に分割しているだけです。

投稿2020/01/08 15:29

編集2020/01/08 15:44
magichan

総合スコア15898

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

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

mas_555

2020/01/10 09:27 編集

回答ありがとうございます。 おかげさまで不明点がかなり解消し、データの見え方が変わりました。 丁寧に教えていただき大変助かりました。 もしご存じでしたら、新たに浮かんだ疑問にもお答え願えますでしょうか? センサから受け取った電圧値をバイナリデータに変換して.wavとして保存しているはずなので、 グラフ化するには バイナリデータ→正規化した振幅値→電圧値 という処理過程が必要かと考えております。 正規化振幅値→電圧値 の変換には何かしらの係数をかける必要があると思うのですが、 ここにはどういった数字をかけるべきでしょうか? (teratailでするべき質問ではないかもしれません。申し訳ありません)
magichan

2020/01/10 10:06

使用している音波測定機器の入力レンジの仕様によるかとおもいます。 測定器の取説に書かれてるのではないでしょうか。
mas_555

2020/01/10 12:55

いろいろと教えていただきありがとうございました。 説明書含めもっと調べてみます。 大変参考になりました。
guest

0

←なぜチャンネル数をかけているのでしょうか?

そりゃチャンネル数分の音声データがフレーム分並んでるからでしょう。

投稿2020/01/08 13:02

y_waiwai

総合スコア87719

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問