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

📄 mp3decode.cpp

📁 symbian下mp3文件的解码源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
    This file is part of MP3DecodeDLL for Symbian.

    MP3DecodeDLL for Symbian
    Copyright (C) 2004 Denis Mingulov <denis@mingulov.com>

    MP3DecodeDLL for Symbian is free software; you can redistribute
    it and/or modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2 of
    the License, or (at your option) any later version.

    MP3DecodeDLL for Symbian is distributed in the hope that it
    will be useful, but WITHOUT ANY WARRANTY; without even the implied
    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MP3DecodeDLL for Symbian; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/

#include "string.h"
#include "MP3Decode.h"

#define BUFFERSIZE 512
#include "math.h"

CMP3Decode::CMP3Decode() : bFileOpened(EFalse), iFileSession(NULL), iResampleRate(8000)
{
}

CMP3Decode::~CMP3Decode()
{
	Close();
	delete iInputBuf;
}

CMP3Decode * CMP3Decode::NewL()
{
    CMP3Decode* iMP3Decode = CMP3Decode::NewLC();
    CleanupStack::Pop(iMP3Decode);
    return iMP3Decode;

}

CMP3Decode * CMP3Decode::NewLC()
{
	CMP3Decode* iMP3Decode = new (ELeave) CMP3Decode();
    CleanupStack::PushL(iMP3Decode);
    iMP3Decode->ConstructL();
    return iMP3Decode;

}

void CMP3Decode::ConstructL()
{
	iInputBuf = new TPtr8((TUint8*)InputBuffer2, INPUT_BUFFER_SIZE, INPUT_BUFFER_SIZE);
}

TInt CMP3Decode::Open(RFs &aFileServer, const TDesC &aFileName) 
{
	iFileSession = &aFileServer;
	strFileNameMP3.Copy(aFileName);

	TInt iErr = InitMP3();

	if(iErr)
		bFileOpened = EFalse;
	else
		bFileOpened = ETrue;

	return iErr;
}

TInt CMP3Decode::Close()
{
	if(bFileOpened)
	{
		CloseMP3();
	}
	return 0;
}

TInt CMP3Decode::SetResampleRate(TInt aResampleRate)
{
	iResampleRate = aResampleRate;
	return 0;
}

TInt CMP3Decode::SetEqualizer (TInt aEq60, TInt aEq170, TInt aEq310, TInt aEq600, TInt aEq1K, TInt aEq3K, TInt aEq6K, TInt aEq12K, TInt aEq14K, TInt aEq16K, TInt aEqZero, TInt aEqDiv)
{
	// 60, 170, 310, 600, 1K, 3K
	iEqualizer[0] = mad_f_tofixed (pow (10,((double)(aEq60-aEqZero))/(double)aEqDiv));
	iEqualizer[1] = mad_f_tofixed (pow (10,((double)(aEq170-aEqZero))/(double)aEqDiv));
	iEqualizer[2] = mad_f_tofixed (pow (10,((double)(aEq310-aEqZero))/(double)aEqDiv));
	iEqualizer[3] = mad_f_tofixed (pow (10,((double)(aEq600-aEqZero))/(double)aEqDiv));
	iEqualizer[4] = mad_f_tofixed (pow (10,((double)(aEq1K-aEqZero))/(double)aEqDiv));
	iEqualizer[5] = mad_f_tofixed (pow (10,((double)(aEq3K-aEqZero))/(double)aEqDiv));
	//6K
	iEqualizer[6] = mad_f_tofixed (pow (10,((double)(aEq6K-aEqZero))/(double)aEqDiv));
	iEqualizer[7] = iEqualizer[6];
	//12K
	iEqualizer[8] = mad_f_tofixed (pow (10,((double)(aEq12K-aEqZero))/(double)aEqDiv));
	iEqualizer[9] = iEqualizer[8];
	iEqualizer[10] = iEqualizer[8];
	iEqualizer[11] = iEqualizer[8];
	//14K
	iEqualizer[12] = mad_f_tofixed (pow (10,((double)(aEq14K-aEqZero))/(double)aEqDiv));
	iEqualizer[13] = iEqualizer[12];
	iEqualizer[14] = iEqualizer[12];
	iEqualizer[15] = iEqualizer[12];
	iEqualizer[16] = iEqualizer[12];
	iEqualizer[17] = iEqualizer[12];
	iEqualizer[18] = iEqualizer[12];
	iEqualizer[19] = iEqualizer[12];
	//16K
	iEqualizer[20] = mad_f_tofixed (pow (10,((double)(aEq16K-aEqZero))/(double)aEqDiv));
	iEqualizer[21] = iEqualizer[20];
	iEqualizer[22] = iEqualizer[20];
	iEqualizer[23] = iEqualizer[20];
	iEqualizer[24] = iEqualizer[20];
	iEqualizer[25] = iEqualizer[20];
	iEqualizer[26] = iEqualizer[20];
	iEqualizer[27] = iEqualizer[20];
	iEqualizer[28] = iEqualizer[20];
	iEqualizer[29] = iEqualizer[20];
	iEqualizer[30] = iEqualizer[20];
	iEqualizer[31] = iEqualizer[20];

	return 0;
}

TInt CMP3Decode::GetFileLength()
{
	TInt iLength=0;
	
	if(iFile.Size(iLength)==KErrNone)
	{
		return iLength;
	}
	else
	{
		return 0;
	}
}

TInt CMP3Decode::GetFilePosition()
{
	TInt iPos=0;
	if(iFile.Seek(ESeekCurrent, iPos)==KErrNone)
	{
		return iPos;
	}
	else
	{
		return 0;
	}
}

TInt CMP3Decode::InitMP3()
{
	TInt iErr=0;
	iErr = iFile.Open(*iFileSession,strFileNameMP3,EFileRead|EFileShareReadersOnly);

	SetEqualizer(100,100,100,100,100,100,100,100,100,100,100,20);

	/* First the structures used by libmad must be initialized. */
	mad_stream_init(&Stream);
	mad_frame_init(&Frame);
	mad_synth_init(&Synth);
	mad_timer_reset(&Timer);

	Status=0;
	iOutputBufferCurrent=0;

	return iErr;
}

TInt CMP3Decode::CloseMP3()
{
	iFile.Close();

	/* Mad is no longer used, the structures that were initialized must
     * now be cleared.
	 */
	mad_synth_finish(&Synth);
	mad_frame_finish(&Frame);
	mad_stream_finish(&Stream);

	return 0;
}

TInt CMP3Decode::DecodeOneFrame(TDes& aBuffer)
{
	int iErr = DecodeOneFrameLow();
	if(iErr==0&&iOutputBufferLength[iOutputBufferCurrent]==0)
	{
		iErr = DecodeOneFrameLow();
	}
	aBuffer.Copy((const TUint16*)OutputBuffer[iOutputBufferCurrent],iOutputBufferLength[iOutputBufferCurrent]);
	return iErr;
}

int CMP3Decode::DecodeOneFrameLow()
// based on sources of 
// madplay - MPEG audio decoder and player
// Copyright (C) 2000-2004 Robert Leslie


{
	TInt16 *OutputPtr=OutputBuffer[iOutputBufferCurrent];
	TInt16 *OutputBufferEnd=OutputPtr+OUTPUT_BUFFER_SIZE;
	int iCycle=0;

	iOutputBufferLength[iOutputBufferCurrent]=0;

	for(iCycle=0;iCycle<1;iCycle++)
	{
		/* The input bucket must be filled if it becomes empty or if
		 * it's the first execution of the loop.
		 */
		if(Stream.buffer==NULL || Stream.error==MAD_ERROR_BUFLEN)
		{
			size_t			ReadSize, ReadSize2,
							Remaining;
			unsigned char	*ReadStart;

			/* {2} libmad may not consume all bytes of the input
			 * buffer. If the last frame in the buffer is not wholly
			 * contained by it, then that frame's start is pointed by
			 * the next_frame member of the Stream structure. This
			 * common situation occurs when mad_frame_decode() fails,
			 * sets the stream error code to MAD_ERROR_BUFLEN, and
			 * sets the next_frame pointer to a non NULL value. (See
			 * also the comment marked {4} bellow.)
			 *
			 * When this occurs, the remaining unused bytes must be
			 * put back at the beginning of the buffer and taken in
			 * account before refilling the buffer. This means that
			 * the input buffer must be large enough to hold a whole
			 * frame at the highest observable bit-rate (currently 448
			 * kb/s). XXX=XXX Is 2016 bytes the size of the largest
			 * frame? (448000*(1152/32000))/8
			 */
			if(Stream.next_frame!=NULL)
			{
//				iFilePos+=Stream.next_frame-Stream.buffer;
				Remaining=Stream.bufend-Stream.next_frame;
				memmove(InputBuffer,Stream.next_frame,Remaining);
				ReadStart=InputBuffer+Remaining;
				ReadSize=INPUT_BUFFER_SIZE-Remaining;

/*				ReadSize=INPUT_BUFFER_SIZE,
					ReadStart=InputBuffer,
					Remaining=0;*/
			}
			else
				ReadSize=INPUT_BUFFER_SIZE,
					ReadStart=InputBuffer,
					Remaining=0;
			
			/* Fill-in the buffer. If an error occurs print a message
			 * and leave the decoding loop. If the end of stream is
			 * reached we also leave the loop but the return status is
			 * left untouched.
			 */
//			fprintf(stderr,"file pos: %x\n",iFilePos);
//			fseek(fr,iFilePos,SEEK_SET);
			iInputBuf->SetLength(INPUT_BUFFER_SIZE);
			iFile.Read(*iInputBuf,ReadSize);
//			ReadSize=fread(ReadStart,1,ReadSize,fr);
			ReadSize2=ReadSize;
			ReadSize=iInputBuf->Length();

			memmove(ReadStart,InputBuffer2,ReadSize);

			if(ReadSize<=0)
			{
//				if(ferror(fr))
				{
//					fprintf(stderr,"%s: read error on bitstream (%s)\n",
//							ProgName,strerror(errno));
//					Status=1;
				}
//				if(feof(fr))
					;//fprintf(stderr,"%s: end of input stream\n",ProgName);
				return 1;
//				break;
			}

			/* {3} When decoding the last frame of a file, it must be
			 * followed by MAD_BUFFER_GUARD zero bytes if one wants to
			 * decode that last frame. When the end of file is
			 * detected we append that quantity of bytes at the end of
			 * the available data. Note that the buffer can't overflow
			 * as the guard size was allocated but not used the the
			 * buffer managment code. (See also the comment marked
			 * {1}.)
			 *
			 * In a message to the mad-dev mailing list on May 29th,
			 * 2001, Rob leslie explains the guard zone as follows:
			 * 
			 *    "The reason for MAD_BUFFER_GUARD has to do with the
			 *    way decoding is performed. In Layer III, Huffman
			 *    decoding may inadvertently read a few bytes beyond
			 *    the end of the buffer in the case of certain invalid
			 *    input. This is not detected until after the fact. To
			 *    prevent this from causing problems, and also to
			 *    ensure the next frame's main_data_begin pointer is
			 *    always accessible, MAD requires MAD_BUFFER_GUARD
			 *    (currently 8) bytes to be present in the buffer past
			 *    the end of the current frame in order to decode the
			 *    frame."
			 */
//			if(feof(fr))
			if(ReadSize!=ReadSize2)
			{
				memset(ReadStart+ReadSize,0,MAD_BUFFER_GUARD);
				ReadSize+=MAD_BUFFER_GUARD;

⌨️ 快捷键说明

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