GracenoteのAPIは結構前に一般公開が停止してしまったのでMusicBrainzを使用してみます。
MusicBrainz
https://musicbrainz.org
MusicBrainzはDiskIDとtoc情報でCDを特定できますが、私の技術不足でDiscIDが算出できなかったので
tocのみで特定する方法です。(すみません)
DiscIDの算出方法はここに詳しく解説されています。
https://musicbrainz.org/doc/Disc_ID_Calculation
tocのみで特定する場合、CD自体が膨大にあり複数ヒットしてしまうので
ユーザー自身でヒットしたリストから特定する必要があります。
今回はwindowsがCDを読み込んだ際に生成される.cdaファイルからtocを読み出し算出します。
.cdaファイルの構造についてはここから (英語ですが)
https://en.wikipedia.org/wiki/.cda_file
検索用のtocデータは
(最初のトラック番号) + (最後のトラック番号) + (曲の全長) + (全トラックの開始位置)...
で構築できます
*start
#include "hspinet.as"
#include "hsp3utf.as"
#uselib "Kernel32"
#func GetLogicalDriveStrings "GetLogicalDriveStringsA" int,var
#cfunc GetDriveType "GetDriveTypeA" var
dim drives_info,30
sdim cda_data, 44
sdim toc_data, 1024
sdim drives_list, 1024
request_url_root = "https://musicbrainz.org/ws/2/"
*search_drive
//参考: http://gpsnmeajp.sblo.jp/article/181155322.html
//ドライブ一覧を取得
GetLogicalDriveStrings 1024, drives_list
null_cnt=0
//NULL文字で区切られているので、分離して文字列に
repeat 1024
null_peek = peek(drives_list,cnt)
if null_peek = 0 {
null_cnt++
poke drives_list,cnt,','
}else{
null_cnt=0
}
if null_cnt >= 2 {
poke drives_list,cnt,0
break
}
loop
//末端に付いた,を除去
drives_list = strtrim(drives_list,2,',')
//文字列を分離して配列に
split drives_list,",",drives
//詳細情報取得
foreach drives
drives_info(cnt) = GetDriveType(drives(cnt))
loop
//CDROMドライブの特定
foreach drives
if drives_info(cnt) = 5 : drive_letter_cdrom = drives(cnt)
loop
*read_toc
//////////////////////////////////////////////////////////
//検索用のtocデータは
//(最初のトラック番号) + (最後のトラック番号) + (曲の全長) + (全トラックの開始位置)...
//で構築できる
//cdaファイルの構造: https://en.wikipedia.org/wiki/.cda_file
//////////////////////////////////////////////////////////
//cdaファイルのリスト作成
chdir drive_letter_cdrom
dirlist cda_list, "*.*", 2
notesel cda_list
cda_list_num = noteinfo(0)
//cdaファイルを配列に格納
dim cda_list_dim, cda_list_num
split cda_list, "\n", cda_list_dim
//トラックの最初の番号と最終トラック番号を挿入
toc_data = "1+" + str(cda_list_num) + "+"
toc_data_track = ""
repeat cda_list_num
//バッファにファイル読み込み
bload drive_letter_cdrom + cda_list_dim(cnt), cda_data
//それぞれの曲の開始位置を取得
toc_minutes = peek(cda_data, 38)
toc_seconds = peek(cda_data, 37)
toc_frames = peek(cda_data, 36)
// 1/75秒おきに読み出されるので、すべてフレームに換算する
toc_minutes = (toc_minutes * 60) * 75
toc_seconds = toc_seconds * 75
toc_all_track = toc_minutes + toc_seconds + toc_frames
//送信用データ作成
//最終トラックのみデュレーションを取得
if cda_list_num = cnt+1 {
toc_data_track += str(toc_all_track)
toc_minutes_duration = peek(cda_data, 42)
toc_seconds_duration = peek(cda_data, 41)
toc_frames_duration = peek(cda_data, 40)
//同様にフレーム換算
toc_minutes_duration = (toc_minutes_duration * 60) * 75
toc_seconds_duration = toc_seconds_duration * 75
//曲の全長を算出
//先にtoc_dataに挿入
toc_data += str(toc_minutes_duration + toc_seconds_duration + toc_frames_duration + toc_all_track) + "+"
}else{
//全トラックの開始位置を控えておく
toc_data_track += str(toc_all_track) + "+"
}
loop
//toc_dataに後付
toc_data += toc_data_track
*get_json
netinit
//GETリクエスト
//&fmt=jsonをつけることでjsonで受け取れる (デフォルトはxml)
//ヘッダに application/json でも有効
neturl request_url_root
netrequest_get "discid/-?toc=" + toc_data + "&fmt=json"
//レスポンス待機
repeat
netexec wait_res
if wait_res=1 : break
await 1
loop
//結果を変数へ
netgetv responce_json_raw
netterm
*get_title
album_title_all = ""
//hsp3utfをインクルードしない場合変換が必要
//nkfcnv responce_json_raw, responce_json_raw, "s"
//json読み込み
jsonopen root_ptr,responce_json_raw
jsongetobj releases_ptr,"releases",root_ptr
jsonnext releases_ptr,releases_ptr,2
//tocの重複によりいくつか出てくる場合がある
//そのため存在するタイトルはすべて読み込む
while(releases_ptr != NULL)
jsongets album_title,"title",releases_ptr
jsonnext releases_ptr,releases_ptr,0
album_title_all += album_title + "\n"
wend
jsonclose
mes album_title_all
stop
曲名というよりアルバム名の取得ですね。
APIに関してはここで詳しく解説されています。
https://musicbrainz.org/doc/MusicBrainz_API