ラズベリーパイでI2S出力
by K.I
2017/03/29〜
Index
- ラズベリーパイでの、I2S出力を確認する。
- といっても、データ出力の確認が主目的の個人的メモなので、
- この記事は一般的なオーディオ出力用としてはあまり役に立たないと思う
- カーネルの再コンパイルはせずに、インストール済みのドライバを流用する
No | Name | Description |
12 | BCK | ビットクロック |
35 | LRCK | L:Left、H:Right、サンプリング周波数と同じ |
40 | DATA | PCMデータ、通常はMSBファースト |
| | |
2,4 | +5V | +5V電源 |
6,9,14,20,25,30,34 | GND | |
- 実際に音を出してみたかったので、I2S入力のD級アンプを使う
No. | Name | Description |
1 | Vin | 2.5〜5.5Vだが、通常は+5Vとする |
2 | GND | グラウンド |
3 | SD_MODE | 0.16V以下:Shutdown、0.16〜0.77V:Left+Right、0.77〜1.4V:Right、1.4V以上:Left |
4 | GAIN | 15dB:100kΩPullDown、12dB:GND、9dB:default、6dB:Vin、3dB:100kΩPullUp |
5 | DIN | Data Input |
6 | BCLK | Bit Clock |
7 | LRCLK | Left/Right Clock |
- SD_MODE端子は、内部100kΩでPullDown、外部で1MΩPullUpされているので、約0.45V(L+R)、
- さらに例えば680kΩPullUpで約0.99V(R)、180kΩ以下でPullUpすれば約1.98V以上になる(L)
- モノラルアンプなので、ステレオにするためには、2個必要になる。
- GAINは、最低の3dBになるように、100kΩでプルアップ
- SD_MODEは、右チャンネルが680kΩプルアップ、左チャンネルが100kΩプルアップ
[top]
- ΔΣ変調器の記事で作ったDDSのプログラムを使う(idds.c)
- 1つめのパラメータで、生成する周波数
- 2つめのパラメータで、サンプリング周波数を指定する
% idds 1000 44100 | head -100 | gp_wav > sin1000w.png
- サンプリング周波数44.1kHzで、1kHz正弦波のwavファイルを作る
$ idds 1000 44100 > dds1k44100.dat
$ txt2wav -44100 dds1k44100.dat
dds1k44100.wav : 44100 Hz sampling, 16 bit, 1 channel
file size (header + data) = 88236 [Byte]
PCM type = 1
sampling rate = 44100 [Hz]
Byte / second = 88200 [Byte]
Byte / block = 2 [Byte]
bit / sample = 16 [bit]
file size (data) = 88200 [Byte]
44100 points write
dds1k44100.wav : 88244 bytes (1 sec)
- ステレオのファイルも作る
- とは言っても、単に左右同じ音を出すだけなので、本当のステレオとは言えないけど。。
$ idds 1000 44100 | stereo > dds1k44100s.dat
$ txt2wav -44100 dds1k44100s.dat
dds1k44100s.wav : 44100 Hz sampling, 16 bit, 2 channel
file size (header + data) = 176436 [Byte]
PCM type = 1
sampling rate = 44100 [Hz]
Byte / second = 176400 [Byte]
Byte / block = 4 [Byte]
bit / sample = 16 [bit]
file size (data) = 176400 [Byte]
44100 points write
dds1k44100s.wav : 176444 bytes (1 sec)
- こんな具合に、8つの1kHz正弦波のwavファイルを作っておく
- ビットレートは1秒あたりのビット数なので1
- 例えば、48kHzサンプリング、16bitステレオならば、48000 x 16 x 2 = 1536000
- Hifiberry DACというのは、ラズベリーパイ用のDACボードらしいが、このドライバを使う
$ uname -a
Linux raspberrypi 4.4.34-v7+ #930 SMP Wed Nov 23 15:20:41 GMT 2016 armv7l GNU/Linux
- 最近のRaspbianには、Hifiberryのドライバが含まれているので、設定のみで、
- /boot/config.txt でドライバのマッピングの指定
dtoverlay=hifiberry-dac
- これは、/boot/overlaysにあるファイルを指定するらしい
$ ls -l /boot/overlays/
合計 848
-rwxr-xr-x 1 root root 55994 4月 12 12:45 README
-rwxr-xr-x 1 root root 1411 4月 12 12:45 adau1977-adc.dtbo
-rwxr-xr-x 1 root root 2425 4月 12 12:45 ads1015.dtbo
-rwxr-xr-x 1 root root 2426 4月 12 12:45 ads7846.dtbo
-rwxr-xr-x 1 root root 1130 4月 12 12:45 akkordion-iqdacplus.dtbo
-rwxr-xr-x 1 root root 1011 4月 12 12:45 allo-piano-dac-pcm512x-audio.dtbo
-rwxr-xr-x 1 root root 1668 4月 12 12:45 at86rf233.dtbo
-rwxr-xr-x 1 root root 787 4月 12 12:45 audioinjector-wm8731-audio.dtbo
-rwxr-xr-x 1 root root 575 4月 12 12:45 audremap.dtbo
-rwxr-xr-x 1 root root 449 4月 12 12:45 bmp085_i2c-sensor.dtbo
-rwxr-xr-x 1 root root 983 4月 12 12:45 dht11.dtbo
-rwxr-xr-x 1 root root 663 4月 12 12:45 dionaudio-loco.dtbo
-rwxr-xr-x 1 root root 765 4月 12 12:45 dpi18.dtbo
-rwxr-xr-x 1 root root 789 4月 12 12:45 dpi24.dtbo
-rwxr-xr-x 1 root root 423 4月 12 12:45 dwc-otg.dtbo
-rwxr-xr-x 1 root root 908 4月 12 12:45 dwc2.dtbo
-rwxr-xr-x 1 root root 1279 4月 12 12:45 enc28j60-spi2.dtbo
-rwxr-xr-x 1 root root 1403 4月 12 12:45 enc28j60.dtbo
-rwxr-xr-x 1 root root 1036 4月 12 12:45 gpio-ir.dtbo
-rwxr-xr-x 1 root root 901 4月 12 12:45 gpio-poweroff.dtbo
-rwxr-xr-x 1 root root 779 4月 12 12:45 hifiberry-amp.dtbo
-rwxr-xr-x 1 root root 655 4月 12 12:45 hifiberry-dac.dtbo
-rwxr-xr-x 1 root root 1436 4月 12 12:45 hifiberry-dacplus.dtbo
-rwxr-xr-x 1 root root 949 4月 12 12:45 hifiberry-digi-pro.dtbo
-rwxr-xr-x 1 root root 783 4月 12 12:45 hifiberry-digi.dtbo
-rwxr-xr-x 1 root root 2468 4月 12 12:45 hy28a.dtbo
-rwxr-xr-x 1 root root 2939 4月 12 12:45 hy28b.dtbo
-rwxr-xr-x 1 root root 991 4月 12 12:45 i2c-gpio.dtbo
-rwxr-xr-x 1 root root 2185 4月 12 12:45 i2c-mux.dtbo
:
:
- /etc/modules で、起動時にドライバをロードするように設定
snd_soc_hifiberry_dac
- カーネルのバージョンは、4.4.34-v7+ なんだけど、
$ uname -a
Linux raspberrypi 4.4.34-v7+ #930 SMP Wed Nov 23 15:20:41 GMT 2016 armv7l GNU/Linux
- 同じ名前のフォルダが無いので、一番新しいものが使われるのかな?
$ ls -l /lib/modules/
合計 16
drwxr-xr-x 3 root root 4096 12月 18 20:58 4.4.38+
drwxr-xr-x 3 root root 4096 12月 18 20:58 4.4.38-v7+
drwxr-xr-x 3 root root 4096 4月 12 12:36 4.4.50+
drwxr-xr-x 3 root root 4096 4月 12 12:36 4.4.50-v7+
$ ls -l /lib/modules/4.4.50-v7+/kernel/sound/soc/bcm/
合計 216
-rw-r--r-- 1 root root 7516 3月 3 01:52 snd-soc-adau1977-adc.ko
-rw-r--r-- 1 root root 8424 3月 3 01:52 snd-soc-allo-piano-dac.ko
-rw-r--r-- 1 root root 9936 3月 3 01:52 snd-soc-audioinjector-pi-soundcard.ko
-rw-r--r-- 1 root root 14052 3月 3 01:52 snd-soc-bcm2835-i2s.ko
-rw-r--r-- 1 root root 15860 3月 3 01:52 snd-soc-digidac1-soundcard.ko
-rw-r--r-- 1 root root 7700 3月 3 01:52 snd-soc-dionaudio-loco.ko
-rw-r--r-- 1 root root 7604 3月 3 01:52 snd-soc-hifiberry-amp.ko
-rw-r--r-- 1 root root 7852 3月 3 01:52 snd-soc-hifiberry-dac.ko
-rw-r--r-- 1 root root 11184 3月 3 01:52 snd-soc-hifiberry-dacplus.ko
-rw-r--r-- 1 root root 10776 3月 3 01:52 snd-soc-hifiberry-digi.ko
-rw-r--r-- 1 root root 10900 3月 3 01:52 snd-soc-iqaudio-dac.ko
-rw-r--r-- 1 root root 10400 3月 3 01:52 snd-soc-iqaudio-digi.ko
-rw-r--r-- 1 root root 9032 3月 3 01:52 snd-soc-justboom-dac.ko
-rw-r--r-- 1 root root 9012 3月 3 01:52 snd-soc-justboom-digi.ko
-rw-r--r-- 1 root root 25964 3月 3 01:52 snd-soc-pisound.ko
-rw-r--r-- 1 root root 9764 3月 3 01:52 snd-soc-raspidac3.ko
-rw-r--r-- 1 root root 7456 3月 3 01:52 snd-soc-rpi-dac.ko
-rw-r--r-- 1 root root 8144 3月 3 01:52 snd-soc-rpi-proto.ko
- 再起動後に lsmodで、ロードされているドライバを確認する
$ lsmod
:
:
snd_bcm2835 20447 1
snd_soc_bcm2835_i2s 6354 2
bcm2835_gpiomem 3040 0
bcm2835_wdt 3225 0
snd_soc_pcm5102a 1763 1
uio_pdrv_genirq 3164 0
uio 8000 1 uio_pdrv_genirq
snd_soc_hifiberry_dac 2511 0
snd_soc_core 125949 3 snd_soc_bcm2835_i2s,snd_soc_hifiberry_dac,snd_soc_pcm5102a
snd_pcm_dmaengine 3391 1 snd_soc_core
snd_pcm 75762 4 snd_bcm2835,snd_soc_core,snd_soc_hifiberry_dac,snd_pcm_dmaengine
snd_timer 19288 1 snd_pcm
snd 51908 6 snd_bcm2835,snd_soc_core,snd_timer,snd_pcm
:
:
- hifiberry_dacが、ちゃんとロードされている
aplay -l
**** ハードウェアデバイス PLAYBACK のリスト ****
カード 0: sndrpihifiberry [snd_rpi_hifiberry_dac], デバイス 0: HifiBerry DAC HiFi pcm5102a-hifi-0 []
サブデバイス: 1/1
サブデバイス #0: subdevice #0
カード 1: ALSA [bcm2835 ALSA], デバイス 0: bcm2835 ALSA [bcm2835 ALSA]
サブデバイス: 8/8
サブデバイス #0: subdevice #0
サブデバイス #1: subdevice #1
サブデバイス #2: subdevice #2
サブデバイス #3: subdevice #3
サブデバイス #4: subdevice #4
サブデバイス #5: subdevice #5
サブデバイス #6: subdevice #6
サブデバイス #7: subdevice #7
カード 1: ALSA [bcm2835 ALSA], デバイス 1: bcm2835 ALSA [bcm2835 IEC958/HDMI]
サブデバイス: 1/1
サブデバイス #0: subdevice #0
- hifiberry_dacは、カード0,デバイス0に割り当てられている
- カード0,デバイス0で、dds1k44100.wavを再生しようとするがエラーになる
$ aplay -D hw:0,0 dds1k44100.wav
再生中 WAVE 'dds1k44100.wav' : Signed 16 bit Little Endian, レート 44100 Hz, モノラル
aplay: set_params:1239: チャネル数が使用不可能
- 今度は、plughwで、リサンプリングでの再生を試みるが、やはりエラーになる
$ aplay -D plughw:0,0 dds1k44100.wav
再生中 WAVE 'dds1k44100.wav' : Signed 16 bit Little Endian, レート 44100 Hz, モノラル
aplay: set_params:1297: hw params のインストールに失敗しました:
ACCESS: RW_INTERLEAVED
FORMAT: S16_LE
SUBFORMAT: STD
SAMPLE_BITS: 16
FRAME_BITS: 16
CHANNELS: 1
RATE: 44100
PERIOD_TIME: (125011 125012)
PERIOD_SIZE: 5513
PERIOD_BYTES: 11026
PERIODS: 4
BUFFER_TIME: (500045 500046)
BUFFER_SIZE: 22052
BUFFER_BYTES: 44104
TICK_TIME: 0
$ aplay -D hw:0,0 dds1k44100s.wav
再生中 WAVE 'dds1k44100s.wav' : Signed 16 bit Little Endian, レート 44100 Hz, ステレオ
1WAVファイルは圧縮されてないので計算は簡単だが、圧縮されている場合は圧縮形式によりビットレートが変わるので、単純に比較できない。
[top]
- ロジックアナライザのプロトコル解析機能を使って、I2S出力信号を確認してみた
- BCKは、音声出力の約0.5ms前から出力されるようだ
- USB Audioで、BCKやLRCLKが出っ放しなのとはちょっと違っている
- 出力終了後は、約0.1msぐらいでBCKが停止する
- サンプリング周波数が、44.1k、48k、96k、192kHzでもちゃんとそのまま出力されている。
- 但し、192kHzは、データ出力はされているが、再生されなかった
- おそらくD級アンプのDACが対応していないと思われる
- L/Rの1データあたりのBCLKは、16bitになっている
- データ長が16bitを超えると、おそらく32bit/1データになると思う2
- LRCLKの変化から、1BCLK分遅らせて、DATAのMSBからBCLKの立ち上がりで読み込む
- 16bit/1データの場合は16ビット、32bit/1データの場合は24ビットのデータ長として読み込めば良さそう3
2でも16bit以上のデータの出力方法がわからないので未確認。
3おそらく、それで良いと思うが、実際に16bitより多ビットのデータの再生が出来ていないので未確認。
[top]
- ステレオの16ビットwavファイルであれば、サンプリング周波数に関わらず、データがそのまま出力される。
- それなりの速度でリアルタイムのデータ転送を行う手段として、有効だと思う
- USB_Audioでは、データをそのまま出力するのは、いろいろ面倒だったので、
- 単純に出力だけなら、こちらの方がずっと簡単そうだ。
- でも、ラズベリーパイのI2S出力のクロックの精度は不明
- 本当は、直接再生する場合は、外部クロックによって転送したいところなんだけど。。
- ラズベリーパイは外部クロックによってI2S入出力も出来るらしいが、
- カーネルの再コンパイルが必要になるらしいので、今回はパス
- ラズベリーパイのI2S入出力は、標準のドライバというものは無くて、
- サードパーティのボード用の専用のドライバになっているみたいで、
- 互換の仕様の回路じゃないと、動作させるのが難しいと思う
- とりあえず出力だけなら単純なので、適当なドライバを流用できそうだが、
- 入出力となると、制御用の接続も必要だったりして、ちょっと厄介だ
- FPGAでデジタルフィルタという記事で、
- RaspberryPiのI2S出力に、FPGAで作ったデジタルフィルタを掛けてみました(170607追記)
[top]
[電子工作関連に戻る]