Raspberry PiのSonic Piの音をi2s pcm5102 DACから出す

Raspberry Pi zeroにi2s pcm5102 DACを追加して、そこからSonic Piの音を出すようにしましたので、その備忘録です。

## バージョンなど

|ソフトウェア|バージョン|
|:--|:--|
|raspbian|2016-11-25-raspbian-jessie.img|
|Sonic Pi|2.10.0|

## i2s pcm5102 DACのための設定
http://qiita.com/eggman/items/aa53f3208ed174f7e912 にあるとおり、`/boot/config.txt`と`/etc/modules`に追記します。

/boot/config.txt

```
dtoverlay=hifiberry-dac
```
/etc/modules

```
snd_soc_hifiberry_dac
```

`aplay -l`の実行結果は以下のとおりです。

```shell-session
# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: sndrpihifiberry [snd_rpi_hifiberry_dac], device 0: HifiBerry DAC HiFi pcm5102a-hifi-0 []
  Subdevices: 0/1
  Subdevice #0: subdevice #0
card 1: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]
  Subdevices: 8/8
  Subdevice #0: subdevice #0
  Subdevice #1: subdevice #1
  Subdevice #2: subdevice #2
  Subdevice #3: subdevice #3
  Subdevice #4: subdevice #4
  Subdevice #5: subdevice #5
  Subdevice #6: subdevice #6
  Subdevice #7: subdevice #7
card 1: ALSA [bcm2835 ALSA], device 1: bcm2835 ALSA [bcm2835 IEC958/HDMI]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

```
私の環境では、aplayでテストしようとしたところ、以下のエラーが出たので、

```shell-session
# aplay -D hw:0,0 /usr/share/sounds/alsa/Front_Right.wav
Playing WAVE '/usr/share/sounds/alsa/Front_Right.wav' : Signed 16 bit
Little Endian, Rate 48000 Hz, Mono
aplay: set_params:1297: Unable to install hw params:
ACCESS: RW_INTERLEAVED
FORMAT: S16_LE
SUBFORMAT: STD
SAMPLE_BITS: 16
FRAME_BITS: 16
CHANNELS: 1
RATE: 48000
PERIOD_TIME: 125000
PERIOD_SIZE: 6000
PERIOD_BYTES: 12000
PERIODS: 4
BUFFER_TIME: 500000
BUFFER_SIZE: 24000
BUFFER_BYTES: 48000
TICK_TIME: 0
```

`speaker-test -t wav -c 2 -D hw:0,0`を試したところ、正常に音が出ました。https://support.hifiberry.com/hc/en-us/community/posts/206636389/comments/207167425 を参考にしました。

## Sonic Piの音を出すための設定

上記の設定でSonic Piで生成した音を出力しようとしたが、上手く行かずでした。

結論としては、以下の2つが理由でした。

* サウンドカードの指定(`.asoundrc`の設定)
* mmapの設定(`dtoverlay=i2s-mmap`の追加)

### サウンドカードの指定(`.asoundrc`の設定)

Sonic Piサーバーが起動する際にjackを起動する箇所があるのですが、そこのログを見ると、以下のようにhw:1のサウンドカードで起動するようになっていました。

```
Acquire audio card Audio1
creating alsa driver ... hw:1|hw:1|2048|3|44100|2|2|nomon|swmeter|-|32bit
```

調べていくと、Sonic Piのscsynthexternal.rb#L349-L355 で`/home/pi/.asoundrc`の内容でjackを起動しているようでした。

https://github.com/samaaron/sonic-pi/blob/v2.10.0/app/server/sonicpi/lib/sonicpi/scsynthexternal.rb#L349-L355

```rb
      begin
        asoundrc = File.read(Dir.home + "/.asoundrc")
        audio_card = (asoundrc.match /pcm.!default\s+{[^}]+\n\s+card\s+([0-9]+)/m)[1]
      rescue
        audio_card = "0"
      end
      sys("jackd -R -p 32 -d alsa -d hw:#{audio_card} -n 3 -p 2048 -r 44100& ")

```


`.asoundrc`が以下のようになっていたので、これをhw:0を見るように変更しました。

```
pcm.!default {
	type hw
	card 1
}

ctl.!default {
	type hw
	card 1
}
```
以下のようにする。

```
pcm.!default {
	type hw
	card 0
}

ctl.!default {
	type hw
	card 0
}
```

### mmapの設定(`dtoverlay=i2s-mmap`の追加)

上記でSonic Piサーバーを起動すると、今度は以下のようなエラーが出ました。

```
Acquire audio card Audio0
creating alsa driver ... hw:0|hw:0|2048|3|44100|2|2|nomon|swmeter|-|32bit
ALSA: Cannot open PCM device alsa_pcm for capture. Falling back to playback-only
 mode
configuring for 44100Hz, period = 2048 frames (46.4 ms), buffer = 3 periods
ALSA: mmap-based access is not possible for the playback stream of this audio in
terface
ALSA: cannot configure playback channel
Cannot initialize driver
JackServer::Open failed with -1
Failed to open server
```

https://support.hifiberry.com/hc/en-us/community/posts/201858531/comments/200805762 を参考に、`/boot/config.txt`に以下を追記しました。

/boot/config.txt

```
dtoverlay=i2s-mmap
```

## まとめ

上記全てをAnsibleのplaybookに反映させたのが以下です。

```yaml
    - name: add i2s settings to config.txt
      lineinfile:
        dest=/boot/config.txt
        line={{ item }}
      with_items:
        - 'dtoverlay=hifiberry-dac'
        - 'dtoverlay=i2s-mmap'
    - name: add snd_soc_hifiberry_dac driver to /etc/modules
      lineinfile:
        dest=/etc/modules
        line={{ item }}
      with_items:
        - 'snd_soc_hifiberry_dac'
    - name: copy /home/pi/.asoundrc
      copy: src=./files/asoundrc dest=/home/pi/.asoundrc

```

この件で2時間ほど嵌りました。jackは当分また関わりたくないです。