static void
sndfile_stream_decode(struct decoder *decoder, struct input_stream *is)
{
	GError *error = NULL;
	SNDFILE *sf;
	SF_INFO info;
	struct audio_format audio_format;
	size_t frame_size;
	sf_count_t read_frames, num_frames;
	int buffer[4096];
	enum decoder_command cmd;

	info.format = 0;

	sf = sf_open_virtual(&vio, SFM_READ, &info, is);
	if (sf == NULL) {
		g_warning("sf_open_virtual() failed");
		return;
	}

	/* for now, always read 32 bit samples.  Later, we could lower
	   MPD's CPU usage by reading 16 bit samples with
	   sf_readf_short() on low-quality source files. */
	if (!audio_format_init_checked(&audio_format, info.samplerate,
				       SAMPLE_FORMAT_S32,
				       info.channels, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		return;
	}

	decoder_initialized(decoder, &audio_format, info.seekable,
			    frame_to_time(info.frames, &audio_format));

	frame_size = audio_format_frame_size(&audio_format);
	read_frames = sizeof(buffer) / frame_size;

	do {
		num_frames = sf_readf_int(sf, buffer, read_frames);
		if (num_frames <= 0)
			break;

		cmd = decoder_data(decoder, is,
				   buffer, num_frames * frame_size,
				   0);
		if (cmd == DECODE_COMMAND_SEEK) {
			sf_count_t c =
				time_to_frame(decoder_seek_where(decoder),
					      &audio_format);
			c = sf_seek(sf, c, SEEK_SET);
			if (c < 0)
				decoder_seek_error(decoder);
			else
				decoder_command_finished(decoder);
			cmd = DECODE_COMMAND_NONE;
		}
	} while (cmd == DECODE_COMMAND_NONE);

	sf_close(sf);
}
Пример #2
0
static void
flac_got_stream_info(struct flac_data *data,
		     const FLAC__StreamMetadata_StreamInfo *stream_info)
{
	if (data->initialized || data->unsupported)
		return;

	GError *error = NULL;
	if (!audio_format_init_checked(&data->audio_format,
				       stream_info->sample_rate,
				       flac_sample_format(stream_info->bits_per_sample),
				       stream_info->channels, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		data->unsupported = true;
		return;
	}

	data->frame_size = audio_format_frame_size(&data->audio_format);

	if (data->total_frames == 0)
		data->total_frames = stream_info->total_samples;

	data->initialized = true;
}
Пример #3
0
/**
 * This function attempts to call decoder_initialized() in case there
 * was no STREAMINFO block.  This is allowed for nonseekable streams,
 * where the server sends us only a part of the file, without
 * providing the STREAMINFO block from the beginning of the file
 * (e.g. when seeking with SqueezeBox Server).
 */
static bool
flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header)
{
	if (data->unsupported)
		return false;

	GError *error = NULL;
	if (!audio_format_init_checked(&data->audio_format,
				       header->sample_rate,
				       flac_sample_format(header->bits_per_sample),
				       header->channels, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		data->unsupported = true;
		return false;
	}

	data->frame_size = audio_format_frame_size(&data->audio_format);

	decoder_initialized(data->decoder, &data->audio_format,
			    data->input_stream->seekable,
			    (float)data->total_frames /
			    (float)data->audio_format.sample_rate);

	data->initialized = true;

	return true;
}
Пример #4
0
static void
mp3_decode(struct decoder *decoder, struct input_stream *input_stream)
{
	struct mp3_data data;
	GError *error = NULL;
	struct tag *tag = NULL;
	struct audio_format audio_format;

	if (!mp3_open(input_stream, &data, decoder, &tag)) {
		if (decoder_get_command(decoder) == DECODE_COMMAND_NONE)
			g_warning
			    ("Input does not appear to be a mp3 bit stream.\n");
		return;
	}

	if (!audio_format_init_checked(&audio_format,
				       data.frame.header.samplerate,
				       SAMPLE_FORMAT_S24_P32,
				       MAD_NCHANNELS(&data.frame.header),
				       &error)) {
		g_warning("%s", error->message);
		g_error_free(error);

		if (tag != NULL)
			tag_free(tag);
		mp3_data_finish(&data);
		return;
	}

	decoder_initialized(decoder, &audio_format,
			    data.input_stream->seekable, data.total_time);

	if (tag != NULL) {
		decoder_tag(decoder, input_stream, tag);
		tag_free(tag);
	}

	while (mp3_read(&data)) ;

	mp3_data_finish(&data);
}
Пример #5
0
static void
dsf_stream_decode(struct decoder *decoder, struct input_stream *is)
{
	struct dsf_metadata metadata = {
		.sample_rate = 0,
		.channels = 0,
	};

	/* check if it is a proper DSF file */
	if (!dsf_read_metadata(decoder, is, &metadata))
		return;

	GError *error = NULL;
	struct audio_format audio_format;
	if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
				       SAMPLE_FORMAT_DSD,
				       metadata.channels, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		return;
	}

	/* success: file was recognized */
	decoder_initialized(decoder, &audio_format, false, -1);

	if (!dsf_decode_chunk(decoder, is, metadata.channels,
			      metadata.chunk_size,
			      metadata.bitreverse))
		return;
}

static bool
dsf_scan_stream(struct input_stream *is,
		   G_GNUC_UNUSED const struct tag_handler *handler,
		   G_GNUC_UNUSED void *handler_ctx)
{
	struct dsf_metadata metadata = {
		.sample_rate = 0,
		.channels = 0,
	};

	/* check DSF metadata */
	if (!dsf_read_metadata(NULL, is, &metadata))
		return false;

	struct audio_format audio_format;
	if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
				       SAMPLE_FORMAT_DSD,
				       metadata.channels, NULL))
		/* refuse to parse files which we cannot play anyway */
		return false;

	return true;
}

static const char *const dsf_suffixes[] = {
	"dsf",
	NULL
};

static const char *const dsf_mime_types[] = {
	"application/x-dsf",
	NULL
};

const struct decoder_plugin dsf_decoder_plugin = {
	.name = "dsf",
	.stream_decode = dsf_stream_decode,
	.scan_stream = dsf_scan_stream,
	.suffixes = dsf_suffixes,
	.mime_types = dsf_mime_types,
};
Пример #6
0
/* public */
static void
vorbis_stream_decode(struct decoder *decoder,
		     struct input_stream *input_stream)
{
	GError *error = NULL;
	OggVorbis_File vf;
	struct vorbis_input_stream vis;
	struct audio_format audio_format;
	float total_time;
	int current_section;
	int prev_section = -1;
	long ret;
	char chunk[OGG_CHUNK_SIZE];
	long bitRate = 0;
	long test;
	const vorbis_info *vi;
	enum decoder_command cmd = DECODE_COMMAND_NONE;

	if (ogg_stream_type_detect(input_stream) != VORBIS)
		return;

	/* rewind the stream, because ogg_stream_type_detect() has
	   moved it */
	input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL);

	if (!vorbis_is_open(&vis, &vf, decoder, input_stream))
		return;

	vi = ov_info(&vf, -1);
	if (vi == NULL) {
		g_warning("ov_info() has failed");
		return;
	}

	if (!audio_format_init_checked(&audio_format, vi->rate,
				       SAMPLE_FORMAT_S16,
				       vi->channels, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		return;
	}

	total_time = ov_time_total(&vf, -1);
	if (total_time < 0)
		total_time = 0;

	decoder_initialized(decoder, &audio_format, vis.seekable, total_time);

	do {
		if (cmd == DECODE_COMMAND_SEEK) {
			double seek_where = decoder_seek_where(decoder);
			if (0 == ov_time_seek_page(&vf, seek_where)) {
				decoder_command_finished(decoder);
			} else
				decoder_seek_error(decoder);
		}

		ret = ov_read(&vf, chunk, sizeof(chunk),
			      OGG_DECODE_USE_BIGENDIAN, 2, 1, &current_section);
		if (ret == OV_HOLE) /* bad packet */
			ret = 0;
		else if (ret <= 0)
			/* break on EOF or other error */
			break;

		if (current_section != prev_section) {
			char **comments;

			vi = ov_info(&vf, -1);
			if (vi == NULL) {
				g_warning("ov_info() has failed");
				break;
			}

			if (vi->rate != (long)audio_format.sample_rate ||
			    vi->channels != (int)audio_format.channels) {
				/* we don't support audio format
				   change yet */
				g_warning("audio format change, stopping here");
				break;
			}

			comments = ov_comment(&vf, -1)->user_comments;
			vorbis_send_comments(decoder, input_stream, comments);

			struct replay_gain_info rgi;
			if (vorbis_comments_to_replay_gain(&rgi, comments))
				decoder_replay_gain(decoder, &rgi);

			prev_section = current_section;
		}

		if ((test = ov_bitrate_instant(&vf)) > 0)
			bitRate = test / 1000;

		cmd = decoder_data(decoder, input_stream,
				   chunk, ret,
				   bitRate);
	} while (cmd != DECODE_COMMAND_STOP);

	ov_clear(&vf);
}
Пример #7
0
static void
dsdiff_stream_decode(struct decoder *decoder, struct input_stream *is)
{
	struct dsdiff_metadata metadata = {
		.sample_rate = 0,
		.channels = 0,
	};

	struct dsdiff_chunk_header chunk_header;
	/* First see if it is is a DFF file */
	if (!dsdiff_read_metadata(decoder, is, &metadata, &chunk_header))
	{
		/* It was not a DFF file, now check if it is a DSF file */
		if (!dsf_read_metadata(decoder, is, &metadata))
			return;
	}

	GError *error = NULL;
	struct audio_format audio_format;
	if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
				       SAMPLE_FORMAT_DSD,
				       metadata.channels, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		return;
	}

	/* success: file was recognized */
	decoder_initialized(decoder, &audio_format, false, -1);

	if (!metadata.fileisdff) {
		uint64_t chunk_size = metadata.chunk_size;
		if (!dsdiff_decode_chunk(decoder, is,
					 metadata.channels,
					 chunk_size,
					 metadata.fileisdff,
					 metadata.bitreverse))
			return;

	} else {

		/* every iteration of the following loop decodes one "DSD"
		   chunk from a DFF file */

		while (true) {

			uint64_t chunk_size = dsdiff_chunk_size(&chunk_header);

			if (dsdiff_id_equals(&chunk_header.id, "DSD ")) {
				if (!dsdiff_decode_chunk(decoder, is,
							 metadata.channels,
							 chunk_size,
							 metadata.fileisdff,
						/* Set bitreverse to
						   false for DFF files */
							false))
					break;
			} else {
				/* ignore other chunks */

				if (!dsdiff_skip(decoder, is, chunk_size))
					break;
			}

			/* read next chunk header; the first one was read by
			   dsdiff_read_metadata() */

			if (!dsdiff_read_chunk_header(decoder,
						      is, &chunk_header))
				break;
		}
	}
}

static bool
dsdiff_scan_stream(struct input_stream *is,
		   G_GNUC_UNUSED const struct tag_handler *handler,
		   G_GNUC_UNUSED void *handler_ctx)
{
	struct dsdiff_metadata metadata = {
		.sample_rate = 0,
		.channels = 0,
	};

	struct dsdiff_chunk_header chunk_header;
	/* First check for DFF metadata */
	if (!dsdiff_read_metadata(NULL, is, &metadata, &chunk_header))
	{
		/* It was not an DFF file, now check for DSF metadata */
		if (!dsf_read_metadata(NULL, is, &metadata))
			return false;
	}

	struct audio_format audio_format;
	if (!audio_format_init_checked(&audio_format, metadata.sample_rate / 8,
				       SAMPLE_FORMAT_DSD,
				       metadata.channels, NULL))
		/* refuse to parse files which we cannot play anyway */
		return false;

	/* no total time estimate, no tags implemented yet */
	return true;
}

static const char *const dsdiff_suffixes[] = {
	"dff",
	"dsf",
	NULL
};

static const char *const dsdiff_mime_types[] = {
	"application/x-dff",
	"application/x-dsf",
	NULL
};

const struct decoder_plugin dsdiff_decoder_plugin = {
	.name = "dsdiff",
	.init = dsdiff_init,
	.stream_decode = dsdiff_stream_decode,
	.scan_stream = dsdiff_scan_stream,
	.suffixes = dsdiff_suffixes,
	.mime_types = dsdiff_mime_types,
};
Пример #8
0
static void
audiofile_stream_decode(struct decoder *decoder, struct input_stream *is)
{
	GError *error = NULL;
	AFvirtualfile *vf;
	int fs, frame_count;
	AFfilehandle af_fp;
	struct audio_format audio_format;
	float total_time;
	uint16_t bit_rate;
	int ret;
	char chunk[CHUNK_SIZE];
	enum decoder_command cmd;

	if (!is->seekable) {
		g_warning("not seekable");
		return;
	}

	vf = setup_virtual_fops(is);

	af_fp = afOpenVirtualFile(vf, "r", NULL);
	if (af_fp == AF_NULL_FILEHANDLE) {
		g_warning("failed to input stream\n");
		return;
	}

	if (!audio_format_init_checked(&audio_format,
				       afGetRate(af_fp, AF_DEFAULT_TRACK),
				       audiofile_setup_sample_format(af_fp),
				       afGetVirtualChannels(af_fp, AF_DEFAULT_TRACK),
				       &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		afCloseFile(af_fp);
		return;
	}

	frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK);

	total_time = ((float)frame_count / (float)audio_format.sample_rate);

	bit_rate = (uint16_t)(is->size * 8.0 / total_time / 1000.0 + 0.5);

	fs = (int)afGetVirtualFrameSize(af_fp, AF_DEFAULT_TRACK, 1);

	decoder_initialized(decoder, &audio_format, true, total_time);

	do {
		ret = afReadFrames(af_fp, AF_DEFAULT_TRACK, chunk,
				   CHUNK_SIZE / fs);
		if (ret <= 0)
			break;

		cmd = decoder_data(decoder, NULL,
				   chunk, ret * fs,
				   bit_rate);

		if (cmd == DECODE_COMMAND_SEEK) {
			AFframecount frame = decoder_seek_where(decoder) *
				audio_format.sample_rate;
			afSeekFrame(af_fp, AF_DEFAULT_TRACK, frame);

			decoder_command_finished(decoder);
			cmd = DECODE_COMMAND_NONE;
		}
	} while (cmd == DECODE_COMMAND_NONE);

	afCloseFile(af_fp);
}
Пример #9
0
/* public */
static void
vorbis_stream_decode(struct decoder *decoder,
		     struct input_stream *input_stream)
{
	GError *error = NULL;

	if (ogg_codec_detect(decoder, input_stream) != OGG_CODEC_VORBIS)
		return;

	/* rewind the stream, because ogg_codec_detect() has
	   moved it */
	input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL);

	struct vorbis_input_stream vis;
	OggVorbis_File vf;
	if (!vorbis_is_open(&vis, &vf, decoder, input_stream))
		return;

	const vorbis_info *vi = ov_info(&vf, -1);
	if (vi == NULL) {
		g_warning("ov_info() has failed");
		return;
	}

	struct audio_format audio_format;
	if (!audio_format_init_checked(&audio_format, vi->rate,
#ifdef HAVE_TREMOR
				       SAMPLE_FORMAT_S16,
#else
				       SAMPLE_FORMAT_FLOAT,
#endif
				       vi->channels, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		return;
	}

	float total_time = ov_time_total(&vf, -1);
	if (total_time < 0)
		total_time = 0;

	decoder_initialized(decoder, &audio_format, vis.seekable, total_time);

	enum decoder_command cmd = decoder_get_command(decoder);

#ifdef HAVE_TREMOR
	char buffer[4096];
#else
	float buffer[2048];
	const int frames_per_buffer =
		G_N_ELEMENTS(buffer) / audio_format.channels;
	const unsigned frame_size = sizeof(buffer[0]) * audio_format.channels;
#endif

	int prev_section = -1;
	unsigned kbit_rate = 0;

	do {
		if (cmd == DECODE_COMMAND_SEEK) {
			double seek_where = decoder_seek_where(decoder);
			if (0 == ov_time_seek_page(&vf, seek_where)) {
				decoder_command_finished(decoder);
			} else
				decoder_seek_error(decoder);
		}

		int current_section;

#ifdef HAVE_TREMOR
		long nbytes = ov_read(&vf, buffer, sizeof(buffer),
				      VORBIS_BIG_ENDIAN, 2, 1,
				      &current_section);
#else
		float **per_channel;
		long nframes = ov_read_float(&vf, &per_channel,
					     frames_per_buffer,
					     &current_section);
		long nbytes = nframes;
		if (nframes > 0) {
			vorbis_interleave(buffer,
					  (const float*const*)per_channel,
					  nframes, audio_format.channels);
			nbytes *= frame_size;
		}
#endif

		if (nbytes == OV_HOLE) /* bad packet */
			nbytes = 0;
		else if (nbytes <= 0)
			/* break on EOF or other error */
			break;

		if (current_section != prev_section) {
			vi = ov_info(&vf, -1);
			if (vi == NULL) {
				g_warning("ov_info() has failed");
				break;
			}

			if (vi->rate != (long)audio_format.sample_rate ||
			    vi->channels != (int)audio_format.channels) {
				/* we don't support audio format
				   change yet */
				g_warning("audio format change, stopping here");
				break;
			}

			char **comments = ov_comment(&vf, -1)->user_comments;
			vorbis_send_comments(decoder, input_stream, comments);

			struct replay_gain_info rgi;
			if (vorbis_comments_to_replay_gain(&rgi, comments))
				decoder_replay_gain(decoder, &rgi);

			prev_section = current_section;
		}

		long test = ov_bitrate_instant(&vf);
		if (test > 0)
			kbit_rate = test / 1000;

		cmd = decoder_data(decoder, input_stream,
				   buffer, nbytes,
				   kbit_rate);
	} while (cmd != DECODE_COMMAND_STOP);

	ov_clear(&vf);
}
Пример #10
0
/*
 * This does the main decoding thing.
 * Requires an already opened WavpackContext.
 */
static void
wavpack_decode(struct decoder *decoder, WavpackContext *wpc, bool can_seek)
{
	GError *error = NULL;
	bool is_float;
	enum sample_format sample_format;
	struct audio_format audio_format;
	format_samples_t format_samples;
	float total_time;
	int bytes_per_sample, output_sample_size;

	is_float = (WavpackGetMode(wpc) & MODE_FLOAT) != 0;
	sample_format =
		wavpack_bits_to_sample_format(is_float,
					      WavpackGetBytesPerSample(wpc));

	if (!audio_format_init_checked(&audio_format,
				       WavpackGetSampleRate(wpc),
				       sample_format,
				       WavpackGetNumChannels(wpc), &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		return;
	}

	if (is_float) {
		format_samples = format_samples_float;
	} else {
		format_samples = format_samples_int;
	}

	total_time = WavpackGetNumSamples(wpc);
	total_time /= audio_format.sample_rate;
	bytes_per_sample = WavpackGetBytesPerSample(wpc);
	output_sample_size = audio_format_frame_size(&audio_format);

	/* wavpack gives us all kind of samples in a 32-bit space */
	int32_t chunk[1024];
	const uint32_t samples_requested = G_N_ELEMENTS(chunk) /
		audio_format.channels;

	decoder_initialized(decoder, &audio_format, can_seek, total_time);

	enum decoder_command cmd = decoder_get_command(decoder);
	while (cmd != DECODE_COMMAND_STOP) {
		if (cmd == DECODE_COMMAND_SEEK) {
			if (can_seek) {
				unsigned where = decoder_seek_where(decoder) *
					audio_format.sample_rate;

				if (WavpackSeekSample(wpc, where)) {
					decoder_command_finished(decoder);
				} else {
					decoder_seek_error(decoder);
				}
			} else {
				decoder_seek_error(decoder);
			}
		}

		uint32_t samples_got = WavpackUnpackSamples(wpc, chunk,
							    samples_requested);
		if (samples_got == 0)
			break;

		int bitrate = (int)(WavpackGetInstantBitrate(wpc) / 1000 +
				    0.5);
		format_samples(bytes_per_sample, chunk,
			       samples_got * audio_format.channels);

		cmd = decoder_data(decoder, NULL, chunk,
				   samples_got * output_sample_size,
				   bitrate);
	}
}