/**
 * Recalculates the new volume after a property was changed.
 */
static void
replay_gain_filter_update(struct replay_gain_filter *filter)
{
	if (filter->mode != REPLAY_GAIN_OFF) {
		const struct replay_gain_tuple *tuple =
			&filter->info.tuples[filter->mode];
		float scale = replay_gain_tuple_defined(tuple)
			? replay_gain_tuple_scale(tuple, replay_gain_preamp)
			: replay_gain_missing_preamp;
		g_debug("scale=%f\n", (double)scale);

		filter->volume = pcm_float_to_volume(scale);
	} else
		filter->volume = PCM_VOLUME_1;

	if (filter->mixer != NULL) {
		/* update the hardware mixer volume */

		unsigned volume = (filter->volume * filter->base) / PCM_VOLUME_1;
		if (volume > 100)
			volume = 100;

		GError *error = NULL;
		if (!mixer_set_volume(filter->mixer, volume, &error)) {
			g_warning("Failed to update hardware mixer: %s",
				  error->message);
			g_error_free(error);
		}
	}
}
Example #2
0
float
decoder_replay_gain(struct decoder *decoder,
		    const struct replay_gain_info *replay_gain_info)
{
	float return_db = 0;
	assert(decoder != NULL);

	if (replay_gain_info != NULL) {
		static unsigned serial;
		if (++serial == 0)
			serial = 1;

		if (REPLAY_GAIN_OFF != replay_gain_mode) {
			return_db = 20.0 * log10f(
				replay_gain_tuple_scale(
					&replay_gain_info->tuples[replay_gain_get_real_mode()],
					replay_gain_preamp, replay_gain_missing_preamp,
					replay_gain_limit));
		}

		decoder->replay_gain_info = *replay_gain_info;
		decoder->replay_gain_serial = serial;

		if (decoder->chunk != NULL) {
			/* flush the current chunk because the new
			   replay gain values affect the following
			   samples */
			decoder_flush_chunk(decoder);
			player_lock_signal();
		}
	} else
		decoder->replay_gain_serial = 0;

	return return_db;
}