Edited at

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

More than 1 year has passed since last update.


概要

MPDで音楽再生サーバを構築し、再生中の曲名、アーティスト名、アルバム名と、ジャケットイメージをOLEDに表示する。もちろん、日本語でOK!!

そして、3つのボタンで「前の曲」「再生/一時停止」「次の曲」も出来たりする。

おそらくSingleBoardComputingにおけるMPDの完成形の一つになるのではなかろうか(笑

せっかくなので環境構築含めた完全版でお送りする。

_72D8924.jpg

左側が 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

Official image


  • 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


  • 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


/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


音楽ディレクトリの変更

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


/etc/mpd.conf

music_directory  "/media/"



音声出力の設定

まず、

cat /proc/asound/cards

で、サウンドカードの一覧を出力します。

こんな感じででたりします。

とりあえずありったけ繋いだ状態です(笑


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



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です。

複数あると、同時出力指定もできます。


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も設定します。


J20(JAVS_X-DDC)の場合

audio_output {

type "alsa"
name "JAVS X-DDC"
device "hw:J20,0"
mixer_type "none"
}

※BitPerfect出力したいためmixer_typeにnone設定します。その代わり、ソフトウェア上からの音量調整ができなくなります。


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


/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




//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で音楽再生サーバ(完全体)」にてOLED表示のほかLCD表示にも対応しました。お好みの表示ソフトウェアをご利用ください。

主な仕様


  • 曲名の表示。長い場合は自動スクロールします。

  • アーティスト名・アルバム名の表示

  • 現在の再生位置の表示 (タイトルの下のアンダーバーです)

  • Freq,BitDepth,Ch の表示

  • アルバムジャケットイメージの表示(mutagen使用)

  • 物理ボタンで、「前の曲」、「再生・一時停止」、「次の曲」が操作可能

  • 一時停止中は、現在日時を表示

  • 日本語表示OK

仕組み他


  • ボタンの押下検出は、NanoPi Officialのプログラム(C言語)を使います。ボタン押したのを検知して、Python側にイベント飛ばしてくれます。

  • NanoPi OfficialのOLED表示プログラムを参考にして作ってましたが、表示データを1バイトずつ親切丁寧にI2C書き込みしてましたので、32バイト単位転送に全面書き直しています。表示速度が2,3倍に速くなりました。

  • ジャケットイメージは、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


/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


/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を入れてみます。

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


/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

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


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


  • I2S_MCLK

も出力可能になっており、GPIOA6 に出力されます。

これは、H5のみの仕様で、H3では対応していないようです。(データシート見る限り)

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

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

■2018/01/13追加

ついに出力できました!

NanoPi-NEO2 のI2SでMCLK出力&384kHz対応


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系の方か、レースカーテン1枚分鮮明に出てきます。音も細かいです。

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


最後に

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