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

📄 ogg.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 <stdio.h>#include <fcntl.h>#include <string.h>#include <ctype.h>#include "sndfile.h"#include "config.h"#include "sfendian.h"#include "common.h"#if (ENABLE_EXPERIMENTAL_CODE == 0)intogg_open	(SF_PRIVATE *psf){	if (psf)		return SFE_UNIMPLEMENTED ;	return (psf && 0) ;} /* ogg_open */#else#define	SFE_OGG_NOT_OGG	666/*------------------------------------------------------------------------------** Macros to handle big/little endian issues.*/#define ALAW_MARKER		MAKE_MARKER ('A', 'L', 'a', 'w')#define SOUN_MARKER		MAKE_MARKER ('S', 'o', 'u', 'n')#define DFIL_MARKER		MAKE_MARKER ('d', 'F', 'i', 'l')/*------------------------------------------------------------------------------** Private static functions.*/static int	ogg_read_header (SF_PRIVATE *psf) ;/*------------------------------------------------------------------------------** Public function.*/intogg_open (SF_PRIVATE *psf){	OGG_PRIVATE *pogg ;	int	subformat, error = 0 ;	if (psf->mode == SFM_RDWR)		return SFE_UNIMPLEMENTED ;	psf->sf.sections = 1 ;	psf->datalength = psf->filelength ;	psf->dataoffset = 0 ;	psf->blockwidth = 0 ;	psf->bytewidth = 1 ;	if (! (pogg = calloc (1, sizeof (OGG_PRIVATE))))		return SFE_MALLOC_FAILED ;	psf->fdata = pogg ;	if (psf->mode == SFM_READ)	{	if ((error = pogg_read_header (psf)))			return error ;		} ;	if (psf->mode == SFM_WRITE)	{	psf->str_flags = SF_STR_ALLOW_START ;		if ((error = pogg_write_header (psf)))			return error ;		} ;	if ((psf->sf.format & SF_FORMAT_TYPEMASK) == 0)		return	SFE_BAD_OPEN_FORMAT ;	subformat = psf->sf.format & SF_FORMAT_SUBMASK ;	if (subformat == 0)		return SFE_BAD_OPEN_FORMAT ;	return pogg_init (psf) ;} /* ogg_open *//*------------------------------------------------------------------------------** Private functions*/static intpogg_init (SF_PRIVATE * psf){	psf->close = pogg_close ;	if (psf->mode == SFM_READ)	{	/* set the virtual functions for reading */		psf->read_short = pogg_read_s ;		psf->read_int = pogg_read_i ;		psf->read_float = pogg_read_f ;		psf->read_double = pogg_read_d ;		/* set the virtual function for seeking */		psf->seek = pogg_seek ;		} ;	if (psf->mode == SFM_WRITE)	{	/* set the virtual functions for writing */		psf->write_short = pogg_write_s ;		psf->write_int = pogg_write_i ;		psf->write_float = pogg_write_f ;		psf->write_double = pogg_write_d ;		} ;	return 0 ;} /* pogg_init */static intpogg_close (SF_PRIVATE * psf){	OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;	long n ;	if (psf->mode == SFM_READ)	{	if (pogg->cache_pcm != NULL)			free (pogg->cache_pcm) ;		/* MUST NOT free pogg->ptr, it is a pointer into the user's buffers */		} ;	if (psf->mode == SFM_WRITE)	{	fish_sound_flush (pogg->fsound) ;		while ((n = oggz_write (pogg->oggz, 1024)) > 0) ;		} ;	if (pogg->oggz)			oggz_close (pogg->oggz) ;	if (pogg->fsound)		fish_sound_delete (pogg->fsound) ;	return 0 ;} /* pogg_close *//*------------------------------------------------------------------------------** OggzIO methods*/static size_tpogg_io_read (void * user_handle, void * buf, size_t n){	SF_PRIVATE * psf = (SF_PRIVATE *) user_handle ;	return (size_t) psf_fread (buf, 1, n, psf) ;} /* pogg_io_read */static intpogg_io_seek (void * user_handle, long offset, int whence){	SF_PRIVATE * psf = (SF_PRIVATE *) user_handle ;	return (size_t) psf_fseek (psf, offset, whence) ;} /* pogg_io_seek */static longpogg_io_tell (void * user_handle){	SF_PRIVATE * psf = (SF_PRIVATE *) user_handle ;	return (size_t) psf_ftell (psf) ;} /* pogg_io_tell */static size_tpogg_io_write (void * user_handle, void * buf, size_t n){	SF_PRIVATE * psf = (SF_PRIVATE *) user_handle ;	return (size_t) psf_fwrite (buf, 1, n, psf) ;} /* pogg_io_write *//*------------------------------------------------------------------------------** Read last packet -- set the number of frames to be the last recorded** granulepos.*/static intpogg_read_last_packet (OGGZ * oggz, ogg_packet * op, long serialno, void * data){	SF_PRIVATE * psf = (SF_PRIVATE *) data ;	/* Avoid compiler warning. */	oggz = NULL ;	serialno = 0 ;	if (op->granulepos == -1)		return OGGZ_CONTINUE ;	psf->sf.frames = op->granulepos ;	return OGGZ_STOP_OK ;} /* pogg_read_least_packet *//*------------------------------------------------------------------------------** Decode header -- by the time FishSound calls this, all header codebooks etc.** have been parsed and the Oggz is ready for seeking.*/static intpogg_decode_header (FishSound * fsound, float ** pcm, long frames, void * user_data){	SF_PRIVATE * psf = (SF_PRIVATE *) user_data ;	FishSoundInfo fsinfo ;	const FishSoundComment * comment ;	/* Avoid compiler warnings. */	pcm = NULL ;	frames = 0 ;	fish_sound_command (fsound, FISH_SOUND_GET_INFO, &fsinfo, sizeof (FishSoundInfo)) ;	switch (fsinfo.format)	{	case FISH_SOUND_VORBIS :			psf_log_printf (psf, "Vorbis\n") ;			psf->sf.format |= SF_FORMAT_VORBIS ;			break ;		case FISH_SOUND_SPEEX :			psf_log_printf (psf, "Speex\n") ;			psf->sf.format |= SF_FORMAT_SPEEX ;			break ;		default :			psf_log_printf (psf, "Unknown Ogg codec\n") ;			break ;		} ;	psf->sf.samplerate = fsinfo.samplerate ;	psf->sf.channels = fsinfo.channels ;	/* Get comments */	for (comment = fish_sound_comment_first (fsound) ; comment ;						comment = fish_sound_comment_next (fsound, comment))	{	psf_log_printf (psf, "%s : %s\n", comment->name, comment->value) ;		if (strcasecmp (comment->name, "TITLE") == 0)			psf_store_string (psf, SF_STR_TITLE, comment->value) ;		else if (strcasecmp (comment->name, "COPYRIGHT") == 0)			psf_store_string (psf, SF_STR_COPYRIGHT, comment->value) ;		else if (strcasecmp (comment->name, "ENCODER") == 0)			psf_store_string (psf, SF_STR_SOFTWARE, comment->value) ;		else if (strcasecmp (comment->name, "ARTIST") == 0)			psf_store_string (psf, SF_STR_ARTIST, comment->value) ;		else if (strcasecmp (comment->name, "DATE") == 0)			psf_store_string (psf, SF_STR_DATE, comment->value) ;		else if (strcasecmp (comment->name, "author") == 0)		{	/* speexenc provides this */			psf_store_string (psf, SF_STR_ARTIST, comment->value) ;			} ;		} ;	puts (psf->logbuffer) ;	return 1 ;} /* pogg_decode_header */static intpogg_read_header_packet (OGGZ * oggz, ogg_packet * op, long serialno, void * data){	SF_PRIVATE * psf = (SF_PRIVATE *) data ;	OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;	int format ;	/* Avoid compiler warning. */	oggz = NULL ;	if (pogg->serialno == -1)		psf_log_printf (psf, "Read Ogg packet header : [%s]\n", op->packet) ;	if (pogg->serialno == -1 && op->bytes >= 8)	{	format = fish_sound_identify (op->packet, 8) ;		if (format == FISH_SOUND_VORBIS || format == FISH_SOUND_SPEEX)		{	/*			** Detect this is (probably) the audio stream. Don't set the subformat			** yet, do that in the decoded callback, once FishSound has had a proper			** look at all the headers and codebooks etc. and the file is ready for			** decoding and seeking. We use the value of (psf->sf.format & _SUBMASK)			** below to determine whether the headers have all been read or not.			*/			pogg->serialno = serialno ;			}		else if (strncmp (op->packet, "Annodex", 8) == 0)		{	/* The overall stream encpasulation is Annodex */			psf->sf.format = SF_FORMAT_ANX ;			} ;		} ;	if (serialno == pogg->serialno)		fish_sound_decode (pogg->fsound, op->packet, op->bytes) ;	if ((psf->sf.format & SF_FORMAT_SUBMASK) == 0)		return OGGZ_CONTINUE ;	return OGGZ_STOP_OK ;} /* pogg_read_header_packet */static intpogg_read_header (SF_PRIVATE *psf){	OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;	unsigned char buf [1024] ;	OGGZ * oggz ;	FishSound * fsound ;	FishSoundInfo fsinfo ;	int nread = 1024 ;	psf->sf.format = SF_FORMAT_OGG ;	psf->sf.frames = 0 ;	oggz = oggz_new (OGGZ_READ|OGGZ_AUTO) ;	oggz_io_set_read (oggz, pogg_io_read, psf) ;	oggz_io_set_seek (oggz, pogg_io_seek, psf) ;	oggz_io_set_tell (oggz, pogg_io_tell, psf) ;	fsound = fish_sound_new (FISH_SOUND_DECODE, &fsinfo) ;	fish_sound_set_interleave (fsound, 1) ;	fish_sound_set_decoded_callback (fsound, pogg_decode_header, psf) ;	pogg->oggz = oggz ;	pogg->fsound = fsound ;	pogg->serialno = -1 ;	pogg->cache_pcm = NULL ;	pogg->cache_size = 0 ;	pogg->cache_granulepos = 0 ; /* We set this to a known value of zero to begin */	pogg->cache_frames = 0 ;	pogg->cache_remaining = 0 ;	pogg->ptr = NULL ;	pogg->pcmtype = POGG_PCM_SHORT ;	pogg->remaining = 0 ;	pogg->seek_from_start = 0 ;	/* Set position to start of file to begin reading header. */	psf_binheader_readf (psf, "p", 0) ;	/* Get the header info */	oggz_set_read_callback (oggz, -1, pogg_read_header_packet, psf) ;	while (nread > 0 && ((psf->sf.format & SF_FORMAT_SUBMASK) == 0))	{	nread = psf_binheader_readf (psf, "b", buf, sizeof (buf)) ;		oggz_read_input (oggz, buf, nread) ;		} ;	/* Get the duration */	oggz_set_read_callback (oggz, -1, NULL, NULL) ;	oggz_set_read_callback (oggz, pogg->serialno, pogg_read_last_packet, psf) ;	oggz_seek_units (oggz, 0, SEEK_END) ;	nread = 1024 ;	while (nread > 0)		nread = oggz_read (oggz, 1024) ;	/* reset to the beginning of the audio data */	oggz_seek_units (oggz, 0, SEEK_SET) ;	psf->dataoffset = oggz_tell (oggz) ;	psf->datalength = psf->filelength - psf->dataoffset ;	/* set the Oggz and FishSound up for decoding */	oggz_set_read_callback (oggz, -1, NULL, NULL) ;	oggz_set_read_callback (oggz, pogg->serialno, pogg_read_packet, psf) ;	fish_sound_set_decoded_callback (fsound, pogg_decode, psf) ;	return 0 ;} /* pogg_read_header *//*------------------------------------------------------------------------------** Decode functions*/static intpogg_copyout (SF_PRIVATE * psf){	OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;	size_t frame_size, bytes, cache_offset ;	long cache_usable, i ;	unsigned char * src ;	if (pogg->seek_from_start > 0)	{	/* If we've seeked and don't know where we are, don't do anything yet */		if (pogg->cache_granulepos == -1)			return -1 ;		/* If we've seeked and are before the seek point, don't do anything yet */		else if (pogg->cache_granulepos < pogg->seek_from_start)			return -1 ;		/* If this block contains the seek point, adjust the cache offset accordingly */		else if (pogg->cache_granulepos - pogg->cache_frames <= pogg->seek_from_start)		{	pogg->cache_remaining = pogg->cache_granulepos - pogg->seek_from_start ;			pogg->seek_from_start = 0 ; /* bingo */			} ;		} ;	frame_size = psf->sf.channels * sizeof (float) ;	cache_usable = SF_MIN (pogg->remaining, pogg->cache_remaining) ;	if (cache_usable <= 0)		return 0 ;	bytes = cache_usable * frame_size ;	cache_offset = (pogg->cache_frames - pogg->cache_remaining) * frame_size ;	src = (unsigned char *) pogg->cache_pcm + cache_offset ;	switch (pogg->pcmtype)	{	case POGG_PCM_SHORT :			for (i = 0 ; i < cache_usable ; i++)				((short *) pogg->ptr) [i] = (short) (((float *) src) [i] * SHRT_MAX) ;			break ;		case POGG_PCM_INT :			for (i = 0 ; i < cache_usable ; i++)				((double *) pogg->ptr) [i] = (double) (((float *) src) [i] * INT_MAX) ;			break ;		case POGG_PCM_FLOAT :			memcpy (pogg->ptr, src, bytes) ;			break ;		case POGG_PCM_DOUBLE :			for (i = 0 ; i < cache_usable ; i++)				((double *) pogg->ptr) [i] = (double) ((float *) src) [i] ;			break ;		} ;	pogg->ptr += bytes ;	pogg->cache_remaining -= cache_usable ;	pogg->remaining -= cache_usable ;	return 0 ;} /* pogg_copyout*/static intpogg_decode (FishSound * fsound, float ** pcm, long frames, void * user_data){	SF_PRIVATE * psf = (SF_PRIVATE *) user_data ;	OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;	size_t bytes ;	float ** new_block ;	/* Avoid compiler warning. */	fsound = NULL ;

⌨️ 快捷键说明

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