Audio-FLAC-Decoder

 view release on metacpan or  search on metacpan

Decoder.xs  view on Meta::CPAN

#define FLACdecoder_delete(x)                   FLAC__stream_decoder_delete(x)
#define FLACdecoder_set_read_callback(x, y)     FLAC__stream_decoder_set_read_callback(x, y)
#define FLACdecoder_set_write_callback(x, y)    FLAC__stream_decoder_set_write_callback(x, y)
#define FLACdecoder_set_metadata_callback(x, y) FLAC__stream_decoder_set_metadata_callback(x, y)
#define FLACdecoder_set_error_callback(x, y)    FLAC__stream_decoder_set_error_callback(x, y)
#define FLACdecoder_set_client_data(x, y)       FLAC__stream_decoder_set_client_data(x, y)
#define FLACdecoder_set_seek_callback(x, y)     FLAC__stream_decoder_set_seek_callback(x, y)
#define FLACdecoder_set_tell_callback(x, y)     FLAC__stream_decoder_set_tell_callback(x, y)
#define FLACdecoder_set_length_callback(x, y)   FLAC__stream_decoder_set_length_callback(x, y)
#define FLACdecoder_set_eof_callback(x, y)      FLAC__stream_decoder_set_eof_callback(x, y)
#define FLACdecoder_seek_absolute(x, y)         FLAC__stream_decoder_seek_absolute(x, y)

#define FLACdecoder_get_state(x)                FLAC__stream_decoder_get_state(x)
#define FLACdecoder_get_channels(x)             FLAC__stream_decoder_get_channels(x)
#define FLACdecoder_get_blocksize(x)		FLAC__stream_decoder_get_blocksize(x)
#define FLACdecoder_get_sample_rate(x)		FLAC__stream_decoder_get_sample_rate(x)
#define FLACdecoder_get_bits_per_sample(x)	FLAC__stream_decoder_get_bits_per_sample(x)
#define FLACdecoder_get_decode_position(x, y)   FLAC__stream_decoder_get_decode_position(x, y)

#define SAMPLES_PER_WRITE 512

typedef struct {
	/* i.e. specification string started with + or - */
	FLAC__bool is_relative;
	FLAC__bool value_is_samples;
	union {
		double seconds;
		FLAC__int64 samples;
	} value;
} SkipUntilSpecification;

/* Allow multiple instances of the decoder object. Stuff each filehandle into (void*)stream */
typedef struct {
	int abort_flag;
	int bytes_streamed;
	int is_streaming;
	FLAC__uint64 stream_length;
	void *buffer;
	PerlIO *stream;
	decoder_t *decoder;
	FLAC__bool has_replaygain;

	/* (24/8) for max bytes per sample */
	FLAC__byte sample_buffer[SAMPLES_PER_WRITE * FLAC__MAX_SUPPORTED_CHANNELS * (24/8)];
	FLAC__int32 reservoir[FLAC__MAX_BLOCK_SIZE * 2 * FLAC__MAX_SUPPORTED_CHANNELS];
	FLAC__uint64 decode_position_last;
	FLAC__uint64 decode_position_frame_last;
	FLAC__uint64 decode_position_frame;
	unsigned buffer_size;
	FLAC__int64 total_samples;
        unsigned bps;
        unsigned channels;
        FLAC__int64 sample_rate;
        FLAC__int64 length_in_msec;
	unsigned wide_samples_in_reservoir;
	SkipUntilSpecification skip_specification;
	SkipUntilSpecification until_specification;

} flac_datasource;

/* start all the callbacks here. */
static void meta_callback(
	const decoder_t *decoder,
	const FLAC__StreamMetadata *metadata, void *client_data) {

	flac_datasource *datasource = (flac_datasource *)client_data;

	if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {

		FLAC__uint64 skip, until;

		/* flac__utils_canonicalize_skip_until_specification(decoder_session->skip_specification, decoder_session->sample_rate);
		FLAC__ASSERT(datasource->skip_specification->value.samples >= 0); */
		skip = (FLAC__uint64)datasource->skip_specification.value.samples;

                /* remember, metadata->data.stream_info.total_samples can be 0, meaning 'unknown' */
                if (metadata->data.stream_info.total_samples > 0 && skip >= metadata->data.stream_info.total_samples) {
                        warn("ERROR trying to skip more samples than in stream\n");
                        datasource->abort_flag = true;
                        return;

                } else if (metadata->data.stream_info.total_samples == 0 && skip > 0) {
                        warn("ERROR, can't skip when FLAC metadata has total sample count of 0\n");
                        datasource->abort_flag = true;
                        return;
                }

		datasource->bps		    = metadata->data.stream_info.bits_per_sample;
		datasource->channels        = metadata->data.stream_info.channels;
		datasource->sample_rate     = metadata->data.stream_info.sample_rate;
		datasource->total_samples   = metadata->data.stream_info.total_samples - skip;

		datasource->length_in_msec  = datasource->total_samples * 10 / (datasource->sample_rate / 100);

		/* if (!canonicalize_until_specification(
			datasource->until_specification, datasource->inbasefilename,
			datasource>n->sample_rate, skip, metadata->data.stream_info.total_samples)) {
                        datasource->abort_flag = true;
                        return;
                } */

                FLAC__ASSERT(datasource->until_specification.value.samples >= 0);
                until = (FLAC__uint64)datasource->until_specification.value.samples;

                if (until > 0) {
                        datasource->total_samples -= (metadata->data.stream_info.total_samples - until);
		}

                if (datasource->bps != 8 && datasource->bps != 16 && datasource->bps != 24) {
                        warn("ERROR: bits per sample is not 8/16/24\n");
                        datasource->abort_flag = true;
                        return;
                }
	}
}

static void error_callback(
	const decoder_t *decoder,
	FLAC__StreamDecoderErrorStatus status, void *client_data) {

	/* flac_datasource *datasource = (flac_datasource *)client_data; */



( run in 0.519 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )