コマンドライン上でapeファイルをmp3にエンコード

コマンドライン上でapeファイルをmp3にエンコードしたかったので調べた。Linuxユーザを想定しているけど、GUIでやりたい人は

を参考にすればできると思う。Windowsユーザはググれば何か見つかるでしょう。

まず結論を先に言うと、shntoollamemac をインストールして端末上で

shnsplit CDImage.ape -f CDImage.cue -o 'cust ext=mp3 lame --quiet - %f' -t "%n. %t"

を実行すれば、CDImage.ape をmp3ファイルにエンコードして、分割できる。

実行例の解説

簡単にこの実行例を解説すると、
shntool(shnsplit)は可逆圧縮されたファイルに多彩な処理(デコード・分割・エンコード)が可能で、wav, flac, ape, tta, wma などの入力に対応しているらしい。
-f オプションで、cueファイルを指定する。cueファイルは「この時間からこの時間まではhogeという曲で、fugaという歌手が歌ってる」といった風なapeファイルを分割するために必要なメタ情報を含んだテキストファイル。
-o オプションで、入力ファイルをどういう形式のファイルにエンコードするか記述する。mp3にエンコードする場合、ここで lame が必要となる。
-t オプションで、出力ファイル名のフォーマットを記述する。上の実行例で使ってる%nはトラック番号、%tはトラック番号を表す。他には%a(アルバム名)、%p(作曲家)というのがある。

shntool には他にも色んなオプションがあるので、詳しくは man shntool をご覧ください。

必要なもののインストール方法

前者2つ shntool と lame は apt で次のようにすればインストールできる。

sudo aptitude install shntool lame

最後の mac のインストールは

wget http://supermmx.org/resources/linux/mac/mac-3.99-u4-b5.tar.gz
tar zxvf mac-3.99-u4-b5.tar.gz
cd mac-3.99-u4-b5
./configure
make
sudo make install

で完了の筈だったけど、make時に次のようなコンパイルエラーがでた。

APELink.cpp: In member function 'void CAPELink::ParseData(const char*, const str_utf16*)':
APELink.cpp:66: error: invalid conversion from 'const char*' to 'char*'
APELink.cpp:67: error: invalid conversion from 'const char*' to 'char*'
APELink.cpp:68: error: invalid conversion from 'const char*' to 'char*'
APELink.cpp:69: error: invalid conversion from 'const char*' to 'char*'

これは mac-3.99-u4-b5/src/MACLib/APELink.cpp というファイルでconstが必要なのに付いてないがために起こるエラー。なので、constを付けるだけで修正できる。修正後のファイルとの差分 *1 は次のようになった。

66,69c66,69
<         char * pHeader = strstr(pData, APE_LINK_HEADER);
<         char * pImageFile = strstr(pData, APE_LINK_IMAGE_FILE_TAG);
<         char * pStartBlock = strstr(pData, APE_LINK_START_BLOCK_TAG);
<         char * pFinishBlock = strstr(pData, APE_LINK_FINISH_BLOCK_TAG);
---
>         const char * pHeader = strstr(pData, APE_LINK_HEADER);
>         const char * pImageFile = strstr(pData, APE_LINK_IMAGE_FILE_TAG);
>         const char * pStartBlock = strstr(pData, APE_LINK_START_BLOCK_TAG);
>         const char * pFinishBlock = strstr(pData, APE_LINK_FINISH_BLOCK_TAG);
84c84
<                 char * pImageCharacter = &pImageFile[strlen(APE_LINK_IMAGE_FILE_TAG)];
---
>                 const char * pImageCharacter = &pImageFile[strlen(APE_LINK_IMAGE_FILE_TAG)];
>

これでもう一度makeし直すと、無事コンパイルできた。

*1:差分は diff -Naur 修正前のAPELink.cpp 修正後のAPELink.cpp で取った