見出し画像

libcddbを使った開発:CDDB(Gnudb)から音楽CD情報の取得

音楽CDのタイトルや楽曲情報のデータベースとしてGnudb(Global Network Universal Database)があります。ここでは、Libcddbを使ってGnudbから音楽CDの楽曲データの取得方法について説明します。

音楽CDにはCDを識別するユニークなIDのようなものは無いので、音楽CDに含まれるトラック(曲)のオフセット位置(セクター単位)と、全体の記録時間とから生成されるユニークなIDでCDの識別を行っているようです。

下記のプログラムは、disc_length, frame_offsets, track_numで指定されたCDの情報を表示するC/C++のサンプルコードです。 全体構成をわかりやすくするため、エラー処理なども削ったシンプルなものにしてあります。

下記のサンプルでハードコーディングされているdisc_length, frame_offsets, track_numの値には、「paranoiaライブラリを使った開発:音楽CDのリッピング」の説明で取得した、「角川映画スペシャル」のCDのTOC(Table of Contents)情報を使っています。

#include <stdio.h>
#include <stdlib.h>

// (1)
#include <cddb/cddb.h>

static void print_disc_info(cddb_disc_t *disc)
{
	printf("CDDB ID = 0x%04x\n", cddb_disc_get_discid(disc));
	printf("CDDB Category = %d\n", cddb_disc_get_category(disc));
	printf("Music Genre = %s\n", cddb_disc_get_genre(disc));
	printf("Length = %d\n", cddb_disc_get_length(disc));
	printf("Title = %s\n", cddb_disc_get_title(disc));
	printf("Artist name = %s\n", cddb_disc_get_artist(disc));
	printf("Track count = %d\n", cddb_disc_get_track_count(disc));
}

static void	print_track_info(cddb_track_t *track)
{
	printf("Number = %d\n", cddb_track_get_number(track));
	printf("Frame offset = %d\n", cddb_track_get_frame_offset(track));
	printf("Length = %d\n", cddb_track_get_length(track));
	printf("Title = %s\n", cddb_track_get_title(track));
	printf("Artist name = %s\n", cddb_track_get_artist(track));
}

int main(int argc, char *argv[])
{
	static int disc_length = 2875;
	static int frame_offsets[12] = {
		0, 19495, 35907, 54187, 74947, 96240,
		115432, 133270, 151032, 165907, 181517, 198142
	};
	static int track_num = 12;

	// (2)
	cddb_conn_t *conn = cddb_new();
	if(conn == NULL) {
		printf("cddb_new error\n");
		return -1;
	}


	// (3)
	cddb_http_proxy_enable(conn);
	cddb_set_http_proxy_server_name(conn, "gnudb.gnudb.org");
	cddb_set_http_proxy_server_port(conn, 3128);
	cddb_set_server_port(conn, 8880);

	// (4)
	cddb_cache_enable(conn);

	// (5)
	cddb_disc_t *disc = cddb_disc_new();
	if (disc == NULL) {
		printf("cddb_disc_new error\n");
		return -1;
	}

	// (6)
	cddb_disc_set_length(disc, disc_length);

	for(int i = 0; i < track_num; i++) {
		// (7)
		cddb_track_t *track = cddb_track_new(); 
		if(track == NULL){ 
			printf("cddb_track_new error\n");
			return -1;
		}
		// (8)
		cddb_track_set_frame_offset(track, frame_offsets[i] + SECONDS_TO_FRAMES(2));
		// (9)
		cddb_disc_add_track(disc, track);
	}

	// (10)
	int matches = cddb_query(conn, disc);
	if(matches == -1) {
		cddb_error_print(cddb_errno(conn));
		exit(-1);
	}
	printf("matches = %d\n", matches);

	for(int m = 0; m < matches; ++m){
		// (11)
		int success = cddb_read(conn, disc);
		if(!success){
			cddb_error_print(cddb_errno(conn));
			continue;
		}

		printf("\n---- matches = %d ----\n", m);
		print_disc_info(disc);
		for(int i = 0; i < cddb_disc_get_track_count(disc); ++i){
			// (12)
			cddb_track_t *track = cddb_disc_get_track(disc, i);
			printf("---- track = %d ----\n", i);
			if(track != NULL){
				print_track_info(track);
			}
		}

		// (13)
		if(!cddb_search_next(conn, disc)) {
			break;
		}
	}

	// (14)
	cddb_disc_destroy(disc);
	cddb_destroy(conn);
	libcddb_shutdown();

	return 0;
}

Libcddbの使い方はチュートリアルに説明があります。このチュートリアルとソースコードで大体分かると思いますが、簡単に説明を書いておきます。

(1) libcddbを使うためにcddb/cddb.hをインクルードします。
(2) cddb_newでコネクションを作成します。
(3) コネクションにCDDBのアドレスやポート番号などを指定します。ここではGnudbが提供するProxyを使う設定をしています。
(4) cddb_cache_enableでキャッシュを使用する設定にしています。以前に取得した情報はローカルのキャッシュに保管され、同じCD情報に関してはキャッシュから取得するようになります。cddb_cache_disable(キャッシュを使わない)や、cddb_cache_only(キャッシュのみ使う)などの設定にもできます。キャッシュはデフォルトでは$HOME/.cddbslaveディレクトリ内に保管されます。cddb_cache_set_dirで異なる場所にすることもできます。
(5) cddb_disc_newでdiscオブジェクトを生成します。
(6) cddb_disc_set_lengthでCD全体の記録時間(sec)を設定します。
(7) (7)~(9)でdiscオブジェクトにtrackオブジェクトをトラックの数だけ追加します。cddb_track_newでトラックオブジェクトを生成。
(8) cddb_track_set_frame_offsetでそのトラックの先頭位置(セクター単位)を設定します。トラックの先頭位置ですが、paranoiaライブラリで取得したTOC情報の先頭位置は1曲目の先頭が0になっていますが、ここでの位置はCDの先頭からの位置となります。なので、Lead Inの長さ分(Lead Inは2秒分の長さのようなのでSECONDS_TO_FRAMES(2)=150)を追加する必要があります。
(9) cddb_disc_add_trackで先頭位置を指定したトラックオブジェクトを、discオブジェクトに追加登録します。
(10) discに再生時間、トラックに先頭位置を設定すれば、cddb_queryによってCDDBに問い合わせができます。見つかった場合は、見つかった個数が戻ります。
(11) cddb_queryで情報が見つかった場合はcddb_readでさらに情報を取得します。cddb_queryではトラックの情報(曲名やアーティスト名など)は取得されません。cddb_readによってトラックの情報が取得されます。
(12) cddb_readを実行したら、cddb_disc_get_trackで各トラック情報を読み出すことができます。
(13) cddb_queryで複数のCD情報が見つかった場合は、cddb_search_nextを呼び出すことで、順番にCD情報を読み出すことができます。
(14) 最後に(5)で生成したdiscオブジェクトをcddb_disc_destroyで解放します。discに登録されたtrackオブジェクトも解放されるので、trackオブジェクトを個々に解放する必要はないようです。cddb_destroyで(2)で生成したコネクションも解放しておいたほうが良いようです。また、libcddb_shutdownでライブラリ全体の終了もしておいた方が良いかもしれません。

上記のサンプルコードをcddb_simple.cppなどのファイル名で保存し、下記のようにコンパイルすれば良いでしょう。ライブラリの指定にpkg-configを使っていますが、単に-lcddbとしてもOKでしょう。

$ g++ -o cddb_simple cddb_simple.cpp `pkg-config --cflags --libs libcddb`

コンパイルしたプログラムを実行すると、下記のようにCDの情報と各トラック(曲)の情報が取得できたことが確認できると思います。

$ ./cddb_simple
matches = 1

---- matches = 0 ----
CDDB ID = 0x820b3a86
CDDB Category = 0
Music Genre = Soundtrack
Length = 2876
Title = 角川映画スペシャル
Artist name = Various
Track count = 12
---- track = 0 ----
Number = 1
Frame offset = 150
Length = 259
Title = 人間の証明のテーマ
Artist name = ジョー山中
---- track = 1 ----
Number = 2
Frame offset = 19645
Length = 218
Title = 戦士の休息
Artist name = 町田義人
---- track = 2 ----
Number = 3
Frame offset = 36057
Length = 243
Title = 蘇える金狼のテーマ
Artist name = 前野曜子
---- track = 3 ----
Number = 4
Frame offset = 54337
Length = 276
Title = 戦国自衛隊のテーマ
Artist name = 松村とおる
---- track = 4 ----
Number = 5
Frame offset = 75097
Length = 283
Title = セーラー服と機関銃
Artist name = 薬師丸ひろ子
---- track = 5 ----
Number = 6
Frame offset = 96390
Length = 255
Title = ローズマリー・バトラー
Artist name = 汚れた英雄
---- track = 6 ----
Number = 7
Frame offset = 115582
Length = 237
Title = 探偵物語
Artist name = 薬師丸ひろ子
---- track = 7 ----
Number = 8
Frame offset = 133420
Length = 236
Title = 時をかける少女
Artist name = 原田知世
---- track = 8 ----
Number = 9
Frame offset = 151182
Length = 198
Title = 里見八犬伝
Artist name = ジョン・オバニオン
---- track = 9 ----
Number = 10
Frame offset = 166057
Length = 208
Title = メイン・テーマ
Artist name = 薬師丸ひろ子
---- track = 10 ----
Number = 11
Frame offset = 181667
Length = 221
Title = 愛情物語
Artist name = 原田知世
---- track = 11 ----
Number = 12
Frame offset = 198292
Length = 233
Title = Woman~Wの悲劇~より
Artist name = 薬師丸ひろ子


この記事が気に入ったらサポートをしてみませんか?