NanoPi-NEOとMPDとOLEDで音楽再生サーバ

# 概要

MPDで音楽再生サーバを構築し、再生中の曲名、アーティスト名、アルバム名と、ジャケットイメージをOLEDに表示する。もちろん、日本語でOK!!
そして、３つのボタンで「前の曲」「再生/一時停止」「次の曲」も出来たりする。

おそらくSingleBoardComputingにおけるMPDの完成形の一つになるのではなかろうか(笑
せっかくなので環境構築含めた完全版でお送りする。

![_72D8924.jpg](https://qiita-image-store.s3.amazonaws.com/0/187531/4e253a97-e4ab-4c0b-1e6c-d3d98bf72501.jpeg)

左側が NEO2 Complete Starter Kit. ずぅ～っとOutOfStockの状態で、5/26に一瞬InStockになった瞬間に巡り合い奇跡的？にゲットできた逸品。
右側が、NanoPi-NEO + NanoHat PCM5102a + NanoHat OLED の組み合わせ。

今回メインとなるPythonによるOLEDへの各種情報表示のコードは下記に登録してあります。
https://github.com/blue777/NanoPi-NEO_OLED_MPD

### 関連シリーズ紹介

- [NanoPi-NEOとMPDとLCDとI2S-DACとTDA7297で音楽再生サーバ(完全体)](https://qiita.com/blue-7/items/07ad5661607799053d44)
- [NanoPi-NEO2 の I2SでMCLK出力 & 384kHz, 768kHz, 1536kHz, 8kHz対応](https://qiita.com/blue-7/items/d643cc9e441ca594a01e)

# 必要なもの

## ハードウェア

- [NanoPi NEO ($7.99)](http://www.friendlyarm.com/index.php?route=product/product&product_id=132) もしくは [NanoPi NEO2 ($14.99)](http://www.friendlyarm.com/index.php?route=product/product&product_id=180)
- [NanoHat OLED ($6.99)](http://www.friendlyarm.com/index.php?route=product/product&product_id=191)
- [NanoHat PCM5102a ($9.99)](http://www.friendlyarm.com/index.php?route=product/product&product_id=169) か USB DAC か 3.5mmジャック

あるいは

- [NEO Complete Starter Kit ($29)](http://www.friendlyarm.com/index.php?route=product/product&product_id=190)
- USB DAC

あるいは

- [NEO2 Complete Starter Kit ($34)](http://www.friendlyarm.com/index.php?route=product/product&product_id=189)
- USB DAC

## ソフトウェア

### NanoPi NEO

[Official image](https://www.mediafire.com/folder/n5o8ihvqhnf6s/Nanopi-NEO#umkhdtp5nkect)

- nanopi-neo_ubuntu-core-xenial_3.4.39_20170523.img.zip
- nanopi-neo_ubuntu-core-xenial_4.11.2_20170605.img.zip

のいずれかを前提にしています。
※イメージによってはNanoHat PCM5102a 動かなかったりします。

### NanoPi NEO2

[Official rom image](https://www.mediafire.com/folder/ah4i6w029912b/NanoPi-NEO2#b7f7bt3s240uw)

- nanopi-neo2_ubuntu-core-xenial_3.10.65_20170523.img.zip
- nanopi-neo2_ubuntu-core-xenial_4.11.2_20170605.img.zip

のいずれかを前提にしています。
※イメージによってはNanoHat PCM5102a 動かなかったりします。というより、未検証です。

# サーバー側構築手順

BootImageをMicroSDに転送して起動した状態を前提にしています。

## 1. 初期セットアップ

timedatectl set-timezone Asia/Tokyo
apt-get update
apt-get upgrade
npi-config

あたりで下準備します。
固定IPが良い場合は下のような感じです。

nano /etc/network/interfaces

```bash:/etc/network/interfaces
allow-hotplug eth0
#        iface eth0 inet dhcp
        iface eth0 inet static
            address 192.168.1.100
            netmask 255.255.255.0
            gateway 192.168.1.1
            dns-nameservers 192.168.1.1
```

## 2. MPD (Music Player Daemon) のインストール

次のコマンドでインストールします。
インストール終わったら設定変更していきます。

apt-get install mpd
nano /etc/mpd.conf

### 音楽ディレクトリの変更

該当行を探して、以下にします。(下記を前提に説明していきます)

```bash:/etc/mpd.conf
music_directory  "/media/"
```

### 音声出力の設定

まず、
cat /proc/asound/cards
で、サウンドカードの一覧を出力します。

こんな感じででたりします。
とりあえずありったけ繋いだ状態です(笑

```bash:NanoPi-NEO
root@NanoPi-NEO:~# cat /proc/asound/cards
 0 [Pcm5102a       ]: Pcm5102a - Pcm5102a
                      Pcm5102a
 1 [sndhdmi        ]: sndhdmi - sndhdmi
                      sndhdmi
 2 [DAC            ]: USB-Audio - USB Audio DAC
                      Burr-Brown from TI USB Audio DAC at usb-sunxi-ehci-1.2, full speed
 3 [J20            ]: USB-Audio - JAVS USB Audio 2.0
                      JAVS JAVS USB Audio 2.0 at usb-sunxi-ehci-1.3, high speed
 4 [N2             ]: USB-Audio - NuForce µDAC 2
                      NuForce, Inc. NuForce µDAC 2 at usb-sunxi-ehci-1.4, full speed
 5 [AI301DA        ]: USB-Audio - TEAC AI-301DA
                      TEAC Corporation TEAC AI-301DA at usb-sunxi-ehci-1.1, high speed

root@NanoPi-NEO:~# uname -a
Linux NanoPi-NEO 3.4.39-h3 #3 SMP PREEMPT Tue May 23 17:37:51 CST 2017 armv7l armv7l armv7l GNU/Linux
```

```bash:NanoPi-NEO2
root@NanoPi-NEO2:~# cat /proc/asound/cards
 0 [Codec          ]: H3_Audio_Codec - H3 Audio Codec
                      H3 Audio Codec
 1 [USBCamera      ]: USB-Audio - USB_Camera
                      KYE Systems Corp. USB_Camera at usb-1c1d000.usb-1, high speed

root@NanoPi-NEO2:~# uname -a
Linux NanoPi-NEO2 4.11.2 #1 SMP Wed Jun 7 03:24:53 PDT 2017 aarch64 aarch64 aarch64 GNU/Linux
```

上から順番に説明していくと、

|InstanceNo.|DeviceName|解説|
|:---|:---|:---|
|0|Pcm5102a|NanoHat Pcm5102aです。NanoPi-NEO Kernel=3.4.39の場合の表示名です。KernelVer変わると表示名も変わったりします|
|1|sndhdmi|HDMIのAudio信号出力だと思いますが、HDMIコネクタ無いので使えません|
|2|DAC|USB DACです。|
|3|J20|USB DDCです。JAVS X-DDC というUSB→SPDIF変換器です。|
|4|N2|USB DACです。NuForce μDACです。|
|5|AI301DA|USB DACです。Teac AI-301DAです。|
|0|Codec|NanoPi-NEO2 の基板上のLineOutです。はんだ付けすると使えるはずです。H5なのにH3なのはドライバが共通のためと思われます。|
|1|USBCamera|マイク入力ついているカメラです。音声出力は出来ないので使えません。|

それぞれに対する基本的な書き方です。
こんな感じで書きます。audio_output のタグは複数あってもOKです。
複数あると、同時出力指定もできます。

```bash:NanoHatPCM5102aの場合
audio_output {
        type            "alsa"
        name            "HanoHat PCM5102a"
        device          "hw:Pcm5102a,0"
        mixer_type      "software"
        format          "*:32:2"
        replay_gain_handler "software"
}
```
※PCM5102aはI2S接続されており、24bitフォーマットの時に音が極端に小さくなる現象がでます。これはデータが24bitのまま32bit出力されているためのようです。その対策のため、formatを強制指定の上、mixer_type,replay_gain_handlerも設定します。

```bash:J20(JAVS_X-DDC)の場合
audio_output {
        type            "alsa"
        name            "JAVS X-DDC"
        device          "hw:J20,0"
        mixer_type      "none"
}
```
※BitPerfect出力したいためmixer_typeにnone設定します。その代わり、ソフトウェア上からの音量調整ができなくなります。

```bash:Codecの場合
audio_output {
        type            "alsa"
        name            "NanoPi-NEO2 LineOut"
        device          "hw:Codec,0"
        mixer_type      "software"
}
```

それぞれ、name に指定したものが、MPDクライアントからの表示名になります。
device の 「hw:XXXX,0」 の XXXX の部分には、InstanceNo. もしくはDeviceNameを入れます。
USB接続で自動認識させたい場合は、最後尾となるInstanceNo. などを入れたりします。が、InstanceNo.による割り当て、接続順により変わったりするため、DeviceNameによる指定がおすすめです。
(ALSAでの番号割り当て順を変更することもできますが、割愛します)


## 3. 音楽データの準備

### microSD を共有フォルダ化する場合

OSをインストールしたmicroSDを共有フォルダにして、
外部PC等から音楽データをNanopiNEOにアップロードする形になります。

Sambaのインストールおよび、
/media/local のディレクトリを作成し、共有設定します。
共有設定は、フルアクセス設定です。(笑


apt-get install samba
mkdir /media/local
chmod 777 /media/local
nano /etc/samba/smb.conf

```bash:/etc/samba/smb.conf
  ・
  ・
  ・
[Music]
   comment = share folder
   path = /media/local
   public = yes
   writable = yes
   guest ok = yes
   guest only = yes
   create mode = 0777
   directory mode = 0777
```
※最後尾に追加します。Musicが共有フォルダ名として見えます。
設定完了したら、Sambaの共有を開始させます。

systemctl enable smbd
systemctl start smbd

### NASなど外部の共有フォルダを使う場合

Windowsファイル共有やNASをマウントして使う場合です。

apt-get install cifs-utils
mkdir /media/nas
nano /etc/fstab

```bash/etc/fstab
  ・
  ・
  ・
//192.168.1.9/Public /media/nas cifs username=guest,password=,uid=root,iocharset=utf8 0 0
```
※最後尾にでも追加します。
※DNS使えなかったりするので、IP直指定です。

設定後、

mount -a
df

で正しくマウントされることを確認します。

※iocharset=utf8はKernelVerやディストリビューションにより使えなかったりします。
そんなときは、
・あきらめて違うディストリビューション使うか、
・日本語のファイル名を諦めるか、
・カーネルオプション変えてカーネルビルドするか、
・mpd.confを「music_directory "smb://192.168.1.9/Public"」としてサンバ直アクセス
にしたりします。


## 4. OLED表示のセットアップ

曲名表示やジャケットイメージの取得・表示をPythonで書いてみました。
今回Pythonを初めて使ったのですが、2日ほどでこれが仕上がりました。。。
途中、タブとスペースの混在に苦しめられたり、紆余曲折ありましたが、
思いのほか出来が良かったため、この記事書くきっかけになったりもしてます。

2017/08/31追記: 続編 [「NanoPi-NEOとMPDとLCDとI2S-DACとTDA7297で音楽再生サーバ(完全体)」](http://qiita.com/blue-7/items/07ad5661607799053d44)にてOLED表示のほかLCD表示にも対応しました。お好みの表示ソフトウェアをご利用ください。

主な仕様

- 曲名の表示。長い場合は自動スクロールします。
- アーティスト名・アルバム名の表示
- 現在の再生位置の表示 (タイトルの下のアンダーバーです)
- Freq,BitDepth,Ch の表示
- アルバムジャケットイメージの表示（mutagen使用)
- 物理ボタンで、「前の曲」、「再生・一時停止」、「次の曲」が操作可能
- 一時停止中は、現在日時を表示
- 日本語表示OK

仕組み他

- ボタンの押下検出は、NanoPi Officialのプログラム(C言語)を使います。ボタン押したのを検知して、Python側にイベント飛ばしてくれます。
- NanoPi OfficialのOLED表示プログラムを参考にして作ってましたが、表示データを1バイトずつ親切丁寧にI2C書き込みしてましたので、32バイト単位転送に全面書き直しています。表示速度が２，３倍に速くなりました。
- ジャケットイメージは、mutagenによりローカルファイルアクセスして埋め込み済み画像を取ってきます。画像が無い場合は、同じディレクトリ内にある　front.jpg が使用されます。
- mpdからの情報取得は、TCP経由で行っています。制御もまたしかりです。
- OSによってI2C通信が100kだったり400kだったりします。これにより表示速度が大きく変わります。
- タイトルのスクロール速度を調整する場合は、oled_mpd.pyの　scroll_unit = 3　で調整可能です。

それでは、本題のインストール手順に行きます

### NanoHat OLED関係を入れる

参考: http://wiki.friendlyarm.com/wiki/index.php/NanoHat_OLED

下記手順でインストールします。(インストール先は/root にしてます)
NanoHat OLEDは、CプログラムとPythonプログラムの2本構成で動いていて、OLEDの表示自体はPythonで閉じていますが、キー操作はCプログラム側で受信後、Python側に通知する仕組みになっていました。

そして、Cプログラム側ではPythonプログラムの起動も行っており、標準品を起動しないようにします。とりあえず、下記の例ではコメントアウトしています。
(代わりのPythonコードの起動はrc.localからやってます)


cd /root
git clone https://github.com/friendlyarm/NanoHatOLED.git
nano /root/NanoHatOLED/Source/main.c

```C:/root/NanoHatOLED/Source/main.c
 ・
 ・
 ・
int load_python_view() {
/*
    int ret;
    char* cmd = (char*)malloc(255);
    sprintf(cmd, "cd %s/BakeBit/Software/Python && python %s 2>&1 | tee /tmp/nanoled-python.log", workpath, python_file);

    ret = pthread_create(&view_thread_id, NULL, (void*)threadfunc,cmd);
    if(ret) {
        log2file("create pthread error \n");
        return 1;
    }
//*/
    return 0;
}
 ・
 ・
 ・
```

cd NanoHatOLED
./install.sh


### 本題(OLED表示)を入れる

外部依存パッケージが含めインストールし、rc.localで自動起動するようにします。
すでに、NanoHatOLEDの自動起動(oled-start)が書き込まれていますので、
その次の行に起動コマンドを追加してあげます。

apt-get install fonts-takao-pgothic
apt-get install python-mutagen python3-mutagen

cd /root
git clone https://github.com/blue777/NanoPi-NEO_OLED_MPD

nano /etc/rc.local

```bash:/etc/rc.local
 ・
 ・
 ・
/usr/local/bin/oled-start &
cd /root/NanoPi-NEO_OLED_MPD
python oled_mpd.py &
 ・
 ・
 ・
```

## 5. ympd (MPD Web GUI)をインストールする

ネットワーク上の各クライアントからhttpアクセスし、コントロールできるようにympdを入れてみます。

```console:
apt install cmake
apt install libmpdclient-dev
apt install libssl-dev

cd /usr/lib
git clone https://github.com/notandy/ympd
cd ympd
mkdir -p build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX_PATH=/usr
make
make install 
```

./ympd で起動しますが、都度起動も大変なので自動起動するように、rc.localを編集します。

nano /etc/rc.local

```bash:/etc/rc.local
 ・
 ・
 ・
/usr/lib/ympd/build/ympd &
```

アクセスポートは8080 になるので、
http://YourMpdServer:8080/
のような形でアクセスします。

port80が良い場合は、以下のような指定を行います。

./ympd -w 80



これにてサーバー側は終了です。リブートしてお楽しみください。

reboot

# クライアント側の準備

Webアクセスにて再生制御できますが、やはり専用アプリがいい！というときには、お好きな MPDクライアントを入れて下さい。

iOS, Windows, Androidなど各種MPDクライアントが出ています。MPDクライアントで検索すればいろいろ出てきますので、好きなものをインストールします。

当方はWindows機のため　gmpc　を使っています。
https://gmpclient.org/

![image.png](https://qiita-image-store.s3.amazonaws.com/0/187531/f2d558e7-55de-5994-4d36-b4e08b02596c.png)

audio_output で設定した項目は、Serverメニューから選択できます。


# おまけ
## NanoHat PCM5102a について

標準状態ではハードウェア的に、De-Emphasis,　Low-Latency 状態になっています。
特にDe-Emphasisは、44.1KHz　において高域カットされてしまい、若干のこもり気味に聞こえます。
De-emphasis, Low-Latencyの個所のハンダ付けがお勧めします。

音質については、普通に良いです。
10万クラスのCDプレイヤは太刀打ちできないでしょう。

ただ、(フルオケのピークなど)音が複雑に絡み合ったりすると、解像度低下が目立ち団子になります。
といっても、電源がスイッチング電源で、かつ、NanoPi-NEO共用の状態ですので、別電源など改造すればきっと覚醒してくれることでしょう。

## NanoPi-NEO, NEO2 のI2S信号について

参照先
http://wiki.friendlyarm.com/wiki/index.php/NanoPi_NEO2

NanoPi-NEOで出力されるI2S信号は

- I2S0_LRC    I2S/PCM Sample Rate Clock/Sync  
- I2S0_BCK    I2S/PCM Sample Rate Clock  
- I2S0_SDOUT  I2S/PCM Serial Data Output  

の３つが出力されますが、NanoPi-NEO2は、上記に加え

- I2S_MCLK

も出力可能になっており、GPIOA6 に出力されます。
これは、H5のみの仕様で、H3では対応していないようです。(データシート見る限り)

そして、さらに見るとGPIOA6にPWMと書いていますが、H3/H5ともにPWMの出力先にはなれません。どこから来た誤植なのかが気になります(H2+とか？)

ひそかに I2S_MCLK　出力できるドライバ提供を期待していたりします。

■2018/01/13追加
ついに出力できました！
[NanoPi-NEO2 のI2SでMCLK出力&384kHz対応](https://qiita.com/blue-7/items/d643cc9e441ca594a01e)


## NanoPiNEO系とBeagleBone系の音質

SBC(SingleBoardComputing)でMPDを使用する理由は、まぎれもなく音質追及である。
ですので、NanoPiシリーズと、BeagleBoneシリーズの音質の個人的主観評価は、こんな感じです。
※NanoPi系はOLED取り付けていない状態です

NanoPi-NEO < NanoPi-NEO2 << BeagleBoneBlack <= BeagleBoneGreen

いずれも、SBC ---(USB)--> JAVS X-DDC(改) ---(Coaxial spdif)--> DAC とつないでの評価で、SBC, X-DDCにはInfineonのSiC SBDでブリッジ整流で組んだシリーズ電源(SBC側にはLM350、X-DDCには CreeのSiC FETでディスクリート)使用しています。
この場合において、BeagleBone系の方か、レースカーテン１枚分鮮明に出てきます。音も細かいです。

また、NanoPi-NEOおよびNanoPi-NEO2において、MPD専用ディストリビューションである　lightMPDが対応してくれたのはとても喜ばしいことです。

#最後に

思いのほか出来が良かったとか、いろいろ書いたOLEDの表示回りですが、自分の本番?環境では、使われません。(笑