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

📄 sds.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** Copyright (C) 2002-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 <fcntl.h>#include <string.h>#include <ctype.h>#include "sndfile.h"#include "sfendian.h"#include "common.h"#include "float_cast.h"/*------------------------------------------------------------------------------*/#define	SDS_DATA_OFFSET				0x15#define SDS_BLOCK_SIZE				127#define SDS_AUDIO_BYTES_PER_BLOCK	120#define SDS_3BYTE_TO_INT_DECODE(x) (((x) & 0x7F) | (((x) & 0x7F00) >> 1) | (((x) & 0x7F0000) >> 2))#define SDS_INT_TO_3BYTE_ENCODE(x) (((x) & 0x7F) | (((x) << 1) & 0x7F00) | (((x) << 2) & 0x7F0000))/*------------------------------------------------------------------------------** Typedefs.*/typedef struct tag_SDS_PRIVATE{	int bitwidth, frames ;	int	samplesperblock, total_blocks ;	int (*reader) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ;	int (*writer) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ;	int read_block, read_count ;	unsigned char read_data [SDS_BLOCK_SIZE] ;	int	read_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */	int write_block, write_count ;	unsigned char write_data [SDS_BLOCK_SIZE] ;	int	write_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */} SDS_PRIVATE ;/*------------------------------------------------------------------------------** Private static functions.*/static int	sds_close	(SF_PRIVATE *psf) ;static int	sds_write_header (SF_PRIVATE *psf, int calc_length) ;static int	sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;static int	sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;static sf_count_t sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;static sf_count_t sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;static sf_count_t sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;static sf_count_t sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;static sf_count_t sds_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;static sf_count_t sds_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;static sf_count_t sds_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;static sf_count_t sds_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;static sf_count_t sds_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;static int sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;static int sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;static int sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;static int sds_read (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *iptr, int readcount) ;static int sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;static int sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;static int sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;static int sds_write (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *iptr, int writecount) ;/*------------------------------------------------------------------------------** Public function.*/intsds_open	(SF_PRIVATE *psf){	SDS_PRIVATE	*psds ;	int			subformat, error = 0 ;	/* Hmmmm, need this here to pass update_header_test. */	psf->sf.frames = 0 ;	if (! (psds = calloc (1, sizeof (SDS_PRIVATE))))		return SFE_MALLOC_FAILED ;	psf->fdata = psds ;	if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))	{	if ((error = sds_read_header (psf, psds)))			return error ;		} ;	if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SDS)		return	SFE_BAD_OPEN_FORMAT ;	subformat = psf->sf.format & SF_FORMAT_SUBMASK ;	if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)	{	if (sds_write_header (psf, SF_FALSE))			return psf->error ;		psf->write_header = sds_write_header ;		psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ;		} ;	if ((error = sds_init (psf, psds)) != 0)		return error ;	psf->seek = sds_seek ;	psf->close = sds_close ;	psf->blockwidth = 0 ;	return error ;} /* sds_open *//*------------------------------------------------------------------------------*/static intsds_close	(SF_PRIVATE *psf){	if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)	{	SDS_PRIVATE *psds ;		if ((psds = (SDS_PRIVATE *) psf->fdata) == NULL)		{	psf_log_printf (psf, "*** Bad psf->fdata ptr.\n") ;			return SFE_INTERNAL ;			} ;		if (psds->write_count > 0)		{	memset (&(psds->write_data [psds->write_count]), 0, (psds->samplesperblock - psds->write_count) * sizeof (int)) ;			psds->writer (psf, psds) ;			} ;		sds_write_header (psf, SF_TRUE) ;		} ;	return 0 ;} /* sds_close */static intsds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds){	if (psds->bitwidth < 8 || psds->bitwidth > 28)		return (psf->error = SFE_SDS_BAD_BIT_WIDTH) ;	if (psds->bitwidth < 14)	{	psds->reader = sds_2byte_read ;		psds->writer = sds_2byte_write ;		psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 2 ;		}	else if (psds->bitwidth < 21)	{	psds->reader = sds_3byte_read ;		psds->writer = sds_3byte_write ;		psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 3 ;		}	else	{	psds->reader = sds_4byte_read ;		psds->writer = sds_4byte_write ;		psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 4 ;		} ;	if (psf->mode == SFM_READ || psf->mode == SFM_RDWR)	{	psf->read_short		= sds_read_s ;		psf->read_int		= sds_read_i ;		psf->read_float		= sds_read_f ;		psf->read_double	= sds_read_d ;		/* Read first block. */		psds->reader (psf, psds) ;		} ;	if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)	{	psf->write_short	= sds_write_s ;		psf->write_int		= sds_write_i ;		psf->write_float	= sds_write_f ;		psf->write_double	= sds_write_d ;		} ;	return 0 ;} /* sds_init */static intsds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds){	unsigned char	channel, bitwidth, loop_type, byte ;	unsigned short	sample_no, marker ;	unsigned int	samp_period, data_length, sustain_loop_start, sustain_loop_end ;	int		bytesread, blockcount ;	/* Set position to start of file to begin reading header. */	bytesread = psf_binheader_readf (psf, "pE211", 0, &marker, &channel, &byte) ;	if (marker != 0xF07E || byte != 0x01)		return SFE_SDS_NOT_SDS ;	psf_log_printf (psf, "Midi Sample Dump Standard (.sds)\nF07E\n Midi Channel  : %d\n", channel) ;	bytesread += psf_binheader_readf (psf, "e213", &sample_no, &bitwidth, &samp_period) ;	sample_no = SDS_3BYTE_TO_INT_DECODE (sample_no) ;	samp_period = SDS_3BYTE_TO_INT_DECODE (samp_period) ;	psds->bitwidth = bitwidth ;	psf->sf.samplerate = 1000000000 / samp_period ;	psf_log_printf (psf, 	" Sample Number : %d\n"							" Bit Width     : %d\n"							" Sample Rate   : %d\n",			sample_no, psds->bitwidth, psf->sf.samplerate) ;	bytesread += psf_binheader_readf (psf, "e3331", &data_length, &sustain_loop_start, &sustain_loop_end, &loop_type) ;	data_length = SDS_3BYTE_TO_INT_DECODE (data_length) ;	sustain_loop_start = SDS_3BYTE_TO_INT_DECODE (sustain_loop_start) ;	sustain_loop_end = SDS_3BYTE_TO_INT_DECODE (sustain_loop_end) ;	psf_log_printf (psf, 	" Sustain Loop\n"							"     Start     : %d\n"							"     End       : %d\n"							"     Loop Type : %d\n",			sustain_loop_start, sustain_loop_end, loop_type) ;	psf->dataoffset = SDS_DATA_OFFSET ;	psf->datalength = psf->filelength - psf->dataoffset ;	if (data_length != psf->filelength - psf->dataoffset)	{	psf_log_printf (psf, " Datalength     : %d (truncated data??? %d)\n", data_length, psf->filelength - psf->dataoffset) ;		data_length = psf->filelength - psf->dataoffset ;		}	else		psf_log_printf (psf, " Datalength     : %d\n", data_length) ;	bytesread += psf_binheader_readf (psf, "1", &byte) ;	if (byte != 0xF7)		psf_log_printf (psf, "bad end : %X\n", byte & 0xFF) ;	for (blockcount = 0 ; bytesread < psf->filelength ; blockcount++)	{		bytesread += psf_fread (&marker, 1, 2, psf) ;		if (marker == 0)			break ;		psf_fseek (psf, SDS_BLOCK_SIZE - 2, SEEK_CUR) ;		bytesread += SDS_BLOCK_SIZE - 2 ;		} ;	psf_log_printf (psf, "\nBlocks         : %d\n", blockcount) ;	psds->total_blocks = blockcount ;	psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / ((psds->bitwidth + 6) / 7) ;	psf_log_printf (psf, "Samples/Block  : %d\n", psds->samplesperblock) ;	psf_log_printf (psf, "Frames         : %d\n", blockcount * psds->samplesperblock) ;	psf->sf.frames = blockcount * psds->samplesperblock ;	psds->frames = blockcount * psds->samplesperblock ;	/* Always Mono */	psf->sf.channels = 1 ;	psf->sf.sections = 1 ;	/*	** Lie to the user about PCM bit width. Always round up to	** the next multiple of 8.	*/	switch ((psds->bitwidth + 7) / 8)	{	case 1 :			psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_S8 ;			break ;		case 2 :			psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_16 ;			break ;		case 3 :			psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_24 ;			break ;		case 4 :			psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_32 ;			break ;		default :			psf_log_printf (psf, "*** Weird byte width (%d)\n", (psds->bitwidth + 7) / 8) ;			return SFE_SDS_BAD_BIT_WIDTH ;		} ;	psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ;	return 0 ;} /* sds_read_header */static intsds_write_header (SF_PRIVATE *psf, int calc_length){	SDS_PRIVATE *psds ;	sf_count_t	current ;	int samp_period, data_length, sustain_loop_start, sustain_loop_end ;	unsigned char loop_type = 0 ;	if ((psds = (SDS_PRIVATE *) psf->fdata) == NULL)	{	psf_log_printf (psf, "*** Bad psf->fdata ptr.\n") ;		return SFE_INTERNAL ;		} ;	if (psf->pipeoffset > 0)		return 0 ;	current = psf_ftell (psf) ;	if (calc_length)		psf->sf.frames = psds->total_blocks * psds->samplesperblock + psds->write_count ;	if (psds->write_count > 0)	{	int current_count = psds->write_count ;		int current_block = psds->write_block ;		psds->writer (psf, psds) ;		psf_fseek (psf, -1 * SDS_BLOCK_SIZE, SEEK_CUR) ;		psds->write_count = current_count ;		psds->write_block = current_block ;		} ;	/* Reset the current header length to zero. */	psf->header [0] = 0 ;	psf->headindex = 0 ;	if (psf->is_pipe == SF_FALSE)		psf_fseek (psf, 0, SEEK_SET) ;	psf_binheader_writef (psf, "E211", 0xF07E, 0, 1) ;	switch (psf->sf.format & SF_FORMAT_SUBMASK)	{	case SF_FORMAT_PCM_S8 :				psds->bitwidth = 8 ;				break ;		case SF_FORMAT_PCM_16 :				psds->bitwidth = 16 ;				break ;		case SF_FORMAT_PCM_24 :				psds->bitwidth = 24 ;				break ;		default:			return SFE_SDS_BAD_BIT_WIDTH ;		} ;	samp_period = SDS_INT_TO_3BYTE_ENCODE (1000000000 / psf->sf.samplerate) ;	psf_binheader_writef (psf, "e213", 0, psds->bitwidth, samp_period) ;	data_length			= SDS_INT_TO_3BYTE_ENCODE (psds->total_blocks * SDS_BLOCK_SIZE) ;	sustain_loop_start	= SDS_INT_TO_3BYTE_ENCODE (0) ;	sustain_loop_end	= SDS_INT_TO_3BYTE_ENCODE (psf->sf.frames) ;	psf_binheader_writef (psf, "e33311", data_length, sustain_loop_start, sustain_loop_end, loop_type, 0xF7) ;	/* Header construction complete so write it out. */	psf_fwrite (psf->header, psf->headindex, 1, psf) ;	if (psf->error)		return psf->error ;	psf->dataoffset = psf->headindex ;	psf->datalength = psds->write_block * SDS_BLOCK_SIZE ;	if (current > 0)		psf_fseek (psf, current, SEEK_SET) ;	return psf->error ;} /* sds_write_header *//*------------------------------------------------------------------------------*/static intsds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds){	unsigned char *ucptr, checksum ;	unsigned int sample ;	int 	k ;	psds->read_block ++ ;	psds->read_count = 0 ;	if (psds->read_block * psds->samplesperblock > psds->frames)	{	memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ;		return 1 ;		} ;	if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)		psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ;	if (psds->read_data [0] != 0xF0)	{	printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ;		} ;	checksum = psds->read_data [1] ;	if (checksum != 0x7E)	{	printf ("Error 1 : %02X\n", checksum & 0xFF) ;		}	for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)		checksum ^= psds->read_data [k] ;	checksum &= 0x7F ;	if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2])	{	psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ;		} ;	ucptr = psds->read_data + 5 ;	for (k = 0 ; k < 120 ; k += 2)	{	sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) ;		psds->read_samples [k / 2] = (int) (sample - 0x80000000) ;		} ;	return 1 ;} /* sds_2byte_read */static intsds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds){	unsigned char *ucptr, checksum ;	unsigned int sample ;	int 	k ;	psds->read_block ++ ;	psds->read_count = 0 ;	if (psds->read_block * psds->samplesperblock > psds->frames)	{	memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ;		return 1 ;		} ;	if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)		psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ;	if (psds->read_data [0] != 0xF0)	{	printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ;		} ;	checksum = psds->read_data [1] ;	if (checksum != 0x7E)	{	printf ("Error 1 : %02X\n", checksum & 0xFF) ;		}	for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)		checksum ^= psds->read_data [k] ;	checksum &= 0x7F ;	if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2])	{	psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ;		} ;	ucptr = psds->read_data + 5 ;	for (k = 0 ; k < 120 ; k += 3)	{	sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) + (ucptr [k + 2] << 11) ;		psds->read_samples [k / 3] = (int) (sample - 0x80000000) ;		} ;	return 1 ;} /* sds_3byte_read */static intsds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds){	unsigned char *ucptr, checksum ;

⌨️ 快捷键说明

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