/** * 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); } } }
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; }