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

📄 mp3decode.cpp

📁 symbian下mp3文件的解码源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			}

			/* Pipe the new buffer content to libmad's stream decoder
             * facility.
			 */
			mad_stream_buffer(&Stream,InputBuffer,ReadSize+Remaining);
			Stream.error=MAD_ERROR_NONE;
		}

		/* Decode the next mpeg frame. The streams is read from the
		 * buffer, its constituents are break down and stored the the
		 * Frame structure, ready for examination/alteration or PCM
		 * synthesis. Decoding options are carried in the Frame
		 * structure from the Stream structure.
		 *
		 * Error handling: mad_frame_decode() returns a non zero value
		 * when an error occurs. The error condition can be checked in
		 * the error member of the Stream structure. A mad error is
		 * recoverable or fatal, the error status is checked with the
		 * MAD_RECOVERABLE macro.
		 *
		 * {4} When a fatal error is encountered all decoding
		 * activities shall be stopped, except when a MAD_ERROR_BUFLEN
		 * is signaled. This condition means that the
		 * mad_frame_decode() function needs more input to achieve
		 * it's work. One shall refill the buffer and repeat the
		 * mad_frame_decode() call. Some bytes may be left unused at
		 * the end of the buffer if those bytes forms an incomplete
		 * frame. Before refilling, the remainign bytes must be moved
		 * to the begining of the buffer and used for input for the
		 * next mad_frame_decode() invocation. (See the comments marked
		 * {2} earlier for more details.)
		 *
		 * Recoverable errors are caused by malformed bit-streams, in
		 * this case one can call again mad_frame_decode() in order to
		 * skip the faulty part and re-sync to the next frame.
		 */
		if(mad_frame_decode(&Frame,&Stream))
		{
			if(MAD_RECOVERABLE(Stream.error))
			{
//				char s[300];
//				sprintf(s,"%s: recoverable frame level error (%s)\n",
//						ProgName,MadErrorString(&Stream));
//				fprintf(stderr,"%s: recoverable frame level error (%s)\n",
//						ProgName,MadErrorString(&Stream));
//				fflush(stderr);
				return 0;//Stream.error;
			}
			else
				if(Stream.error==MAD_ERROR_BUFLEN)
					return 0;//MAD_ERROR_BUFLEN;
				else
				{
//					fprintf(stderr,"%s: unrecoverable frame level error (%s).\n",
//							ProgName,MadErrorString(&Stream));
					Status=1;
					return -1;
//					break;
				}
		}

		/* The characteristics of the stream's first frame is printed
		 * on stderr. The first frame is representative of the entire
		 * stream.
		 */
		if(FrameCount==0)
			;
//			if(PrintFrameInfo(stderr,&Frame.header))
//			{
//				Status=1;
//				return 1;
//				break;
//			}

		/* Accounting. The computed frame duration is in the frame
		 * header structure. It is expressed as a fixed point number
		 * whole data type is mad_timer_t. It is different from the
		 * samples fixed point format and unlike it, it can't directly
		 * be added or substracted. The timer module provides several
		 * functions to operate on such numbers. Be careful there, as
		 * some functions of mad's timer module receive some of their
		 * mad_timer_t arguments by value!
		 */
		FrameCount++;
		mad_timer_add(&Timer,Frame.header.duration);

		/* Between the frame decoding and samples synthesis we can
		 * perform some operations on the audio data. We do this only
		 * if some processing was required. Detailed explanations are
		 * given in the ApplyFilter() function.
		 */
//		if(DoFilter)
			ApplyFilter(&Frame);
				
		/* Once decoded the frame is synthesized to PCM samples. No errors
		 * are reported by mad_synth_frame();
		 */
		Frame.options |= MAD_OPTION_IGNORECRC;
		if(Frame.header.samplerate>=iResampleRate*2)
			Frame.options |= MAD_OPTION_HALFSAMPLERATE;

		mad_synth_frame(&Synth,&Frame);

		int samplerate=Synth.pcm.samplerate;
		{
			resample_state resample;
			resample_init(&resample,samplerate,iResampleRate);
			int iLen=resample_block(&resample, Synth.pcm.length, Synth.pcm.samples[0], &OutputPtr[iOutputBufferLength[iOutputBufferCurrent]]);
			iOutputBufferLength[iOutputBufferCurrent]+=iLen;
//			iSoundBuf2[iOutputBufferCurrent]->SetLength(iOutputBufferLength[iOutputBufferCurrent]*2);

		}

		/* Synthesized samples must be converted from mad's fixed
		 * point number to the consumer format. Here we use unsigned
		 * 16 bit big endian integers on two channels. Integer samples
		 * are temporarily stored in a buffer that is flushed when
		 * full.
		 */
//		int i;
//		iOutputBufferLength[iOutputBufferCurrent]=Synth.pcm.length;
//		iSoundBuf2[iOutputBufferCurrent]->SetLength(iOutputBufferLength[iOutputBufferCurrent]*2);
//		for(i=0;i<Synth.pcm.length;i++)
//		{
//			signed short	Sample;

			/* Left channel */
//			Sample=MP3FixedToShort/*MadFixedToSshort*/(Synth.pcm.samples[0][i]);
//			*(OutputPtr++)=Sample;
//			*(OutputPtr++)=(Sample>>0)&0xff;
//			*(OutputPtr++)=(Sample>>8)&0xff;

			/* Right channel. If the decoded stream is monophonic then
			 * the right output channel is the same as the left one.
			 */
//			if(MAD_NCHANNELS(&Frame.header)==2)
//				Sample=MP3FixedToShort/*MadFixedToSshort*/(Synth.pcm.samples[1][i]);
//			*(OutputPtr++)=Sample;
//			*(OutputPtr++)=(Sample>>0)&0xff;
//			*(OutputPtr++)=(Sample>>8)&0xff;

			/* Flush the output buffer if it is full. */
/*			if(OutputPtr==OutputBufferEnd)
			{
				if(fwrite(OutputBuffer,1,OUTPUT_BUFFER_SIZE,fw)!=OUTPUT_BUFFER_SIZE)
				{
//					fprintf(stderr,"%s: PCM write error (%s).\n",
//							ProgName,strerror(errno));
					Status=2;
					return 1;
//					break;
				}
				OutputPtr=OutputBuffer;
			}*/
//		}
	}
	return 0;
}

void CMP3Decode::ApplyFilter(mad_frame *Frame)
{
//mono
	if (Frame->header.mode != MAD_MODE_SINGLE_CHANNEL) 
	{
	    unsigned int ns, s, sb;
	    mad_fixed_t left, right;

		ns = MAD_NSBSAMPLES(&Frame->header);

		for (s = 0; s < ns; ++s) 
		{
			for (sb = 0; sb < 32; ++sb) 
			{
				left  = Frame->sbsample[0][s][sb];
				right = Frame->sbsample[1][s][sb];

				Frame->sbsample[0][s][sb] = (left + right) / 2;
//				Frame->sbsample[0][s][sb] = mad_f_div(left + right,mad_f_tofixed(2));
//				Frame->sbsample[0][s][sb] = Frame->sbsample[1][s][sb];
				// frame->sbsample[1][s][sb] = 0; 
			}
		}

		Frame->header.mode = MAD_MODE_SINGLE_CHANNEL;
	}
	//Frame->header.mode = MAD_MODE_SINGLE_CHANNEL;


	int	Channel,
		Sample,
		Samples,
		SubBand;
	
	/* There is two application loops, each optimized for the number
	 * of audio channels to process. The first alternative is for
	 * two-channel frames, the second is for mono-audio.
	 */
	mad_fixed_t *Filter=iEqualizer;
	Samples=MAD_NSBSAMPLES(&Frame->header);
	if(Frame->header.mode!=MAD_MODE_SINGLE_CHANNEL)
		for(Channel=0;Channel<2;Channel++)
			for(Sample=0;Sample<Samples;Sample++)
				for(SubBand=0;SubBand<32;SubBand++)
					Frame->sbsample[Channel][Sample][SubBand]=
						mad_f_mul(Frame->sbsample[Channel][Sample][SubBand],
								  Filter[SubBand]);
	else
		for(Sample=0;Sample<Samples;Sample++)
			for(SubBand=0;SubBand<32;SubBand++)
				Frame->sbsample[0][Sample][SubBand]=
					mad_f_mul(Frame->sbsample[0][Sample][SubBand],
							  Filter[SubBand]);

}

signed int CMP3Decode::MP3FixedToShort(mad_fixed_t sample)
{
	/* round */
	sample += (1L << (MAD_F_FRACBITS - 16));

	/* clip */
	if (sample >= MAD_F_ONE)	
		sample = MAD_F_ONE - 1;
	else if (sample < -MAD_F_ONE)
		sample = -MAD_F_ONE;

	/* quantize */
	return sample >> (MAD_F_FRACBITS + 1 - 16);
}

int CMP3Decode::resample_init(resample_state *state, unsigned int oldrate, unsigned int newrate)
{
	mad_fixed_t ratio;

	if (newrate == 0)
		return -1;

	ratio = mad_f_div(oldrate, newrate);
	if (ratio <= 0 || ratio > MAX_RESAMPLEFACTOR * MAD_F_ONE)
		return -1;

	state->ratio = ratio;

	state->step = 0;
	state->last = 0;

	return 0;
}

unsigned int CMP3Decode::resample_block(resample_state *state, unsigned int nsamples, const mad_fixed_t *old, TInt16 *newb)
{
	mad_fixed_t const *end;
	TInt16 *begin;

	/*
	 * This resampling algorithm is based on a linear interpolation, which is
     * not at all the best sounding but is relatively fast and efficient.
     *
     * A better algorithm would be one that implements a bandlimited
     * interpolation.
     */

	if (state->ratio == MAD_F_ONE) 
	{
		unsigned int i;
		for(i=0;i<nsamples;i++)
		{
			signed short	Sample;

			/* Left channel */
			Sample=MP3FixedToShort/*MadFixedToSshort*/(old[i]);
			(*newb++)=Sample;
		}
//	memcpy(newb, old, nsamples * sizeof(mad_fixed_t));
//    return nsamples;
	}

	end   = old + nsamples;
	begin = newb;

	if (state->step < 0) 
	{
		state->step = mad_f_fracpart(-state->step);

		while (state->step < MAD_F_ONE) 
		{
			*newb++ = MP3FixedToShort (state->step ? state->last + mad_f_mul(*old - state->last, state->step) : state->last);

			state->step += state->ratio;
			if (((state->step + 0x00000080L) & 0x0fffff00L) == 0)
				state->step = (state->step + 0x00000080L) & ~0x0fffffffL;
		}

		state->step -= MAD_F_ONE;
	}

	while (end - old > 1 + mad_f_intpart(state->step)) 
	{
		old        += mad_f_intpart(state->step);
		state->step = mad_f_fracpart(state->step);

		*newb++ = MP3FixedToShort (state->step ? *old + mad_f_mul(old[1] - old[0], state->step) : *old);

		state->step += state->ratio;
		if (((state->step + 0x00000080L) & 0x0fffff00L) == 0)
			state->step = (state->step + 0x00000080L) & ~0x0fffffffL;
	}

	if (end - old == 1 + mad_f_intpart(state->step)) 
	{
		state->last = end[-1];
		state->step = -state->step;
	}
	else
		state->step -= mad_f_fromint(end - old);

	return newb - begin;
}

⌨️ 快捷键说明

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