Alcohol52%のイメージファイルmdf + mdsをwav + cueに変換する
前回めでたく成功したbin + cue→wav + cue変換。
bin + cueをwav + cueに変換する - もぐてっく
でも、うちのライブラリはbin + cueじゃなくてAlcohol52%ネイティブのフォーマットであるmds + mdfファイルなのよね。
ひとつずつ再変換しても良いんだけど、超面倒だよね。うん。面倒だ。
まぁ、mdfとbinは完全互換なのは調査済みだから、後はmdsファイルを適当にパースしてcueファイル作れば良いんじゃね?
(mdsファイルをテキストエディットで開く)
バババ、バイナリィィィィィィィィィィィィィィ!?
バイナリファイルでした(泣)。
でも、こんなことではめげません。めげずに調べます。
mdsファイルのデータ構造はここにドキュメントがあるのですが、所々計算が間違っててどうも怪しいです。
http://developer.berlios.de/docman/display_doc.php?docid=840&group_id=2545
なので、大変参考にしつつ(ありがとうございます)hexdumpとにらめっこしながらそれっぽい構造体を作ってみました。
これでmdsファイルの中身が読めるようになりました。
でも、それだけではダメでした。ダメダメでした。
mdsのdata_blockに格納されてる値でcueファイルを作ると、全体的に2秒ずれてしまいました。単純に2秒引けば良いんですけど、なにかとてもきもち悪いから調べてみました。
なんでも、CD-DAは「きかくじょう」、トラック1の前に2秒(150フレーム)の無音区間(プリギャップ)が必要なのだそうです。
そして、その2秒の無音区間は無駄なので、mdfファイルからは削られてます。
でもでも、mdsは2秒のプリギャップを削る前のタイムスタンプを保持しているので、件のズレが発生します。
多分ヘッダのpregap_corrに入ってる-150が削ったプリギャップだと思うので、これを75で割って引き去るようにしました。
はい。これで出来ました。
第一引数にmdsファイルを指定すると、同じフォルダにcueファイルとwavファイルが出来ます。
これで本気でWindowsが捨てられる準備が出来ましたv
bin + cueをwav + cueに変換する
約1ヶ月半にMacBook Airを買って、現時点での究極のGUIを堪能している今日この頃ですが、一つだけ不満が・・・。
MacってCD-DAのイメージファイルをマウント出来る仕組みが無いのよね。
Windows時代に物理的耐用年数(20年)を過ぎたCD達をイメージ化してたんだけど、これが死んでしまうのは非常に痛い。
LINDBERGのEXTRA FLIGHTとかFlight Recorderとかが聞けなくなったらと思うと、もうウルウルっす・・・。
ウルウルしながら調べたところ、XLDってフリーソフトを使えばwav + cueファイルを分割してiTunesに登録してくれることを発見。やった。
ああ、でも愛用のAlcohol52%はcueシート付きのイメージファイルが作れるけど、イメージ本体はbinファイルなのでアウト。
号泣しながらさらに調べたところ、binとwavの差はRIFFコンテナへの格納有無だけらしいので簡単に変換出来そう。
よし、bin + cueファイルをwav + cueファイルに変換してみよう!
やることの説明
CD-DAのイメージファイルであるところのbinファイルは、CD-DAの内容を44.1kHz、16bit、2チャンネル(ステレオ)のPCM形式で保存したものです。サウンドレコーダでいう「CDの音質」と言う奴です。
(CDなんだから当たり前ですが。てか最近の子ってサウンドレコーダ知ってんの?)
一方のwavファイルは、RIFFコンテナに格納されたサウンドデータです。
RIFFはチャンク構造を持っており、名前付きの可変長データを複数格納出来るようになっています。
[RIFFヘッダ][チャンクヘッダ1(チャンク名)(データサイズ)][データ1][チャックヘッダ2(チャンク名)(データサイズ)][データ2]・・・
最近の概念だと、キーバリューストアだと思ってもらったら良いです。
さて、RIFFについて何となく理解したところで、wavファイルを形成するためのチャンクを見ていきます。
最低限必要なチャンクは"fmt"と"data"の2つ。
先に書いたサンプリングレートその他の情報はイメージファイルからは推測が不能なため、"fmt"チャンクにフォーマットの情報を格納する必要があります。
そして、肝心のデータは"data"チャンクに格納します。
受け売り文献:wav ファイルフォーマット
と、言う訳でbinファイルをwavファイルに変換するには、以下の情報を納めたファイルを作れば良いことになります。
- RIFFヘッダ(ファイルサイズ以外は固定データ)
- fmtチャンクヘッダ(固定データ)
- フォーマット情報(固定データ)
- dataチャンクヘッダ(データサイズ以外は固定データ)
- binファイルの内容(可変データ)
割と簡単。
実装してみた
複雑なことはしなくても良いので、シェルスクリプトで変換することにしました。
ついでにcueシート内のイメージファイル名の変換機能も付けました。
#! /bin/sh encode_int32() { X01000000=`printf %d 0x01000000` X00010000=`printf %d 0x00010000` X00000100=`printf %d 0x00000100` printf '\\x%x' `expr $1 % $X00000100` printf '\\x%x' `expr $1 / $X00000100 % $X00000100` printf '\\x%x' `expr $1 / $X00010000 % $X00000100` printf '\\x%x' `expr $1 / $X01000000 % $X00000100` } bin2wav() { WAVE_SIZE=`wc -c "$1" | cut -f2 -d " "` SIZE=`expr 48 + $WAVE_SIZE - 8` HEAD_1=RIFF HEAD_2=`encode_int32 $SIZE` HEAD_3='WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00\x44\xAC\x00\x00\x10\xB1\x02\x00\x04\x00\x10\x00data' HEAD_4=`encode_int32 $WAVE_SIZE` printf "$HEAD_1$HEAD_2$HEAD_3$HEAD_4" > "$2" cat "$1" >> "$2" } rewrite_cue() { mv "$1" "$1"_bin2wav echo FILE \"$2\" WAVE > tmp tail +2 "$1"_bin2wav >> tmp mv tmp "$1" } cd `dirname "$1"` CUE_EXT=`echo "$1" | sed -E 's/^.+(\.[^\.]+)$/\1/g'` BASENAME=`basename "$1" $CUE_EXT` if [ "$CUE_EXT" == ".cue" ];then BIN_EXT=".bin" WAV_EXT=".wav" elif [ "$CUE_EXT" == ".CUE" ];then BIN_EXT=".BIN" WAV_EXT=".WAV" else echo Invalid cue file > /dev/stderr exit 1 fi bin2wav "$BASENAME$BIN_EXT" "$BASENAME$WAV_EXT" rewrite_cue "$BASENAME$CUE_EXT" "$BASENAME$WAV_EXT"
第一引数にcueファイルのファイル名を指定してやれば、めでたくXLDで読めるwav + cueが完成します。
Raspberry Pi meets XBMCなRaspbmcを無線アクセスポイント化してみた
Raspberry Piって超軽いから、出張に持って行っても苦にならないよね。
これをホテルに持ち込んでテレビに接続してAirPlayで動画を見れる様にしたら¥1,000/泊のメディア費削減になるんじゃね!
ついでにこれが無線ルータになったら、ホテルのネット回線も使い放題!超実用的!!
AirPlayはRaspbmcと言うRaspberry PiをXBMC箱にするディストリを使えば可能。
これに出っ張らないUSB無線LANをつなげてアクセスポイントにしてやればいいね。
と、言う訳でRaspbmcの無線アクセスポイント化スタートです。
用意するもの
・Raspbmc導入済みのRaspberry Pi(Model B、256MB版)
・PLANEX GW-USNano2
PLANEX ハイパワー無線LAN ゲーム機用 Wi-Fi USBアダプタ GW-USNANO2-G
- 出版社/メーカー: プラネックス
- 発売日: 2010/12/10
- メディア: Video Game
- 購入: 13人 クリック: 84回
- この商品を含むブログ (3件) を見る
USB無線LANはRealtekのRTL8192CUチップを指名買い。たまたまじゃんぱらで安かったPLANEXのGW-USNano2にしました。
指名買いの理由は、Linuxでのアクセスポイント利用をサポートしてた(公式ドライバに専用のhostapdが同梱されてる)から。独自改変したhostapdを使うってのはなんかダサいんですが、裏を返せばこのチップ専用にフィッティングされてる訳で、細かいトラブルを避けられると思った次第。
ドライバのダウンロード
まずはブラウザの使えるクライアントでRealtekのサイトにアクセスして、RTL8192CUのドライバを取ってきます。今回はRTL8192xC_USB_linux_v3.4.4_4749.20121105.zipを使います。
RaspbmcにはRTL8192CUのドライバが標準で入っているので、今回使うのはこの中のhostapdだけです。
取りあえずRaspbmcにログイン
Raspbmcが起動したのを確認して、sshでアクセスします。
AvahiやBonjourが生きてる環境なら名前でアクセス出来るから超便利。なんでWindowsはサポートしないんだろ。
なお、パスワードはraspberryです。
$ ssh pi@raspbmc.local
初回ログイン時にロケールとかタイムゾーンとかを訊いてきますが、まあお好みで。
(ここでははen_US.UTF-8とAsia/Tokyoにしました。)
今後sudoが面倒なのでrootになっておきます。
(なんかいい方法があったはずだけど忘れた。)
$ sudo su - #
後、別の端末を開いてさっきダウンロードしたドライバをRaspbmcに転送しときます。
$ scp -p ~/Downloads/RTL8192xC_USB_linux_v3.4.4_4749.20121105-1.zip pi@raspbmc.local:/tmp/
必要なパッケージをインストール
ここからはRaspbmcにログインした端末での作業です。
hostapdのコンパイルに必要なパッケージとお手軽DHCP&DNSサーバであるところのdnsmasqを導入します。
# apt-get update # apt-get install unzip build-essential dnsmasq
専用hostapdのインストール
なぜかzipなアーカイブを解凍しつつ、最深部(※)にあるソースコードをコンパイルすればこのステージはクリアです。
(※:パスが100文字超になって笑けます。)
途中に設定ファイルのテンプレートが落ちているので、忘れずにゲットして/etc/にコピーしておきましょう。
# unzip /tmp/RTL8192xC_USB_linux_v3.4.4_4749.20121105-1.zip # cd RTL8188C_8192C_USB_linux_v3.4.4_4749.20121105/wpa_supplicant_hostapd/ # cp -p rtl_hostapd_2G.conf /etc/hostapd.conf # unzip wpa_supplicant_hostapd-0.8_rtw_20120803.zip # cd wpa_supplicant_hostapd-0.8/hostapd/ # make # make install
/etc/hostapd.confの修正
さっき手に入れた設定ファイルをカスタマイズします。
WPSがONだとWPA設定でもWEPのアクセスポイントになってしまうのでWPSを切ります。
13 ##### Wi-Fi Protected Setup (WPS) ############################################# 14 15 eap_server=1 16 17 # WPS state 18 # 0 = WPS disabled (default) 19 # 1 = WPS enabled, not configured 20 # 2 = WPS enabled, configured 21 wps_state=0 # 2→0
にっくきNetworkManagerとの戦い
近頃クライアント系で流行のNetworkManager。
GUIで設定が出来たり、ケーブル接続時に通知メッセージが出たりとかで格好良いんですけど、そいつが古き良きネットワーク設定の仕組みを見事にぶち壊してくれています。
ifconfigでIPアドレス設定してても、LANケーブルを抜いたらそれが吹っ飛ぶとか勘弁して欲しいです。
今回も例によってNetworkManagerがしっかり無線LANを管理しちゃってて、hostapdの動きをことごとく邪魔してくれやがります。シネバイイノニ。
しかしながら安易にNetworkManagerを停止させると今度はRaspbmcのXBMCが文句を言い出すので、今回はなんとか共存の道を探らねばなりません。
爆乳の魔王が相手なら和平交渉も楽しいんでしょうが、相手バイナリファイルだし。面倒いなぁ。
まぁいいや。んでは、色々ファイルを書き換えていきます。
/etc/NetworkManager/NetworkManager.confの編集
「ごめんなさい。そして、ありがとうございました。
私に、私のwlan0を返してください。それは私が背負うべき物でした。」
などと、NetworkManager様に丁重にお願いします。ちっ。
あらかじめ、ifconfigで無線インターフェースのMACアドレスを控えておきます。
# ifconfig wlan0 wlan0 Link encap:Ethernet HWaddr 00:22:cf:b7:a5:da ←コレ UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
メモしたMACアドレスをNetworkManagerの管理対象外にします。
1 [main] 2 plugins=ifupdown,keyfile 3 4 no-auto-default=B8:27:EB:9B:C0:8C, 5 6 [ifupdown] 7 managed=false 8 9 # 以下追加。11行目のmac以降は調べたMACアドレス 10 [keyfile] 11 unmanaged-devices=mac:00:22:cf:b7:a5:da
これを保存すると即座に対象のインターフェースがダウンするので、その誠実さにちょっと感激したりしました。
/etc/network/if-up.d/secure-rmcの編集
まだいました!お邪魔設定ファイル!
こやつはifupしたタイミングで実行されて、そのインターフェース用の基本的なnetfilterルールを設定しやがります。
(インターフェースのサブネットからのパケットはACCEPT、それ以外はDROP。)
通常の用途だと毒にも薬にもならないルールですが、今回のアクセスポイント化に当たっては、クライアントからのDHCPパケット(0.0.0.0→255.255.255.255)が捨てられてしまうのでダメダメです。
# こいつのせいでifupで立ち上げたらうまくDHCPでIPアドレスが取れなくて、ifconfigでなら正常動作と言う謎の動作になって数時間悩んだよ。。。
ルールを追加してやります。
125 logger -t iptables "Configuring ip tables for interface $IFACE" 126 if [ "$IFACE" != "lo" ]; then 127 NETMASK=$(get_subnet $IFACE) 128 iptables -A INPUT -s $NETMASK -i $IFACE -j ACCEPT 129 # DHCPを許可するルールを追加 130 iptables -A INPUT -s 0.0.0.0 -i $IFACE -j ACCEPT 131 iptables -A INPUT -i $IFACE -j DROP 132 fi
/etc/network/interfacesの編集
ここからは前向きな設定作業です。
無線インターフェースのIPアドレス他を設定していきます。
hostapdのinitスクリプトを書くのが面倒なのでpost-up/pre-downで起動・停止を制御することにします。
さらに、IPマスカレードの設定も入れときます。
interfaces超便利!
1 allow-hotplug wlan0 2 3 iface wlan0 inet static 4 address 192.168.0.1 5 netmask 255.255.255.0 6 broadcast 192.168.0.255 7 network 192.168.0.0 8 post-up /usr/local/bin/hostapd -B /etc/hostapd.conf 9 post-up iptables -t nat -A POSTROUTING -o eth0 -s 192.168.0.0/24 -j MASQUERADE 9 pre-down kill `pidof hostapd` 10 pre-down iptables -t nat -D POSTROUTING -o eth0 -s 192.168.0.0/24 -j MASQUERADE
なぜかauto wlan0ではインターフェースが上がらなかったので、allow-hotplugにしてます。
/etc/dnsmasq.confの編集
無線インターフェースに対するDHCPサーバの設定を行います。
90行目のinterfaceのコメントを外して、wlan0を指定します。
これを忘れると家中のIPネットワークが混乱の渦に巻き込まれるので注意。
86 # If you want dnsmasq to listen for DHCP and DNS requests only on 87 # specified interfaces (and the loopback) give the name of the 88 # interface (eg eth0) here. 89 # Repeat the line for more than one interface. 90 interface=wlan0
147行目のdhcp-rangeのコメントを外します。
143 # This is an example of a DHCP range where the netmask is given. This 144 # is needed for networks we reach the dnsmasq DHCP server via a relay 145 # agent. If you don't know what a DHCP relay agent is, you probably 146 # don't need to worry about this. 147 dhcp-range=192.168.0.50,192.168.0.150,255.255.255.0,12h
/etc/sysctl.d/ipv6.confの新規作成
RaspbmcのAirPlayでハマったでござる - もぐてっく
で、書いたAirPlayのためのIPv6無効化を行っておきます。
1 net.ipv6.conf.all.disable_ipv6 = 1
/opt/xbmc-bcm/xbmc-bin/share/xbmc/addons/script.raspbmc.settings/autostart.pyの編集
Raspbmcはリセットボタンを押さずに電源を引っこ抜くと、次回起動時に
「ちゃんと画面端のパワーボタン押して終了せぇやボケぇ!死ぬかと思たわ!!」
と、怒られます。
その主張はごもっともなんですが、外出先でこのダイアログが出たら消す方法が無いので、当該コードをコメントアウトします。
126 # if DISTRO == "Raspbmc" and os.path.isfile("/home/pi/.bootstatus") and check_service_running("wd") == "true" and not os.path.isfile("/home/pi/.nowarning"): 127 # import xbmcgui 128 # dialog = xbmcgui.Dialog() 129 # dialog.ok("Raspbmc did not shut down properly", "Raspbmc should always be shut down via the\npower icon in the lower left corner")
リブート!
これでRaspberry Piの無線AP化は完了です。リブートして成果を確認します。
お手持ちの無線クライアントを見ると、rtwapってアクセスポイントが増えています。
パスワード87654321で接続出来れば成功です!