Click here to Skip to main content
15,886,067 members
Articles / Desktop Programming / MFC

DLL To Decode MP3 To WAV/PCM

Rate me:
Please Sign up or sign in to vote.
4.56/5 (19 votes)
12 Jul 20043 min read 381.8K   9.2K   83  
Source code to produce a DLL that converts MP3 files to WAV or PCM. It is based on the open source library libmad.
/* HTAB = 4 */
/****************************************************************************
 * bstdfile.c -- This module implements a buffered interface for the		*
 * fread(2)	standard function that can signal an eof of file condition		*
 * synchronously with the transmission of the last bytes of a file.			*
 *--------------------------------------------------------------------------*
 * (c) 2004 Bertrand Petit													*
 *																			*
 * Redistribution and use in source and binary forms, with or without		*
 * modification, are permitted provided that the following conditions		*
 * are met:																	*
 *																			*
 * 1. Redistributions of source code must retain the above copyright		*
 *    notice, this list of conditions and the following disclaimer.			*
 *																			*
 * 2. Redistributions in binary form must reproduce the above				*
 *    copyright notice, this list of conditions and the following			*
 *    disclaimer in the documentation and/or other materials provided		*
 *    with the distribution.												*
 * 																			*
 * 3. Neither the name of the author nor the names of its contributors		*
 *    may be used to endorse or promote products derived from this			*
 *    software without specific prior written permission.					*
 * 																			*
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''		*
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED		*
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A			*
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR		*
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,				*
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT			*
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF			*
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND		*
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,		*
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT		*
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF		*
 * SUCH DAMAGE.																*
 *																			*
 ****************************************************************************/

/*
 * $Name:  $
 * $Date: 2004/04/26 20:40:31 $
 * $Revision: 1.1.1.1 $
 */

/****************************************************************************
 * Includes.																*
 ****************************************************************************/
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include "bstdfile.h"

/****************************************************************************
 * Preprocessor definitions													*
 ****************************************************************************/
#define BFILE_BUFSIZE	(8192U)

/* We use some errno symbols that may be undefined. We supply such
 * definitions, all with the 1 value, only to achieve compilation: the
 * semantics of the signaled errors may thus be broken. It is the
 * responsibility of this module user to map the following symbols to
 * the symbols provided by the target system.
 */
#if (!defined(unix) && !defined (__unix__) && !defined(__unix))
/* Memory exhausted */
# ifndef ENOMEM
#  define ENOMEM	(1)
# endif

/* Bad file descriptor */
# ifndef EBADF
#  define EBADF		(1)
# endif

/* Invalid address. */
# ifndef EFAULT
#  define EFAULT	(1)
# endif

/* Invalid argument. */
# ifndef EINVAL
#  define EINVAL	(1)
# endif
#endif

/****************************************************************************
 * Datatypes definitions													*
 ****************************************************************************/
struct bstdfile
{
	/* buffer is an internal buffer used by BstdRead(). live points
	 * inside that buffer to the data that was not yet transmitted to
	 * the user. live_size is the number of bytes available for direct
	 * consumption to feed the user buffer from the live pointer.
	 */
	char	buffer[BFILE_BUFSIZE],
			*live;
	size_t	live_size;

	/* fp is the file opened for reading associated with that bfile. */
	FILE	*fp;

	/* Error management: eof is non-zero when an end of file condition
	 * was detected. error is zero when no error was detected (error
	 * is zero when eof is 1), it stores the errno of the detected
	 * error.
	 */
	int		eof,
			error;
};

/****************************************************************************
 * Creates a new bstdfile from an already opened file.						*
 ****************************************************************************/
bstdfile_t *NewBstdFile(FILE *fp)
{
	bstdfile_t	*BstdFile;

	/* Allocate the bstdfile structure. */
	BstdFile=(bstdfile_t *)malloc(sizeof(bstdfile_t));
	if(BstdFile==NULL)
	{
		errno=ENOMEM;
		return(NULL);
	}

	/* Initialize the structure to safe defaults. */
	BstdFile->live=BstdFile->buffer;
	BstdFile->live_size=0;
	BstdFile->eof=0;
	BstdFile->error=0;
	BstdFile->fp=fp;

	/* Return the new bfile. */
	return(BstdFile);
}

/****************************************************************************
 * Destroys a previously allocated BstdFile.								*
 ****************************************************************************/
int BstdFileDestroy(bstdfile_t *BstdFile)
{
	if(BstdFile==NULL)
	{
		errno=EBADF;
		return(1);
	}
	free(BstdFile);
	return(0);
}

/****************************************************************************
 * This predicate returns a non nul value when there is an end of file		*
 * condition on the BstdFile argument.										*
 ****************************************************************************/
int BstdFileEofP(const bstdfile_t *BstdFile)
{
	return(BstdFile->eof);
}

/****************************************************************************
 * This predicate returns a non nul value when there is an error condition	*
 * on the BstdFile argument.												*
 ****************************************************************************/
int BstdFileErrorP(const bstdfile_t *BstdFile)
{
	return(BstdFile->error);
}

/****************************************************************************
 * This works as read(2) but operates on a bfile instead of a file			*
 * descriptor.																*
 ****************************************************************************/
size_t BstdRead(void *UserBuffer, size_t ElementSize, size_t ElementsCount, bstdfile_t *BstdFile)
{
	size_t	RequestSize=ElementSize*ElementsCount,
			FeededSize=0,
			ReadSize,
			ObtainedSize;
	int		OldErrno=errno;

	/* Check the validity of the arguments. */
	if(BstdFile==NULL)
	{
		errno=EBADF;
		return((size_t)0);
	}
	if(UserBuffer==NULL)
	{
		errno=EFAULT;
		return((size_t)0);
	}
	if(RequestSize<1)
	{
		errno=EINVAL;
		return((size_t)0);
	}

	/* Return immediately if an exceptional situation exists. */
	if(BstdFile->eof)
		return((size_t)0);
	if(BstdFile->error)
	{
		errno=BstdFile->error;
		return((size_t)0);
	}

	/* The easy case. */
	if(RequestSize==0U)
		return((size_t)0);

	/* First feed the target buffer from the BstdFile buffer if it has
	 * some meat to be feeded on.
	 */
	if(BstdFile->live_size>0)
	{
		/* If there is more data in the buffer than requested by the
		 * user then we feed him directly from our buffer without a
		 * read operation.
		 */
		if(BstdFile->live_size>RequestSize)
		{
			memcpy(UserBuffer,BstdFile->live,RequestSize);
			BstdFile->live+=RequestSize;
			BstdFile->live_size-=RequestSize;
			return(RequestSize);
		}
		/* Else we drain our buffer. */
		else
		{
			memcpy(UserBuffer,BstdFile->live,BstdFile->live_size);
			UserBuffer=(char *)UserBuffer+BstdFile->live_size;
			FeededSize=BstdFile->live_size;
			BstdFile->live=BstdFile->buffer;
			BstdFile->live_size=0;
		}
	}

	/* If the user request was not yet fulfilled we then read from the
     * file the remaining data requested by the user.
	 */
	if(FeededSize<RequestSize)
	{
		ReadSize=RequestSize-FeededSize;
		ObtainedSize=fread(UserBuffer,1,ReadSize,BstdFile->fp);
		FeededSize+=ObtainedSize;

		/* If an error occurs we return the amount of data that was
		 * feeded from the buffer and store the error condition for a
		 * later call. If our buffer was empty and we thus have
		 * transferred no data to the user buffer then we directly
		 * return the error.
		 */
		if(ObtainedSize==0U)
		{
			if(feof(BstdFile->fp))
				BstdFile->eof=1;
			else
			{
				BstdFile->error=errno;
				errno=OldErrno;
			}
			if(FeededSize!=0)
				return(FeededSize);
			else
				return(0U);
		}
	}

	/* Fill again our buffer. In case of error, or end of file, that
	 * error is recorded but we still report the amount of data that
	 * was feeded to the user buffer.
	 */
	ObtainedSize=fread(BstdFile->buffer,1,BFILE_BUFSIZE,BstdFile->fp);
	if(ObtainedSize==0)
	{
		if(feof(BstdFile->fp))
			BstdFile->eof=1;
		else
		{
			BstdFile->error=errno;
			errno=OldErrno;
		}
	}
	else
	{
		BstdFile->live=BstdFile->buffer;
		BstdFile->live_size=ObtainedSize;
	}

	/* Eventually return the number ob bytes feeded to the user
     * buffer.
	 */
	return(FeededSize);
}

/*  LocalWords:  HTAB bstdfile fread Datatypes BstdRead fp bfile BstdFile
 */
/*
 * Local Variables:
 * tab-width: 4
 * End:
 */

/****************************************************************************
 * End of file bstdfile.c														*
 ****************************************************************************/

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions