ホーム >プログラム >Delphi 6 ローテクTips >ID3タグ取得・自作関数 ID3v1

mp3やwmaなどのID3タグを取得したり書き込んだりするための自作関数を作ろうと思います。
わざわざ自作しなくともShellを利用したりTWindowsMediaPlayerやmp3infp.dllなどを使えばよいものを、、とは自分でも思いますし実際やってきました。
が、それでも自作をめざすのにはそれなりのわけがあるのです。


Shellを使って取得するのはUnicodeに対応していて一見手軽で良いのですが書き込みはできませんしファイルシステムがNTFSでないとなりませんし実はOSが違うと処理を振り分けなければならないなど意外と手間がかかります。
というか2000、 XP、 Vistaでそれぞれ仕様が違うというのはなぜなんだろう、、と疑念が尽きません。

TWindowsMediaPlayerを利用するのはUnicodeに対応していて書き込みもできるのですが、なんといっても遅いのがネックです。
特に書き込みに関してはWMPのライブラリ操作をしないといけない関係もあってすごく遅くなってしまいます。

mp3infp.dllを利用するのは軽いしあらゆるフォーマットに対応していて実績もあって大変魅力なのですがUnicodeに対応していないのが唯一のネックです。

結局、Unicode 対応で書き込みもできてそこそこ軽いものを、、と望むと自作するのが一番かなぁ、、と。
そういうわけです。

と、意気込んだはいいものの。
色々調べたりやってみた結果書き込みに対応するのは断念しました。
色々整合性をとらないといけないようで大変面倒くさいと。
そしてTWindowsMediaPlayerを利用したタグの書き込みが以前よりも格段に速く(それでも遅いけれど)できるようになったので、自作するのは読み込みだけでもいいかと。
じゃぁShell 利用でいいじゃないかとも思いますが、Shell利用で2000に対応してみたものの結果が芳しくなかった(取得できなかった)ので、まぁそれなりに意味はあるかなと。

そういうわけで目標はmp3、wma、wmvの三種類のタグが取得できればそれでよし、と。


ID3v1

何はともあれまずはID3v1の取得からいってみましょう。


ファイルの後ろから128バイトを読み込んで頭の3文字が「TAG」 であればID3v1タグであると判定します。
そしてタイトルやアーティストなどは固定長となっているので簡単に取得できます。
唯一ジャンルの取得がバージョンの違いでちょっとややこしくなってるだけです。

type
  TMyID3v1 = record
    Ver      Byte;
    Title:   String[30];
    Author:  String[30];
    Album:   String[30];
    Date:    String[4];
    Comment: String[30];
    Track:   Byte;
    Genre:   Byte;
  end;

function gfnsByteCopy(pStr: PAnsiChar; iIndex, iCount: DWORD): AnsiString;
//pStr[iIndex]からiCountバイトの文字列をコピーして返す。
var
  i: DWORD;
begin
  SetLength(Result, iCount);
  for i := 1 to iCount do begin
    Result[i] := pStr[i + iIndex -1];
  end;
end;


function gfnrTagID3v1Read(const sFile: WideString): TMyID3v1;
{
ID3タグVer1を取得
http://ja.wikipedia.org/wiki/ID3タグ
}

var
  lp_Buff: PChar;
  li_Size: DWORD;
begin
  FillChar(Result, SizeOf(TMyID3v1), 0);
  li_Size := gfniFileEndRead(lp_Buff, sFile, 128);
  try
    if (li_Size = 128) then begin
      if  (lp_Buff[0] = 'T')
      and (lp_Buff[1] = 'A')
      and (lp_Buff[2] = 'G')
      then begin
        Result.Title   := gfnsByteCopy(lp_Buff,  3, 30);  //曲名
        Result.Author  := gfnsByteCopy(lp_Buff, 33, 30);  //アーティスト
        Result.Album   := gfnsByteCopy(lp_Buff, 63, 30);  //アルバム
        Result.Date    := gfnsByteCopy(lp_Buff, 93,  4);  //日付
        Result.Comment := gfnsByteCopy(lp_Buff, 97, 30);  //コメント
        Result.Genre   := Ord(lp_Buff[127]);  //トラック
        if (lp_Buff[125] = #0) and (lp_Buff[126] <> #0) then begin
          //オフセットの125が#0で126が#0でなければV1.1でトラックあり
          Result.Track := Ord(lp_Buff[126]);  //トラック
          Result.Ver   := 1;
        end;
      end;
    end;
  finally
    FreeMem(lp_Buff);
  end;
end;

ジャンルは整数値でセットされているので対応する文字列に変換。

function gfnsTagID3GenreToStr(const iGenre: BYTE): String;
{
ジャンルのIDを文字列に変換して返す
http://www.tsg.ne.jp/GANA/S/maid3/README.txt
}

begin
  case iGenre of
      0: Result := 'Blues';
      1: Result := 'Classic Rock';
      2: Result := 'Country';
      3: Result := 'Dance';
      4: Result := 'Disco';
      5: Result := 'Funk';
      6: Result := 'Grunge';
      7: Result := 'Hip-Hop';
      8: Result := 'Jazz';
      9: Result := 'Metal';
     10: Result := 'New Age';
     11: Result := 'Oldies';
     12: Result := 'Other';
     13: Result := 'Pop';
     14: Result := 'R&B';
     15: Result := 'Rap';
     16: Result := 'Reggae';
     17: Result := 'Rock';
     18: Result := 'Techno';
     19: Result := 'Industrial';
     20: Result := 'Alternative';
     21: Result := 'Ska';
     22: Result := 'Death Metal';
     23: Result := 'Pranks';
     24: Result := 'Soundtrack';
     25: Result := 'Euro-Techno';
     26: Result := 'Ambient';
     27: Result := 'Trip-Hop';
     28: Result := 'Vocal';
     29: Result := 'Jazz+Funk';
     30: Result := 'Fusion';
     31: Result := 'Trance';
     32: Result := 'Classical';
     33: Result := 'Instrumental';
     34: Result := 'Acid';
     35: Result := 'House';
     36: Result := 'Game';
     37: Result := 'Sound Clip';
     38: Result := 'Gospel';
     39: Result := 'Noise';
     40: Result := 'AlternRock';
     41: Result := 'Bass';
     42: Result := 'Soul';
     43: Result := 'Punk';
     44: Result := 'Space';
     45: Result := 'Meditative';
     46: Result := 'Instrumental Pop';
     47: Result := 'Instrumental Rock';
     48: Result := 'Ethnic';
     49: Result := 'Gothic';
     50: Result := 'Darkwave';
     51: Result := 'Techno-Industrial';
     52: Result := 'Electronic';
     53: Result := 'Pop-Folk';
     54: Result := 'Eurodance';
     55: Result := 'Dream';
     56: Result := 'Southern Rock';
     57: Result := 'Comedy';
     58: Result := 'Cult';
     59: Result := 'Gangsta';
     60: Result := 'Top 40';
     61: Result := 'Christian Rap';
     62: Result := 'Pop/Funk';
     63: Result := 'Jungle';
     64: Result := 'Native American';
     65: Result := 'Cabaret';
     66: Result := 'New Wave';
     67: Result := 'Psychedelic';
     68: Result := 'Rave';
     69: Result := 'Showtunes';
     70: Result := 'Trailer';
     71: Result := 'Lo-Fi';
     72: Result := 'Tribal';
     73: Result := 'Acid Punk';
     74: Result := 'Acid Jazz';
     75: Result := 'Polka';
     76: Result := 'Retro';
     77: Result := 'Musical';
     78: Result := 'Rock & Roll';
     79: Result := 'Hard Rock';
     80: Result := 'Folk';
     81: Result := 'Folk/Rock';
     82: Result := 'National Folk';
     83: Result := 'Swing';
//以下winamp準拠
     84: Result := 'Fast Fusion';
     85: Result := 'Bebob';
     86: Result := 'Latin';
     87: Result := 'Revival';
     88: Result := 'Celtic';
     89: Result := 'Bluegrass';
     90: Result := 'Avantgarde';
     91: Result := 'Gothic Rock';
     92: Result := 'Progressive Rock';
     93: Result := 'Psychedelic Rock';
     94: Result := 'Symphonic Rock';
     95: Result := 'Slow Rock';
     96: Result := 'Big Band';
     97: Result := 'Chorus';
     98: Result := 'Easy Listening';
     99: Result := 'Acoustic';
    100: Result := 'Humour';
    101: Result := 'Speech';
    102: Result := 'Chanson';
    103: Result := 'Opera';
    104: Result := 'Chamber Music';
    105: Result := 'Sonata';
    106: Result := 'Symphony';
    107: Result := 'Booty Bass';
    108: Result := 'Primus';
    109: Result := 'Porn Groove';
    110: Result := 'Satire';
    111: Result := 'Slow Jam';
    112: Result := 'Club';
    113: Result := 'Tango';
    114: Result := 'Samba';
    115: Result := 'Folklore';
    116: Result := 'Ballad';
    117: Result := 'Power Ballad';
    118: Result := 'Rhythmic Soul';
    119: Result := 'Freestyle';
    120: Result := 'Duet';
    121: Result := 'Punk Rock';
    122: Result := 'Drum Solo';
    123: Result := 'A Cappella';
    124: Result := 'Euro-House';
    125: Result := 'Dance Hall';
    126: Result := 'Goa';
    127: Result := 'Drum & Bass';
    128: Result := 'Club-House';
    129: Result := 'Hardcore';
    130: Result := 'Terror';
    131: Result := 'Indie';
    132: Result := 'BritPop';
    133: Result := 'Negerpunk';
    134: Result := 'Polsk Punk';
    135: Result := 'Beat';
    136: Result := 'Christian Gangsta Rap';
    137: Result := 'Heavy Metal';
    138: Result := 'Black Metal';
    139: Result := 'Crossover';
    140: Result := 'Contemporary Christian';
    141: Result := 'Christian Rock';
    142: Result := 'Merengue';
    143: Result := 'Salsa';
    144: Result := 'Thrash Metal';
    145: Result := 'Anime';
    146: Result := 'Jpop';
    147: Result := 'Synthpop';
  else  Result := '';
  end;
end;

2008-04-04