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

📄 madlld.c

📁 OggPlay for Symbian 是symbian上的一个媒体播放程序的源码。它支持ogg,wav等等多媒体格式。
💻 C
📖 第 1 页 / 共 2 页
字号:
				ReadSize+=MAD_BUFFER_GUARD;
			}

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

		/* 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 complete
		 * its 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 remaining bytes must be moved
		 * to the beginning 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))
			{
				/* Do not print a message if the error is a loss of
				 * synchronization and this loss is due to the end of
				 * stream guard bytes. (See the comments marked {3}
				 * supra for more informations about guard bytes.)
				 */
				if(Stream.error!=MAD_ERROR_LOSTSYNC ||
				   Stream.this_frame!=GuardPtr)
				{
					fprintf(stderr,"%s: recoverable frame level error (%s)\n",
							ProgName,MadErrorString(&Stream));
					fflush(stderr);
				}
				continue;
			}
			else
				if(Stream.error==MAD_ERROR_BUFLEN)
					continue;
				else
				{
					fprintf(stderr,"%s: unrecoverable frame level error (%s).\n",
							ProgName,MadErrorString(&Stream));
					Status=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;
				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 subtracted. The timer module provides several
		 * functions to operate on such numbers. Be careful there, as
		 * some functions of libmad'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();
		 */
		mad_synth_frame(&Synth,&Frame);

		/* Synthesized samples must be converted from libmad'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.
		 */
		for(i=0;i<Synth.pcm.length;i++)
		{
			signed short	Sample;

			/* Left channel */
			Sample=MadFixedToSshort(Synth.pcm.samples[0][i]);
			*(OutputPtr++)=Sample>>8;
			*(OutputPtr++)=Sample&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=MadFixedToSshort(Synth.pcm.samples[1][i]);
			*(OutputPtr++)=Sample>>8;
			*(OutputPtr++)=Sample&0xff;

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

	/* The input file was completely read; the memory allocated by our
	 * reading module must be reclaimed.
	 */
	BstdFileDestroy(BstdFile);

	/* 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);

	/* If the output buffer is not empty and no error occurred during
     * the last write, then flush it.
	 */
	if(OutputPtr!=OutputBuffer && Status!=2)
	{
		size_t	BufferSize=OutputPtr-OutputBuffer;

		if(fwrite(OutputBuffer,1,BufferSize,OutputFp)!=BufferSize)
		{
			fprintf(stderr,"%s: PCM write error (%s).\n",
					ProgName,strerror(errno));
			Status=2;
		}
	}

	/* Accounting report if no error occurred. */
	if(!Status)
	{
		char	Buffer[80];

		/* The duration timer is converted to a human readable string
		 * with the versatile, but still constrained mad_timer_string()
		 * function, in a fashion not unlike strftime(). The main
		 * difference is that the timer is broken into several
		 * values according some of it's arguments. The units and
		 * fracunits arguments specify the intended conversion to be
		 * executed.
		 *
		 * The conversion unit (MAD_UNIT_MINUTES in our example) also
		 * specify the order and kind of conversion specifications
		 * that can be used in the format string.
		 *
		 * It is best to examine libmad's timer.c source-code for details
		 * of the available units, fraction of units, their meanings,
		 * the format arguments, etc.
		 */
		mad_timer_string(Timer,Buffer,"%lu:%02lu.%03u",
						 MAD_UNITS_MINUTES,MAD_UNITS_MILLISECONDS,0);
		fprintf(stderr,"%s: %lu frames decoded (%s).\n",
				ProgName,FrameCount,Buffer);
	}

	/* That's the end of the world (in the H. G. Wells way). */
	return(Status);
}

/****************************************************************************
 * Prints a message on stderr explaining the usage of the program. Two		*
 * versions of this function are provided, depending on the system type.	*
 ****************************************************************************/
static void PrintUsage(void)
{
#ifdef HAVE_GETOPT /* This version is for Unix systems. */
	fprintf(stderr,"usage: %s [-p] [-a <amp/atten>]\n"
			"\t-a\tSets an amplification or attenuation factor expressed\n"
			"\t\tin dB. The factor bounds are [-Inf,%f].\n"
			"\t-p\tRequests that the output samples be filtered as if\n"
			"\t\ttransmitted through a telephone switch.\n",
			ProgName,
			20.*log10(mad_f_todouble(MAD_F_MAX)));
#else /* HAVE_GETOPT */ /* This other version is for non-Unix systems. */
	fprintf(stderr,"usage: %s [<number>] [phone]\n"
			"\t<number> is a floating point number expressing an "
			"amplification\n"
			"\t\tor attenuation factor expressed in dB. The factor bounds\n"
			"\t\tare [-Inf,%f].\n"
			"\tThe \"phone\" argument requests that the output samples be "
			"filtered\n"
			"\t\tas if transmitted through a telephone switch.\n",
			ProgName,
			20.*log10(mad_f_todouble(MAD_F_MAX)));
#endif /* HAVE_GETOPT */
}

/****************************************************************************
 * Command-line arguments parsing. We use two methods and two command-line	*
 * formats depending on the system type. On unix system we apply the good	*
 * old getopt() method, other system are offered a really primitive options	*
 * interface.																*
 ****************************************************************************/
static int ParseArgs(int argc, char * const argv[])
{
	int				DoPhoneFilter=0,
					i;
	double			AmpFactor;
	mad_fixed_t		Amp=MAD_F_ONE;

#ifdef HAVE_GETOPT /* This version is for Unix systems. */
	int				Option;

	/* Parse the command line. */
	while((Option=getopt(argc,argv,"a:p"))!=-1)
		switch(Option)
		{
			/* {5} Set the amplification/attenuation factor, expressed
			 * in dB.
			 */
			case 'a':
				/* If the current linear amplification factor is not
				 * one (MAD_F_ONE) then is was already set. Setting it
				 * again is not permitted.
				 */
				if(Amp!=MAD_F_ONE)
				{
					fprintf(stderr,"%s: the amplification/attenuation factor "
							"was set several times.\n",ProgName);
					return(1);
				}

				/* The decibel value is converted to a linear factor.
				 * That factor is checked against the maximum value
				 * that can be stored in a mad_fixed_t. The upper
				 * bound is MAD_F_MAX, it is converted to a double
				 * value with mad_f_todouble() for comparison.
				 */
				AmpFactor=pow(10.,atof(optarg)/20);
				if(AmpFactor>mad_f_todouble(MAD_F_MAX))
				{
					fprintf(stderr,"%s: amplification out of range.\n",
							ProgName);
					return(1);
				}

				/* Eventually the amplification factor is converted
				 * from double to fixed point with mad_f_tofixed().
				 */
				Amp=mad_f_tofixed(AmpFactor);
				break;

			/* {6} The output is filtered through a telephone wire. */
			case 'p':
				/* Only one occurrence of the option is permitted. */
				if(DoPhoneFilter)
				{
					fprintf(stderr,"%s: the phone-line simulation option "
							"was already set.\n",ProgName);
					return(1);
				}

				/* The output will be filtered through a band-pass
				 * filter simulating a phone line transmission.
				 */
				DoPhoneFilter=1;
				break;

			/* Print usage guide for invalid options. */
			case '?':
			default:
				PrintUsage();
				return(1);
		}
#else /* HAVE_GETOPT */ /* This other version is for non-Unix systems. */
	/* Scan all command-line arguments. */
	for(i=1;i<argc;i++)
	{
		/* Set the amplification factor if the current argument looks
		 * like a number. Look at the comment of the case marked {5}
		 * in the Unix section for details.
		 */
		if(*argv[i]=='+' || *argv[i]=='-' || isdigit(*argv[i]))
		{
			if(Amp!=MAD_F_ONE)
			{
				fprintf(stderr,"%s: the amplification/attenuation factor "
						"was set several times.\n",ProgName);
				return(1);
			}

			AmpFactor=pow(10.,atof(argv[i])/20);
			if(AmpFactor>mad_f_todouble(MAD_F_MAX))
			{
				fprintf(stderr,"%s: amplification out of range.\n",
						ProgName);
				return(1);
			}

			Amp=mad_f_tofixed(AmpFactor);
		}
		else
			/* Use the phone-like filter if the argument is the *
			 * 'phone' string. Look at the comment of the case marked
			 * {6} in the Unix section for details.
			 */
			if(strcmp(argv[i],"phone")==0)
			{
				if(DoPhoneFilter)
				{
					fprintf(stderr,"%s: the phone-line simulation option "
							"was already set.\n",ProgName);
					return(1);
				}
				DoPhoneFilter=1;
			}
			else
			{
				/* The argument is not a recognized one. Print the
				 * usage guidelines and stop there.
				 */
				PrintUsage();
				return(1);
			}
	}
#endif /* HAVE_GETOPT */

	/* Initialize the subband-domain filter coefficients to one if
	 * filtering is requested.
	 */
	if(Amp!=MAD_F_ONE || DoPhoneFilter)
		for(i=0;i<32;i++)
			Filter[i]=MAD_F_ONE;

	/* The amplification/attenuation is applied to the subband-domain
     * filter definition.
	 */
	if(Amp!=MAD_F_ONE)
	{
		DoFilter=1;
		for(i=0;i<32;i++)
			Filter[i]=Amp;
	}

	/* The telephone-like filter is applied to the subband-domain
	 * filter definition. All subbands are set to zero except bands 2
	 * to 6. This programs author has no access to the MPEG audio
	 * specification, he does not know the frequencies bands covered
	 * by the MPEG subbands.
	 */
	if(DoPhoneFilter)
	{
		DoFilter=1;
		Filter[0]=MAD_F(0);
		for(i=5;i<32;i++)
			Filter[i]=MAD_F(0);
	}

	/* Command-line arguments are okay. */
	return(0);
}

/****************************************************************************
 * Program entry point.														*
 ****************************************************************************/
int main(int argc, char *argv[])
{
	char	*cptr;
	int		Status;

	/* Keep this for error messages. */
	cptr=strrchr(argv[0],'/');
	if(cptr==NULL)
		ProgName=argv[0];
	else
		ProgName=cptr+1;

	/* The command-line arguments are analyzed. */
	if(ParseArgs(argc,argv))
		return(1);

	/* Decode stdin to stdout. */
	Status=MpegAudioDecoder(stdin,stdout);
	if(Status)
		fprintf(stderr,"%s: an error occurred during decoding.\n",ProgName);

	/* All done. */
	return(Status);
}

/*  LocalWords:  BUFLEN HTAB madlld libmad bstdfile getopt subband ParseArgs JS
 */
/*  LocalWords:  DoFilter subbands errorstr bitrate scalefactor libmad's lu kb
 */
/*  LocalWords:  SWWWFFFFFFFFFFFFFFFFFFFFFFFFFFFF FRACBITS madplay fread synth
 */
/*  LocalWords:  ApplyFilter strftime fracunits atten tSets tRequest tThe tas
 */
/*  LocalWords:  ttransmitted unix todouble tofixed
 */
/*
 * Local Variables:
 * tab-width: 4
 * End:
 */

/****************************************************************************
 * End of file madlld.c														*
 ****************************************************************************/

⌨️ 快捷键说明

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