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

📄 aiff.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 3 页
字号:
/*** Copyright (C) 1999-2004 Erik de Castro Lopo <erikd@mega-nerd.com>**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU Lesser General Public License as published by** the Free Software Foundation; either version 2.1 of the License, or** (at your option) any later version.**** This program 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 Lesser General Public License for more details.**** You should have received a copy of the GNU Lesser General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#include "config.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <ctype.h>#include "sndfile.h"#include "sfendian.h"#include "common.h"/*------------------------------------------------------------------------------ * Macros to handle big/little endian issues. */#define FORM_MARKER	(MAKE_MARKER ('F', 'O', 'R', 'M'))#define AIFF_MARKER	(MAKE_MARKER ('A', 'I', 'F', 'F'))#define AIFC_MARKER	(MAKE_MARKER ('A', 'I', 'F', 'C'))#define COMM_MARKER	(MAKE_MARKER ('C', 'O', 'M', 'M'))#define SSND_MARKER	(MAKE_MARKER ('S', 'S', 'N', 'D'))#define MARK_MARKER	(MAKE_MARKER ('M', 'A', 'R', 'K'))#define INST_MARKER	(MAKE_MARKER ('I', 'N', 'S', 'T'))#define APPL_MARKER	(MAKE_MARKER ('A', 'P', 'P', 'L'))#define c_MARKER	(MAKE_MARKER ('(', 'c', ')', ' '))#define NAME_MARKER	(MAKE_MARKER ('N', 'A', 'M', 'E'))#define AUTH_MARKER	(MAKE_MARKER ('A', 'U', 'T', 'H'))#define ANNO_MARKER	(MAKE_MARKER ('A', 'N', 'N', 'O'))#define COMT_MARKER	(MAKE_MARKER ('C', 'O', 'M', 'T'))#define FVER_MARKER	(MAKE_MARKER ('F', 'V', 'E', 'R'))#define SFX_MARKER	(MAKE_MARKER ('S', 'F', 'X', '!'))#define PEAK_MARKER	(MAKE_MARKER ('P', 'E', 'A', 'K'))#define basc_MARKER	(MAKE_MARKER ('b', 'a', 's', 'c'))/* Supported AIFC encodings.*/#define NONE_MARKER	(MAKE_MARKER ('N', 'O', 'N', 'E'))#define sowt_MARKER	(MAKE_MARKER ('s', 'o', 'w', 't'))#define twos_MARKER	(MAKE_MARKER ('t', 'w', 'o', 's'))#define raw_MARKER	(MAKE_MARKER ('r', 'a', 'w', ' '))#define in32_MARKER	(MAKE_MARKER ('i', 'n', '3', '2'))#define ni32_MARKER	(MAKE_MARKER ('2', '3', 'n', 'i'))#define fl32_MARKER	(MAKE_MARKER ('f', 'l', '3', '2'))#define FL32_MARKER	(MAKE_MARKER ('F', 'L', '3', '2'))#define fl64_MARKER	(MAKE_MARKER ('f', 'l', '6', '4'))#define FL64_MARKER	(MAKE_MARKER ('F', 'L', '6', '4'))#define ulaw_MARKER	(MAKE_MARKER ('u', 'l', 'a', 'w'))#define ULAW_MARKER	(MAKE_MARKER ('U', 'L', 'A', 'W'))#define alaw_MARKER	(MAKE_MARKER ('a', 'l', 'a', 'w'))#define ALAW_MARKER	(MAKE_MARKER ('A', 'L', 'A', 'W'))#define DWVW_MARKER	(MAKE_MARKER ('D', 'W', 'V', 'W'))#define GSM_MARKER	(MAKE_MARKER ('G', 'S', 'M', ' '))#define ima4_MARKER	(MAKE_MARKER ('i', 'm', 'a', '4'))/* Unsupported AIFC encodings.*/#define MAC3_MARKER	(MAKE_MARKER ('M', 'A', 'C', '3'))#define MAC6_MARKER	(MAKE_MARKER ('M', 'A', 'C', '6'))#define ADP4_MARKER	(MAKE_MARKER ('A', 'D', 'P', '4'))/* Predfined chunk sizes. */#define SIZEOF_AIFF_COMM		18#define SIZEOF_AIFC_COMM_MIN	22#define SIZEOF_AIFC_COMM		24#define SIZEOF_SSND_CHUNK		8#define SIZEOF_INST_CHUNK		20/* Is it constant? */#define SIZEOF_basc_CHUNK				0x54#define SIZEOF_basc_CHUNK_PADDING		66/* AIFC/IMA4 defines. */#define AIFC_IMA4_BLOCK_LEN				34#define	AIFC_IMA4_SAMPLES_PER_BLOCK		64/*------------------------------------------------------------------------------ * Typedefs for file chunks. */enum{	HAVE_FORM	= 0x01,	HAVE_AIFF	= 0x02,	HAVE_COMM	= 0x04,	HAVE_SSND	= 0x08} ;typedef struct{	unsigned int	size ;	short			numChannels ;	unsigned int	numSampleFrames ;	short			sampleSize ;	unsigned char	sampleRate [10] ;	unsigned int	encoding ;	char			zero_bytes [2] ;} COMM_CHUNK ;typedef struct{	unsigned int	offset ;	unsigned int	blocksize ;} SSND_CHUNK ;typedef struct{	short			playMode ;    unsigned short	beginLoop ;	unsigned short	endLoop ;} INST_LOOP ;typedef struct{	char		baseNote ;		/* all notes are MIDI note numbers */	char		detune ;		/* cents off, only -50 to +50 are significant */	char		lowNote ;	char		highNote ;	char		lowVelocity ;	/* 1 to 127 */	char		highVelocity ;	/* 1 to 127 */	short		gain ;			/* in dB, 0 is normal */	INST_LOOP	sustain_loop ;	INST_LOOP	release_loop ;} INST_CHUNK ;enum{	basc_SCALE_MINOR = 1,	basc_SCALE_MAJOR,	basc_SCALE_NEITHER,	basc_SCALE_BOTH,} ;enum{	basc_TYPE_LOOP = 0,	basc_TYPE_ONE_SHOT,} ;typedef struct{	unsigned int	version ;	unsigned int	numBeats ;	unsigned short	rootNote ;	unsigned short	scaleType ;	unsigned short	sigNumerator ;	unsigned short	sigDenominator ;	unsigned short	loopType ;	char			zero_bytes [SIZEOF_basc_CHUNK_PADDING] ;} basc_CHUNK ;/*------------------------------------------------------------------------------ * Private static functions. */static int	aiff_close	(SF_PRIVATE *psf) ;static int	tenbytefloat2int (unsigned char *bytes) ;static void	uint2tenbytefloat (unsigned int num, unsigned char *bytes) ;static int	aiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) ;static int	aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) ;static int	aiff_write_header (SF_PRIVATE *psf, int calc_length) ;static int	aiff_write_tailer (SF_PRIVATE *psf) ;static void aiff_write_strings (SF_PRIVATE *psf, int location) ;static int	aiff_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;static const char *get_loop_mode_str (short mode) ;static int aiff_read_basc_chunk (SF_PRIVATE * psf) ;/*------------------------------------------------------------------------------** Public function.*/intaiff_open	(SF_PRIVATE *psf){	COMM_CHUNK comm_fmt ;	int error, subformat ;	subformat = psf->sf.format & SF_FORMAT_SUBMASK ;	if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))	{	if ((error = aiff_read_header (psf, &comm_fmt)))			return error ;		psf_fseek (psf, psf->dataoffset, SEEK_SET) ;		} ;	if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)	{	if (psf->is_pipe)			return SFE_NO_PIPE_WRITE ;		if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AIFF)			return	SFE_BAD_OPEN_FORMAT ;		if (psf->mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE))		{	psf->pchunk = calloc (1, sizeof (PEAK_CHUNK) * psf->sf.channels * sizeof (PEAK_POS)) ;			if (psf->pchunk == NULL)				return SFE_MALLOC_FAILED ;			psf->has_peak = SF_TRUE ;			psf->peak_loc = SF_PEAK_START ;			} ;		if (psf->mode != SFM_RDWR || psf->filelength < 40)		{	psf->filelength = 0 ;			psf->datalength = 0 ;			psf->dataoffset = 0 ;			psf->sf.frames = 0 ;			} ;		psf->str_flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ;		if ((error = aiff_write_header (psf, SF_FALSE)))			return error ;		psf->write_header = aiff_write_header ;		} ;	psf->close = aiff_close ;	psf->command = aiff_command ;	psf->blockwidth = psf->sf.channels * psf->bytewidth ;	switch (psf->sf.format & SF_FORMAT_SUBMASK)	{	case SF_FORMAT_PCM_U8 :				error = pcm_init (psf) ;				break ;		case SF_FORMAT_PCM_S8 :				error = pcm_init (psf) ;				break ;		case SF_FORMAT_PCM_16 :		case SF_FORMAT_PCM_24 :		case SF_FORMAT_PCM_32 :				error = pcm_init (psf) ;				break ;		case SF_FORMAT_ULAW :				error = ulaw_init (psf) ;				break ;		case SF_FORMAT_ALAW :				error = alaw_init (psf) ;				break ;		/* Lite remove start */		case SF_FORMAT_FLOAT :				error = float32_init (psf) ;				break ;		case SF_FORMAT_DOUBLE :				error = double64_init (psf) ;				break ;		case SF_FORMAT_DWVW_12 :				error = dwvw_init (psf, 12) ;				break ;		case SF_FORMAT_DWVW_16 :				error = dwvw_init (psf, 16) ;				break ;		case SF_FORMAT_DWVW_24 :				error = dwvw_init (psf, 24) ;				break ;		case SF_FORMAT_DWVW_N :				if (psf->mode != SFM_READ)				{	error = SFE_DWVW_BAD_BITWIDTH ;					break ;					} ;				if (comm_fmt.sampleSize >= 8 && comm_fmt.sampleSize < 24)				{	error = dwvw_init (psf, comm_fmt.sampleSize) ;					psf->sf.frames = comm_fmt.numSampleFrames ;					break ;					} ;				psf_log_printf (psf, "AIFC/DWVW : Bad bitwidth %d\n", comm_fmt.sampleSize) ;				error = SFE_DWVW_BAD_BITWIDTH ;				break ;		case SF_FORMAT_IMA_ADPCM :				/*				**	IMA ADPCM encoded AIFF files always have a block length				**	of 34 which decodes to 64 samples.				*/				error = aiff_ima_init (psf, AIFC_IMA4_BLOCK_LEN, AIFC_IMA4_SAMPLES_PER_BLOCK) ;				break ;		/* Lite remove end */		case SF_FORMAT_GSM610 :				error = gsm610_init (psf) ;				break ;		default : return SFE_UNIMPLEMENTED ;		} ;	if (psf->mode == SFM_READ)		psf->blockwidth = psf->sf.channels * psf->bytewidth ;	return error ;} /* aiff_open *//*==========================================================================================** Private functions.*/static intaiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt){	SSND_CHUNK	ssnd_fmt ;	int			marker, dword, bytesread, k ;	int			FORMsize, SSNDsize ;	int			filetype, found_chunk = 0, done = 0, error = 0 ;	char		*cptr, byte ;	/* Set position to start of file to begin reading header. */	psf_binheader_readf (psf, "p", 0) ;	memset (comm_fmt, 0, sizeof (COMM_CHUNK)) ;	/* Until recently AIF* file were all BIG endian. */	psf->endian = SF_ENDIAN_BIG ;	/* 	AIFF files can apparently have their chunks in any order. However, they	**	must have a FORM chunk. Approach here is to read all the chunks one by	**  one and then check for the mandatory chunks at the end.	*/	while (! done)	{	psf_binheader_readf (psf, "m", &marker) ;		if (psf->mode == SFM_RDWR && (found_chunk & HAVE_SSND))			return SFE_AIFF_RW_SSND_NOT_LAST ;		switch (marker)		{	case FORM_MARKER :					if (found_chunk)						return SFE_AIFF_NO_FORM ;					psf_binheader_readf (psf, "E4", &FORMsize) ;					if (psf->fileoffset > 0 && psf->filelength > FORMsize + 8)					{	/* Set file length. */						psf->filelength = FORMsize + 8 ;						psf_log_printf (psf, "FORM : %u\n", FORMsize) ;						}					else if (FORMsize != psf->filelength - 2 * SIGNED_SIZEOF (dword))					{	dword = psf->filelength - 2 * sizeof (dword) ;						psf_log_printf (psf, "FORM : %u (should be %u)\n", FORMsize, dword) ;						FORMsize = dword ;						}					else						psf_log_printf (psf, "FORM : %u\n", FORMsize) ;					found_chunk |= HAVE_FORM ;					break ;			case AIFC_MARKER :			case AIFF_MARKER :					if (! (found_chunk & HAVE_FORM))						return SFE_AIFF_AIFF_NO_FORM ;					filetype = marker ;					psf_log_printf (psf, " %M\n", marker) ;					found_chunk |= HAVE_AIFF ;					break ;			case COMM_MARKER :					error = aiff_read_comm_chunk (psf, comm_fmt) ;					psf->sf.samplerate 	= tenbytefloat2int (comm_fmt->sampleRate) ;					psf->sf.frames 	= comm_fmt->numSampleFrames ;					psf->sf.channels 	= comm_fmt->numChannels ;					psf->bytewidth 		= BITWIDTH2BYTES (comm_fmt->sampleSize) ;					if (error)						return error ;					found_chunk |= HAVE_COMM ;					break ;			case PEAK_MARKER :					/* Must have COMM chunk before PEAK chunk. */					if ((found_chunk & (HAVE_FORM | HAVE_AIFF | HAVE_COMM)) != (HAVE_FORM | HAVE_AIFF | HAVE_COMM))						return SFE_AIFF_PEAK_B4_COMM ;					psf_binheader_readf (psf, "E4", &dword) ;					psf_log_printf (psf, "%M : %d\n", marker, dword) ;					if (dword != SIGNED_SIZEOF (PEAK_CHUNK) + psf->sf.channels * SIGNED_SIZEOF (PEAK_POS))					{	psf_binheader_readf (psf, "j", dword) ;						psf_log_printf (psf, "*** File PEAK chunk bigger than sizeof (PEAK_CHUNK).\n") ;						return SFE_WAV_BAD_PEAK ;						} ;					psf->pchunk = calloc (1, sizeof (PEAK_CHUNK) * psf->sf.channels * sizeof (PEAK_POS)) ;					if (psf->pchunk == NULL)						return SFE_MALLOC_FAILED ;					/* read in rest of PEAK chunk. */					psf_binheader_readf (psf, "E44", &(psf->pchunk->version), &(psf->pchunk->timestamp)) ;					if (psf->pchunk->version != 1)						psf_log_printf (psf, "  version    : %d *** (should be version 1)\n", psf->pchunk->version) ;					else						psf_log_printf (psf, "  version    : %d\n", psf->pchunk->version) ;					psf_log_printf (psf, "  time stamp : %d\n", psf->pchunk->timestamp) ;					psf_log_printf (psf, "    Ch   Position       Value\n") ;					cptr = psf->u.scbuf ;					for (dword = 0 ; dword < psf->sf.channels ; dword++)					{	psf_binheader_readf (psf, "Ef4", &(psf->pchunk->peaks [dword].value),														&(psf->pchunk->peaks [dword].position)) ;						LSF_SNPRINTF (cptr, sizeof (psf->u.scbuf), "    %2d   %-12d   %g\n",								dword, psf->pchunk->peaks [dword].position, psf->pchunk->peaks [dword].value) ;						cptr [sizeof (psf->u.scbuf) - 1] = 0 ;						psf_log_printf (psf, cptr) ;						} ;					psf->has_peak = SF_TRUE ; /* Found PEAK chunk. */					break ;			case SSND_MARKER :					psf_binheader_readf (psf, "E444", &SSNDsize, &(ssnd_fmt.offset), &(ssnd_fmt.blocksize)) ;					psf->datalength = SSNDsize - sizeof (ssnd_fmt) ;					psf->dataoffset = psf_ftell (psf) ;					if (psf->datalength > psf->filelength - psf->dataoffset || psf->datalength < 0)					{	psf_log_printf (psf, " SSND : %u (should be %D)\n", SSNDsize, psf->filelength - psf->dataoffset + sizeof (SSND_CHUNK)) ;						psf->datalength = psf->filelength - psf->dataoffset ;

⌨️ 快捷键说明

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