Torque3D/Engine/lib/libsndfile/src/flac.c
marauder2k7 a745fc3757 Initial commit
added libraries:
opus
flac
libsndfile

updated:
libvorbis
libogg
openal

- Everything works as expected for now. Bare in mind libsndfile needed the check for whether or not it could find the xiph libraries removed in order for this to work.
2024-03-21 17:33:47 +00:00

1463 lines
42 KiB
C

/*
** Copyright (C) 2004-2017 Erik de Castro Lopo <erikd@mega-nerd.com>
** Copyright (C) 2004 Tobias Gehrig <tgehrig@ira.uka.de>
**
** 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 "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "sndfile.h"
#include "common.h"
#if HAVE_EXTERNAL_XIPH_LIBS
#include <FLAC/stream_decoder.h>
#include <FLAC/stream_encoder.h>
#include <FLAC/metadata.h>
/*------------------------------------------------------------------------------
** Private static functions.
*/
#define FLAC_DEFAULT_COMPRESSION_LEVEL 5
#define ENC_BUFFER_SIZE 8192
/*
** READ_LOOP_MAX_LEN is the maximum 'len' that will be passed to
** flac_read_loop(). This is somewhat arbitrary, but must be less
** than (UINT_MAX - FLAC__MAX_CHANNELS * FLAC__MAX_BLOCK_SIZE) to
** avoid overflows, and must also be a multiple of the number of
** channels (which is between 1 and 8.)
*/
#define READ_LOOP_MAX_LEN (0x10000 * 3 * 5 * 7)
typedef enum
{ PFLAC_PCM_SHORT = 50,
PFLAC_PCM_INT = 51,
PFLAC_PCM_FLOAT = 52,
PFLAC_PCM_DOUBLE = 53
} PFLAC_PCM ;
typedef struct
{
FLAC__StreamDecoder *fsd ;
FLAC__StreamEncoder *fse ;
PFLAC_PCM pcmtype ;
void* ptr ;
unsigned pos, len, remain ;
FLAC__StreamMetadata *metadata ;
const int32_t * const * wbuffer ;
int32_t * rbuffer [FLAC__MAX_CHANNELS] ;
int32_t* encbuffer ;
unsigned bufferpos ;
const FLAC__Frame *frame ;
unsigned compression ;
} FLAC_PRIVATE ;
typedef struct
{ const char *tag ;
int type ;
} FLAC_TAG ;
static sf_count_t flac_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
static int flac_byterate (SF_PRIVATE *psf) ;
static int flac_close (SF_PRIVATE *psf) ;
static int flac_enc_init (SF_PRIVATE *psf) ;
static int flac_read_header (SF_PRIVATE *psf) ;
static sf_count_t flac_read_flac2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t flac_read_flac2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t flac_read_flac2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t flac_read_flac2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t flac_write_s2flac (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t flac_write_i2flac (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t flac_write_f2flac (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t flac_write_d2flac (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static void f2flac8_array (const float *src, int32_t *dest, int count, int normalize) ;
static void f2flac16_array (const float *src, int32_t *dest, int count, int normalize) ;
static void f2flac24_array (const float *src, int32_t *dest, int count, int normalize) ;
static void f2flac8_clip_array (const float *src, int32_t *dest, int count, int normalize) ;
static void f2flac16_clip_array (const float *src, int32_t *dest, int count, int normalize) ;
static void f2flac24_clip_array (const float *src, int32_t *dest, int count, int normalize) ;
static void d2flac8_array (const double *src, int32_t *dest, int count, int normalize) ;
static void d2flac16_array (const double *src, int32_t *dest, int count, int normalize) ;
static void d2flac24_array (const double *src, int32_t *dest, int count, int normalize) ;
static void d2flac8_clip_array (const double *src, int32_t *dest, int count, int normalize) ;
static void d2flac16_clip_array (const double *src, int32_t *dest, int count, int normalize) ;
static void d2flac24_clip_array (const double *src, int32_t *dest, int count, int normalize) ;
static int flac_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
/* Decoder Callbacks */
static FLAC__StreamDecoderReadStatus sf_flac_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer [], size_t *bytes, void *client_data) ;
static FLAC__StreamDecoderSeekStatus sf_flac_seek_callback (const FLAC__StreamDecoder *decoder, FLAC__uint64 absolute_byte_offset, void *client_data) ;
static FLAC__StreamDecoderTellStatus sf_flac_tell_callback (const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) ;
static FLAC__StreamDecoderLengthStatus sf_flac_length_callback (const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) ;
static FLAC__bool sf_flac_eof_callback (const FLAC__StreamDecoder *decoder, void *client_data) ;
static FLAC__StreamDecoderWriteStatus sf_flac_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const int32_t * const buffer [], void *client_data) ;
static void sf_flac_meta_callback (const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) ;
static void sf_flac_error_callback (const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) ;
/* Encoder Callbacks */
static FLAC__StreamEncoderSeekStatus sf_flac_enc_seek_callback (const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data) ;
static FLAC__StreamEncoderTellStatus sf_flac_enc_tell_callback (const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data) ;
static FLAC__StreamEncoderWriteStatus sf_flac_enc_write_callback (const FLAC__StreamEncoder *encoder, const FLAC__byte buffer [], size_t bytes, unsigned samples, unsigned current_frame, void *client_data) ;
static void
s2flac8_array (const short *src, int32_t *dest, int count)
{ for (int i = 0 ; i < count ; i++)
dest [i] = src [i] >> 8 ;
} /* s2flac8_array */
static void
s2flac16_array (const short *src, int32_t *dest, int count)
{ for (int i = 0 ; i < count ; i++)
dest [i] = src [i] ;
} /* s2flac16_array */
static void
s2flac24_array (const short *src, int32_t *dest, int count)
{ for (int i = 0 ; i < count ; i++)
dest [i] = src [i] << 8 ;
} /* s2flac24_array */
static void
i2flac8_array (const int *src, int32_t *dest, int count)
{ for (int i = 0 ; i < count ; i++)
dest [i] = src [i] >> 24 ;
} /* i2flac8_array */
static void
i2flac16_array (const int *src, int32_t *dest, int count)
{
for (int i = 0 ; i < count ; i++)
dest [i] = src [i] >> 16 ;
} /* i2flac16_array */
static void
i2flac24_array (const int *src, int32_t *dest, int count)
{ for (int i = 0 ; i < count ; i++)
dest [i] = src [i] >> 8 ;
} /* i2flac24_array */
static sf_count_t
flac_buffer_copy (SF_PRIVATE *psf)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
const FLAC__Frame *frame = pflac->frame ;
const int32_t* const *buffer = pflac->wbuffer ;
unsigned i = 0, j, offset, channels, len ;
if (psf->sf.channels != (int) frame->header.channels)
{ psf_log_printf (psf, "Error: FLAC frame changed from %d to %d channels\n"
"Nothing to do but to error out.\n" ,
psf->sf.channels, frame->header.channels) ;
psf->error = SFE_FLAC_CHANNEL_COUNT_CHANGED ;
return 0 ;
} ;
/*
** frame->header.blocksize is variable and we're using a constant blocksize
** of FLAC__MAX_BLOCK_SIZE.
** Check our assumptions here.
*/
if (frame->header.blocksize > FLAC__MAX_BLOCK_SIZE)
{ psf_log_printf (psf, "Ooops : frame->header.blocksize (%d) > FLAC__MAX_BLOCK_SIZE (%d)\n", __func__, __LINE__, frame->header.blocksize, FLAC__MAX_BLOCK_SIZE) ;
psf->error = SFE_INTERNAL ;
return 0 ;
} ;
if (frame->header.channels > FLAC__MAX_CHANNELS)
psf_log_printf (psf, "Ooops : frame->header.channels (%d) > FLAC__MAX_BLOCK_SIZE (%d)\n", __func__, __LINE__, frame->header.channels, FLAC__MAX_CHANNELS) ;
channels = SF_MIN (frame->header.channels, FLAC__MAX_CHANNELS) ;
if (pflac->ptr == NULL)
{ /*
** This pointer is reset to NULL each time the current frame has been
** decoded. Somehow its used during encoding and decoding.
*/
for (i = 0 ; i < channels ; i++)
{
if (pflac->rbuffer [i] == NULL)
pflac->rbuffer [i] = calloc (FLAC__MAX_BLOCK_SIZE, sizeof (int32_t)) ;
memcpy (pflac->rbuffer [i], buffer [i], frame->header.blocksize * sizeof (int32_t)) ;
} ;
pflac->wbuffer = (const int32_t* const*) pflac->rbuffer ;
return 0 ;
} ;
len = SF_MIN (pflac->len, frame->header.blocksize) ;
if (pflac->remain % channels != 0)
{ psf_log_printf (psf, "Error: pflac->remain %u channels %u\n", pflac->remain, channels) ;
return 0 ;
} ;
switch (pflac->pcmtype)
{ case PFLAC_PCM_SHORT :
{ short *retpcm = (short*) pflac->ptr ;
int shift = 16 - frame->header.bits_per_sample ;
if (shift < 0)
{ shift = abs (shift) ;
for (i = 0 ; i < len && pflac->remain > 0 ; i++)
{ offset = pflac->pos + i * channels ;
if (pflac->bufferpos >= frame->header.blocksize)
break ;
if (offset + channels > pflac->len)
break ;
for (j = 0 ; j < channels ; j++)
retpcm [offset + j] = buffer [j][pflac->bufferpos] >> shift ;
pflac->remain -= channels ;
pflac->bufferpos ++ ;
}
}
else
{ for (i = 0 ; i < len && pflac->remain > 0 ; i++)
{ offset = pflac->pos + i * channels ;
if (pflac->bufferpos >= frame->header.blocksize)
break ;
if (offset + channels > pflac->len)
break ;
for (j = 0 ; j < channels ; j++)
retpcm [offset + j] = ((uint16_t) buffer [j][pflac->bufferpos]) << shift ;
pflac->remain -= channels ;
pflac->bufferpos ++ ;
} ;
} ;
} ;
break ;
case PFLAC_PCM_INT :
{ int *retpcm = (int*) pflac->ptr ;
int shift = 32 - frame->header.bits_per_sample ;
for (i = 0 ; i < len && pflac->remain > 0 ; i++)
{ offset = pflac->pos + i * channels ;
if (pflac->bufferpos >= frame->header.blocksize)
break ;
if (offset + channels > pflac->len)
break ;
for (j = 0 ; j < channels ; j++)
retpcm [offset + j] = ((uint32_t) buffer [j][pflac->bufferpos]) << shift ;
pflac->remain -= channels ;
pflac->bufferpos++ ;
} ;
} ;
break ;
case PFLAC_PCM_FLOAT :
{ float *retpcm = (float*) pflac->ptr ;
float norm = (psf->norm_float == SF_TRUE) ? 1.0 / (1 << (frame->header.bits_per_sample - 1)) : 1.0 ;
for (i = 0 ; i < len && pflac->remain > 0 ; i++)
{ offset = pflac->pos + i * channels ;
if (pflac->bufferpos >= frame->header.blocksize)
break ;
if (offset + channels > pflac->len)
break ;
for (j = 0 ; j < channels ; j++)
retpcm [offset + j] = buffer [j][pflac->bufferpos] * norm ;
pflac->remain -= channels ;
pflac->bufferpos++ ;
} ;
} ;
break ;
case PFLAC_PCM_DOUBLE :
{ double *retpcm = (double*) pflac->ptr ;
double norm = (psf->norm_double == SF_TRUE) ? 1.0 / (1 << (frame->header.bits_per_sample - 1)) : 1.0 ;
for (i = 0 ; i < len && pflac->remain > 0 ; i++)
{ offset = pflac->pos + i * channels ;
if (pflac->bufferpos >= frame->header.blocksize)
break ;
if (offset + channels > pflac->len)
break ;
for (j = 0 ; j < channels ; j++)
retpcm [offset + j] = buffer [j][pflac->bufferpos] * norm ;
pflac->remain -= channels ;
pflac->bufferpos++ ;
} ;
} ;
break ;
default :
return 0 ;
} ;
offset = i * channels ;
pflac->pos += i * channels ;
return offset ;
} /* flac_buffer_copy */
static FLAC__StreamDecoderReadStatus
sf_flac_read_callback (const FLAC__StreamDecoder * UNUSED (decoder), FLAC__byte buffer [], size_t *bytes, void *client_data)
{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
*bytes = psf_fread (buffer, 1, *bytes, psf) ;
if (*bytes > 0 && psf->error == 0)
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE ;
return FLAC__STREAM_DECODER_READ_STATUS_ABORT ;
} /* sf_flac_read_callback */
static FLAC__StreamDecoderSeekStatus
sf_flac_seek_callback (const FLAC__StreamDecoder * UNUSED (decoder), FLAC__uint64 absolute_byte_offset, void *client_data)
{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
psf_fseek (psf, absolute_byte_offset, SEEK_SET) ;
if (psf->error)
return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR ;
return FLAC__STREAM_DECODER_SEEK_STATUS_OK ;
} /* sf_flac_seek_callback */
static FLAC__StreamDecoderTellStatus
sf_flac_tell_callback (const FLAC__StreamDecoder * UNUSED (decoder), FLAC__uint64 *absolute_byte_offset, void *client_data)
{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
*absolute_byte_offset = psf_ftell (psf) ;
if (psf->error)
return FLAC__STREAM_DECODER_TELL_STATUS_ERROR ;
return FLAC__STREAM_DECODER_TELL_STATUS_OK ;
} /* sf_flac_tell_callback */
static FLAC__StreamDecoderLengthStatus
sf_flac_length_callback (const FLAC__StreamDecoder * UNUSED (decoder), FLAC__uint64 *stream_length, void *client_data)
{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
if ((*stream_length = psf->filelength) == 0)
return FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR ;
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK ;
} /* sf_flac_length_callback */
static FLAC__bool
sf_flac_eof_callback (const FLAC__StreamDecoder *UNUSED (decoder), void *client_data)
{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
if (psf_ftell (psf) == psf->filelength)
return SF_TRUE ;
return SF_FALSE ;
} /* sf_flac_eof_callback */
static FLAC__StreamDecoderWriteStatus
sf_flac_write_callback (const FLAC__StreamDecoder * UNUSED (decoder), const FLAC__Frame *frame, const int32_t * const buffer [], void *client_data)
{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
pflac->frame = frame ;
pflac->bufferpos = 0 ;
pflac->wbuffer = buffer ;
flac_buffer_copy (psf) ;
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE ;
} /* sf_flac_write_callback */
static void
sf_flac_meta_get_vorbiscomments (SF_PRIVATE *psf, const FLAC__StreamMetadata *metadata)
{ static FLAC_TAG tags [] =
{ { "title", SF_STR_TITLE },
{ "copyright", SF_STR_COPYRIGHT },
{ "software", SF_STR_SOFTWARE },
{ "artist", SF_STR_ARTIST },
{ "comment", SF_STR_COMMENT },
{ "date", SF_STR_DATE },
{ "album", SF_STR_ALBUM },
{ "license", SF_STR_LICENSE },
{ "tracknumber", SF_STR_TRACKNUMBER },
{ "genre", SF_STR_GENRE }
} ;
const char *value, *cptr ;
int k, tag_num ;
for (k = 0 ; k < ARRAY_LEN (tags) ; k++)
{ tag_num = FLAC__metadata_object_vorbiscomment_find_entry_from (metadata, 0, tags [k].tag) ;
if (tag_num < 0)
continue ;
value = (const char*) metadata->data.vorbis_comment.comments [tag_num].entry ;
if ((cptr = strchr (value, '=')) != NULL)
value = cptr + 1 ;
psf_log_printf (psf, " %-12s : %s\n", tags [k].tag, value) ;
psf_store_string (psf, tags [k].type, value) ;
} ;
return ;
} /* sf_flac_meta_get_vorbiscomments */
static void
sf_flac_meta_callback (const FLAC__StreamDecoder * UNUSED (decoder), const FLAC__StreamMetadata *metadata, void *client_data)
{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
int bitwidth = 0 ;
switch (metadata->type)
{ case FLAC__METADATA_TYPE_STREAMINFO :
if (psf->sf.channels > 0 && psf->sf.channels != (int) metadata->data.stream_info.channels)
{ psf_log_printf (psf, "Error: FLAC stream changed from %d to %d channels\n"
"Nothing to do but to error out.\n" ,
psf->sf.channels, metadata->data.stream_info.channels) ;
psf->error = SFE_FLAC_CHANNEL_COUNT_CHANGED ;
return ;
} ;
if (psf->sf.channels > 0 && psf->sf.samplerate != (int) metadata->data.stream_info.sample_rate)
{ psf_log_printf (psf, "Warning: FLAC stream changed sample rates from %d to %d.\n"
"Carrying on as if nothing happened.",
psf->sf.samplerate, metadata->data.stream_info.sample_rate) ;
} ;
psf->sf.channels = metadata->data.stream_info.channels ;
psf->sf.samplerate = metadata->data.stream_info.sample_rate ;
psf->sf.frames = metadata->data.stream_info.total_samples ;
psf_log_printf (psf, "FLAC Stream Metadata\n Channels : %d\n Sample rate : %d\n", psf->sf.channels, psf->sf.samplerate) ;
if (psf->sf.frames == 0)
{ psf_log_printf (psf, " Frames : 0 (bumping to SF_COUNT_MAX)\n") ;
psf->sf.frames = SF_COUNT_MAX ;
}
else
psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ;
switch (metadata->data.stream_info.bits_per_sample)
{ case 8 :
psf->sf.format |= SF_FORMAT_PCM_S8 ;
bitwidth = 8 ;
break ;
case 16 :
psf->sf.format |= SF_FORMAT_PCM_16 ;
bitwidth = 16 ;
break ;
case 24 :
psf->sf.format |= SF_FORMAT_PCM_24 ;
bitwidth = 24 ;
break ;
default :
psf_log_printf (psf, "sf_flac_meta_callback : bits_per_sample %d not yet implemented.\n", metadata->data.stream_info.bits_per_sample) ;
break ;
} ;
if (bitwidth > 0)
psf_log_printf (psf, " Bit width : %d\n", bitwidth) ;
break ;
case FLAC__METADATA_TYPE_VORBIS_COMMENT :
psf_log_printf (psf, "Vorbis Comment Metadata\n") ;
sf_flac_meta_get_vorbiscomments (psf, metadata) ;
break ;
case FLAC__METADATA_TYPE_PADDING :
psf_log_printf (psf, "Padding Metadata\n") ;
break ;
case FLAC__METADATA_TYPE_APPLICATION :
psf_log_printf (psf, "Application Metadata\n") ;
break ;
case FLAC__METADATA_TYPE_SEEKTABLE :
psf_log_printf (psf, "Seektable Metadata\n") ;
break ;
case FLAC__METADATA_TYPE_CUESHEET :
psf_log_printf (psf, "Cuesheet Metadata\n") ;
break ;
case FLAC__METADATA_TYPE_PICTURE :
psf_log_printf (psf, "Picture Metadata\n") ;
break ;
case FLAC__METADATA_TYPE_UNDEFINED :
psf_log_printf (psf, "Undefined Metadata\n") ;
break ;
default :
psf_log_printf (psf, "sf_flac_meta_callback : metadata-type %d not yet implemented.\n", metadata->type) ;
break ;
} ;
return ;
} /* sf_flac_meta_callback */
static void
sf_flac_error_callback (const FLAC__StreamDecoder * UNUSED (decoder), FLAC__StreamDecoderErrorStatus status, void *client_data)
{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
psf_log_printf (psf, "ERROR : %s\n", FLAC__StreamDecoderErrorStatusString [status]) ;
switch (status)
{ case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC :
psf->error = SFE_FLAC_LOST_SYNC ;
break ;
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER :
psf->error = SFE_FLAC_BAD_HEADER ;
break ;
default :
psf->error = SFE_FLAC_UNKOWN_ERROR ;
break ;
} ;
return ;
} /* sf_flac_error_callback */
static FLAC__StreamEncoderSeekStatus
sf_flac_enc_seek_callback (const FLAC__StreamEncoder * UNUSED (encoder), FLAC__uint64 absolute_byte_offset, void *client_data)
{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
psf_fseek (psf, absolute_byte_offset, SEEK_SET) ;
if (psf->error)
return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR ;
return FLAC__STREAM_ENCODER_SEEK_STATUS_OK ;
} /* sf_flac_enc_seek_callback */
static FLAC__StreamEncoderTellStatus
sf_flac_enc_tell_callback (const FLAC__StreamEncoder *UNUSED (encoder), FLAC__uint64 *absolute_byte_offset, void *client_data)
{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
*absolute_byte_offset = psf_ftell (psf) ;
if (psf->error)
return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR ;
return FLAC__STREAM_ENCODER_TELL_STATUS_OK ;
} /* sf_flac_enc_tell_callback */
static FLAC__StreamEncoderWriteStatus
sf_flac_enc_write_callback (const FLAC__StreamEncoder * UNUSED (encoder), const FLAC__byte buffer [], size_t bytes, unsigned UNUSED (samples), unsigned UNUSED (current_frame), void *client_data)
{ SF_PRIVATE *psf = (SF_PRIVATE*) client_data ;
if (psf_fwrite (buffer, 1, bytes, psf) == (sf_count_t) bytes && psf->error == 0)
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK ;
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR ;
} /* sf_flac_enc_write_callback */
static void
flac_write_strings (SF_PRIVATE *psf, FLAC_PRIVATE* pflac)
{ FLAC__StreamMetadata_VorbisComment_Entry entry ;
int k, string_count = 0 ;
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
{ if (psf->strings.data [k].type != 0)
string_count ++ ;
} ;
if (string_count == 0)
return ;
if (pflac->metadata == NULL && (pflac->metadata = FLAC__metadata_object_new (FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL)
{ psf_log_printf (psf, "FLAC__metadata_object_new returned NULL\n") ;
return ;
} ;
for (k = 0 ; k < SF_MAX_STRINGS && psf->strings.data [k].type != 0 ; k++)
{ const char * key, * value ;
switch (psf->strings.data [k].type)
{ case SF_STR_SOFTWARE :
key = "software" ;
break ;
case SF_STR_TITLE :
key = "title" ;
break ;
case SF_STR_COPYRIGHT :
key = "copyright" ;
break ;
case SF_STR_ARTIST :
key = "artist" ;
break ;
case SF_STR_COMMENT :
key = "comment" ;
break ;
case SF_STR_DATE :
key = "date" ;
break ;
case SF_STR_ALBUM :
key = "album" ;
break ;
case SF_STR_LICENSE :
key = "license" ;
break ;
case SF_STR_TRACKNUMBER :
key = "tracknumber" ;
break ;
case SF_STR_GENRE :
key = "genre" ;
break ;
default :
continue ;
} ;
value = psf->strings.storage + psf->strings.data [k].offset ;
FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair (&entry, key, value) ;
FLAC__metadata_object_vorbiscomment_append_comment (pflac->metadata, entry, /* copy */ SF_FALSE) ;
} ;
if (! FLAC__stream_encoder_set_metadata (pflac->fse, &pflac->metadata, 1))
{ printf ("%s %d : fail\n", __func__, __LINE__) ;
return ;
} ;
return ;
} /* flac_write_strings */
static int
flac_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
int err ;
flac_write_strings (psf, pflac) ;
if ((err = FLAC__stream_encoder_init_stream (pflac->fse, sf_flac_enc_write_callback, sf_flac_enc_seek_callback, sf_flac_enc_tell_callback, NULL, psf)) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
{ psf_log_printf (psf, "Error : FLAC encoder init returned error : %s\n", FLAC__StreamEncoderInitStatusString [err]) ;
return SFE_FLAC_INIT_DECODER ;
} ;
if (psf->error == 0)
psf->dataoffset = psf_ftell (psf) ;
pflac->encbuffer = calloc (ENC_BUFFER_SIZE, sizeof (int32_t)) ;
/* can only call init_stream once */
psf->write_header = NULL ;
return psf->error ;
} /* flac_write_header */
/*------------------------------------------------------------------------------
** Public function.
*/
int
flac_open (SF_PRIVATE *psf)
{ int subformat ;
int error = 0 ;
FLAC_PRIVATE* pflac = calloc (1, sizeof (FLAC_PRIVATE)) ;
psf->codec_data = pflac ;
/* Set the default value here. Over-ridden later if necessary. */
pflac->compression = FLAC_DEFAULT_COMPRESSION_LEVEL ;
if (psf->file.mode == SFM_RDWR)
return SFE_BAD_MODE_RW ;
if (psf->file.mode == SFM_READ)
{ if ((error = flac_read_header (psf)))
return error ;
} ;
subformat = SF_CODEC (psf->sf.format) ;
if (psf->file.mode == SFM_WRITE)
{ if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_FLAC)
return SFE_BAD_OPEN_FORMAT ;
psf->endian = SF_ENDIAN_BIG ;
psf->sf.seekable = 0 ;
psf->strings.flags = SF_STR_ALLOW_START ;
if ((error = flac_enc_init (psf)))
return error ;
/* In an ideal world we would write the header at this point. Unfortunately
** that would prevent string metadata being added so we have to hold off.
*/
psf->write_header = flac_write_header ;
} ;
psf->datalength = psf->filelength ;
psf->dataoffset = 0 ;
psf->container_close = flac_close ;
psf->seek = flac_seek ;
psf->byterate = flac_byterate ;
psf->command = flac_command ;
switch (subformat)
{ case SF_FORMAT_PCM_S8 : /* 8-bit FLAC. */
case SF_FORMAT_PCM_16 : /* 16-bit FLAC. */
case SF_FORMAT_PCM_24 : /* 24-bit FLAC. */
error = flac_init (psf) ;
break ;
default : return SFE_UNIMPLEMENTED ;
} ;
return error ;
} /* flac_open */
/*------------------------------------------------------------------------------
*/
static int
flac_close (SF_PRIVATE *psf)
{ FLAC_PRIVATE* pflac ;
int k ;
if ((pflac = (FLAC_PRIVATE*) psf->codec_data) == NULL)
return 0 ;
if (pflac->metadata != NULL)
FLAC__metadata_object_delete (pflac->metadata) ;
if (psf->file.mode == SFM_WRITE)
{ FLAC__stream_encoder_finish (pflac->fse) ;
FLAC__stream_encoder_delete (pflac->fse) ;
free (pflac->encbuffer) ;
} ;
if (psf->file.mode == SFM_READ)
{ FLAC__stream_decoder_finish (pflac->fsd) ;
FLAC__stream_decoder_delete (pflac->fsd) ;
} ;
for (k = 0 ; k < ARRAY_LEN (pflac->rbuffer) ; k++)
free (pflac->rbuffer [k]) ;
free (pflac) ;
psf->codec_data = NULL ;
return 0 ;
} /* flac_close */
static int
flac_enc_init (SF_PRIVATE *psf)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
unsigned bps ;
/* To cite the flac FAQ at
** http://flac.sourceforge.net/faq.html#general__samples
** "FLAC supports linear sample rates from 1Hz - 655350Hz in 1Hz
** increments."
*/
if (psf->sf.samplerate < 1 || psf->sf.samplerate > 655350)
{ psf_log_printf (psf, "flac sample rate out of range.\n", psf->sf.samplerate) ;
return SFE_FLAC_BAD_SAMPLE_RATE ;
} ;
psf_fseek (psf, 0, SEEK_SET) ;
switch (SF_CODEC (psf->sf.format))
{ case SF_FORMAT_PCM_S8 :
bps = 8 ;
break ;
case SF_FORMAT_PCM_16 :
bps = 16 ;
break ;
case SF_FORMAT_PCM_24 :
bps = 24 ;
break ;
default :
bps = 0 ;
break ;
} ;
if (pflac->fse)
FLAC__stream_encoder_delete (pflac->fse) ;
if ((pflac->fse = FLAC__stream_encoder_new ()) == NULL)
return SFE_FLAC_NEW_DECODER ;
if (! FLAC__stream_encoder_set_channels (pflac->fse, psf->sf.channels))
{ psf_log_printf (psf, "FLAC__stream_encoder_set_channels (%d) return false.\n", psf->sf.channels) ;
return SFE_FLAC_INIT_DECODER ;
} ;
if (! FLAC__stream_encoder_set_sample_rate (pflac->fse, psf->sf.samplerate))
{ psf_log_printf (psf, "FLAC__stream_encoder_set_sample_rate (%d) returned false.\n", psf->sf.samplerate) ;
return SFE_FLAC_BAD_SAMPLE_RATE ;
} ;
if (! FLAC__stream_encoder_set_bits_per_sample (pflac->fse, bps))
{ psf_log_printf (psf, "FLAC__stream_encoder_set_bits_per_sample (%d) return false.\n", bps) ;
return SFE_FLAC_INIT_DECODER ;
} ;
if (! FLAC__stream_encoder_set_compression_level (pflac->fse, pflac->compression))
{ psf_log_printf (psf, "FLAC__stream_encoder_set_compression_level (%d) return false.\n", pflac->compression) ;
return SFE_FLAC_INIT_DECODER ;
} ;
return 0 ;
} /* flac_enc_init */
static int
flac_read_header (SF_PRIVATE *psf)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
psf_fseek (psf, 0, SEEK_SET) ;
if (pflac->fsd)
FLAC__stream_decoder_delete (pflac->fsd) ;
if ((pflac->fsd = FLAC__stream_decoder_new ()) == NULL)
return SFE_FLAC_NEW_DECODER ;
FLAC__stream_decoder_set_metadata_respond_all (pflac->fsd) ;
if (FLAC__stream_decoder_init_stream (pflac->fsd, sf_flac_read_callback, sf_flac_seek_callback, sf_flac_tell_callback, sf_flac_length_callback, sf_flac_eof_callback, sf_flac_write_callback, sf_flac_meta_callback, sf_flac_error_callback, psf) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
return SFE_FLAC_INIT_DECODER ;
FLAC__stream_decoder_process_until_end_of_metadata (pflac->fsd) ;
psf_log_printf (psf, "End\n") ;
if (psf->error != 0)
FLAC__stream_decoder_delete (pflac->fsd) ;
else
{ FLAC__uint64 position ;
FLAC__stream_decoder_get_decode_position (pflac->fsd, &position) ;
psf->dataoffset = position ;
} ;
return psf->error ;
} /* flac_read_header */
static int
flac_command (SF_PRIVATE * psf, int command, void * data, int datasize)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
double quality ;
switch (command)
{ case SFC_SET_COMPRESSION_LEVEL :
if (data == NULL || datasize != sizeof (double))
return SF_FALSE ;
if (psf->have_written)
return SF_FALSE ;
/* FLAC compression level is in the range [0, 8] while libsndfile takes
** values in the range [0.0, 1.0]. Massage the libsndfile value here.
*/
quality = (*((double *) data)) * 8.0 ;
/* Clip range. */
pflac->compression = psf_lrint (SF_MAX (0.0, SF_MIN (8.0, quality))) ;
psf_log_printf (psf, "%s : Setting SFC_SET_COMPRESSION_LEVEL to %u.\n", __func__, pflac->compression) ;
if (flac_enc_init (psf))
return SF_FALSE ;
return SF_TRUE ;
default :
return SF_FALSE ;
} ;
return SF_FALSE ;
} /* flac_command */
int
flac_init (SF_PRIVATE *psf)
{
if (psf->file.mode == SFM_RDWR)
return SFE_BAD_MODE_RW ;
if (psf->file.mode == SFM_READ)
{ psf->read_short = flac_read_flac2s ;
psf->read_int = flac_read_flac2i ;
psf->read_float = flac_read_flac2f ;
psf->read_double = flac_read_flac2d ;
} ;
if (psf->file.mode == SFM_WRITE)
{ psf->write_short = flac_write_s2flac ;
psf->write_int = flac_write_i2flac ;
psf->write_float = flac_write_f2flac ;
psf->write_double = flac_write_d2flac ;
} ;
if (psf->filelength > psf->dataoffset)
psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ;
else
psf->datalength = 0 ;
return 0 ;
} /* flac_init */
static unsigned
flac_read_loop (SF_PRIVATE *psf, unsigned len)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
FLAC__StreamDecoderState state ;
pflac->pos = 0 ;
pflac->len = len ;
pflac->remain = len ;
state = FLAC__stream_decoder_get_state (pflac->fsd) ;
if (state > FLAC__STREAM_DECODER_END_OF_STREAM)
{ psf_log_printf (psf, "FLAC__stream_decoder_get_state returned %s\n", FLAC__StreamDecoderStateString [state]) ;
/* Current frame is busted, so NULL the pointer. */
pflac->frame = NULL ;
} ;
/* First copy data that has already been decoded and buffered. */
if (pflac->frame != NULL && pflac->bufferpos < pflac->frame->header.blocksize)
flac_buffer_copy (psf) ;
/* Decode some more. */
while (pflac->pos < pflac->len)
{ if (FLAC__stream_decoder_process_single (pflac->fsd) == 0)
{ psf_log_printf (psf, "FLAC__stream_decoder_process_single returned false\n") ;
/* Current frame is busted, so NULL the pointer. */
pflac->frame = NULL ;
break ;
} ;
state = FLAC__stream_decoder_get_state (pflac->fsd) ;
if (state >= FLAC__STREAM_DECODER_END_OF_STREAM)
{ psf_log_printf (psf, "FLAC__stream_decoder_get_state returned %s\n", FLAC__StreamDecoderStateString [state]) ;
/* Current frame is busted, so NULL the pointer. */
pflac->frame = NULL ;
break ;
} ;
} ;
pflac->ptr = NULL ;
return pflac->pos ;
} /* flac_read_loop */
static sf_count_t
flac_read_flac2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
sf_count_t total = 0, current ;
unsigned readlen ;
pflac->pcmtype = PFLAC_PCM_SHORT ;
while (total < len)
{ pflac->ptr = ptr + total ;
readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
current = flac_read_loop (psf, readlen) ;
if (current == 0)
break ;
total += current ;
} ;
return total ;
} /* flac_read_flac2s */
static sf_count_t
flac_read_flac2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
sf_count_t total = 0, current ;
unsigned readlen ;
pflac->pcmtype = PFLAC_PCM_INT ;
while (total < len)
{ pflac->ptr = ptr + total ;
readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
current = flac_read_loop (psf, readlen) ;
if (current == 0)
break ;
total += current ;
} ;
return total ;
} /* flac_read_flac2i */
static sf_count_t
flac_read_flac2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
sf_count_t total = 0, current ;
unsigned readlen ;
pflac->pcmtype = PFLAC_PCM_FLOAT ;
while (total < len)
{ pflac->ptr = ptr + total ;
readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
current = flac_read_loop (psf, readlen) ;
if (current == 0)
break ;
total += current ;
} ;
return total ;
} /* flac_read_flac2f */
static sf_count_t
flac_read_flac2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
sf_count_t total = 0, current ;
unsigned readlen ;
pflac->pcmtype = PFLAC_PCM_DOUBLE ;
while (total < len)
{ pflac->ptr = ptr + total ;
readlen = (len - total > READ_LOOP_MAX_LEN) ? READ_LOOP_MAX_LEN : (unsigned) (len - total) ;
current = flac_read_loop (psf, readlen) ;
if (current == 0)
break ;
total += current ;
} ;
return total ;
} /* flac_read_flac2d */
static sf_count_t
flac_write_s2flac (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
void (*convert) (const short *, int32_t *, int) ;
int bufferlen, writecount, thiswrite ;
sf_count_t total = 0 ;
int32_t* buffer = pflac->encbuffer ;
switch (SF_CODEC (psf->sf.format))
{ case SF_FORMAT_PCM_S8 :
convert = s2flac8_array ;
break ;
case SF_FORMAT_PCM_16 :
convert = s2flac16_array ;
break ;
case SF_FORMAT_PCM_24 :
convert = s2flac24_array ;
break ;
default :
return -1 ;
} ;
bufferlen = ENC_BUFFER_SIZE / (sizeof (int32_t) * psf->sf.channels) ;
bufferlen *= psf->sf.channels ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
convert (ptr + total, buffer, writecount) ;
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount / psf->sf.channels))
thiswrite = writecount ;
else
break ;
total += thiswrite ;
if (thiswrite < writecount)
break ;
len -= thiswrite ;
} ;
return total ;
} /* flac_write_s2flac */
static sf_count_t
flac_write_i2flac (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
void (*convert) (const int *, int32_t *, int) ;
int bufferlen, writecount, thiswrite ;
sf_count_t total = 0 ;
int32_t* buffer = pflac->encbuffer ;
switch (SF_CODEC (psf->sf.format))
{ case SF_FORMAT_PCM_S8 :
convert = i2flac8_array ;
break ;
case SF_FORMAT_PCM_16 :
convert = i2flac16_array ;
break ;
case SF_FORMAT_PCM_24 :
convert = i2flac24_array ;
break ;
default :
return -1 ;
} ;
bufferlen = ENC_BUFFER_SIZE / (sizeof (int32_t) * psf->sf.channels) ;
bufferlen *= psf->sf.channels ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
convert (ptr + total, buffer, writecount) ;
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount / psf->sf.channels))
thiswrite = writecount ;
else
break ;
total += thiswrite ;
if (thiswrite < writecount)
break ;
len -= thiswrite ;
} ;
return total ;
} /* flac_write_i2flac */
static sf_count_t
flac_write_f2flac (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
void (*convert) (const float *, int32_t *, int, int) ;
int bufferlen, writecount, thiswrite ;
sf_count_t total = 0 ;
int32_t* buffer = pflac->encbuffer ;
switch (SF_CODEC (psf->sf.format))
{ case SF_FORMAT_PCM_S8 :
convert = (psf->add_clipping) ? f2flac8_clip_array : f2flac8_array ;
break ;
case SF_FORMAT_PCM_16 :
convert = (psf->add_clipping) ? f2flac16_clip_array : f2flac16_array ;
break ;
case SF_FORMAT_PCM_24 :
convert = (psf->add_clipping) ? f2flac24_clip_array : f2flac24_array ;
break ;
default :
return -1 ;
} ;
bufferlen = ENC_BUFFER_SIZE / (sizeof (int32_t) * psf->sf.channels) ;
bufferlen *= psf->sf.channels ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
convert (ptr + total, buffer, writecount, psf->norm_float) ;
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount / psf->sf.channels))
thiswrite = writecount ;
else
break ;
total += thiswrite ;
if (thiswrite < writecount)
break ;
len -= thiswrite ;
} ;
return total ;
} /* flac_write_f2flac */
static void
f2flac8_clip_array (const float *src, int32_t *dest, int count, int normalize)
{ float normfact, scaled_value ;
normfact = normalize ? (8.0 * 0x10) : 1.0 ;
for (int i = 0 ; i < count ; i++)
{ scaled_value = src [i] * normfact ;
if (scaled_value >= (1.0 * 0x7F))
{ dest [i] = 0x7F ;
continue ;
} ;
if (scaled_value <= (-8.0 * 0x10))
{ dest [i] = -0x80 ;
continue ;
} ;
dest [i] = psf_lrintf (scaled_value) ;
} ;
return ;
} /* f2flac8_clip_array */
static void
f2flac16_clip_array (const float *src, int32_t *dest, int count, int normalize)
{ float normfact, scaled_value ;
normfact = normalize ? (8.0 * 0x1000) : 1.0 ;
for (int i = 0 ; i < count ; i++)
{ scaled_value = src [i] * normfact ;
if (scaled_value >= (1.0 * 0x7FFF))
{ dest [i] = 0x7FFF ;
continue ;
} ;
if (scaled_value <= (-8.0 * 0x1000))
{ dest [i] = -0x8000 ;
continue ;
} ;
dest [i] = psf_lrintf (scaled_value) ;
} ;
} /* f2flac16_clip_array */
static void
f2flac24_clip_array (const float *src, int32_t *dest, int count, int normalize)
{ float normfact, scaled_value ;
normfact = normalize ? (8.0 * 0x100000) : 1.0 ;
for (int i = 0 ; i < count ; i++)
{ scaled_value = src [i] * normfact ;
if (scaled_value >= (1.0 * 0x7FFFFF))
{ dest [i] = 0x7FFFFF ;
continue ;
} ;
if (scaled_value <= (-8.0 * 0x100000))
{ dest [i] = -0x800000 ;
continue ;
}
dest [i] = psf_lrintf (scaled_value) ;
} ;
return ;
} /* f2flac24_clip_array */
static void
f2flac8_array (const float *src, int32_t *dest, int count, int normalize)
{ float normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
for (int i = 0 ; i < count ; i++)
dest [i] = psf_lrintf (src [i] * normfact) ;
} /* f2flac8_array */
static void
f2flac16_array (const float *src, int32_t *dest, int count, int normalize)
{ float normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
for (int i = 0 ; i < count ; i++)
dest [i] = psf_lrintf (src [i] * normfact) ;
} /* f2flac16_array */
static void
f2flac24_array (const float *src, int32_t *dest, int count, int normalize)
{ float normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
for (int i = 0 ; i < count ; i++)
dest [i] = psf_lrintf (src [i] * normfact) ;
} /* f2flac24_array */
static sf_count_t
flac_write_d2flac (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
void (*convert) (const double *, int32_t *, int, int) ;
int bufferlen, writecount, thiswrite ;
sf_count_t total = 0 ;
int32_t* buffer = pflac->encbuffer ;
switch (SF_CODEC (psf->sf.format))
{ case SF_FORMAT_PCM_S8 :
convert = (psf->add_clipping) ? d2flac8_clip_array : d2flac8_array ;
break ;
case SF_FORMAT_PCM_16 :
convert = (psf->add_clipping) ? d2flac16_clip_array : d2flac16_array ;
break ;
case SF_FORMAT_PCM_24 :
convert = (psf->add_clipping) ? d2flac24_clip_array : d2flac24_array ;
break ;
default :
return -1 ;
} ;
bufferlen = ENC_BUFFER_SIZE / (sizeof (int32_t) * psf->sf.channels) ;
bufferlen *= psf->sf.channels ;
while (len > 0)
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
convert (ptr + total, buffer, writecount, psf->norm_double) ;
if (FLAC__stream_encoder_process_interleaved (pflac->fse, buffer, writecount / psf->sf.channels))
thiswrite = writecount ;
else
break ;
total += thiswrite ;
if (thiswrite < writecount)
break ;
len -= thiswrite ;
} ;
return total ;
} /* flac_write_d2flac */
static void
d2flac8_clip_array (const double *src, int32_t *dest, int count, int normalize)
{ double normfact, scaled_value ;
normfact = normalize ? (8.0 * 0x10) : 1.0 ;
for (int i = 0 ; i < count ; i++)
{ scaled_value = src [i] * normfact ;
if (scaled_value >= (1.0 * 0x7F))
{ dest [i] = 0x7F ;
continue ;
} ;
if (scaled_value <= (-8.0 * 0x10))
{ dest [i] = -0x80 ;
continue ;
} ;
dest [i] = psf_lrint (scaled_value) ;
} ;
return ;
} /* d2flac8_clip_array */
static void
d2flac16_clip_array (const double *src, int32_t *dest, int count, int normalize)
{ double normfact, scaled_value ;
normfact = normalize ? (8.0 * 0x1000) : 1.0 ;
for (int i = 0 ; i < count ; i++)
{ scaled_value = src [i] * normfact ;
if (scaled_value >= (1.0 * 0x7FFF))
{ dest [i] = 0x7FFF ;
continue ;
} ;
if (scaled_value <= (-8.0 * 0x1000))
{ dest [i] = -0x8000 ;
continue ;
} ;
dest [i] = psf_lrint (scaled_value) ;
} ;
return ;
} /* d2flac16_clip_array */
static void
d2flac24_clip_array (const double *src, int32_t *dest, int count, int normalize)
{ double normfact, scaled_value ;
normfact = normalize ? (8.0 * 0x100000) : 1.0 ;
for (int i = 0 ; i < count ; i++)
{ scaled_value = src [i] * normfact ;
if (scaled_value >= (1.0 * 0x7FFFFF))
{ dest [i] = 0x7FFFFF ;
continue ;
} ;
if (scaled_value <= (-8.0 * 0x100000))
{ dest [i] = -0x800000 ;
continue ;
} ;
dest [i] = psf_lrint (scaled_value) ;
} ;
return ;
} /* d2flac24_clip_array */
static void
d2flac8_array (const double *src, int32_t *dest, int count, int normalize)
{ double normfact = normalize ? (1.0 * 0x7F) : 1.0 ;
for (int i = 0 ; i < count ; i++)
dest [i] = psf_lrint (src [i] * normfact) ;
} /* d2flac8_array */
static void
d2flac16_array (const double *src, int32_t *dest, int count, int normalize)
{ double normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
for (int i = 0 ; i < count ; i++)
dest [i] = psf_lrint (src [i] * normfact) ;
} /* d2flac16_array */
static void
d2flac24_array (const double *src, int32_t *dest, int count, int normalize)
{ double normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ;
for (int i = 0 ; i < count ; i++)
dest [i] = psf_lrint (src [i] * normfact) ;
} /* d2flac24_array */
static sf_count_t
flac_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
{ FLAC_PRIVATE* pflac = (FLAC_PRIVATE*) psf->codec_data ;
if (pflac == NULL)
return 0 ;
if (psf->dataoffset < 0)
{ psf->error = SFE_BAD_SEEK ;
return ((sf_count_t) -1) ;
} ;
pflac->frame = NULL ;
if (psf->file.mode == SFM_READ)
{ if (FLAC__stream_decoder_seek_absolute (pflac->fsd, offset))
return offset ;
if (offset == psf->sf.frames)
{ /*
** If we've been asked to seek to the very end of the file, libFLAC
** will return an error. However, we know the length of the file so
** instead of returning an error, we can return the offset.
*/
return offset ;
} ;
psf->error = SFE_BAD_SEEK ;
return ((sf_count_t) -1) ;
} ;
/* Seeking in write mode not yet supported. */
psf->error = SFE_BAD_SEEK ;
return ((sf_count_t) -1) ;
} /* flac_seek */
static int
flac_byterate (SF_PRIVATE *psf)
{
if (psf->file.mode == SFM_READ)
return (psf->datalength * psf->sf.samplerate) / psf->sf.frames ;
return -1 ;
} /* flac_byterate */
#else /* HAVE_EXTERNAL_XIPH_LIBS */
int
flac_open (SF_PRIVATE *psf)
{
psf_log_printf (psf, "This version of libsndfile was compiled without FLAC support.\n") ;
return SFE_UNIMPLEMENTED ;
} /* flac_open */
#endif