FC2ブログ

ホーム > MP3ファイルフォーマット > MP3ファイルの書き込み 第2部

MP3ファイルの書き込み 第2部



ACMドライバーとそのドライバーがサポートしているフォーマットの中から、目的に一致したフォーマットを選択するために、CDialogクラスを基底クラスにしたCAcmDriverDlgを独自に定義しました。(AcmDriverDlg.h)

#pragma once

typedef struct HACMDRIVERID__ HACMDRIVERID__;
typedef HACMDRIVERID__ *HACMDRIVERID; //構造体の型のみ宣言しておきます。
typedef struct tWAVEFORMATEX tWAVEFORMATEX;
typedef tWAVEFORMATEX WAVEFORMATEX;

class CMP3File;

class CAcmDriverDlg : public CDialog
{
DECLARE_DYNAMIC(CAcmDriverDlg)

public:
CAcmDriverDlg(CMP3File* pMP3File,WORD wFormatTag,CWnd* pParent = NULL); // standard constructor
virtual ~CAcmDriverDlg();

// Dialog Data
enum { IDD = IDD_DIALOG_ACMDRIVER };

protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

DECLARE_MESSAGE_MAP()
public:
virtual BOOL OnInitDialog();
protected:
virtual void OnOK();
private:
CMP3File* m_pMP3File; //対象とするCMP3Fileクラスへのポインタ

//コントロール変数
CComboBox m_comboFormatTag; //フォーマットタグ選択コンボ
CComboBoxEx m_comboexDriver; //ドライバー選択コンボ
CImageList m_listIcon; //ドライバーアイコン格納用イメージリスト
CListBox m_listFormatDetails; //フォーマットの詳細リストボックス
CListBox m_listFormatTagSupport;//フォーマットタグサポートリストボックス
public:
//ドライバー詳細表示エディットボックス用コントロール変数
CString m_strLongName;
CString m_strShortName;
CString m_strCopyRight;
CString m_strLicense;
CString m_strFeature;
CString m_strManuID;
CString m_strProductID;
CString m_strVersion;
CString m_strPriority;
CString m_strNFormatTag;
//選択結果を親に引渡すためのメンバー変数
HACMDRIVERID m_hadid; //ドライバーID
WORD m_wFormatTag; //フォーマットタグ
DWORD m_dwFormatIndex;//フォーマット番号
WAVEFORMATEX* m_pwfxDst; //WAVEFORMATEX構造体
int m_iFormatSize; //上記構造体のサイズ

private:
//ドライバー選択コンボの選択項目変更時のイベント関数
afx_msg void OnCbnSelchangeComboboxexDriver();
//フォーマットタグ選択コンボの選択項目変更時のイベント関数
afx_msg void OnCbnSelchangeComboFormattag();
//フォーマットタグサポートリストボックスの選択項目変更時のイベント関数
afx_msg void OnLbnSelchangeListFormattagSupport();
};


CAcmDriverDlgクラスのソースファイルです。(AcmDriverDlg.cpp)

// AcmDriverDlg.cpp : implementation file
//


#include "stdafx.h"
#include "MP3FileTest.h"
#include "AcmDriverDlg.h"
#include ".\acmdriverdlg.h"

#include "MP3File.h"

// CAcmDriverDlg dialog

IMPLEMENT_DYNAMIC(CAcmDriverDlg, CDialog)

CAcmDriverDlg::CAcmDriverDlg(CMP3File* pMP3File,WORD wFormatTag,CWnd* pParent /*=NULL*/)
: CDialog(CAcmDriverDlg::IDD, pParent)
, m_strLongName(_T(""))
, m_strShortName(_T(""))
, m_strCopyRight(_T(""))
, m_strLicense(_T(""))
, m_strFeature(_T(""))
, m_strManuID(_T(""))
, m_strProductID(_T(""))
, m_strVersion(_T(""))
, m_strPriority(_T(""))
, m_strNFormatTag(_T(""))
{
m_wFormatTag=WAVE_FORMAT_UNKNOWN;
ASSERT(AfxIsValidAddress(pMP3File,sizeof(CMP3File)));
m_pMP3File=pMP3File;
m_wFormatTag=wFormatTag;
m_hadid=0;
//CMP3FileクラスのドライバーIDを取得します。
HACMDRIVERID hadidEnc,hadidDec;
m_pMP3File->GetDriverID(&hadidEnc,&hadidDec);
//引数のフォーマットタグがWAVE_FORMAT_PCMの場合は、
//デコード用、それ以外はエンコード用ドライバーIDを格納します。

m_hadid=(m_wFormatTag==WAVE_FORMAT_PCM)? hadidDec:hadidEnc;
m_pwfxDst=NULL;
}

CAcmDriverDlg::~CAcmDriverDlg()
{
delete[]m_pwfxDst;
}

void CAcmDriverDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_COMBO_FORMATTAG, m_comboFormatTag);
DDX_Control(pDX, IDC_COMBOBOXEX_DRIVER, m_comboexDriver);
DDX_Text(pDX, IDC_EDIT_LONGNAME, m_strLongName);
DDX_Text(pDX, IDC_EDIT_SHORTNAME, m_strShortName);
DDX_Text(pDX, IDC_EDIT_COPYRIGHT, m_strCopyRight);
DDX_Text(pDX, IDC_EDIT_LICENSE, m_strLicense);
DDX_Text(pDX, IDC_EDIT_FEATURE, m_strFeature);
DDX_Text(pDX, IDC_EDIT_MANUFACTURER_ID, m_strManuID);
DDX_Text(pDX, IDC_EDIT_PRODUCT_ID, m_strProductID);
DDX_Text(pDX, IDC_EDIT_ASMVERSION, m_strVersion);
DDX_Text(pDX, IDC_EDIT_PRIORITY, m_strPriority);
DDX_Text(pDX, IDC_EDIT_FORMATTAG, m_strNFormatTag);
DDX_Control(pDX, IDC_LIST_FORMATDETAILS, m_listFormatDetails);
DDX_Control(pDX, IDC_LIST_FORMATTAG_SUPPORT, m_listFormatTagSupport);
}


BEGIN_MESSAGE_MAP(CAcmDriverDlg, CDialog)
ON_CBN_SELCHANGE(IDC_COMBOBOXEX_DRIVER, OnCbnSelchangeComboboxexDriver)
ON_CBN_SELCHANGE(IDC_COMBO_FORMATTAG, OnCbnSelchangeComboFormattag)
ON_LBN_SELCHANGE(IDC_LIST_FORMATTAG_SUPPORT, OnLbnSelchangeListFormattagSupport)
END_MESSAGE_MAP()

// CAcmDriverDlg message handlers

BOOL CAcmDriverDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// TODO: Add extra initialization here

//フォーマットタグ番号を0にします。
m_dwFormatIndex=0;

WAVEFORMATEX wfx={0};
m_pMP3File->GetWaveFormatEx(&wfx,0);
//ドライバーIDリストの取得
ASSERT(AfxIsValidAddress(m_pMP3File,sizeof(CMP3File)));
CObArray listHadid;
_GetAcmDriverIDList(listHadid);
int nCount=(int)listHadid.GetCount();
if (!nCount) return FALSE;

//イメージリストの作成
m_listIcon.Create(16,16,ILC_COLOR32|ILC_MASK,nCount,0);
m_comboexDriver.SetImageList(&m_listIcon);

//ドライバー選択コンボの作成
int cursel=-1;
int curselFormat=-1;
int iItem=0;
for (int i=0;i<nCount;i++){
ACMDRIVERDETAILS add={0};
add.cbStruct=sizeof(ACMDRIVERDETAILS);
HACMDRIVERID hadid=(HACMDRIVERID)listHadid.GetAt(i);
MMRESULT mmr=::acmDriverDetails(hadid,&add,0);
if (mmr!=MMSYSERR_NOERROR) return FALSE;
int indexImage=m_listIcon.Add(add.hicon);
//ドライバー選択コンボにアイテムを挿入します。
COMBOBOXEXITEM exItem={0};
exItem.mask=CBEIF_IMAGE|CBEIF_SELECTEDIMAGE|CBEIF_TEXT|CBEIF_LPARAM;
exItem.iItem=i;
exItem.iImage=indexImage;
exItem.iSelectedImage=indexImage;
exItem.pszText=add.szShortName;
exItem.lParam=(LPARAM)hadid;
if (m_comboexDriver.InsertItem(&exItem)==-1) return FALSE;
//ドライバーIDの初期値と一致する場合は、
//ドライバー選択コンボのカーセルを設定します。

if (hadid==m_hadid) cursel=i;
HACMDRIVER hDriver=NULL;
::acmDriverOpen(&hDriver,hadid,0);
//すべてのドライバーのフォーマットタグ名を抽出して、
//フォーマットタグ選択コンボを作成します。

for(UINT j=0;j<add.cFormatTags;j++){
ACMFORMATTAGDETAILS aftd={0};
aftd.cbStruct=sizeof(ACMFORMATTAGDETAILS);
aftd.dwFormatTagIndex=j;
aftd.dwFormatTag =WAVE_FORMAT_UNKNOWN;
aftd.fdwSupport =0;
::acmFormatTagDetails(hDriver,&aftd,ACM_FORMATTAGDETAILSF_INDEX);
//フォーマットタグ選択コンボの内容と重複していないか確かめます。
BOOL bFind=FALSE;
for(int k=0;k<iItem;k++){
if (aftd.dwFormatTag==m_comboFormatTag.GetItemData(k)){
bFind=TRUE;
break;
}
}
//重複してないタグ名をフォーマットタグ選択コンボに挿入します。
if (!bFind){
//フォーマットタグの初期値と一致する場合は、
//フォーマットタグ選択コンボのカーセルを設定します。

if (aftd.dwFormatTag==m_wFormatTag) curselFormat=iItem;
m_comboFormatTag.InsertString(iItem,aftd.szFormatTag);
m_comboFormatTag.SetItemData(iItem,aftd.dwFormatTag);
iItem++;
}
}
::acmDriverClose(hDriver, 0);
}
m_comboexDriver.SetCurSel(cursel);
m_comboFormatTag.SetCurSel(curselFormat);
//ドライバー選択コンボの選択項目変更時のイベント関数を呼び出して、
//選択されたドライバーの詳細データと、フォーマットタグの内容に合わせるために
//各コントロールの内容を設定します。

OnCbnSelchangeComboboxexDriver();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE

}

void CAcmDriverDlg::OnOK()
{
// TODO: Add your specialized code here and/or call the base class
UpdateData(TRUE);
//選択されたドライバーIDを取得します。
int cursel=m_comboexDriver.GetCurSel();
if (cursel>-1) m_hadid=(HACMDRIVERID)m_comboexDriver.GetItemData(cursel);
//選択されたフォーマットタグを取得します。
cursel=m_listFormatTagSupport.GetCurSel();
if (cursel>-1) m_wFormatTag=(WORD)m_listFormatTagSupport.GetItemData(cursel);
//選択されたフォーマットタグ番号を取得します。
m_dwFormatIndex=m_listFormatDetails.GetCurSel();

//選択されたフォーマットタグ番号に合致するWAVEFORMAT構造体を取得します。
m_iFormatSize=0;
::acmMetrics(NULL,ACM_METRIC_MAX_SIZE_FORMAT,&m_iFormatSize);
if ((m_iFormatSize)&&((int)m_dwFormatIndex>-1)){
m_pwfxDst=(LPWAVEFORMATEX)(new BYTE[m_iFormatSize]);
::ZeroMemory(m_pwfxDst,m_iFormatSize);
_GetAcmDriverWaveFormat(m_hadid,m_wFormatTag,m_dwFormatIndex,m_pwfxDst,m_iFormatSize);
}
CDialog::OnOK();
}

//ドライバー選択コンボの選択項目変更時のイベント関数
void CAcmDriverDlg::OnCbnSelchangeComboboxexDriver()
{
// TODO: Add your control notification handler code here
int cursel=m_comboexDriver.GetCurSel();
if (cursel==-1) return;

HACMDRIVERID hadid=(HACMDRIVERID)m_comboexDriver.GetItemData(cursel);

//選択されたドライバーIDの詳細データを、各エディットボックスに書き込みます。
ACMDRIVERDETAILS add={0};
add.cbStruct=sizeof(ACMDRIVERDETAILS);
MMRESULT mmr=::acmDriverDetails(hadid,&add,0);
if (mmr!=MMSYSERR_NOERROR) return;
m_strLongName=add.szLongName;
m_strShortName=add.szShortName;
m_strCopyRight=add.szCopyright;
m_strLicense=add.szLicensing;
m_strFeature=add.szFeatures;
m_strManuID.Format(_T("%d"),add.wMid);
m_strProductID.Format(_T("%d"),add.wPid);
m_strVersion.Format(_T("%d.%d.%d"),(add.vdwDriver>>24),(add.vdwDriver>>16)&0xFF,add.vdwDriver&0xFFFF);
DWORD dwPriority=0;
::acmMetrics((HACMOBJ)hadid,ACM_METRIC_DRIVER_PRIORITY,&dwPriority);
m_strPriority.Format(_T("%d"),dwPriority);
m_strNFormatTag.Format(_T("%d"),add.cFormatTags);

//選択されたドライバーを開きます。
HACMDRIVER hDriver=NULL;
::acmDriverOpen(&hDriver,hadid,0);

//フォーマットタグサポートリストボックスと
//フォーマットの詳細リストボックスの内容を削除します。

m_listFormatTagSupport.ResetContent();
m_listFormatDetails.ResetContent();


//サポートしているフォーマットタグの詳細を調べます。
for(UINT i=0;i<add.cFormatTags;i++){
ACMFORMATTAGDETAILS aftd={0};
aftd.cbStruct=sizeof(ACMFORMATTAGDETAILS);
aftd.dwFormatTagIndex=i;
aftd.dwFormatTag =WAVE_FORMAT_UNKNOWN;
aftd.fdwSupport =0;
::acmFormatTagDetails(hDriver,&aftd,ACM_FORMATTAGDETAILSF_INDEX);

//サポートしているフォーマットタグ名をリストボックスに挿入します。
CString strFormatTagSupport;
strFormatTagSupport.Format(_T("%s(%#04x)"),aftd.szFormatTag,aftd.dwFormatTag);
m_listFormatTagSupport.InsertString(i,strFormatTagSupport);
m_listFormatTagSupport.SetItemData(i,aftd.dwFormatTag);

//選択されたフォーマットタグと一致する場合。
int cursel=m_comboFormatTag.GetCurSel();
if ((cursel>-1)&&
(m_comboFormatTag.GetItemData(cursel)==aftd.dwFormatTag))
{
m_listFormatTagSupport.SetCurSel(i);
DWORD dwSize=0;
::acmMetrics(NULL,ACM_METRIC_MAX_SIZE_FORMAT,&dwSize);
LPWAVEFORMATEX pwfxSrc=(LPWAVEFORMATEX)(new BYTE[dwSize]);
LPWAVEFORMATEX pwfxDst=(LPWAVEFORMATEX)(new BYTE[dwSize]);
switch(aftd.dwFormatTag){
case WAVE_FORMAT_MPEGLAYER3:
if (m_wFormatTag==WAVE_FORMAT_PCM)
//フォーマットタグの初期値がデコードの場合は、
//CMP3Fileクラスからデコード用フォーマットを取得します。

m_pMP3File->GetMpegLayer3WaveFormat(0,(MPEGLAYER3WAVEFORMAT*)pwfxSrc);
else
//エンコードの場合は、CMP3Fileクラスからエンコード用フォーマットを取得します。
m_pMP3File->GetMpegLayer3WaveFormat((MPEGLAYER3WAVEFORMAT*)pwfxSrc,0);
break;
case WAVE_FORMAT_PCM:
default:
//WAVE再生用のフォーマットを取得します。
m_pMP3File->GetWaveFormatEx(pwfxSrc,0);
break;
}
int cursel=-1;
//フォーマット詳細リストボックスに、フォーマット内容テキストを入力します。
for (UINT j=0;j<aftd.cStandardFormats;j++){
::ZeroMemory(pwfxDst,dwSize);
ACMFORMATDETAILS afd={0};
afd.cbStruct =sizeof(ACMFORMATDETAILS);
afd.dwFormatIndex =j;
afd.dwFormatTag =aftd.dwFormatTag;
afd.fdwSupport =0;
afd.pwfx =pwfxDst;
afd.cbwfx =dwSize;
::acmFormatDetails(hDriver,&afd,ACM_FORMATDETAILSF_INDEX);
m_listFormatDetails.InsertString(j,afd.szFormat);
//カーセル位置が未定義の場合は、適当な位置を検索します。
if (cursel==-1){
switch(aftd.dwFormatTag){
case WAVE_FORMAT_PCM://WAVE音源にデコードする場合。
//周波数、チャンネル数、ビット数/サンプルが一致する場合は、
//フォーマット詳細リストボックスのカーセルを設定します。

if ((pwfxDst->nSamplesPerSec==pwfxSrc->nSamplesPerSec)&&
(pwfxDst->nChannels==pwfxSrc->nChannels)&&
(pwfxDst->wBitsPerSample==pwfxSrc->wBitsPerSample))
cursel=j;
break;
case WAVE_FORMAT_MPEGLAYER3://MP3にエンコードする場合。
//周波数、チャンネル数、平均バイト数/秒が一致する場合は、
//フォーマット詳細リストボックスのカーセルを設定します。

if ((pwfxDst->nSamplesPerSec==pwfxSrc->nSamplesPerSec)&&
(pwfxDst->nChannels==pwfxSrc->nChannels)&&
(pwfxDst->nAvgBytesPerSec==pwfxSrc->nAvgBytesPerSec))
cursel=j;
break;
}
}
}
if (cursel==-1) cursel=0;
m_listFormatDetails.SetCurSel(cursel);
delete[]pwfxSrc;
delete[]pwfxDst;
}
}
//ドライバーを閉じます。
::acmDriverClose(hDriver, 0);

UpdateData(FALSE);
}

//フォーマットタグ選択コンボの選択項目変更時のイベント関数
void CAcmDriverDlg::OnCbnSelchangeComboFormattag()
{
// TODO: Add your control notification handler code here
int cursel=m_comboFormatTag.GetCurSel();
if (cursel==-1) return;
//ドライバー選択コンボの選択項目変更時のイベント関数を呼び出します。
OnCbnSelchangeComboboxexDriver();
}

//フォーマットタグサポートリストボックスの選択項目変更時のイベント関数
void CAcmDriverDlg::OnLbnSelchangeListFormattagSupport()
{
// TODO: Add your control notification handler code here
//フォーマットタグサポートリストボックスの選択された項目内容に、
//フォーマットタグ選択コンボの選択内容を一致させます。

int cursel=m_listFormatTagSupport.GetCurSel();
if (cursel>-1){
DWORD dwFormatTag=(DWORD)m_listFormatTagSupport.GetItemData(cursel);
cursel=-1;
for(int i=0;i<m_comboFormatTag.GetCount();i++){
if (dwFormatTag==m_comboFormatTag.GetItemData(i)){
cursel=i;
break;
}
}
}
m_comboFormatTag.SetCurSel(cursel);

//ドライバー選択コンボの選択項目変更時のイベント関数を呼び出します。
OnCbnSelchangeComboboxexDriver();
}


CAcmDriverDlgクラスの起動と引数引渡しの例です。

//ACMドライバー変更項目選択時のイベント関数
void CMP3FileTestDlg::OnToolAcmdriver()
{
// TODO: Add your command handler code here
CAcmDriverDlg dlg(m_pSound,WAVE_FORMAT_PCM,this);
if ((dlg.DoModal()==IDOK)&&(dlg.m_hadid)){
//デコード用ドライバーを設定する場合。
if (dlg.m_wFormatTag==WAVE_FORMAT_PCM){
//演奏状態を保存します。
BOOL bActivate=m_pSound->IsActivate();
BOOL bPaused=m_pSound->IsPaused();
UINT uPos=m_pSound->GetPos();
m_pSound->SetDriverID((HACMDRIVERID)-1,dlg.m_hadid);
//再生準備をします。
OnCbnSelchangeComboFilename(FALSE);
//再生位置を設定します。
m_pSound->SetPos(uPos);
//再生中だった場合は、再生を開始します。
if (bActivate) OnBnClickedButtonPlay();
//一時停止中だった場合は、一時停止します。
if (bPaused) OnBnClickedButtonPlay();
}
//エンコード用ドライバーを設定する場合。
else{
m_pSound->SetDriverID(dlg.m_hadid,(HACMDRIVERID)-1);
m_pSound->SetMpegLayer3WaveFormat((MPEGLAYER3WAVEFORMAT*)dlg.m_pwfxDst);
}
}
}


CAcmDriverDlgクラスを呼び出すと、「ACMドライバーの設定」ダイヤログが表示されます。



ACMドライバーを変更する場合は、「フォーマットの選択」コンボで、エンコードするか(MPEG Layer3)、デコードするか(PCM)を選択してから、「ドライバーの選択」コンボで選択し、同時に「フォーマットタグサポート」に目的のフォーマットがあるかどうか確認します。
ドライバーのエンコードフォーマットを設定する場合は、「フォーマットの詳細」リストボックスで目的のフォーマットを選択します。但し、入力するWAVE音源データの周波数より高いフォーマットを選択した場合は、エンコード出来ないのでご注意ください。

サンプルプログラム(VisualC++net2003ソリューション)MP3FileTest04.zip

上記のzipファイルをダウンロードしてからWinRAR等で解凍し、「MP3FileTest04」フォルダー内にある「MP3FileTest.sln」を開きます。
「F5」キーを押すと、ビルド確認のダイヤログが表示されるので「Yes」を選択してソリューションをビルドします。



ビルドが終わると直ちにプログラムが自動起動して下の図にあるダイヤログが表示されます。



パソコン本体のCDROMドライブに音楽CDを入れてCDROMドライブのドアをクローズし、ダイヤログにある「CDDA」ボタンをクリックするとCDが読み込まれてトラック1から再生されます。
(※この時ウィンドウズのCDROMドライブのAUTOPLAY機能は解除しておいて下さい。)

CDテキストがない場合、ダイヤログのタイトルバーは「CDDAFileTest」のままで、曲名はトラック1から順に「Track??.cdda」と表示されますが、freeDBからのCDDBの読み込みに成功すると、ドロップダウンリストにCD内の全ての曲名が登録され、その内容からID3v1/v2タグを自動作成し、「MP3のプロパティ」ダイヤログの下段にあるリストビューに表示します。



メニューから「ファイル」/「CDの一括保存...」を選択し、「書き込みの設定」ダイヤログを表示させます。



「書き込む場所」、「フォルダー名」、「曲名チェックボックス」、「曲名」等を確認/変更してから、「保存ファイル形式」は「MP3ファイル」を選択して、「適用する」ボタンを押すと、「ACMドライバーの設定」ダイヤログが表示されます。



ドライバーに「LAME MP3」を選択し、フォーマットは「44100Hz,128 kbps CBR, Stereo」を選択して「適用する」ボタンを押すと、一括保存シーケンスが開始されます。



「曲名チェックボックス」にチェックのあった全てのトラックの保存が終了すると、一番最初に保存したMP3ファイルに戻ってから、また順に再生が始まります。



「MP3のプロパティ」ダイヤログで、作成されたMP3ファイルのビットレート/フレームサイズ等のスペック値と、作成されたID3タグの内容を確認してください。尚上図中において、ID3v1タグにおける曲名の文字化けは、2バイト文字は受け付けられないためです。

<<MP3ファイルの書き込み 第1部ページの先頭id3libのインストール>>


スポンサーサイト



コメント: 0

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

Trackback+Pingback: 0

TrackBack URL for this entry
http://hiroshi0945.blog75.fc2.com/tb.php/65-6d9b7108
Listed below are links to weblogs that reference
MP3ファイルの書き込み 第2部 from マルチメディアファイルフォーマット

Home > MP3ファイルフォーマット > MP3ファイルの書き込み 第2部

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

この人とブロともになる

ブロとも一覧

このページの先頭へ戻る