mirror of
https://gitee.com/openharmony/third_party_libsnd
synced 2024-11-23 09:59:54 +00:00
Rmove broken ogg code.
This commit is contained in:
parent
7b12c9d636
commit
eebaf47a13
@ -1,3 +1,10 @@
|
||||
2005-10-28 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
* src/ogg.c
|
||||
Removed the horribly broken and non-functional OGG implementation when
|
||||
--enable-experimental was enabled. When OGG does finally work it will be
|
||||
merged.
|
||||
|
||||
2005-10-27 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
* src/g72x.c src/G72x/*.(c|h) src/common.h src/sndfile.c src/wav.c src/au.c
|
||||
|
855
src/ogg.c
855
src/ogg.c
@ -27,8 +27,6 @@
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (ENABLE_EXPERIMENTAL_CODE == 0)
|
||||
|
||||
int
|
||||
ogg_open (SF_PRIVATE *psf)
|
||||
{ if (psf)
|
||||
@ -36,859 +34,6 @@ ogg_open (SF_PRIVATE *psf)
|
||||
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.
|
||||
*/
|
||||
|
||||
int
|
||||
ogg_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 int
|
||||
pogg_init (SF_PRIVATE * psf)
|
||||
{
|
||||
psf->container_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 int
|
||||
pogg_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_t
|
||||
pogg_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 int
|
||||
pogg_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 long
|
||||
pogg_io_tell (void * user_handle)
|
||||
{ SF_PRIVATE * psf = (SF_PRIVATE *) user_handle ;
|
||||
|
||||
return (size_t) psf_ftell (psf) ;
|
||||
} /* pogg_io_tell */
|
||||
|
||||
static size_t
|
||||
pogg_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 int
|
||||
pogg_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 int
|
||||
pogg_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 int
|
||||
pogg_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 int
|
||||
pogg_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 int
|
||||
pogg_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 int
|
||||
pogg_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 ;
|
||||
|
||||
bytes = sizeof (float) * psf->sf.channels * frames ;
|
||||
|
||||
if (bytes > pogg->cache_size)
|
||||
{ new_block = realloc (pogg->cache_pcm, bytes) ;
|
||||
if (new_block == NULL)
|
||||
/* XXX : SFE_MALLOC_FAILED */
|
||||
return -1 ;
|
||||
|
||||
pogg->cache_pcm = new_block ;
|
||||
pogg->cache_size = bytes ;
|
||||
} ;
|
||||
|
||||
memcpy (pogg->cache_pcm, pcm, bytes) ;
|
||||
pogg->cache_frames = frames ;
|
||||
pogg->cache_remaining = frames ;
|
||||
|
||||
if (pogg->cache_granulepos != -1)
|
||||
pogg->cache_granulepos += frames ;
|
||||
|
||||
pogg_copyout (psf) ;
|
||||
|
||||
return 0 ;
|
||||
} /* pogg_decode */
|
||||
|
||||
static int
|
||||
pogg_read_packet (OGGZ * oggz, ogg_packet * op, long serialno, void * data)
|
||||
{ SF_PRIVATE * psf = (SF_PRIVATE *) data ;
|
||||
OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
FishSound * fsound = pogg->fsound ;
|
||||
|
||||
/* Avoid warning message. */
|
||||
oggz = NULL ;
|
||||
serialno = 0 ;
|
||||
|
||||
fish_sound_decode (fsound, op->packet, op->bytes) ;
|
||||
|
||||
if (op->granulepos != -1)
|
||||
pogg->cache_granulepos = op->granulepos ;
|
||||
|
||||
if (pogg->remaining == 0)
|
||||
return OGGZ_STOP_OK ;
|
||||
|
||||
return OGGZ_CONTINUE ;
|
||||
} /* pogg_read_packet */
|
||||
|
||||
static sf_count_t
|
||||
pogg_read_loop (SF_PRIVATE *psf, sf_count_t len)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
long nread = 1024 ;
|
||||
sf_count_t ret = len ;
|
||||
|
||||
/** Calculate nr. frames remaining */
|
||||
pogg->remaining = len / psf->sf.channels ;
|
||||
|
||||
/** Serve out any remaining cached data first */
|
||||
pogg_copyout (psf) ;
|
||||
|
||||
while (nread > 0 && pogg->remaining > 0)
|
||||
nread = oggz_read (pogg->oggz, 1024) ;
|
||||
|
||||
if (nread == 0)
|
||||
ret -= pogg->remaining * psf->sf.channels ;
|
||||
|
||||
return ret ;
|
||||
} /* pogg_read_loop */
|
||||
|
||||
static sf_count_t
|
||||
pogg_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
|
||||
pogg->ptr = ptr ;
|
||||
pogg->pcmtype = POGG_PCM_SHORT ;
|
||||
|
||||
return pogg_read_loop (psf, len) ;
|
||||
} /* pogg_read_s */
|
||||
|
||||
static sf_count_t
|
||||
pogg_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
|
||||
pogg->ptr = ptr ;
|
||||
pogg->pcmtype = POGG_PCM_INT ;
|
||||
|
||||
return pogg_read_loop (psf, len) ;
|
||||
} /* pogg_read_i */
|
||||
|
||||
static sf_count_t
|
||||
pogg_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
|
||||
pogg->ptr = ptr ;
|
||||
pogg->pcmtype = POGG_PCM_FLOAT ;
|
||||
|
||||
return pogg_read_loop (psf, len) ;
|
||||
} /* pogg_read_f */
|
||||
|
||||
static sf_count_t
|
||||
pogg_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
|
||||
pogg->ptr = ptr ;
|
||||
pogg->pcmtype = POGG_PCM_DOUBLE ;
|
||||
|
||||
return pogg_read_loop (psf, len) ;
|
||||
} /* pogg_read_d */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Seek functions
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
pogg_seek (SF_PRIVATE *psf, int mode, sf_count_t seek_from_start)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
ogg_int64_t units = seek_from_start * 1000 / psf->sf.samplerate ;
|
||||
|
||||
if (mode != SFM_READ)
|
||||
{ psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
oggz_seek_units (pogg->oggz, units, SEEK_SET) ;
|
||||
|
||||
/* Invalidate cache and set the desired seek position */
|
||||
pogg->cache_remaining = 0 ;
|
||||
pogg->cache_granulepos = -1 ;
|
||||
pogg->seek_from_start = seek_from_start ;
|
||||
|
||||
return seek_from_start ;
|
||||
} /* pogg_seek */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Write functions
|
||||
*/
|
||||
|
||||
static int
|
||||
pogg_encoded (FishSound * fsound, unsigned char * buf, long bytes, void * user_data)
|
||||
{ SF_PRIVATE * psf = (SF_PRIVATE *) user_data ;
|
||||
OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
ogg_packet op ;
|
||||
int err ;
|
||||
|
||||
op.packet = buf ;
|
||||
op.bytes = bytes ;
|
||||
op.b_o_s = pogg->b_o_s ;
|
||||
op.e_o_s = 0 ;
|
||||
op.granulepos = fish_sound_get_frameno (fsound) ;
|
||||
op.packetno = -1 ;
|
||||
|
||||
err = oggz_write_feed (pogg->oggz, &op, pogg->serialno, 0, NULL) ;
|
||||
|
||||
pogg->b_o_s = 0 ;
|
||||
|
||||
return OGGZ_CONTINUE ;
|
||||
} /* pogg_encoded */
|
||||
|
||||
static int
|
||||
pogg_write_anx_headers (SF_PRIVATE *psf, int format)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
unsigned char buf [128] ;
|
||||
long anx_serialno ;
|
||||
int headers_len = 0 ;
|
||||
const char * content_type ;
|
||||
ogg_packet op ;
|
||||
int err ;
|
||||
|
||||
anx_serialno = oggz_serialno_new (pogg->oggz) ;
|
||||
|
||||
/* Write Annodex header */
|
||||
memset (buf, 0, 48) ;
|
||||
snprintf (buf, 8, "Annodex") ;
|
||||
|
||||
/* Version */
|
||||
*(ogg_int16_t *) &buf [8] = (ogg_int16_t) POGG_ANX_VERSION_MAJOR ;
|
||||
*(ogg_int16_t *) &buf [10] = (ogg_int16_t) POGG_ANX_VERSION_MINOR ;
|
||||
if (CPU_IS_BIG_ENDIAN)
|
||||
endswap_short_array ((short *) &buf [8], 2) ;
|
||||
|
||||
/* Timebase numerator */
|
||||
*(ogg_int64_t *) &buf [12] = (ogg_int64_t) 0 ;
|
||||
|
||||
/* Timebase denominator */
|
||||
*(ogg_int64_t *) &buf [20] = (ogg_int64_t) 1 ;
|
||||
|
||||
if (CPU_IS_BIG_ENDIAN)
|
||||
endswap_long_array ((long *) &buf [12], 2) ;
|
||||
|
||||
op.packet = buf ;
|
||||
op.bytes = 48 ;
|
||||
op.b_o_s = 1 ;
|
||||
op.e_o_s = 0 ;
|
||||
op.granulepos = 0 ;
|
||||
op.packetno = -1 ;
|
||||
|
||||
err = oggz_write_feed (pogg->oggz, &op, anx_serialno, 0, NULL) ;
|
||||
|
||||
pogg->b_o_s = 0 ;
|
||||
|
||||
/* Write AnxData header */
|
||||
memset (buf, 0, 48) ;
|
||||
snprintf (buf, 8, "AnxData") ;
|
||||
|
||||
/* Granule rate numerator */
|
||||
*(ogg_int64_t *) &buf [8] = (ogg_int64_t) psf->sf.samplerate ;
|
||||
|
||||
/* Granule rate denominator */
|
||||
*(ogg_int64_t *) &buf [16] = (ogg_int64_t) 1 ;
|
||||
|
||||
if (CPU_IS_BIG_ENDIAN)
|
||||
endswap_long_array ((long *) &buf [8], 2) ;
|
||||
|
||||
/* Number of secondary header pages */
|
||||
*(ogg_int32_t *) &buf [24] = (ogg_int32_t) 3 ;
|
||||
if (CPU_IS_BIG_ENDIAN)
|
||||
endswap_int_array ((int *) &buf [24], 1) ;
|
||||
|
||||
/* Headers */
|
||||
if (format == FISH_SOUND_VORBIS)
|
||||
content_type = POGG_VORBIS_CONTENT_TYPE ;
|
||||
else
|
||||
content_type = POGG_SPEEX_CONTENT_TYPE ;
|
||||
|
||||
headers_len = snprintf ((char *) &buf [28], 100, "Content-Type : %s\r\n", content_type) ;
|
||||
|
||||
op.packet = buf ;
|
||||
op.bytes = 28 + headers_len + 1 ;
|
||||
op.b_o_s = 1 ;
|
||||
op.e_o_s = 0 ;
|
||||
op.granulepos = 0 ;
|
||||
op.packetno = -1 ;
|
||||
|
||||
err = oggz_write_feed (pogg->oggz, &op, pogg->serialno, 0, NULL) ;
|
||||
|
||||
/* Write Annodex eos packet */
|
||||
op.packet = NULL ;
|
||||
op.bytes = 0 ;
|
||||
op.b_o_s = 0 ;
|
||||
op.e_o_s = 1 ;
|
||||
op.granulepos = 0 ;
|
||||
op.packetno = -1 ;
|
||||
|
||||
err = oggz_write_feed (pogg->oggz, &op, anx_serialno, 0, NULL) ;
|
||||
|
||||
return 0 ;
|
||||
} /* pogg_write_anx_headers */
|
||||
|
||||
static int
|
||||
pogg_write_header (SF_PRIVATE *psf)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
|
||||
OGGZ * oggz ;
|
||||
FishSound * fsound ;
|
||||
FishSoundInfo fsinfo ;
|
||||
|
||||
oggz = oggz_new (OGGZ_WRITE) ;
|
||||
|
||||
oggz_io_set_write (oggz, pogg_io_write, psf) ;
|
||||
|
||||
fsinfo.samplerate = psf->sf.samplerate ;
|
||||
fsinfo.channels = psf->sf.channels ;
|
||||
|
||||
switch (psf->sf.format & SF_FORMAT_SUBMASK)
|
||||
{ case SF_FORMAT_VORBIS :
|
||||
fsinfo.format = FISH_SOUND_VORBIS ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_SPEEX :
|
||||
fsinfo.format = FISH_SOUND_SPEEX ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
fsound = fish_sound_new (FISH_SOUND_ENCODE, &fsinfo) ;
|
||||
fish_sound_set_interleave (fsound, 1) ;
|
||||
fish_sound_set_encoded_callback (fsound, pogg_encoded, psf) ;
|
||||
|
||||
pogg->oggz = oggz ;
|
||||
pogg->fsound = fsound ;
|
||||
pogg->serialno = oggz_serialno_new (oggz) ;
|
||||
pogg->b_o_s = 1 ;
|
||||
pogg->comments_written = 0 ;
|
||||
pogg->granulepos = 0 ;
|
||||
pogg->fptr = (float *) malloc (sizeof (float) * 1024) ;
|
||||
|
||||
if ((psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_ANX)
|
||||
pogg_write_anx_headers (psf, fsinfo.format) ;
|
||||
|
||||
return 0 ;
|
||||
} /* pogg_write_header */
|
||||
|
||||
static void
|
||||
pogg_write_comments (SF_PRIVATE *psf)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
int k ;
|
||||
int err ;
|
||||
|
||||
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
|
||||
{ printf ("hrumf comment : %d => %s\n", psf->strings [k].type, psf->strings [k].str) ;
|
||||
/*
|
||||
if (psf->strings [k].type == 0)
|
||||
break ;
|
||||
*/
|
||||
|
||||
if (psf->strings [k].type != 0)
|
||||
{ printf ("adding comment : %d => %s\n", psf->strings [k].type, psf->strings [k].str) ;
|
||||
|
||||
switch (psf->strings [k].type)
|
||||
{ case SF_STR_SOFTWARE :
|
||||
err = fish_sound_comment_add_byname (pogg->fsound, "ENCODER", psf->strings [k].str) ;
|
||||
break ;
|
||||
|
||||
case SF_STR_TITLE :
|
||||
err = fish_sound_comment_add_byname (pogg->fsound, "TITLE", psf->strings [k].str) ;
|
||||
break ;
|
||||
|
||||
case SF_STR_COPYRIGHT :
|
||||
err = fish_sound_comment_add_byname (pogg->fsound, "COPYRIGHT", psf->strings [k].str) ;
|
||||
break ;
|
||||
|
||||
case SF_STR_ARTIST :
|
||||
err = fish_sound_comment_add_byname (pogg->fsound, "ARTIST", psf->strings [k].str) ;
|
||||
break ;
|
||||
|
||||
/*
|
||||
case SF_STR_COMMENT :
|
||||
fish_sound_comment_add_byname (pogg->fsound, "COMMENT", psf->strings [k].str) ;
|
||||
break ;
|
||||
*/
|
||||
|
||||
case SF_STR_DATE :
|
||||
err = fish_sound_comment_add_byname (pogg->fsound, "DATE", psf->strings [k].str) ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
} ; /* if type !0 */
|
||||
} ;
|
||||
|
||||
pogg->comments_written = 1 ;
|
||||
|
||||
return ;
|
||||
} /* pogg_write_comments*/
|
||||
|
||||
static sf_count_t
|
||||
pogg_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
long n, i, remaining = len / psf->sf.channels ;
|
||||
|
||||
if (pogg->comments_written == 0)
|
||||
pogg_write_comments (psf) ;
|
||||
|
||||
while (remaining > 0)
|
||||
{ n = SF_MIN (remaining, 1024) ;
|
||||
|
||||
for (i = 0 ; i < n * psf->sf.channels ; i++)
|
||||
pogg->fptr [i] = (float) ptr [i] ;
|
||||
|
||||
fish_sound_encode (pogg->fsound, (float **) ptr, n) ;
|
||||
|
||||
while (oggz_write (pogg->oggz, 1024) > 0) ;
|
||||
|
||||
ptr += n * psf->sf.channels ;
|
||||
remaining -= n ;
|
||||
} ;
|
||||
|
||||
return len ;
|
||||
} /* pogg_write_s */
|
||||
|
||||
static sf_count_t
|
||||
pogg_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{
|
||||
OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
long n, i, remaining = len / psf->sf.channels ;
|
||||
|
||||
if (pogg->comments_written == 0)
|
||||
pogg_write_comments (psf) ;
|
||||
|
||||
while (remaining > 0)
|
||||
{ n = SF_MIN (remaining, 1024) ;
|
||||
|
||||
for (i = 0 ; i < n * psf->sf.channels ; i++)
|
||||
pogg->fptr [i] = (float) ptr [i] ;
|
||||
|
||||
fish_sound_encode (pogg->fsound, (float **) ptr, n) ;
|
||||
|
||||
while (oggz_write (pogg->oggz, 1024) > 0) ;
|
||||
|
||||
ptr += n * psf->sf.channels ;
|
||||
remaining -= n ;
|
||||
} ;
|
||||
|
||||
return len ;
|
||||
} /* pogg_write_i */
|
||||
|
||||
static sf_count_t
|
||||
pogg_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
long n, remaining = len / psf->sf.channels ;
|
||||
|
||||
if (pogg->comments_written == 0)
|
||||
pogg_write_comments (psf) ;
|
||||
|
||||
while (remaining > 0)
|
||||
{ n = SF_MIN (remaining, 1024) ;
|
||||
|
||||
fish_sound_encode (pogg->fsound, (float **) ptr, n) ;
|
||||
|
||||
while (oggz_write (pogg->oggz, 1024) > 0) ;
|
||||
|
||||
ptr += n * psf->sf.channels ;
|
||||
remaining -= n ;
|
||||
} ;
|
||||
|
||||
return len ;
|
||||
} /* pog_write_f */
|
||||
|
||||
static sf_count_t
|
||||
pogg_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
|
||||
long n, i, remaining = len / psf->sf.channels ;
|
||||
|
||||
if (pogg->comments_written == 0)
|
||||
pogg_write_comments (psf) ;
|
||||
|
||||
while (remaining > 0)
|
||||
{ n = SF_MIN (remaining, 1024) ;
|
||||
|
||||
for (i = 0 ; i < n * psf->sf.channels ; i++)
|
||||
pogg->fptr [i] = (float) ptr [i] ;
|
||||
|
||||
fish_sound_encode (pogg->fsound, (float **) ptr, n) ;
|
||||
|
||||
while (oggz_write (pogg->oggz, 1024) > 0) ;
|
||||
|
||||
ptr += n * psf->sf.channels ;
|
||||
remaining -= n ;
|
||||
} ;
|
||||
|
||||
return len ;
|
||||
} /* pogg_write_d */
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Do not edit or modify anything in this comment block.
|
||||
|
Loading…
Reference in New Issue
Block a user