Ejemplo n.º 1
0
void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
			     struct flac_data *data)
{
	if (data->unsupported)
		return;

	struct replay_gain_info rgi;
	char *mixramp_start;
	char *mixramp_end;
	float replay_gain_db = 0;

	switch (block->type) {
	case FLAC__METADATA_TYPE_STREAMINFO:
		flac_got_stream_info(data, &block->data.stream_info);
		break;

	case FLAC__METADATA_TYPE_VORBIS_COMMENT:
		if (flac_parse_replay_gain(&rgi, block))
			replay_gain_db = decoder_replay_gain(data->decoder, &rgi);
		if (flac_parse_mixramp(&mixramp_start, &mixramp_end, block)) {
			g_debug("setting mixramp_tags");
			decoder_mixramp(data->decoder, replay_gain_db,
					mixramp_start, mixramp_end);
		}

		if (data->tag != NULL)
			flac_vorbis_comments_to_tag(data->tag, NULL,
						    &block->data.vorbis_comment);

	default:
		break;
	}
}
Ejemplo n.º 2
0
/**
 * Attempt to load replay gain data, and pass it to
 * decoder_replay_gain().
 */
static void
decoder_load_replay_gain(struct decoder *decoder, const char *path_fs)
{
	struct replay_gain_info info;
	if (replay_gain_ape_read(path_fs, &info))
		decoder_replay_gain(decoder, &info);
}
Ejemplo n.º 3
0
/*
 * Decodes a file.
 */
static void
wavpack_filedecode(struct decoder *decoder, const char *fname)
{
	char error[ERRORLEN];
	WavpackContext *wpc;

	wpc = WavpackOpenFileInput(
		fname, error,
		OPEN_TAGS | OPEN_WVC | OPEN_NORMALIZE, 23
	);
	if (wpc == NULL) {
		g_warning(
			"failed to open WavPack file \"%s\": %s\n",
			fname, error
		);
		return;
	}

	struct replay_gain_info replay_gain_info;
	if (wavpack_replaygain(&replay_gain_info, wpc))
		decoder_replay_gain(decoder, &replay_gain_info);

	wavpack_decode(decoder, wpc, true);

	WavpackCloseFile(wpc);
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
static bool
mp3_decode_first_frame(struct mp3_data *data, struct tag **tag)
{
	struct xing xing;
	struct lame lame;
	struct mad_bitptr ptr;
	int bitlen;
	enum mp3_action ret;

	/* stfu gcc */
	memset(&xing, 0, sizeof(struct xing));
	xing.flags = 0;

	while (true) {
		do {
			ret = decode_next_frame_header(data, tag);
		} while (ret == DECODE_CONT);
		if (ret == DECODE_BREAK)
			return false;
		if (ret == DECODE_SKIP) continue;

		do {
			ret = decodeNextFrame(data);
		} while (ret == DECODE_CONT);
		if (ret == DECODE_BREAK)
			return false;
		if (ret == DECODE_OK) break;
	}

	ptr = data->stream.anc_ptr;
	bitlen = data->stream.anc_bitlen;

	mp3_filesize_to_song_length(data);

	/*
	 * if an xing tag exists, use that!
	 */
	if (parse_xing(&xing, &ptr, &bitlen)) {
		data->found_xing = true;
		data->mute_frame = MUTEFRAME_SKIP;

		if ((xing.flags & XING_FRAMES) && xing.frames) {
			mad_timer_t duration = data->frame.header.duration;
			mad_timer_multiply(&duration, xing.frames);
			data->total_time = ((float)mad_timer_count(duration, MAD_UNITS_MILLISECONDS)) / 1000;
			data->max_frames = xing.frames;
		}

		if (parse_lame(&lame, &ptr, &bitlen)) {
			if (gapless_playback &&
			    data->input_stream->seekable) {
				data->drop_start_samples = lame.encoder_delay +
				                           DECODERDELAY;
				data->drop_end_samples = lame.encoder_padding;
			}

			/* Album gain isn't currently used.  See comment in
			 * parse_lame() for details. -- jat */
			if (data->decoder != NULL &&
			    !data->found_replay_gain &&
			    lame.track_gain) {
				struct replay_gain_info rgi;
				replay_gain_info_init(&rgi);
				rgi.tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain;
				rgi.tuples[REPLAY_GAIN_TRACK].peak = lame.peak;
				decoder_replay_gain(data->decoder, &rgi);
			}
		}
	}

	if (!data->max_frames)
		return false;

	if (data->max_frames > 8 * 1024 * 1024) {
		g_warning("mp3 file header indicates too many frames: %lu\n",
			  data->max_frames);
		return false;
	}

	data->frame_offsets = g_malloc(sizeof(long) * data->max_frames);
	data->times = g_malloc(sizeof(mad_timer_t) * data->max_frames);

	return true;
}
Ejemplo n.º 6
0
static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
			  struct tag **mpd_tag)
{
#ifdef HAVE_ID3TAG
	struct id3_tag *id3_tag = NULL;
	id3_length_t count;
	id3_byte_t const *id3_data;
	id3_byte_t *allocated = NULL;

	count = data->stream.bufend - data->stream.this_frame;

	if (tagsize <= count) {
		id3_data = data->stream.this_frame;
		mad_stream_skip(&(data->stream), tagsize);
	} else {
		allocated = g_malloc(tagsize);
		memcpy(allocated, data->stream.this_frame, count);
		mad_stream_skip(&(data->stream), count);

		while (count < tagsize) {
			size_t len;

			len = decoder_read(data->decoder, data->input_stream,
					   allocated + count, tagsize - count);
			if (len == 0)
				break;
			else
				count += len;
		}

		if (count != tagsize) {
			g_debug("error parsing ID3 tag");
			g_free(allocated);
			return;
		}

		id3_data = allocated;
	}

	id3_tag = id3_tag_parse(id3_data, tagsize);
	if (id3_tag == NULL) {
		g_free(allocated);
		return;
	}

	if (mpd_tag) {
		struct tag *tmp_tag = tag_id3_import(id3_tag);
		if (tmp_tag != NULL) {
			if (*mpd_tag != NULL)
				tag_free(*mpd_tag);
			*mpd_tag = tmp_tag;
		}
	}

	if (data->decoder != NULL) {
		struct replay_gain_info rgi;
		char *mixramp_start;
		char *mixramp_end;
		float replay_gain_db = 0;

		if (parse_id3_replay_gain_info(&rgi, id3_tag)) {
			replay_gain_db = decoder_replay_gain(data->decoder, &rgi);
			data->found_replay_gain = true;
		}
		if (parse_id3_mixramp(&mixramp_start, &mixramp_end, id3_tag)) {
			g_debug("setting mixramp_tags");
			decoder_mixramp(data->decoder, replay_gain_db,
					mixramp_start, mixramp_end);
		}
	}

	id3_tag_delete(id3_tag);

	g_free(allocated);
#else /* !HAVE_ID3TAG */
	(void)mpd_tag;

	/* This code is enabled when libid3tag is disabled.  Instead
	   of parsing the ID3 frame, it just skips it. */

	size_t count = data->stream.bufend - data->stream.this_frame;

	if (tagsize <= count) {
		mad_stream_skip(&data->stream, tagsize);
	} else {
		mad_stream_skip(&data->stream, count);

		while (count < tagsize) {
			size_t len = tagsize - count;
			char ignored[1024];
			if (len > sizeof(ignored))
				len = sizeof(ignored);

			len = decoder_read(data->decoder, data->input_stream,
					   ignored, len);
			if (len == 0)
				break;
			else
				count += len;
		}
	}
#endif
}
Ejemplo n.º 7
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);
}