FC2ブログ

ホーム > MP3ファイルフォーマット > ID3タグの書き込み(id3lib) 第1部

ID3タグの書き込み(id3lib) 第1部



ID3タグ編集用ライブラリ「id3lib-3.8.3」を使用して、ID3タグMP3ファイルに書き込む方法を解説します。尚ID3タグ編集用ライブラリ「id3lib-3.8.3」のインストールについては、id3libのインストールをご参照ください。




id3lib-3.8.3をインクルードするための定義です。

#include <id3.h>
#include <id3\tag.h>


タグフレーム内のフィールドに、文字列情報に対応する値を書き込むstdcall関数です。

//画像名文字列の設定
BOOL __stdcall _SetPictureName(const ID3_Frame* frame,CString& str)
{
ASSERT(frame);
ASSERT(frame->GetID()==ID3FID_PICTURE);
ID3_Field* field=frame->GetField(ID3FN_PICTURETYPE);
ASSERT(field);
if (!field) return FALSE;

int indexFind=g_FindPictureName(str);
if (indexFind<0) return FALSE;

field->Set(indexFind);
return TRUE;
}

//テキストエンコード文字列の取得
BOOL __stdcall _SetTextEncoding(const ID3_Frame* frame,ID3_FieldID fieldID,CString& str)
{
ASSERT(frame);
ID3_Field* fldEnc=frame->GetField(ID3FN_TEXTENC);
ASSERT(fldEnc);
if ((!fldEnc)||(!fldEnc->InScope(frame->GetSpec()))) return FALSE;

ID3_Field* field=frame->GetField(fieldID);
ASSERT(field);
if (!field) return FALSE;

int indexFind=g_FindTextEncoding(str);
if (indexFind<0) return FALSE;

fldEnc->Set((uint32)indexFind);
field->SetEncoding((ID3_TextEnc)indexFind);
return TRUE;
}

//内容タイプ文字列の設定
BOOL __stdcall _SetContentType(const ID3_Frame* frame,CString& str)
{
ASSERT(frame);
ID3_Field* field=frame->GetField(ID3FN_CONTENTTYPE);
ASSERT(field);
if (!field) return FALSE;

int indexFind=g_FindContentType(str);
if (indexFind<0) return FALSE;

field->Set(indexFind);
return TRUE;
}

//タイムスタンプフォーマット文字列の設定
BOOL __stdcall _SetTimeStampFormat(const ID3_Frame* frame,CString& str)
{
ASSERT(frame);
ID3_Field* field=frame->GetField(ID3FN_TIMESTAMPFORMAT);
ASSERT(field);
if (!field) return FALSE;

int indexFind=g_FindTimeStampFormat(str);
if (indexFind<0) return FALSE;

field->Set(indexFind+1);
return TRUE;
}

//Binaryデータの設定
BOOL __stdcall _SetBinaryData(const ID3_Frame* frame,CString& str)
{
ASSERT(frame);
ID3_Field* field=frame->GetField(ID3FN_DATA);
ASSERT(field);
if (!field) return FALSE;

size_t length=(size_t)str.GetAllocLength();
const uchar* binary=(const uchar*)str.GetBuffer();
size_t size=field->Set(binary,length);
if (size<length) return FALSE;
return TRUE;
}

//StringList文字列の設定
BOOL __stdcall _SetStringList(const ID3_Frame* frame,ID3_FieldID fieldID,CString& str,size_t index)
{
ASSERT(frame);
ID3_Field* field=frame->GetField(fieldID);
ASSERT(field);
if (!field) return FALSE;

size_t size=0;
ID3_TextEnc textEnc=field->GetEncoding();
if (textEnc==ID3TE_ISO8859_1){
//テキストエンコードがISO8859-1の場合。
CStringA strA=(CStringA)str;
size=(index==0)? field->Set((const char*)strA.GetBuffer()):
field->Add((const char*)strA.GetBuffer());
}
else{
field->SetEncoding(ID3TE_ASCII);
CStringA strA=(CStringA)str;
size=(index==0)? field->Set((const char*)strA.GetBuffer()):
field->Add((const char*)strA.GetBuffer());
field->SetEncoding(textEnc);
}
if (size!=str.GetLength()) return FALSE;
return TRUE;
}

//String文字列の設定
BOOL __stdcall _SetString(const ID3_Frame* frame,ID3_FieldID fieldID,CString& str)
{
return _SetStringList(frame,fieldID,str,0);
}


ID3タグを編集及び書き込むのためのCID3Tagクラスのメンバー関数です。

//新規フレームの挿入
// indexFrame<0:末尾に追加します。

BOOL CID3Tag::InsertFrameNew(int indexFrame,const char* FrameID)
{
if (!m_pID3Tag) return FALSE;
//引数のFrameIDを元に新規フレームを作成します。
ID3_FrameID eID=ID3_FindFrameID(FrameID);
ID3_Frame *frame=new ID3_Frame(eID);
ID3_V2Spec spec=m_pID3Tag->GetSpec();
frame->SetSpec(spec);
if (!_InsertFrame(indexFrame,frame)){
delete frame;
return FALSE;
}
return TRUE;
}

//指定フレームの挿入
// indexFrame<0:末尾に追加します。

BOOL CID3Tag::_InsertFrame(int indexFrame,ID3_Frame* frame)
{
ASSERT(m_pID3Tag);
//指定フレームをタグ末尾に追加します。
//フレーム番号がフレーム数の範囲内なら、
//新規フレームが正しい位置に来るように並び替えます。

size_t nframes=m_pID3Tag->NumFrames();
if ((indexFrame>=0)&&((UINT)indexFrame<nframes)){
CPtrArray listFrame;
for (UINT i=indexFrame;i<nframes;i++){
//指定番号のフレームを探します。
ID3_Frame* frame=_FindFrame(indexFrame);
if (!frame) break;
m_pID3Tag->RemoveFrame(frame);
listFrame.Add((void*)frame);
}
if (!m_pID3Tag->AttachFrame(frame)) return FALSE;
for (int i=0;i<listFrame.GetCount();i++)
m_pID3Tag->AttachFrame((ID3_Frame*)listFrame.GetAt(i));
}
else if (!m_pID3Tag->AttachFrame(frame)) return FALSE;
return TRUE;
}

//現在のID3タグから指定番号のフレームを抜き出します。
ID3_Frame* CID3Tag::_DetachFrame(UINT indexFrame)
{
ASSERT(m_pID3Tag);

//指定番号のフレームを探します。
ID3_Frame* frame=_FindFrame(indexFrame);
if (!frame) return FALSE;

//フレームをタグから切り離します。
m_pID3Tag->RemoveFrame(frame);
//タグにフレームが一つもない場合は、メンバー変数をすべて削除します。
if (!GetFrameCount()) Delete();
return frame;
}

//フレームの削除
BOOL CID3Tag::DeleteFrame(UINT indexFrame)
{
if (!m_pID3Tag) return FALSE;
ID3_Frame* frame=_DetachFrame(indexFrame);
if (!frame) return FALSE;

//フレームを削除します。
delete frame;
return TRUE;
}

//画像をファイルから読み込みます。
BOOL CID3Tag::LoadImage(LPCTSTR lpszPathName)
{
//ファイルからバイナリーデータを読み込みます。
CFile infile;
if (!infile.Open(lpszPathName,CFile::modeRead|CFile::shareDenyNone)) return FALSE;
UINT length=(UINT)infile.GetLength();
//メンバー変数のCByteArrayクラスに必要なメモリー領域を確保し、
//そのメモリーにデータ読み込みます。

CByteArray arrayImage;
arrayImage.SetSize(length);
BYTE* buffer=arrayImage.GetData();
UINT bytesRead=infile.Read(buffer,length);
infile.Close();
if (!bytesRead) return FALSE;

//ファイル形式の取得
CString strFileType;
if (!g_GetFileType(strFileType,buffer)) return FALSE;

void* dest=(void*)m_strBinary.GetBufferSetLength(length/sizeof(TCHAR));
::CopyMemory(dest,buffer,length);

m_strImmediate=strFileType;
return TRUE;
}

//id3タグの内容をファイル/指定メモリーに更新します。
BOOL CID3Tag::Update(CByteArray* pArrayID3Tag)
{
if (!m_pID3Tag){
pArrayID3Tag->RemoveAll();
return FALSE;
}
//CByteArrayクラスへのポインタが有効な場合。
if (AfxIsValidAddress(pArrayID3Tag,sizeof(CByteArray))){
//ID3v1タグの場合。
if (m_pID3Tag->HasV1Tag()){
//ID3v1タグの生データのサイズを取得します。
size_t size=m_pID3Tag->Size();
if (size<128) return FALSE;
//確保したメモリー領域に書き出します。
CByteArray arrayBuf;
arrayBuf.SetSize(size);
BYTE* buffer=arrayBuf.GetData();
size=m_pID3Tag->Render(buffer,ID3TT_ID3V1);
if (size<128) return FALSE;
pArrayID3Tag->SetSize(128);
::CopyMemory(pArrayID3Tag->GetData(),buffer,128);
}
//ID3v2タグの場合。
else {
//ID3v2タグの生データのサイズを取得します。
size_t size=m_pID3Tag->Size();
if (!size) return FALSE;
//確保したメモリー領域に書き出します。
CByteArray arrayBuf;
arrayBuf.SetSize(size+10);
BYTE* buffer=arrayBuf.GetData();

size=m_pID3Tag->Render(buffer,ID3TT_ID3V2);
if (!size) return FALSE;
//ID3V2タグサイズを算出します。
DWORD sizeTag=((buffer[6]&0x7F)<<21)|((buffer[7]&0x7F)<<14)|
((buffer[8]&0x7F)<< 7)|(buffer[9]&0x7F);
pArrayID3Tag->SetSize(sizeTag+10);
::CopyMemory(pArrayID3Tag->GetData(),buffer,sizeTag+10);
}
}
//ファイルからの読み込みで、CByteArrayクラスの指定が無い場合は
//ファイルを更新します。

else if(m_pID3Tag->GetFileName()) m_pID3Tag->Update();

return TRUE;
}


対象としているフレームの内容をメンバー変数文字列に設定してから、引数にフレーム番号を指定し、このSetFrame関数を呼び出してID3タグに書き込み、Update関数で引数に指定したCByteArrayクラス、もしくはファイルにID3タグの内容を書き出します。

//メンバー変数文字列を、指定位置のフレームに書き込みます。
BOOL CID3Tag::SetFrame(UINT indexFrame)
{
if (!m_pID3Tag) return FALSE;

//指定番号に該当する、フレームへのポインタを取得します。
ID3_Frame* frame=_FindFrame(indexFrame);
if (!frame) return FALSE;

#ifdef _UNICODE
CStringA strA=frame->GetDescription();
m_strTitle =strA;
strA=frame->GetTextID();
m_strID =strA;
#else //_UNICODE
m_strTitle =frame->GetDescription();
m_strID =frame->GetTextID();
#endif//_UNICODE
uint32 nCounter=0;
uint32 nRating=0;
uint32 nSymbol=0;

ID3_FrameID eFrameID=frame->GetID();
switch (eFrameID){
//一意的なファイル識別子
case ID3FID_UNIQUEFILEID: //UFID
if (!_SetString(frame,ID3FN_OWNER,m_strText)) return FALSE;
if (!_SetBinaryData(frame,m_strBinary)) return FALSE;
break;
//ユーザー定義文字情報フレーム
case ID3FID_USERTEXT: //TXXX
if (!_SetTextEncoding(frame,ID3FN_TEXT,m_strTextEnc)) return FALSE;
if (!_SetString(frame,ID3FN_DESCRIPTION,m_strDesc)) return FALSE;
if (!_SetString(frame,ID3FN_TEXT,m_strText)) return FALSE;
break;

//ユーザー定義URLリンクフレーム
case ID3FID_WWWUSER: //WXXX
if (!_SetTextEncoding(frame,ID3FN_DESCRIPTION,m_strTextEnc)) return FALSE;
if (!_SetString(frame,ID3FN_DESCRIPTION,m_strDesc)) return FALSE;
if (!_SetString(frame,ID3FN_URL,m_strText)) return FALSE;
break;

//音楽CD識別子
case ID3FID_CDID: //MCDI
if (!_SetBinaryData(frame,m_strBinary)) return FALSE;
break;

//イベント タイム コード
case ID3FID_EVENTTIMING: //ETCO
if (!_SetTimeStampFormat(frame,m_strTimeStamp)) return FALSE;
if (!_SetBinaryData(frame,m_strBinary)) return FALSE;
break;

//MPEG ロケーション ルックアップ テーブル(省略します)
case ID3FID_MPEGLOOKUP: //MLLT
ASSERT(FALSE);
break;
//同期テンポコード
case ID3FID_SYNCEDTEMPO: //SYTC
if (!_SetTimeStampFormat(frame,m_strTimeStamp)) return FALSE;
if (!_SetBinaryData(frame,m_strBinary)) return FALSE;
break;

//非同期の歌詞/文章のコピー
case ID3FID_UNSYNCEDLYRICS: //USLT
//コメント
case ID3FID_COMMENT: //COMM
if (!_SetTextEncoding(frame,ID3FN_TEXT,m_strTextEnc)) return FALSE;
if (!_SetString(frame,ID3FN_DESCRIPTION,m_strDesc)) return FALSE;
if (!_SetString(frame,ID3FN_TEXT,m_strText)) return FALSE;
if (!_SetString(frame,ID3FN_LANGUAGE,m_strImmediate)) return FALSE;
break;

//同期をとった歌詞/文章
case ID3FID_SYNCEDLYRICS: //SYLT
if (!_SetTextEncoding(frame,ID3FN_TEXT,m_strTextEnc)) return FALSE;
if (!_SetString(frame,ID3FN_LANGUAGE,m_strImmediate)) return FALSE;
if (!_SetTimeStampFormat(frame,m_strTimeStamp)) return FALSE;
if (!_SetContentType(frame,m_strDesc)) return FALSE;
if (!_SetString(frame,ID3FN_TEXT,m_strText)) return FALSE;
if (!_SetBinaryData(frame,m_strBinary)) return FALSE;
break;

//相対ボリューム(v2.3)
case ID3FID_VOLUMEADJ: //RVAD
//均一化
case ID3FID_EQUALIZATION: //EQUA
if (!_SetBinaryData(frame,m_strBinary)) return FALSE;
break;

//リバーブ量(省略します)
case ID3FID_REVERB: //RVRB
ASSERT(FALSE);
break;

//イメージ
case ID3FID_PICTURE: //APIC
if (!_SetTextEncoding(frame,ID3FN_DESCRIPTION,m_strTextEnc)) return FALSE;
if (!_SetString(frame,(m_strID==_T("APIC"))?ID3FN_MIMETYPE:ID3FN_IMAGEFORMAT,
m_strImmediate)) return FALSE;
if (!_SetString(frame,ID3FN_DESCRIPTION,m_strText)) return FALSE;
if (!_SetPictureName(frame,m_strPictureName)) return FALSE;
if (!_SetBinaryData(frame,m_strBinary)) return FALSE;
break;

//パッケージ化された一般的なオブジェクト
case ID3FID_GENERALOBJECT: //GEOB
if (!_SetTextEncoding(frame,ID3FN_TEXT,m_strTextEnc)) return FALSE;
if (!_SetString(frame,ID3FN_MIMETYPE,m_strImmediate)) return FALSE;
if (!_SetString(frame,ID3FN_DESCRIPTION,m_strDesc)) return FALSE;
if (!_SetString(frame,ID3FN_FILENAME,m_strText)) return FALSE;
if (!_SetBinaryData(frame,m_strBinary)) return FALSE;
break;

//再生回数
case ID3FID_PLAYCOUNTER: //PCNT
if (_stscanf(m_strText,_T("counter=%d"),nCounter)<1) return FALSE;
frame->GetField(ID3FN_COUNTER)->Set(nCounter);
break;

//人気
case ID3FID_POPULARIMETER: //POPM
if (!_SetString(frame,ID3FN_EMAIL,m_strDesc)) return FALSE;
if (_stscanf(m_strText,_T("counter=%d rating=%d"),nCounter,nRating)<2) return FALSE;
frame->GetField(ID3FN_COUNTER)->Set(nCounter);
frame->GetField(ID3FN_RATING)->Set(nRating);
break;

//おすすめバッファサイズ(省略します)
case ID3FID_BUFFERSIZE: //RBUF
//オーディオの暗号化(省略します)
case ID3FID_AUDIOCRYPTO: //AENC
ASSERT(FALSE);
break;

//同期位置フレーム
case ID3FID_POSITIONSYNC: //POSS
if (!_SetTimeStampFormat(frame,m_strTimeStamp)) return FALSE;
if (!_SetBinaryData(frame,m_strBinary)) return FALSE;
break;

//所有権フレーム(省略します)
case ID3FID_OWNERSHIP: //OWNE
ASSERT(FALSE);
break;

//暗号化の手法
case ID3FID_CRYPTOREG: //ENCR
//グループ識別子の登録
case ID3FID_GROUPINGREG: //GRID
if (!_SetString(frame,ID3FN_OWNER,m_strDesc)) return FALSE;
if (_stscanf(m_strText,_T("%02x"),&nSymbol)<1) return FALSE;
frame->GetField(ID3FN_ID)->Set(nSymbol);
if (!_SetBinaryData(frame,m_strBinary)) return FALSE;
break;

//プライベートデータ
case ID3FID_PRIVATE: //PRIV
if (!_SetString(frame,ID3FN_OWNER,m_strDesc)) return FALSE;
if (!_SetBinaryData(frame,m_strBinary)) return FALSE;
break;

//ジャンル
case ID3FID_CONTENTTYPE: //TCON
{
CStringA strA=m_strText;
int genre=g_FindGenreName(strA);
if (genre>-1) strA.Format("(%d)",genre);
m_strText=strA;
}
//テキスト情報フレーム
case ID3FID_ALBUM: //TALB
case ID3FID_BPM: //TBPM
case ID3FID_COMPOSER: //TCOM
case ID3FID_COPYRIGHT: //TCOP
case ID3FID_DATE: //TDAT
case ID3FID_PLAYLISTDELAY: //TDLY
case IID3FID_ENCODEDBY: //TENC
case ID3FID_LYRICIST: //TEXT
case ID3FID_FILETYPE: //TFLT
case ID3FID_TIME: //TIME
case ID3FID_CONTENTGROUP: //TIT1
case ID3FID_TITLE: //TIT2
case ID3FID_SUBTITLE: //TIT3
case ID3FID_INITIALKEY: //TKEY
case ID3FID_LANGUAGE: //TLAN
case ID3FID_SONGLEN: //TLEN
case ID3FID_MEDIATYPE: //TMED
case ID3FID_ORIGALBUM: //TOAL
case ID3FID_ORIGFILENAME: //TOFN
case ID3FID_ORIGLYRICIST: //TOLY
case ID3FID_ORIGARTIST: //TOPE
case ID3FID_ORIGYEAR: //TORY
case ID3FID_FILEOWNER: //TOWN
case ID3FID_LEADARTIST: //TPE1
case ID3FID_BAND: //TPE2
case ID3FID_CONDUCTOR: //TPE3
case ID3FID_MIXARTIST: //TPE4
case ID3FID_PARTINSET: //TPOS
case ID3FID_PUBLISHER: //TPUB
case ID3FID_TRACKNUM: //TRCK
case ID3FID_RECORDINGDATES: //TRDA
case ID3FID_NETRADIOSTATION://TRSN
case ID3FID_NETRADIOOWNER: //TRSO
case ID3FID_SIZE: //TSIZ
case ID3FID_ISRC: //TSRC
case ID3FID_ENCODERSETTINGS://TSSE
case ID3FID_YEAR: //TYER
if (!_SetTextEncoding(frame,ID3FN_TEXT,m_strTextEnc)) return FALSE;
if (!_SetString(frame, ID3FN_TEXT,m_strText)) return FALSE;
break;

//URL リンクフレーム
case ID3FID_WWWAUDIOFILE: //WOAF
case ID3FID_WWWARTIST: //WOAR
case ID3FID_WWWAUDIOSOURCE: //WOAS
case ID3FID_WWWCOMMERCIALINFO://WCOM
case ID3FID_WWWCOPYRIGHT: //WCOP
case ID3FID_WWWPUBLISHER: //WPUB
case ID3FID_WWWPAYMENT: //WPAY
case ID3FID_WWWRADIOPAGE: //WORS
if (!_SetString(frame,ID3FN_URL,m_strText)) return FALSE;
break;

//協力者
case ID3FID_INVOLVEDPEOPLE: //IPLS
{
if (!_SetTextEncoding(frame,ID3FN_TEXT,m_strTextEnc)) return FALSE;
CString str;
int iStart=0,index,length;
for(int i=0;;i++){
if ((index=m_strText.Find(',',iStart))<0)
index=m_strText.GetLength();
if ((length=index-iStart)<=0) break;
str=m_strText.Mid(iStart,length);
str.Trim();
iStart=index+1;
if (!_SetStringList(frame,ID3FN_TEXT,str,i)) return FALSE;
}
break;
}

//未知のフレーム
case ID3FID_NOFRAME: //???? No known frame
return FALSE;

//暗号化メタフレーム
case ID3FID_METACRYPTO: //CRM Encrypted meta frame (id3v2.2x)
//圧縮されたメタフレーム
case ID3FID_METACOMPRESSION://CDM Compressed meta frame (id3v2.2.1)
//その他
default:
ASSERT(FALSE);
break;

}
//正常終了
return TRUE;
}




スポンサーサイト



コメント: 0

この記事へのコメント
ブログ著者にのみ知らせます。

Trackback+Pingback: 0

TrackBack URL for this entry
http://hiroshi0945.blog75.fc2.com/tb.php/71-918338eb
Listed below are links to weblogs that reference
ID3タグの書き込み(id3lib) 第1部 from マルチメディアファイルフォーマット

Home > MP3ファイルフォーマット > ID3タグの書き込み(id3lib) 第1部

タグクラウド
ブロとも申請フォーム

この人とブロともになる

ブロとも一覧

このページの先頭へ戻る