コード例 #1
0
ファイル: mad.c プロジェクト: eggpi/xmms2-guilherme
static gint64
xmms_mad_seek (xmms_xform_t *xform, gint64 samples, xmms_xform_seek_mode_t whence, xmms_error_t *err)
{
	xmms_mad_data_t *data;
	guint bytes;
	gint64 res;

	g_return_val_if_fail (whence == XMMS_XFORM_SEEK_SET, -1);
	g_return_val_if_fail (xform, -1);

	data = xmms_xform_private_data_get (xform);

	if (data->xing &&
	    xmms_xing_has_flag (data->xing, XMMS_XING_FRAMES) &&
	    xmms_xing_has_flag (data->xing, XMMS_XING_TOC)) {
		guint i;

		i = (guint) (100ULL * samples / xmms_xing_get_frames (data->xing) / 1152);

		bytes = xmms_xing_get_toc (data->xing, i) * (xmms_xing_get_bytes (data->xing) / 256);
	} else {
		bytes = (guint)(((gdouble)samples) * data->bitrate / data->samplerate) / 8;
	}

	XMMS_DBG ("Try seek %" G_GINT64_FORMAT " samples -> %d bytes", samples, bytes);

	res = xmms_xform_seek (xform, bytes, XMMS_XFORM_SEEK_SET, err);
	if (res == -1) {
		return -1;
	}

	/* we don't have sample accuracy when seeking,
	   so there is no use trying */
	data->samples_to_skip = 0;
	data->samples_to_play = -1;

	return samples;
}
コード例 #2
0
ファイル: mad.c プロジェクト: eggpi/xmms2-guilherme
static gboolean
xmms_mad_init (xmms_xform_t *xform)
{
	struct mad_frame frame;
	struct mad_stream stream;
	xmms_error_t err;
	guchar buf[40960];
	xmms_mad_data_t *data;
	int len;
	const gchar *metakey;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_mad_data_t, 1);

	mad_stream_init (&data->stream);
	mad_frame_init (&data->frame);
	mad_synth_init (&data->synth);

	xmms_xform_private_data_set (xform, data);

	data->buffer_length = 0;

	data->synthpos = 0x7fffffff;

	mad_stream_init (&stream);
	mad_frame_init (&frame);

	len = xmms_xform_peek (xform, buf, 40960, &err);
	mad_stream_buffer (&stream, buf, len);

	while (mad_frame_decode (&frame, &stream) == -1) {
		if (!MAD_RECOVERABLE (stream.error)) {
			XMMS_DBG ("couldn't decode %02x %02x %02x %02x",buf[0],buf[1],buf[2],buf[3]);
			mad_frame_finish (&frame);
			mad_stream_finish (&stream);
			return FALSE;
		}
	}

	data->channels = frame.header.mode == MAD_MODE_SINGLE_CHANNEL ? 1 : 2;
	data->samplerate = frame.header.samplerate;


	if (frame.header.flags & MAD_FLAG_PROTECTION) {
		XMMS_DBG ("Frame has protection enabled");
		if (stream.anc_ptr.byte > stream.buffer + 2) {
			stream.anc_ptr.byte = stream.anc_ptr.byte - 2;
		}
	}

	data->samples_to_play = -1;

	data->xing = xmms_xing_parse (stream.anc_ptr);
	if (data->xing) {
		xmms_xing_lame_t *lame;
		XMMS_DBG ("File with Xing header!");

		metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_IS_VBR;
		xmms_xform_metadata_set_int (xform, metakey, 1);

		if (xmms_xing_has_flag (data->xing, XMMS_XING_FRAMES)) {
			guint duration;
			mad_timer_t timer;

			timer = frame.header.duration;
			mad_timer_multiply (&timer, xmms_xing_get_frames (data->xing));
			duration = mad_timer_count (timer, MAD_UNITS_MILLISECONDS);

			XMMS_DBG ("XING duration %d", duration);

			metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION;
			xmms_xform_metadata_set_int (xform, metakey, duration);

			if (xmms_xing_has_flag (data->xing, XMMS_XING_BYTES) && duration) {
				guint tmp;

				tmp = xmms_xing_get_bytes (data->xing) * ((guint64)8000) / duration;
				XMMS_DBG ("XING bitrate %d", tmp);
				metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE;
				xmms_xform_metadata_set_int (xform, metakey, tmp);
			}
		}

		lame = xmms_xing_get_lame (data->xing);
		if (lame) {
			/* FIXME: add a check for ignore_lame_headers from the medialib */
			data->frames_to_skip = 1;
			data->samples_to_skip = lame->start_delay;
			data->samples_to_play = ((guint64) xmms_xing_get_frames (data->xing) * 1152ULL) -
			                        lame->start_delay - lame->end_padding;
			XMMS_DBG ("Samples to skip in the beginning: %d, total: %" G_GINT64_FORMAT,
			          data->samples_to_skip, data->samples_to_play);
			/*
			metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_ALBUM;
			xmms_xform_metadata_set_int (xform, metakey, lame->audiophile_gain);

			metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_PEAK_TRACK;
			xmms_xform_metadata_set_int (xform, metakey, lame->peak_amplitude);

			metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_GAIN_TRACK;
			xmms_xform_metadata_set_int (xform, metakey, lame->radio_gain);
			*/
		}

	} else {
		gint filesize;

		metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_BITRATE;
		xmms_xform_metadata_set_int (xform, metakey, frame.header.bitrate);

		metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION;
		if (!xmms_xform_metadata_get_int (xform, metakey, &filesize)) {
			metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_SIZE;

			if (xmms_xform_metadata_get_int (xform, metakey, &filesize)) {
				gint32 val;

				val = (gint32) (filesize * (gdouble) 8000.0 / frame.header.bitrate);

				metakey = XMMS_MEDIALIB_ENTRY_PROPERTY_DURATION;
				xmms_xform_metadata_set_int (xform, metakey, val);
			}
		}
	}

	/* seeking needs bitrate */
	data->bitrate = frame.header.bitrate;

	if (xmms_id3v1_get_tags (xform) < 0) {
		mad_stream_finish (&data->stream);
		mad_frame_finish (&data->frame);
		mad_synth_finish (&data->synth);
		if (data->xing) {
			xmms_xing_free (data->xing);
		}
		return FALSE;
	}

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm",
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             XMMS_SAMPLE_FORMAT_S16,
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             data->channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             data->samplerate,
	                             XMMS_STREAM_TYPE_END);

	mad_frame_finish (&frame);
	mad_stream_finish (&stream);

	return TRUE;
}
コード例 #3
0
ファイル: xing.c プロジェクト: kfihihc/xmms2-devel
xmms_xing_t *
xmms_xing_parse (struct mad_bitptr ptr)
{
	xmms_xing_t *xing;
	guint32 xing_magic;

	xing_magic = mad_bit_read (&ptr, 4*8);

	/* Xing or Info */
	if (xing_magic != 0x58696e67 && xing_magic != 0x496e666f) {
		return NULL;
	}

	xing = g_new0 (xmms_xing_t, 1);

	g_return_val_if_fail (xing, NULL);

	xing->flags = mad_bit_read (&ptr, 32);

	if (xmms_xing_has_flag (xing, XMMS_XING_FRAMES))
		xing->frames = mad_bit_read (&ptr, 32);

	if (xmms_xing_has_flag (xing, XMMS_XING_BYTES))
		xing->bytes = mad_bit_read (&ptr, 32);

	if (xmms_xing_has_flag (xing, XMMS_XING_TOC)) {
		gint i;
		for (i = 0; i < 100; i++)
			xing->toc[i] = mad_bit_read (&ptr, 8);
	}

	if (xmms_xing_has_flag (xing, XMMS_XING_SCALE)) {
		/* just move the pointer forward */
		mad_bit_read (&ptr, 32);
	}


	xing->lame = parse_lame (&ptr);

	/*
	if (strncmp ((gchar *)ptr.byte, "LAME", 4) == 0) {
		lame = g_new0 (xmms_xing_lame_t, 1);
		XMMS_DBG ("Parsing LAME tag");
		mad_bit_skip (&ptr, 4 * 8);
		mad_bit_nextbyte (&ptr);
		mad_bit_skip (&ptr, (8 * 5) + 12);
		lame->peak_amplitude = mad_bit_read (&ptr, 32);
		lame->radio_gain = mad_bit_read (&ptr, 16);
		lame->audiophile_gain = mad_bit_read (&ptr, 16);
		mad_bit_skip (&ptr, 16);
		lame->encoder_delay_start = mad_bit_read (&ptr, 12);
		lame->encoder_delay_stop = mad_bit_read (&ptr, 12);
		mad_bit_skip (&ptr, 8);
		lame->mp3_gain = mad_bit_read (&ptr, 8);
		xing->lame = lame;
	}
	*/

	if (xmms_xing_has_flag (xing, XMMS_XING_FRAMES) && xing->frames == 0) {
		xmms_log_info ("Corrupt xing header (frames == 0), ignoring");
		xmms_xing_free (xing);
		return NULL;
	}

	if (xmms_xing_has_flag (xing, XMMS_XING_BYTES) && xing->bytes == 0) {
		xmms_log_info ("Corrupt xing header (bytes == 0), ignoring");
		xmms_xing_free (xing);
		return NULL;
	}

	if (xmms_xing_has_flag (xing, XMMS_XING_TOC)) {
		gint i;
		for (i = 0; i < 99; i++) {
			if (xing->toc[i] > xing->toc[i + 1]) {
				xmms_log_info ("Corrupt xing header (toc not monotonic), ignoring");
				xmms_xing_free (xing);
				return NULL;
			}
		}
	}

	return xing;
}