[日記] CDの曲情報ってどうやって取得しているの? CDDB / TOC

2018/05/3

こんにちは。きんくまです。
最近アルバムを買うのにiTunesでなくて現物のCDを買っています。

PCに取り込む手間がかかるのですが、音質が良いのと、最近iTunesのダウンロード販売を将来的にやめるニュースがあったようにいつサービスが終わるかわからないためです。

(ダウンロード販売をやめていない今でも以前にiTunesで買ったCDが再ダウンロードできなくなっていたりしたことがありました。たぶん版元が急に販売しなくなったのではないかと思います)

さて、CDをPCに取り込むときに作曲者や曲名などの情報が表示されます。
それなりに売れたであろうアルバムから、そんなにユーザー数も多そうでない英語の参考書の付録まで曲名が出たりします。
これってどうやってやっているのか気になったので調べてみることにしました。

CDDB

取り込む挙動をみていると、ネット経由で曲情報をどこかに問い合わせをしているようです。
調べて見ると、CDDBという規格がありそこにアルバムや曲情報が書いてあるみたいです。

>> CD再生時の曲名等の誤表示に関する情報
>> CDDB – Wikipedia

CDDBを管理している団体はいくつかあり、大手でGracenoteという会社がありました。
iTunesではここのDBにネット経由で問い合わせをしているようです。

>> 楽曲認識技術

余談)ちなみにCD制作者がCDDBをちゃんと登録しようと思うといくつも登録する場所があるみたいで大変みたい。
>> 「まだ自作CDをCDDBに登録してないの?」実はあなたも出来ていない?!自作CD情報の、CDDBへの登録について

TOC

さてCDDBに問い合わせするとしても、どうやってやっているんでしょうか?
普通に考えると、自分のPC「このCDの情報を教えて?」-> CDDB「それはこんな情報だよ」という流れになるので、
問い合わせをするためには、「このCD」を識別するキーが必要になります。

するとCD自体の情報はTOC(Table Of Contents)と呼ばれる領域に書かれていることがわかりました。

>> TOC ‐ 通信用語の基礎知識

TOCにCDの長さや曲数が書かれているみたいです。
なんとmacだと何とターミナルからコマンドラインで簡単に読み取れるようです。

>> Accessing Audio CD Table of Contents

手元にラブライブのベスト盤があったのでこれを読み取ってみましょう。

まず接続しているCDドライブを認識します。外付けCDドライブです。

% drutil list
   Vendor   Product           Rev   Bus       SupportLevel
1  TEAC     DV-W28S-V         K.0A  USB       Unsupported

TEACが製造していて、型番が「DV-W28S-V」という製品のようです。
ドライブを認識できたので、TOCを読んでみます。
(-driveのあとの引数は TEAC でも DV-W28S-V でもどちらでもOKなようです。)

% drutil -drive DV-W28S-V toc
 Vendor   Product           Rev
 TEAC     DV-W28S-V         K.0A

    First session:             1
    Last session:              1
    First track:               1
    Disc type:                 0 (CD-DA, or CD-ROM with first track in Mode 1)
    Last track:                14
    Lead-out:                  62:25.21
    Session  1, Track  1:      00:02.00  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track  2:      05:26.25  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track  3:      09:42.48  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track  4:      14:02.68  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track  5:      18:33.55  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track  6:      23:09.05  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track  7:      27:26.18  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track  8:      31:20.58  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track  9:      35:01.35  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track 10:      39:02.17  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track 11:      43:19.43  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track 12:      47:48.43  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track 13:      51:48.10  2ch audio, no pre-emphasis, digital copy prohibited
    Session  1, Track 14:      57:32.53  2ch audio, no pre-emphasis, digital copy prohibited

14曲入っていてトータルが62分25.21秒ということがわかりました。
各曲の再生時間はその通りに書いてあるのではなくて、頭からの相対位置が書いてあるようですね。トラック1は再生2秒から開始、トラック2は5分26.25秒からという感じです。

せっかくなので他のオプションコマンドも試してみます。

% drutil -drive TEAC discinfo
 Vendor   Product           Rev
 TEAC     DV-W28S-V         K.0A

  Disc Info:
                 dataLength: 32
                   erasable: 0
               sessionState: 3
                 discStatus: 2
                 firstTrack: 1
               sessionCount: 1
    firstTrack(lastSession): 1
     lastTrack(lastSession): 14
                      DID_V: 0
                      DBC_V: 0
                      URU_V: 0
                      DAC_V: 0
                       DBit: 0
             BGFormatStatus: 0
                   discType: 0
                     discId: 0
       lastSessionLeadInMSF: 255:255:255
        lastStartLeadOutMSF: 255:255:255
                discBarCode: 0
                discAppCode: 0
% drutil -drive TEAC trackinfo
 Vendor   Product           Rev
 TEAC     DV-W28S-V         K.0A

  Track 1 info:
               dataLength: 34
              trackNumber: 1
            sessionNumber: 1
                   damage: false
                     copy: false
                trackMode: 0
                 dataMode: 15
                       RT: false
                    blank: false
                packetInc: false
               packetSize: 0
                       FP: false
        trackStartAddress: 0
      nextWritableAddress: 0 (not valid)
      lastRecordedAddress: 0 (not valid)
                trackSize: 24325
               freeBlocks: 0

... Track 2から13は長いので省略

  Track 14 info:
               dataLength: 34
              trackNumber: 14
            sessionNumber: 1
                   damage: false
                     copy: false
                trackMode: 0
                 dataMode: 15
                       RT: false
                    blank: false
                packetInc: false
               packetSize: 0
                       FP: false
        trackStartAddress: 258803
      nextWritableAddress: 0 (not valid)
      lastRecordedAddress: 0 (not valid)
                trackSize: 21943
               freeBlocks: 0

細かく何かのデータが出てはいるのですが、やはり曲名などは入っていないようです。

ここでふと気がついたのですが、どこにもCDを識別するIDのようなものが書いてありません、、。
これじゃ「このCD」というのがどのCDかわからないです、、。

disc ID

英語版Wikiにその方法が書いてありました。

>> Example calculation of a CDDB1 (FreeDB) disc ID

定義方法
1. 16進数8桁の XXYYYYZZ 形式でIDを定義する
2. XXは再生開始時間の合計を255で割った余り
3. YYYYは合計再生時間を16進数にしたもの
4. ZZは曲数

ただし残念ながらこの方法はCDDB1です。Gracenoteが管理している現状のバージョンはCDDB2なので、このIDはそのまま使えないと思います。
ですが参考までにどんな感じに定義しているかを見てみます。
たぶんCDDB2もこれに近いことはしているのではないでしょうか。

2だけちょっと自信がないです、、。ソースコードを見る限りだとこの解釈であってそうなのですが、、。

4は曲数なのですが、ZZは2桁しかないから100曲以上になったらどうするんだって思ったのですが、どうやらCDはそもそも仕様で99曲より多くは入れられないみたいです(なんと!?)

というわけでJavaScriptでコードを書いてラブライブCDのdisc IDを計算してみます。

TOCからCDDB1のdisc IDを得るコード(仮)

//TOCのデータ
var tocData = {
    //合計時間
    totalTime: "62:25.21",
    //各トラック再生開始時間(CD頭からの差分時間)
    trackOffsets:[
        "00:02.00",
        "05:26.25",
        "09:42.48",
        "14:02.68",
        "18:33.55",
        "23:09.05",
        "27:26.18",
        "31:20.58",
        "35:01.35",
        "39:02.17",
        "43:19.43",
        "47:48.43",
        "51:48.10",
        "57:32.53"
    ]
};

//2桁の数字を0づめ
function padZeroText(num){
    if(num < 10){
        return "0" + num;
    }
    return "" + num;
}

//digitまでhexTextを0づめ
function padZeroHexText(hexText, digit){
    if(!digit){
        throw new Error("digit " + digit + " is invalid!");
    }
    var result = hexText;
    while(result.length < digit){
        result = "0" + result;
    }
    return result;
}

function convertDurationTextToSeconds(text){
    var comps = text.split(':');
    var minutes = 0;
    var seconds = 0;
    if(comps.length >= 2){
        minutes = parseInt(comps[0], 10);
        seconds = parseFloat(comps[1]);
    //配列が1のときは秒のみ
    }else if(comps.length == 1){
        seconds = parseFloat(comps[0]);
    }else{
        return 0;
    }
    return minutes * 60 + seconds;
}

function calcXX(toc){
    //再生開始時間を全部足して
    var totalSeconds = 0;
    toc.trackOffsets.map(function(offset){
        totalSeconds += convertDurationTextToSeconds(offset);
    });
    totalSeconds = Math.floor(totalSeconds);
    //255で割った余り
    var modResult = totalSeconds % 255;
    return padZeroText(modResult);
}

function calcYYYY(toc){
    //再生時間を16進数にする
    var duration = convertDurationTextToSeconds(toc.totalTime);
    duration = Math.floor(duration);
    var hexText = duration.toString(16);
    return padZeroHexText(hexText, 4);
}

function calcZZ(toc){
    //曲数を返す
    return padZeroText(toc.trackOffsets.length);
}

function calcDiscId(toc){
    return calcXX(toc) + calcYYYY(toc) + calcZZ(toc);
}

var discId = calcDiscId(tocData);
console.log('disc id => ' + discId);

コードで小数点以下の秒数の扱いがわからなかったので切り捨てしてしまったのですが、これで合っているのかわかりません、、。
それで結果は以下のようになりました。

disc id => 290ea114

GracenoteのCDDB2は残念ながら登録した会社やディベロッパーのみが問い合わせできるので、CDDB2のdisc IDの仕様は不明ですが、このような感じにCDのIDを計算してサーバーに問い合わせするんじゃないでしょうか。

とここで、よく考えてみるとこれだけの情報だと絶対にIDがかぶりそうです。
再生開始時間や曲数だけですからね。ですので、CDによっては全然違う情報が複数返ってくる場合があるんじゃないでしょうか。

CDDBについて調べてみました。ではでは。

LINEで送る
Pocket

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

LINEスタンプ作りました!
毎日使える。とぼけたウサギ。LINEスタンプ販売中! 毎日使える。とぼけたウサギ

ページトップへ戻る