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

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

新規登録して質問してみよう
ただいま回答率
85.31%
Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

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

Q&A

1回答

592閲覧

Pythonでpcmデータをflacにするときのコードについて

ngh_orange

総合スコア17

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

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

0グッド

0クリップ

投稿2023/04/29 15:00

編集2023/04/30 12:51

実現したいこと

Raspberry PiのGPIO(ADC)で録音したPCMのデータをwindowsでflacに変換したいです。

前提

現在のコードで変換自体はできるのですが、何故か早送り?倍速みたいになってしまいます。
自分ではビットレートやサンプルなどの数を合わせているつもりなのですが、何故かうまくいきません。ここを改善したいです。

該当のソースコード

録音側(ラズパイ、MicroPython)のコードです。

Python

1import uos 2import ustruct 3import utime 4from machine import Pin, ADC 5from micropython import const 6import os 7 8filename = "/recording.pcm" 9 10mic_pin = ADC(Pin(26)) 11 12with open(filename, "wb") as f: 13 # サンプリング周波数 14 sample_rate = const(16000) 15 # サンプルあたりのバイト数 16 sample_width = const(2) 17 # チャンネル数 18 num_channels = const(1) 19 # 1秒あたりのサンプル数 20 samples_per_second = sample_rate * num_channels 21 # 1フレームあたりのバイト数 22 bytes_per_frame = sample_width * num_channels 23 # 録音する時間 24 record_time = 3 25 # 録音するサンプル数 26 num_samples = record_time * samples_per_second 27 28 # 録音を開始 29 print("start") 30 for i in range(num_samples): 31 sample = mic_pin.read_u16() 32 sample_data = ustruct.pack("<H", sample) 33 f.write(sample_data) 34 35print("stop") 36f.close() 37 38uos.umount("/") 39print("finish") 40

エンコード側(PC、普通のPython)

Python

1from pydub import AudioSegment 2 3pcm_file = AudioSegment.from_file("recording.pcm", format="raw", frame_rate=16000, channels=1, sample_width=2) 4 5pcm_file.export("recording.flac", format="flac")

試したこと

ビットレートを別のに合わせてみたりしましたが、だめでした。

補足情報(FW/ツールのバージョンなど)

Raspberry PiPico
windows10
MicroPython 1.19.1
Python 3.9.7

追記

can110様が教えていただいた通り、適切なサンプリングレートで録音できていないことがわかりました。
何回か測定してみたところ、3000~11000というとても幅があることになり、困っています。
試しに11000ぐらいでエンコードしてみたところ、たしかに速度は適切でしたが、明らかに音が低くなってしまいました。
プログラミング側で16000Hzに固定、またはその周辺での録音か、16000Hzではなくても普通に録音する方法はありませんか?
マイコンで録音したい、というのは珍しいことではないと思うのですが、普通はどうやって実現しているのでしょうか?

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

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

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

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

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

can110

2023/04/30 00:33

録音側コードでのデータ読み取りループでサンプリング数の制御はされているでしょうか? つまり、実時間の1秒での読み取り(ループ)回数はサンプリング周波数に一致している必要があります。
ngh_orange

2023/04/30 01:18

コメントありがとうございます! forのrangeでサンプリングレート*秒数で指定してるつもりなのですが、これでは制御しているということにはならないのでしょうか?
can110

2023/04/30 01:34 編集

はい。rangeではサンプリング総数=読み取り総回数だけを指定していますが、3秒分のつもりで処理していても そのループ処理が実時間では6秒かかっていたら、期待したデータは得られないということです。 つまりmic_pin.read_u16()が期待しているサンプリング周波数(時間間隔)で呼び出されているか確認が必要です。
ngh_orange

2023/04/30 07:13

start_time = utime.ticks_us() for i in range(num_samples): sample = mic_pin.read_u16() sample_data = ustruct.pack("<H", sample) f.write(sample_data) end_time = utime.ticks_us() elapsed_time = utime.ticks_diff(end_time, start_time) / 1000000) actual_sample_rate = num_samples / elapsed_time print("Actual sample rate:", actual_sample_rate) こういった形で計測するであっていますか? ちなみにこうしたら5607hzとでたのですが、これが原因ということでしょうか?
ngh_orange

2023/04/30 12:51

何回も測定してみて、幅があることがわかりました。 質問の方に追記として書かせていただきました、ありがとうございます!
guest

回答1

0

Pico触ったことないので未検証ですが
classmachine.ADC(id, *, sample_ns, atten)にてサンプリング時間を指定できそうです。
ただし、もし値の読込~ファイル出力に時間がかかっていると処理が追い付かなくて思った結果にならない可能性はありえます。

投稿2023/05/01 04:32

can110

総合スコア38352

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

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

ngh_orange

2023/05/01 06:20

再度回答本当にありがとうございます。 早速試してみたところ、そもそもinitメソッドが無いと返されてしまいます。試しにblockメソッドも試したところこちらもないと返されてしまいました。 mic_pin = ADC(Pin(26)) mic_pin.init() print(type(mic_pin)) この順番でしっかりADCオブジェクトを作ってからそれに対しinitをしていますがだめでした。 mic_pin(freq=16000)、mic_pin(16000)など、いろいろな指定方法を試してみましたがメソッドが無いと言われているので検討持つかず.... 公式リファレンス見ても、例えば1.16などはinitでレート指定できないみたいですが私の環境は1.19.1ですし、なにか根本的に間違ってたりするのでしょうか? なにか心当たりあれば何でも試すので教えていただきたいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

アカウントをお持ちの方は

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問