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

📄 voc.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** Copyright (C) 2001-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.*//*	RANT:**	The VOC file format is the most brain damaged format I have yet had to deal**	with. No one programmer could have bee stupid enough to put this together.**	Instead it looks like a series of manic, dyslexic assembly language programmers**	hacked it to fit their needs.**	Utterly woeful.*/#include "config.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include "sndfile.h"#include "sfendian.h"#include "common.h"/*------------------------------------------------------------------------------ * Typedefs for file chunks.*/#define	VOC_MAX_SECTIONS	200enum{	VOC_TERMINATOR		= 0,	VOC_SOUND_DATA		= 1,	VOC_SOUND_CONTINUE	= 2,	VOC_SILENCE			= 3,	VOC_MARKER			= 4,	VOC_ASCII			= 5,	VOC_REPEAT			= 6,	VOC_END_REPEAT		= 7,	VOC_EXTENDED		= 8,	VOC_EXTENDED_II		= 9} ;typedef struct{	int 	samples ;	int		offset ;	/* Offset of zero => silence. */} SND_DATA_BLOCKS ;typedef struct{	unsigned int 	sections, section_types ;	int				samplerate, channels, bitwidth ;	SND_DATA_BLOCKS	blocks [VOC_MAX_SECTIONS] ;} VOC_DATA ;/*------------------------------------------------------------------------------ * Private static functions.*/static	int	voc_close	(SF_PRIVATE *psf) ;static	int voc_write_header (SF_PRIVATE *psf, int calc_length) ;static	int voc_read_header	(SF_PRIVATE *psf) ;static const char* voc_encoding2str (int encoding) ;#if 0/*	These functions would be required for files with more than one VOC_SOUND_DATA**	segment. Not sure whether to bother implementing this.*/static int	voc_multi_init (SF_PRIVATE *psf, VOC_DATA *pvoc) ;static int	voc_multi_read_uc2s		(SF_PRIVATE *psf, short *ptr, int len) ;static int	voc_multi_read_les2s	(SF_PRIVATE *psf, short *ptr, int len) ;static int	voc_multi_read_uc2i		(SF_PRIVATE *psf, int *ptr, int len) ;static int	voc_multi_read_les2i	(SF_PRIVATE *psf, int *ptr, int len) ;static int	voc_multi_read_uc2f		(SF_PRIVATE *psf, float *ptr, int len) ;static int	voc_multi_read_les2f	(SF_PRIVATE *psf, float *ptr, int len) ;static int	voc_multi_read_uc2d		(SF_PRIVATE *psf, double *ptr, int len) ;static int	voc_multi_read_les2d	(SF_PRIVATE *psf, double *ptr, int len) ;#endif/*------------------------------------------------------------------------------** Public function.*/intvoc_open	(SF_PRIVATE *psf){	int subformat, error = 0 ;	if (psf->is_pipe)		return SFE_VOC_NO_PIPE ;	if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))	{	if ((error = voc_read_header (psf)))			return error ;		} ;	subformat = psf->sf.format & SF_FORMAT_SUBMASK ;	if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)	{	if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC)			return	SFE_BAD_OPEN_FORMAT ;		psf->endian = SF_ENDIAN_LITTLE ;		if ((error = voc_write_header (psf, SF_FALSE)))			return error ;		psf->write_header = voc_write_header ;		} ;	psf->blockwidth = psf->bytewidth * psf->sf.channels ;	psf->close = voc_close ;	switch (subformat)	{	case SF_FORMAT_PCM_U8 :		case SF_FORMAT_PCM_16 :				error = pcm_init (psf) ;				break ;		case SF_FORMAT_ALAW :				error = alaw_init (psf) ;				break ;		case SF_FORMAT_ULAW :				error = ulaw_init (psf) ;				break ;		default : return SFE_UNIMPLEMENTED ;		} ;	return error ;} /* voc_open *//*------------------------------------------------------------------------------*/static intvoc_read_header	(SF_PRIVATE *psf){	VOC_DATA	*pvoc ;	char	creative [20] ;	unsigned char block_type, rate_byte ;	short	version, checksum, encoding, dataoffset ;	int		offset ;	/* Set position to start of file to begin reading header. */	offset = psf_binheader_readf (psf, "pb", 0, creative, SIGNED_SIZEOF (creative)) ;	if (creative [sizeof (creative) - 1] != 0x1A)		return SFE_VOC_NO_CREATIVE ;	/* Terminate the string. */	creative [sizeof (creative) - 1] = 0 ;	if (strcmp ("Creative Voice File", creative))		return SFE_VOC_NO_CREATIVE ;	psf_log_printf (psf, "%s\n", creative) ;	offset += psf_binheader_readf (psf, "e222", &dataoffset, &version, &checksum) ;	psf->dataoffset = dataoffset ;	psf_log_printf (psf, 	"dataoffset : %d\n"							"version    : 0x%X\n"							"checksum   : 0x%X\n", psf->dataoffset, version, checksum) ;	if (version != 0x010A && version != 0x0114)		return SFE_VOC_BAD_VERSION ;	if (! (psf->fdata = malloc (sizeof (VOC_DATA))))		return SFE_MALLOC_FAILED ;	pvoc = (VOC_DATA*) psf->fdata ;	memset (pvoc, 0, sizeof (VOC_DATA)) ;	/* Set the default encoding now. */	psf->sf.format = SF_FORMAT_VOC ; /* Major format */	encoding = SF_FORMAT_PCM_U8 ; /* Minor format */	psf->endian = SF_ENDIAN_LITTLE ;	while (1)	{	offset += psf_binheader_readf (psf, "1", &block_type) ;		switch (block_type)		{	case VOC_ASCII :					{	int size ;						offset += psf_binheader_readf (psf, "e3", &size) ;						psf_log_printf (psf, " ASCII : %d\n", size) ;						offset += psf_binheader_readf (psf, "b", psf->header, size) ;						psf->header [size] = 0 ;						psf_log_printf (psf, "  text : %s\n", psf->header) ;						} ;					continue ;			case VOC_SOUND_DATA :			case VOC_EXTENDED :			case VOC_EXTENDED_II :					break ;			default : psf_log_printf (psf, "*** Weird block marker (%d)\n", block_type) ;			} ;		break ;		} ;	if (block_type == VOC_SOUND_DATA)	{	unsigned char compression ;		int 	size ;		offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ;		psf->sf.samplerate = 1000000 / (256 - (rate_byte & 0xFF)) ;		psf_log_printf (psf, " Sound Data : %d\n  sr   : %d => %dHz\n  comp : %d\n",								size, rate_byte, psf->sf.samplerate, compression) ;		if (offset + size - 1 > psf->filelength)		{	psf_log_printf (psf, "Seems to be a truncated file.\n") ;			psf_log_printf (psf, "offset: %d    size: %d    sum: %d    filelength: %D\n", offset, size, offset + size, psf->filelength) ;			return SFE_VOC_BAD_SECTIONS ;			}		else if (offset + size - 1 < psf->filelength)		{	psf_log_printf (psf, "Seems to be a multi-segment file (#1).\n") ;			psf_log_printf (psf, "offset: %d    size: %d    sum: %d    filelength: %D\n", offset, size, offset + size, psf->filelength) ;			return SFE_VOC_BAD_SECTIONS ;			} ;		psf->dataoffset = offset ;		psf->dataend	= psf->filelength - 1 ;		psf->sf.channels = 1 ;		psf->bytewidth = 1 ;		psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ;		return 0 ;		} ;	if (block_type == VOC_EXTENDED)	{	unsigned char pack, stereo, compression ;		unsigned short rate_short ;		int		size ;		offset += psf_binheader_readf (psf, "e3211", &size, &rate_short, &pack, &stereo) ;		psf_log_printf (psf, " Extended : %d\n", size) ;		if (size == 4)			psf_log_printf (psf, "  size   : 4\n") ;		else			psf_log_printf (psf, "  size   : %d (should be 4)\n", size) ;		psf_log_printf (psf,	"  pack   : %d\n"								"  stereo : %s\n", pack, (stereo ? "yes" : "no")) ;		if (stereo)		{	psf->sf.channels = 2 ;			psf->sf.samplerate = 128000000 / (65536 - rate_short) ;			}		else		{	psf->sf.channels = 1 ;			psf->sf.samplerate = 256000000 / (65536 - rate_short) ;			} ;		psf_log_printf (psf, "  sr     : %d => %dHz\n", (rate_short & 0xFFFF), psf->sf.samplerate) ;		offset += psf_binheader_readf (psf, "1", &block_type) ;		if (block_type != VOC_SOUND_DATA)		{	psf_log_printf (psf, "*** Expecting VOC_SOUND_DATA section.\n") ;			return SFE_VOC_BAD_FORMAT ;			} ;		offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ;		psf_log_printf (psf,	" Sound Data : %d\n"								"  sr     : %d\n"								"  comp   : %d\n", size, rate_byte, compression) ;		if (offset + size - 1 > psf->filelength)		{	psf_log_printf (psf, "Seems to be a truncated file.\n") ;			psf_log_printf (psf, "offset: %d    size: %d    sum: %d    filelength: %D\n", offset, size, offset + size, psf->filelength) ;			return SFE_VOC_BAD_SECTIONS ;			}		else if (offset + size - 1 < psf->filelength)		{	psf_log_printf (psf, "Seems to be a multi-segment file (#2).\n") ;			psf_log_printf (psf, "offset: %d    size: %d    sum: %d    filelength: %D\n", offset, size, offset + size, psf->filelength) ;			return SFE_VOC_BAD_SECTIONS ;			} ;		psf->dataoffset = offset ;		psf->dataend = psf->filelength - 1 ;		psf->bytewidth = 1 ;		psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ;		return 0 ;		}	if (block_type == VOC_EXTENDED_II)	{	unsigned char bitwidth, channels ;		int size, fourbytes ;		offset += psf_binheader_readf (psf, "e341124", &size, &psf->sf.samplerate,								&bitwidth, &channels, &encoding, &fourbytes) ;		if (size * 2 == psf->filelength - 39)		{	int temp_size = psf->filelength - 31 ;			psf_log_printf (psf, " Extended II : %d (SoX bug: should be %d)\n", size, temp_size) ;			size = temp_size ;			}		else			psf_log_printf (psf, " Extended II : %d\n", size) ;		psf_log_printf (psf,	"  sample rate : %d\n"								"  bit width   : %d\n"								"  channels    : %d\n", psf->sf.samplerate, bitwidth, channels) ;		if (bitwidth == 16 && encoding == 0)		{	encoding = 4 ;			psf_log_printf (psf, "  encoding    : 0 (SoX bug: should be 4 for 16 bit signed PCM)\n") ;			}		else			psf_log_printf (psf, "  encoding    : %d => %s\n", encoding, voc_encoding2str (encoding)) ;		psf_log_printf (psf, "  fourbytes   : %X\n", fourbytes) ;		psf->sf.channels = channels ;		psf->dataoffset = offset ;		psf->dataend	= psf->filelength - 1 ;		if (size + 31 == psf->filelength + 1)		{	/* Hack for reading files produced using			** sf_command (SFC_UPDATE_HEADER_NOW).			*/			psf_log_printf (psf, "Missing zero byte at end of file.\n") ;			size = psf->filelength - 30 ;			psf->dataend = 0 ;			}		else if (size + 31 > psf->filelength)		{	psf_log_printf (psf, "Seems to be a truncated file.\n") ;			size = psf->filelength - 31 ;			}		else if (size + 31 < psf->filelength)			psf_log_printf (psf, "Seems to be a multi-segment file (#3).\n") ;		switch (encoding)		{	case 0 :					psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ;					psf->bytewidth = 1 ;					break ;			case 4 :					psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_16 ;					psf->bytewidth = 2 ;					break ;			case 6 :					psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ALAW ;					psf->bytewidth = 1 ;					break ;			case 7 :					psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ULAW ;					psf->bytewidth = 1 ;					break ;			default : /* Unknown */					return SFE_UNKNOWN_FORMAT ;					break ;			} ;		} ;	return 0 ;} /* voc_read_header *//*====================================================================================*/static intvoc_write_header (SF_PRIVATE *psf, int calc_length){	sf_count_t	current ;	int			rate_const, subformat ;	current = psf_ftell (psf) ;	if (calc_length)	{	psf->filelength = psf_get_filelen (psf) ;		psf->datalength = psf->filelength - psf->dataoffset ;		if (psf->dataend)			psf->datalength -= psf->filelength - psf->dataend ;		psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;		} ;	subformat = psf->sf.format & SF_FORMAT_SUBMASK ;	/* Reset the current header length to zero. */	psf->header [0] = 0 ;	psf->headindex = 0 ;	psf_fseek (psf, 0, SEEK_SET) ;	/* VOC marker and 0x1A byte. */	psf_binheader_writef (psf, "eb1", "Creative Voice File", 19, 0x1A) ;	/* Data offset, version and other. */	psf_binheader_writef (psf, "e222", 26, 0x0114, 0x111F) ;	/*	Use same logic as SOX.	**	If the file is mono 8 bit data, use VOC_SOUND_DATA.	**	If the file is mono 16 bit data, use VOC_EXTENED.	**	Otherwise use VOC_EXTENED_2.

⌨️ 快捷键说明

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