Exemple #1
0
/*-------------------------------------------------------------*/
BOOL MPEGHeader::ReadHeader(BYTE *pData, int nSize, int* pnOffset)
{
	unsigned int	i=0;
	BOOL bValidHeader=FALSE;

	while (i<(nSize-sizeof(m_RawMPEGHeader)))
	{
		// Copy header bytes
		memcpy(&m_RawMPEGHeader,&pData[i],sizeof(m_RawMPEGHeader));

		// Check Header
		if (m_RawMPEGHeader.FrameSyncH==0xFF && m_RawMPEGHeader.FrameSyncL==0x0F)
		{
			// we found it
			bValidHeader=TRUE;
			break;
		}

		i++;
	}

	// check if we have found a valid header
	if (bValidHeader==FALSE)
	{
		ASSERT(FALSE);
		return FALSE;
	}

	pData+=i;

	// set the offset if possible
	if (pnOffset)
	{
		*pnOffset=i;
	}

	// get Xing header data
	m_nFlags = 0;     // clear to null incase fail

	// Set SampleRate
	m_nSampleRate= MPEGSamplerates[1-m_RawMPEGHeader.Version][m_RawMPEGHeader.SampleRateIndex];

	// Set BitRate
	m_nBitRate= MPEGBitrates[1-m_RawMPEGHeader.Version][3-m_RawMPEGHeader.Layer][m_RawMPEGHeader.BitRateIndex];

	// Set Frame Size
	CalcFrameSize();


	// Determine offset of header
	if( m_RawMPEGHeader.Version==MPEG_I ) 
	{
		// MPEG-I
		if( m_RawMPEGHeader.ChannelMode != 3 )
		{
			// MONO
			pData+=(32+4);
		}
		else
		{
			// STEREO, DUAL-CHANNEL or JOINT-STEREO
			pData+=(17+4);
		}
	}
	else
	{
		// MPEG-II
		if( m_RawMPEGHeader.ChannelMode != 3 )
		{
			// MONO
			pData+=(17+4);
		}
		else
		{
			// STEREO, DUAL-CHANNEL or JOINT-STEREO
			pData+=(9+4);
		}
	}

	// Check for Xing Tag 
	if( pData[0] != 'X' ) return TRUE;
	if( pData[1] != 'i' ) return TRUE;
	if( pData[2] != 'n' ) return TRUE;
	if( pData[3] != 'g' ) return TRUE;
	pData+=4;

	m_nFlags= ExtractI4(pData);
	pData+=4;

	if( m_nFlags & FRAMES_FLAG )
	{
		m_nFrames= ExtractI4(pData); pData+=4;
	}

	if( m_nFlags & BYTES_FLAG )
	{
		m_nBytes= ExtractI4(pData); pData+=4;
	}

	if( m_nFlags & TOC_FLAG )
	{
		// Get the first 100 bytes
		for(i=0;i<100;i++)
			m_btToc[i] = pData[i];

		// Increase buffer
		pData+=100;
	}

	if( m_nFlags & VBR_SCALE_FLAG )
	{
		m_nVbrScale = ExtractI4(pData); pData+=4;
	}

#ifdef DEBUG_SHOW_TOC
	for(i=0;i<100;i++)
	{
		if( (i%10) == 0 ) printf("\n");
		{
			LTRACE( _T( " %3d" ), m_btToc[ i ] );
		}
	}
#endif

	// This is a valid Xing Header
	m_bIsXingHeader=TRUE;

	return TRUE;
}
Exemple #2
0
BOOL CMp3Info::Load(const TCHAR *szFileName,BOOL bVbrScan)
{
    DWORD dwBeginPtr;
    unsigned char			hbuf[4];
    static unsigned long	head;
    unsigned char			xingTag[4+12+100];
    unsigned char			id3tag[128];
    //XING VBR ヘッダで使用
    const unsigned long FRAMES_FLAG		= 0x0001;
    const unsigned long BYTES_FLAG		= 0x0002;
    const unsigned long TOC_FLAG		= 0x0004;
    const unsigned long VBR_SCALE_FLAG	= 0x0008;

    Release();

    long lDataPtr = 0;	//mp3ストリームの開始位置
    ULONG dataSize = 0;
    //RMP形式のストリームサイズを取得する==========================
    CFile f;
    f.Open(szFileName,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::shareDenyNone,NULL);
//	HMMIO hmmio = mmioOpen((char*)szFileName,NULL,MMIO_COMPAT);
//	if(hmmio)
    {
        //RMP3ファイルの確認
        char hdr[4];
//		LONG ret = mmioRead(hmmio,hdr,sizeof(hdr));
        LONG ret = f.Read(hdr,sizeof(hdr));
        if((ret == 4) && (hdr[0] == 'R') && (hdr[1] == 'I') && (hdr[2] == 'F') && (hdr[3] == 'F'))
        {
//			mmioSeek(hmmio,0,SEEK_SET);
            //RMP3チャンクへ移動
//			MMCKINFO	mmckOutinfoParent;
//			memset(&mmckOutinfoParent,0,sizeof(mmckOutinfoParent));
//			mmckOutinfoParent.fccType = mmioFOURCC('R','M','P','3');
            char buf[256];
            f.SeekToBegin();
            f.Read(buf,256);
            int i;
            for(i=0; i<250; i++) {
                if(buf[i]=='R' || buf[i+1]=='M' || buf[i+2]=='P' || buf[i+3]=='3') break;
            }
            if(i!=250)
//			if(mmioDescend(hmmio,&mmckOutinfoParent,NULL,MMIO_FINDRIFF) == MMSYSERR_NOERROR)
            {
                //dataチャンクへ移動
//				MMCKINFO	mmckOutinfoSubchunk;
//				memset(&mmckOutinfoSubchunk,0,sizeof(mmckOutinfoSubchunk));
//				mmckOutinfoSubchunk.fccType = mmioFOURCC('d','a','t','a');
                for(i=0; i<250; i++) {
                    if(buf[i]=='d' || buf[i+1]=='a' || buf[i+2]=='t' || buf[i+3]=='a') break;
                }
                if(i!=250)
//				if(mmioDescend(hmmio,&mmckOutinfoSubchunk,&mmckOutinfoParent,MMIO_FINDCHUNK) == MMSYSERR_NOERROR)
                {
//					lDataPtr = mmioSeek(hmmio,0,SEEK_CUR);
                    lDataPtr = i+4;
                    i+=4;
//					dataSize = mmckOutinfoSubchunk.cksize; //ストリームサイズを取得
                    dataSize = (int)(BYTE)buf[i]+(int)(BYTE)buf[i+1]*256+(int)(BYTE)buf[i+2]*65536+(int)(BYTE)buf[i+3]*256*65536;
                }
            }
        }
//		mmioClose(hmmio,0);
    }
    f.Close();

    DWORD dwRet;
    HANDLE hFile = CreateFile(
                       szFileName,
                       GENERIC_READ,
                       FILE_SHARE_READ,
                       NULL,
                       OPEN_EXISTING,			//指定したファイルが存在していない場合、この関数は失敗します。
                       FILE_ATTRIBUTE_NORMAL,
                       NULL);
    if(hFile == INVALID_HANDLE_VALUE)
    {
        return FALSE;
    }

    if(dataSize == 0)
    {
        filesize=dataSize = GetFileSize(hFile,NULL);
        //id3tagヘッダを読み込む
        SetFilePointer(hFile,-128,NULL,FILE_END);
        if(!ReadFile(hFile,&id3tag,sizeof(id3tag),&dwRet,NULL))
        {
            CloseHandle(hFile);
            return FALSE;
        }
        if((dwRet == sizeof(id3tag)) && (memcmp(id3tag,"TAG",3) == 0))
        {
            //ID3TAGのサイズ分を差し引く
            dataSize -= 128;
        }
    }
    //ID3V2ヘッダを読み込む
    char id3v2head[10];
    SetFilePointer(hFile,0,NULL,FILE_BEGIN);
    if(ReadFile(hFile,&id3v2head,sizeof(id3v2head),&dwRet,NULL) &&
            (dwRet == sizeof(id3v2head)) &&
            (memcmp(id3v2head,"ID3",3) == 0) )
    {
        lDataPtr = (((long )(id3v2head[6]&0x7f)<<21) | ((long )(id3v2head[7]&0x7f)<<14) | ((long )(id3v2head[8]&0x7f)<<7) | (long )(id3v2head[9]&0x7f));
        lDataPtr += 10;
    }
    SetFilePointer(hFile,lDataPtr,NULL,FILE_BEGIN);
    if(ReadFile(hFile,&id3v2head,sizeof(id3v2head),&dwRet,NULL) &&
            (dwRet == sizeof(id3v2head)) &&
            (memcmp(id3v2head,"ID3",3) == 0) )
    {
        lDataPtr += (((long )(id3v2head[6]&0x7f)<<21) | ((long )(id3v2head[7]&0x7f)<<14) | ((long )(id3v2head[8]&0x7f)<<7) | (long )(id3v2head[9]&0x7f));
        lDataPtr += 10;
    }
    SetFilePointer(hFile,lDataPtr,NULL,FILE_BEGIN);
    if(ReadFile(hFile,&id3v2head,sizeof(id3v2head),&dwRet,NULL) &&
            (dwRet == sizeof(id3v2head)) &&
            (memcmp(id3v2head,"ID3",3) == 0) )
    {
        lDataPtr += (((long )(id3v2head[6]&0x7f)<<21) | ((long )(id3v2head[7]&0x7f)<<14) | ((long )(id3v2head[8]&0x7f)<<7) | (long )(id3v2head[9]&0x7f));
        lDataPtr += 10;
    }
    SetFilePointer(hFile,lDataPtr,NULL,FILE_BEGIN);
    if(ReadFile(hFile,&id3v2head,sizeof(id3v2head),&dwRet,NULL) &&
            (dwRet == sizeof(id3v2head)) &&
            (memcmp(id3v2head,"ID3",3) == 0) )
    {
        lDataPtr += (((long )(id3v2head[6]&0x7f)<<21) | ((long )(id3v2head[7]&0x7f)<<14) | ((long )(id3v2head[8]&0x7f)<<7) | (long )(id3v2head[9]&0x7f));
        lDataPtr += 10;
    }
    SetFilePointer(hFile,lDataPtr,NULL,FILE_BEGIN);
    if(ReadFile(hFile,&id3v2head,sizeof(id3v2head),&dwRet,NULL) &&
            (dwRet == sizeof(id3v2head)) &&
            (memcmp(id3v2head,"ID3",3) == 0) )
    {
        lDataPtr += (((long )(id3v2head[6]&0x7f)<<21) | ((long )(id3v2head[7]&0x7f)<<14) | ((long )(id3v2head[8]&0x7f)<<7) | (long )(id3v2head[9]&0x7f));
        lDataPtr += 10;
    }
    SetFilePointer(hFile,lDataPtr,NULL,FILE_BEGIN);
    if(ReadFile(hFile,&id3v2head,sizeof(id3v2head),&dwRet,NULL) &&
            (dwRet == sizeof(id3v2head)) &&
            (memcmp(id3v2head,"ID3",3) == 0) )
    {
        lDataPtr += (((long )(id3v2head[6]&0x7f)<<21) | ((long )(id3v2head[7]&0x7f)<<14) | ((long )(id3v2head[8]&0x7f)<<7) | (long )(id3v2head[9]&0x7f));
        lDataPtr += 10;
    }

    //Mp3ヘッダ情報の読み取り
    DWORD dwFrameCount = 0;
    MPEGINFO mpegHead;
    MPEGINFO *pMpegHead = &m_mpegInfo;
    SetFilePointer(hFile,lDataPtr,NULL,FILE_BEGIN);
    while(ReadFile(hFile,&hbuf,sizeof(hbuf),&dwRet,NULL) && (dwRet == sizeof(hbuf)))
    {
        head=((unsigned long )hbuf[0] << 24) | ((unsigned long) hbuf[1] << 16) |
             ((unsigned long) hbuf[2] << 8) | (unsigned long) hbuf[3];
        //mp3ヘッダとしての妥当性をチェック
        if(!mp3head_check(head))
        {
            //+1
            if(SetFilePointer(hFile,-3,NULL,FILE_CURRENT) > (DWORD)(lDataPtr + 10 * 1024))
            {
                //先頭の10Kだけを調べる
                break;
            }
            continue;//1バイトずらしてもう一度
        }
        //pMpegHeadに戻すのは最初の1フレームだけ
        if(dwFrameCount > 0)
        {
            pMpegHead = &mpegHead;
        }
        else
        {
            dwBeginPtr = SetFilePointer(hFile,0,NULL,FILE_CURRENT) - 4;
            //最初のMP3ヘッダまでの余分なデータ分をサイズから差し引く
            dataSize -= dwBeginPtr;
        }

        if(head & (1<<20))
        {
            pMpegHead->lsf = (head & (1<<19)) ? 0x0 : 0x1;
            pMpegHead->mpeg25 = 0;
        }
        else
        {
            pMpegHead->lsf = 1;
            pMpegHead->mpeg25 = 1;
        }
        pMpegHead->lay = 4-((head>>17)&3);
        if(pMpegHead->mpeg25)
            pMpegHead->sampling_frequency = 6 + ((head>>10)&0x3);
        else
            pMpegHead->sampling_frequency = ((head>>10)&0x3) + (pMpegHead->lsf*3);
        if(pMpegHead->sampling_frequency > 8)
            pMpegHead->sampling_frequency = 8;
        pMpegHead->sampling_frequency = freqs[pMpegHead->sampling_frequency];
        pMpegHead->error_protection = ((head>>16)&0x1)^0x1;
        pMpegHead->bitrate_index	= ((head>>12)&0xf);
        pMpegHead->padding			= ((head>>9)&0x1);
        pMpegHead->extension		= ((head>>8)&0x1);
        pMpegHead->mode				= ((head>>6)&0x3);
        pMpegHead->mode_ext			= ((head>>4)&0x3);
        pMpegHead->copyright		= ((head>>3)&0x1);
        pMpegHead->original			= ((head>>2)&0x1);
        pMpegHead->emphasis			= head & 0x3;
        pMpegHead->stereo			= (pMpegHead->mode == 3) ? 1 : 2;
        pMpegHead->bps				=	 tabsel_123[pMpegHead->lsf][pMpegHead->lay-1][pMpegHead->bitrate_index];
        switch(pMpegHead->lay)
        {
        case 1:
            pMpegHead->framesize  = (long) tabsel_123[pMpegHead->lsf][0][pMpegHead->bitrate_index] * 12000;
            pMpegHead->framesize /= pMpegHead->sampling_frequency;
            pMpegHead->framesize  = ((pMpegHead->framesize+pMpegHead->padding)<<2)-4;
            break;
        case 2:
            pMpegHead->framesize = (long) tabsel_123[pMpegHead->lsf][1][pMpegHead->bitrate_index] * 144000;
            pMpegHead->framesize /= pMpegHead->sampling_frequency;
            pMpegHead->framesize += pMpegHead->padding - 4;
            break;
        case 3:
            pMpegHead->framesize  = (long) tabsel_123[pMpegHead->lsf][2][pMpegHead->bitrate_index] * 144000;
            pMpegHead->framesize /= pMpegHead->sampling_frequency<<(pMpegHead->lsf);
            pMpegHead->framesize += pMpegHead->padding - 4;
            break;
        }
        //フレーム数と録音時間を計算
        if(dwFrameCount == 0)
        {
            pMpegHead->size = dataSize;
            pMpegHead->msec=0;
            if(!(pMpegHead->framesize+4))
            {
                CloseHandle(hFile);
                return FALSE;//0除算防止
            }
            _int64 i64Msec;
            pMpegHead->flmnum = pMpegHead->size/(pMpegHead->framesize+4);
            //i64Msec = (_int64 )pMpegHead->flmnum * 576 * (pMpegHead->lsf?1:2) * 1000 / pMpegHead->sampling_frequency;
            //pMpegHead->msec = (ULONG )i64Msec;
            if(pMpegHead->bps == 0)
            {
                CloseHandle(hFile);
                return FALSE;// 2004-02-19 0除算防止
            }
            pMpegHead->msec = pMpegHead->size * 8 / (pMpegHead->bps*((pMpegHead->stereo==1)?2:1)) ;
            if(pMpegHead->mpeg25)
            {
                //mpeg2
                if(pMpegHead->stereo == 2)
                {
                    //+17+4
                    SetFilePointer(hFile,17,NULL,FILE_CURRENT);
                } else
                {
                    //+9+4
                    SetFilePointer(hFile,9,NULL,FILE_CURRENT);
                }
            }
            else
            {
                //mpeg1
                if(pMpegHead->stereo == 2)
                {
                    //+32+4
                    SetFilePointer(hFile,32,NULL,FILE_CURRENT);
                } else
                {
                    //+17+4
                    SetFilePointer(hFile,17,NULL,FILE_CURRENT);
                }
            }
            //VBRタグを読み取る
            if(!ReadFile(hFile,&xingTag,sizeof(xingTag),&dwRet,NULL))
            {
                CloseHandle(hFile);
                return FALSE;
            }
            if((dwRet == sizeof(xingTag)) && (memcmp(xingTag,"Xing",4) == 0))
            {
                int iOffset = 4;
                ULONG flag = ExtractI4(&xingTag[iOffset]);
                if(flag & FRAMES_FLAG)
                {
                    iOffset += 4;
                    pMpegHead->flmnum = ExtractI4(&xingTag[iOffset])+1;
                    pMpegHead->msec = (ULONG )((_int64 )pMpegHead->flmnum * 576 * (pMpegHead->lsf?1:2) * 1000 / pMpegHead->sampling_frequency);
                }
                if(flag & BYTES_FLAG)
                {
                    iOffset += 4;
                    pMpegHead->size = ExtractI4(&xingTag[iOffset]);
                }
                if( flag & TOC_FLAG ) {
                    for(int i=0; i<100; i++)  toc[i]=xingTag[i];
                }
                pMpegHead->bps = (ULONG)(_int64 )(pMpegHead->size*8)/(pMpegHead->msec);
                pMpegHead->bVbr = TRUE;
            }
            // 2004-10-04 追加
            // VBRI 形式タグを読み取る
            SetFilePointer(hFile,dwBeginPtr+sizeof(DWORD)*9,NULL,FILE_BEGIN);
            VBRI vbri;
            if(!ReadFile(hFile,&vbri,sizeof(vbri),&dwRet,NULL))
            {
                CloseHandle(hFile);
                return FALSE;
            }
            if(memcmp(vbri.magic,"VBRI",4) == 0)
            {
                vbri.version		= ExtractI2((unsigned char *)&vbri.version);
                vbri.delay			= ExtractI2((unsigned char *)&vbri.delay);
                vbri.quality		= ExtractI2((unsigned char *)&vbri.quality);
                vbri.streamBytes	= ExtractI4((unsigned char *)&vbri.streamBytes);
                vbri.streamFrames	= ExtractI4((unsigned char *)&vbri.streamFrames);
                vbri.tableSize		= ExtractI2((unsigned char *)&vbri.tableSize);
                vbri.tableScale		= ExtractI2((unsigned char *)&vbri.tableScale);
                vbri.entryBytes		= ExtractI2((unsigned char *)&vbri.entryBytes);
                vbri.entryFrames	= ExtractI2((unsigned char *)&vbri.entryFrames);
                pMpegHead->flmnum = vbri.streamFrames;
                pMpegHead->msec = (ULONG )((_int64 )pMpegHead->flmnum * 576 * (pMpegHead->lsf?1:2) * 1000 / pMpegHead->sampling_frequency);
                pMpegHead->size = vbri.streamBytes;
                pMpegHead->bps = (ULONG)(_int64 )(pMpegHead->size*8)/(pMpegHead->msec);
                pMpegHead->bVbr = TRUE;
            }

            SetFilePointer(hFile,dwBeginPtr+4,NULL,FILE_BEGIN);
        }
        dwFrameCount++;
        if(!m_mpegInfo.bVbr)	//VBRのときはすべてのフレームをスキャン
            break;
        if(!bVbrScan)
            break;
        FRAMEINFO frameInfo;
        frameInfo.dwPtr = SetFilePointer(hFile,0,NULL,FILE_CURRENT)-4;
        frameInfo.dwSize = pMpegHead->framesize;
        //m_listFrame.push_back(frameInfo);
        if(!pMpegHead->framesize)
            break;//無限ループを防止
        SetFilePointer(hFile,pMpegHead->framesize,NULL,FILE_CURRENT);
    }