⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mfm.c

📁 好记星的控件,包括button,list,对文件操作
💻 C
📖 第 1 页 / 共 3 页
字号:
	{ 11025,12000,8000,0 },
};

#define	MP3_GETFORMAT_BUFLEN	0x1000

/*BOOL __Mpeg1GetFmt(UINT8 *pbData, MPEG1WAVEFORMAT *pFormat)
{
	UINT32	Layer;

	pFormat->wfx.wFormatTag = WAVE_FORMAT_MPEG;      //  Get number of channels from Mode      
	
	switch (pbData[3] >> 6) 
	{     
	case 0x00:         
		pFormat->fwHeadMode = ACM_MPEG_STEREO;         
		break;     
	case 0x01:         
		pFormat->fwHeadMode = ACM_MPEG_JOINTSTEREO;         
		break;     
	case 0x02:         
		pFormat->fwHeadMode = ACM_MPEG_DUALCHANNEL;         
		break;     
	case 0x03:         
		pFormat->fwHeadMode = ACM_MPEG_SINGLECHANNEL;         
		break;     
	} 
    pFormat->wfx.nChannels = (WORD)(pFormat->fwHeadMode == ACM_MPEG_SINGLECHANNEL ? 1 : 2); 
	pFormat->fwHeadModeExt = (WORD)(1 << (pbData[3] >> 4));     
	pFormat->wHeadEmphasis = (WORD)((pbData[3] & 0x03) + 1);     
	pFormat->fwHeadFlags   = (WORD)(((pbData[2] & 1) ? ACM_MPEG_PRIVATEBIT : 0) + 
		((pbData[3] & 8) ? ACM_MPEG_COPYRIGHT : 0) + 
		((pbData[3] & 4) ? ACM_MPEG_ORIGINALHOME : 0) + 
		((pbData[1] & 1) ? ACM_MPEG_PROTECTIONBIT : 0) + 
		((pbData[1] & 0x08) ? ACM_MPEG_ID_MPEG1 : 0)); 

	switch ((pbData[1] >> 1) & 3) 
	{         
	case 3:             
		pFormat->fwHeadLayer = ACM_MPEG_LAYER1;             
		Layer = 1;             
		break;         
	case 2:             
		pFormat->fwHeadLayer = ACM_MPEG_LAYER2;             
		Layer = 2;             
		break;         
	case 1:             
		pFormat->fwHeadLayer = ACM_MPEG_LAYER3;             
		Layer = 3;             
		break;         
	case 0:             
		return (FALSE);     
	}      
	
	//  Get samples per second from sampling frequency      
	pFormat->wfx.nSamplesPerSec = FreqTable[0][(pbData[2] >> 2) & 3];
	pFormat->dwHeadBitrate = BitrateTable[0][Layer-1][pbData[2] >>4] * 1000;     
	pFormat->wfx.nAvgBytesPerSec = pFormat->dwHeadBitrate / 8;      //  Deal with free format (!)  
	if (pFormat->wfx.nSamplesPerSec != 44100 && 
		//  Layer 3 can sometimes switch bitrates  
		!(Layer == 3 && // !m_pStreamList->AudioLock() &&   
		(pbData[2] >> 4) == 0)) 
	{          
		if (Layer == 1) 
		{    
			pFormat->wfx.nBlockAlign = (WORD)(4 * ((pFormat->dwHeadBitrate * 12) / pFormat->wfx.nSamplesPerSec));         
		} 
		else 
		{
			pFormat->wfx.nBlockAlign = (WORD)((144 * pFormat->dwHeadBitrate) / pFormat->wfx.nSamplesPerSec);   
		}   
	}
	else
	{         
		pFormat->wfx.nBlockAlign = 1;  
	}   
	pFormat->wfx.wBitsPerSample = 0;
	pFormat->wfx.cbSize = sizeof(MPEG1WAVEFORMAT) - sizeof(WAVEFORMATEX);      
	pFormat->dwPTSLow  = 0;
	pFormat->dwPTSHigh = 0; 

	return TRUE;
}
*/

UINT MediaFileGetMP3Format(HMEDIAFILE hmmio, MPEGLAYER3WAVEFORMAT *lpInfo)
{
	MpegFrameHeader	mpegFrameHeader, mpegFrameHeaderNew;
	enum MpegVersion		mpegVersion;
	UINT16			mpegLayer;
	UINT16	wFrameLen;
	UINT32	dwBitRate, dwFreq;

	UINT32	dwMaxSearchTimes, dwLoop, i, j;
	UINT8	*pGetFormatBuf;
	UINT	dwRet;

	if (hmmio == NULL || lpInfo == NULL){
		return MMIOERR_CHUNKNOTFOUND;
	}
	pGetFormatBuf = (UINT8 *)MemAlloc(MP3_GETFORMAT_BUFLEN);
	if(!pGetFormatBuf)
		return MMIOERR_OUTOFMEMORY;
	dwRet = MMIOERR_CHUNKNOTFOUND;
	dwLoop = 0;

    MediaFileSeek(hmmio, 0, 0);
	
	while(dwRet == MMIOERR_CHUNKNOTFOUND)
	{
		dwMaxSearchTimes = MediaFileRead(hmmio, pGetFormatBuf, MP3_GETFORMAT_BUFLEN);
		if((dwMaxSearchTimes < 4) || (dwMaxSearchTimes > MP3_GETFORMAT_BUFLEN))
			break;
		dwMaxSearchTimes -= (4 - 1);
		
		for(i = 0; i < dwMaxSearchTimes; i ++)
		{
			memcpy(&mpegFrameHeader, pGetFormatBuf + i, 4);

//			if(mpegFrameHeader.framesync != 0x7FF
			if(mpegFrameHeader.framesync1 != 0xFF
				|| mpegFrameHeader.framesync2 != 0x7
				|| mpegFrameHeader.mpegver == 1
				|| mpegFrameHeader.mpeglayer == 0
				|| mpegFrameHeader.bitrate == 0xF 
				|| mpegFrameHeader.bitrate == 0x0 
				|| mpegFrameHeader.samplerate == 0x3)
				continue;

			switch (mpegFrameHeader.mpegver)
			{
				case 0: mpegVersion = MPEGVER_25; break;
//				case 1: mpegVersion = MPEGVER_NA; break;
				case 2: mpegVersion = MPEGVER_2; break;
				case 3: mpegVersion = MPEGVER_1; break;
			}

			mpegLayer = 4 - mpegFrameHeader.mpeglayer;

			if(mpegVersion == MPEGVER_1)
				dwBitRate = BitrateTable[0][mpegLayer-1][mpegFrameHeader.bitrate];
			else
				dwBitRate = BitrateTable[1][mpegLayer-1][mpegFrameHeader.bitrate];

			if(mpegVersion == MPEGVER_1)
				dwFreq = FreqTable[0][mpegFrameHeader.samplerate];
			else if(mpegVersion == MPEGVER_2)
				dwFreq = FreqTable[1][mpegFrameHeader.samplerate];
			else if(mpegVersion == MPEGVER_25)
				dwFreq = FreqTable[2][mpegFrameHeader.samplerate];

			if(mpegLayer == 1)
				wFrameLen = (12000 * dwBitRate / dwFreq + mpegFrameHeader.padding) * 4; 
			else if(mpegLayer == 2)
				wFrameLen = 144000 * dwBitRate / dwFreq + mpegFrameHeader.padding;
			else if(mpegLayer == 3)
			{
				if(mpegVersion == MPEGVER_1)
					wFrameLen = 144000 * dwBitRate / dwFreq + mpegFrameHeader.padding;
				else
					wFrameLen = 144000 * dwBitRate / dwFreq / 2 + mpegFrameHeader.padding;
			}

/*			if(mpegFrameHeader.hascrc == 0)
			{
				UINT16	wFrameCrc;

				wFrameCrc = *(UINT16 *)(pGetFormatBuf + i + 4);
				if(wFrameCrc != Crc16(pGetFormatBuf + i + 4 + 2, wFrameLen, 0))
					continue;
			}*/

			if(dwBitRate == 0)
			{
				//固定比特率要计算实际比特率
				for(j = i + 4; j < dwMaxSearchTimes; j ++)
				{
					memcpy(&mpegFrameHeaderNew, pGetFormatBuf + j, 4);
					
					if(mpegFrameHeaderNew.framesync1 != 0xFF
						|| mpegFrameHeaderNew.framesync2 != 0x7
						|| mpegFrameHeaderNew.mpegver == 1
						|| mpegFrameHeaderNew.mpeglayer == 0
						|| mpegFrameHeaderNew.bitrate == 0xF 
						|| mpegFrameHeaderNew.bitrate == 0x0 
						|| mpegFrameHeaderNew.samplerate == 0x3)
						continue;

					if(mpegFrameHeaderNew.mpegver == mpegFrameHeader.mpegver
						&& mpegFrameHeaderNew.mpeglayer == mpegFrameHeader.mpeglayer
						&& mpegFrameHeaderNew.samplerate == mpegFrameHeader.samplerate)
						break;
				}
				if(j >= dwMaxSearchTimes)
					continue;

				if(mpegVersion == MPEGVER_1)
					dwBitRate = mpegFrameHeader.samplerate * (j - i) / 144000;
				else
					dwBitRate = mpegFrameHeader.samplerate * (j - i) / 72000;
			}
			else
			{
				//查找是否紧跟一个新的桢头
				memcpy(&mpegFrameHeaderNew, pGetFormatBuf + i + wFrameLen, 4);
				if(mpegFrameHeaderNew.framesync1 != 0xFF
					|| mpegFrameHeaderNew.framesync2 != 0x7
					|| mpegFrameHeaderNew.mpegver == 1
					|| mpegFrameHeaderNew.mpeglayer == 0
					|| mpegFrameHeaderNew.bitrate == 0xF 
					|| mpegFrameHeaderNew.bitrate == 0x0 
					|| mpegFrameHeaderNew.samplerate == 0x3
					|| mpegFrameHeaderNew.mpegver != mpegFrameHeader.mpegver
					|| mpegFrameHeaderNew.mpeglayer != mpegFrameHeader.mpeglayer
					|| mpegFrameHeaderNew.samplerate != mpegFrameHeader.samplerate
					|| mpegFrameHeaderNew.chanmode != mpegFrameHeader.chanmode)
					continue;
			}

			if(mpegLayer != 3)
			{
//				if(mpegVersion == MPEG_VER_1)
//					__Mpeg1GetFmt(ch, (MPEG1WAVEFORMAT *)lpInfo);

				dwRet = MMIOERR_ACCESSDENIED;
				break;
			}

			lpInfo->wfx.cbSize = MPEGLAYER3_WFX_EXTRA_BYTES;
			lpInfo->wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3;
			lpInfo->wfx.nChannels = (mpegFrameHeader.chanmode == 3) ? 1 : 2;
			lpInfo->wfx.nAvgBytesPerSec = dwBitRate * (1000 / 8);	// not really used but must be one of 64, 96, 112, 128, 160kbps
			lpInfo->wfx.wBitsPerSample = 0;							// MUST BE ZERO
			lpInfo->wfx.nBlockAlign = 1;							// MUST BE ONE
			lpInfo->wfx.nSamplesPerSec = dwFreq;	
			lpInfo->fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF;
			lpInfo->nBlockSize = MP3_BLOCK_SIZE;					// voodoo value #1
			lpInfo->nFramesPerBlock = 1;							// MUST BE ONE
			lpInfo->nCodecDelay = 1393;								// voodoo value #2
#ifdef _WIN32
			lpInfo->wID = MPEGLAYER3_ID_MPEG;
#else
			lpInfo->wID = *(UINT16 *)&mpegFrameHeader;
#endif

//			MediaFileSeek(hmmio, -4, SEEK_CUR);
			MediaFileSeek(hmmio, dwLoop * MP3_GETFORMAT_BUFLEN + i, 0);
			dwRet = MMSYSERR_NOERROR;
			break;
		}
		dwLoop ++;
	}

	MemFree(pGetFormatBuf);
	return dwRet;
}


//pFormat要定义为长度WAVEFORMATEX_MAXLEN
//文件指针会移动到数据开始位置
UINT MediaFileGetFormat(HMEDIAFILE hmmio, UINT8 voiceType, WAVEFORMATEX *pFormat,
                        UINT32 *pdwFileLength, UINT32 *pdwTimeLength)
{
    MMCKINFO    mmckinfoParent;     // parent chunk information 
    MMCKINFO    mmckinfoSubchunk;   // subchunk information structure 
    DWORD       dwFmtSize;          // size of "FMT" chunk 
	UINT		dwError;

	UINT32	dwPos, dwEnd;

	if(voiceType == VOICE_TYPE_MP3)
	{
		// 直接定位 MP3 文件信息
		dwError = MediaFileGetMP3Format(hmmio, (MPEGLAYER3WAVEFORMAT *)pFormat);
		if(dwError != MMSYSERR_NOERROR)
			return dwError;

		dwPos = MediaFileSeek(hmmio, 0, SEEK_CUR);
		dwEnd = MediaFileLength(hmmio);
//		dwEnd = MediaFileSeek(hmmio, 0, SEEK_END);
//		MediaFileSeek(hmmio, dwPos, SEEK_SET);
		*pdwFileLength = (dwEnd - dwPos);
    	*pdwTimeLength = *pdwFileLength / pFormat->nAvgBytesPerSec;
		return MMSYSERR_NOERROR;
	}
	else if(voiceType == VOICE_TYPE_WMA)
	{
        dwError = MediaFileGetWMAFormat(hmmio, (WAVEFORMATEX *)pFormat, pdwTimeLength);
		if(dwError != MMSYSERR_NOERROR)
			return dwError;
		dwPos = MediaFileSeek(hmmio, 0, SEEK_CUR);
		dwEnd = MediaFileLength(hmmio);
//		dwEnd = MediaFileSeek(hmmio, 0, SEEK_END);
//		MediaFileSeek(hmmio, dwPos, SEEK_SET);
		*pdwFileLength = (dwEnd - dwPos);

		return MMSYSERR_NOERROR;
	}
	else
	{
		// 寻找“WAVE”信息块,以确定文件是一个波形声音文件 
		mmckinfoParent.fccType = MediaFileStrToFourCC("WAVE", 0);
		if (MediaFileDescend(hmmio, &mmckinfoParent, NULL, MMIO_FINDRIFF) != MMSYSERR_NOERROR)
			return MMIOERR_CHUNKNOTFOUND; 

		// 寻找信息块中的“FMT”子块
		mmckinfoSubchunk.ckid = MediaFileStrToFourCC("fmt ", 0);
		if (MediaFileDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent, MMIO_FINDCHUNK) != MMSYSERR_NOERROR)
			return MMIOERR_CHUNKNOTFOUND; 
 
		// 读取“FMT”子块数据
		dwFmtSize = mmckinfoSubchunk.cksize; 
		pFormat->cbSize = 0;
		if (MediaFileRead(hmmio,(BYTE *)pFormat, dwFmtSize) != (int)dwFmtSize)
			return MMIOERR_CHUNKNOTFOUND;			

		//mocodifed  by ju 2006-06-21  begin
		{
			INT nBps;			//播放波特率
			nBps  = pFormat->nSamplesPerSec*pFormat->nChannels*pFormat->wBitsPerSample;
			if( nBps > 176000 )   //大于176kbps,不播放			
				return MMIOERR_CHUNKNOTFOUND; 
		}
		//mocodifed  by ju 2006-06-21  end

		// 退出“FMT”子块
		MediaFileAscend(hmmio, &mmckinfoSubchunk, 0);
 
		// 定位到“DATA”子块i
		mmckinfoSubchunk.ckid = MediaFileStrToFourCC("data", 0); 
		if (MediaFileDescend(hmmio, &mmckinfoSubchunk, &mmckinfoParent, MMIO_FINDCHUNK) != MMSYSERR_NOERROR)
			return MMIOERR_CHUNKNOTFOUND; 

		if(pdwFileLength != NULL)
			*pdwFileLength = mmckinfoSubchunk.cksize; 
    	*pdwTimeLength = *pdwFileLength / pFormat->nAvgBytesPerSec;
		return MMSYSERR_NOERROR;
	} 

	return MMSYSERR_NOERROR;
}

/**************************************************************************************
WMA 文件头格式信息
**************************************************************************************/



/* for debugging */
#define WMAERR_OK               0
#define WMAERR_FAIL             1
#define WMAERR_INVALIDARG       2
#define WMAERR_BUFFERTOOSMALL   3

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -