SSK's Blog

C# & One Direction & Taylor Swift好きのブログです

ID3v1、ID3v1.1 タグ構造・読み込み in C#

ID3v1とv1.1のタグの構造とそれを読み込むためのコードをC#で解説します。

知っておいた方が良い基礎知識

ID3v1とID3v2は記載箇所が異なるので、同時に二つのタグを保存することができます。
ID3のv1とv1.1は文字コードが定義されていないので、記事中ではUTF-8を使用しています。
またID3v2とは違いタグのサイズは128バイトで固定されています。

構造

ID3v1

開始位置 長さ 説明
0 3 "TAG"識別子
3 30 曲名
33 30 アーティスト
63 30 アルバム
93 4 日付
97 30 コメント
127 1 ジャンル番号

ID3v1.1

開始位置 長さ 説明
0 3 "TAG"識別子
3 30 曲名
33 30 アーティスト
63 30 アルバム
93 4 日付
97 28 コメント
125 1 0(NULL)が格納
126 1 トラック番号
127 1 ジャンル番号

ID3v1, ID3v1.1

お気づきの方もいると思いますが、v1.1ではコメントが2バイト縮小し、
ジャンル番号の前にNULLとトラック番号が格納されます。

バイト配列をstringとint型に変換するコード

        //バイト型配列を文字列へ変換するメソッド
        private string ByteToStr(byte[] b)
        {
            Encoding Enc = System.Text.Encoding.UTF8;
            return Enc.GetString(b).TrimEnd();
        }

        //バイトをint型整数に変換するメソッド
        private int ByteToInt(byte b)
        {
            return Convert.ToInt32(b);
        }

タグ全体の読み込み

ID3v1とID3v1.1の構造はほとんど同じです。また、とても単純な構造をしています。
タグはファイルの一番最後から128バイト前の位置に保存されています。
なのでタグ全体は以下のコードで取得できます。

            //タグ全体を格納するbyte型配列
            byte[] TagData = new byte[128];
            //ファイルパス
            string FilePath = "Testv1.mp3";

            FileStream fs = new FileStream(FilePath, 
                FileMode.Open, FileAccess.Read);
            
            //ファイルが128バイト以上か確認
            if (fs.Length >= 128)
            {
                fs.Seek(fs.Length - 128, SeekOrigin.Begin);
                fs.Read(TagData, 0, TagData.Length);
            }
            else
            {
                return;
            }
            fs.Close();

タグの確認

128バイト前が場合によってはID3ではない可能性もあるので、
確認をする場合以下のコードを使用します。

            byte[] tag = new byte[3];
            Array.Copy(TagData, 0, tag, 0, 3);
            string str = ByteToStr(tag);

            if (str != "TAG")
            {
                return;
            }

タグからのデータの取得

メインのデータ取得ですが、これは構造を参考にして取得します。

ID3のバージョンの確認

ID3v1.1では125byteの位置にNULL(00)が格納されます。
また、僕が調べたところv1では余ったbyteはすべて空白文字(20)で埋められるので
バージョンを確認する場合125byte目がNULLかどうかを比較します。

            if (TagData[125] == 0)
            {
                //バージョンは1.1
            }
            else
            {
                //バージョンは1
            }
ID3v1のデータ取得
開始位置 長さ 説明
0 3 "TAG"識別子
3 30 曲名
33 30 アーティスト
63 30 アルバム
93 4 日付
97 30 コメント
127 1 ジャンル番号
            //あらかじめバイト型の配列は用意しておいてください。
            Array.Copy(TagData, 0, TAG, 0, 3);
            Array.Copy(TagData, 3, Title, 0, 30);
            Array.Copy(TagData, 33, Artist, 0, 30);
            Array.Copy(TagData, 63, Album, 0, 30);
            Array.Copy(TagData, 93, Date, 0, 4);
            Array.Copy(TagData, 97, Comment, 0, 30);
            Array.Copy(TagData, 127, Genre, 0, 1);
ID3v1.1のデータ取得
開始位置 長さ 説明
0 3 "TAG"識別子
3 30 曲名
33 30 アーティスト
63 30 アルバム
93 4 日付
97 28 コメント
125 1 0(NULL)が格納
126 1 トラック番号
127 1 ジャンル番号
            //あらかじめバイト型の配列は用意しておいてください。
            Array.Copy(TagData, 0, TAG, 0, 3);
            Array.Copy(TagData, 3, Title, 0, 30);
            Array.Copy(TagData, 33, Artist, 0, 30);
            Array.Copy(TagData, 63, Album, 0, 30);
            Array.Copy(TagData, 93, Date, 0, 4);
            Array.Copy(TagData, 97, Comment, 0, 28);
            Array.Copy(TagData, 125, Zero, 0, 1);
            Array.Copy(TagData, 126, Track, 0, 1);
            Array.Copy(TagData, 127, Genre, 0, 1);
データの変換

あとは、必要なデータをByteToStrやByteToIntで変換してください。
ジャンルの名前を取得したい方は以下のコードを利用してください。

ジャンル

唯一厄介なのが、ジャンルが番号で与えられていることです。番号を取得したければそれで良いのですが
文字列として取得すると100以上のジャンルがあるのでかなり大変です。
なのでWikipediaから引用し、配列を作りました。ご自由にお使いください。

        public string[] Genres = new string[]
        {
            "ブルース",
            "Classic Rock",
            "カントリー",
            "ダンス",
            "ディスコ",
            "ファンク",
            "グランジ",
            "ヒップホップ",
            "ジャズ",
            "メタル",
            "ニューエイジ",
            "オールディーズ",
            "その他",
            "ポップ",
            "R&B",
            "ラップ",
            "レゲエ",
            "ロック",
            "テクノ",
            "Industrial",
            "オルタナティブ",
            "スカ",
            "デスメタル",
            "w:Pranks",
            "サウンドトラック",
            "Euro-Techno",
            "環境",
            "Trip-hop",
            "ボーカル",
            "Jazz+Funk",
            "フュージョン",
            "トランス",
            "クラシカル",
            "Instrumental",
            "Acid",
            "ハウス",
            "ゲームミュージック",
            "Sound Clip",
            "ゴスペル",
            "ノイズ",
            "Alt. Rock",
            "バス",
            "ソウル",
            "パンク",
            "Space",
            "Meditative",
            "Instrumental pop",
            "Instrumental rock",
            "フォークソング",
            "Gothic",
            "Darkwave",
            "Techno-Industrial",
            "Electronic",
            "Pop-Folk",
            "Eurodance",
            "Dream",
            "サザン・ロック",
            "喜劇",
            "Cult",
            "Gangsta",
            "Top ",
            "Christian Rap",
            "Pop/Funk",
            "Jungle",
            "Native American",
            "Cabaret",
            "ニューウェーブ",
            "Psychedelic",
            "Rave",
            "Showtunes",
            "Trailer",
            "Lo-Fi",
            "Tribal",
            "Acid Punk",
            "アシッドジャズ",
            "ポルカ",
            "Retro",
            "Musical",
            "Rock & Roll",
            "ハードロック",
            "フォーク",
            "フォークロック",
            "National Folk",
            "スウィング",
            "Fast Fusion",
            "ビバップ",
            "ラテン",
            "Revival",
            "Celtic",
            "ブルーグラス",
            "Avantgarde",
            "Gothic Rock",
            "プログレッシブ・ロック",
            "Psychedelic Rock",
            "Symphonic Rock",
            "Slow Rock",
            "Big Band",
            "Chorus",
            "Easy Listening",
            "アコースティック",
            "ユーモア",
            "Speech",
            "シャンソン",
            "オペラ",
            "Chamber Music",
            "ソナタ",
            "交響曲",
            "Booty Bass",
            "Primus",
            "Porn Groove",
            "Satire",
            "Slow Jam",
            "Club",
            "タンゴ",
            "Samba",
            "Folklore",
            "バラッド",
            "Power Ballad",
            "Rhythmic Soul",
            "Freestyle",
            "Duet",
            "パンク・ロック",
            "Drum Solo",
            "ア・カペラ",
            "Euro-House",
            "Dance Hall",
            "Goa",
            "ドラムンベース",
            "Club-House",
            "Hardcore",
            "Terror",
            "Indie",
            "ブリットポップ",
            "Negerpunk",
            "Polsk Punk",
            "Beat",
            "Christian gangsta rap",
            "ヘヴィメタル",
            "ブラックメタル",
            "クロスオーバー",
            "Contemporary Christian",
            "Christian Rock",
            "Merengue",
            "Salsa",
            "スラッシュメタル",
            "アニメ",
            "JPop",
            "Synthpop"
        };

終わりに

この記事が役に立った!という方は以下のボタンからぜひ読者になってください!
次回はID3v2およびv2.3のタグ取得方法を解説します。