replay_gain: reimplement as a filter plugin
Apply the replay gain in the output thread. This means a new setting will be active instantly, without going through the whole music pipe. And we might have different replay gain settings for each audio output device.
This commit is contained in:
parent
5e0117b444
commit
752dfb3d95
|
@ -55,6 +55,7 @@ mpd_headers = \
|
|||
src/filter/autoconvert_filter_plugin.h \
|
||||
src/filter/chain_filter_plugin.h \
|
||||
src/filter/convert_filter_plugin.h \
|
||||
src/filter/replay_gain_filter_plugin.h \
|
||||
src/filter/volume_filter_plugin.h \
|
||||
src/command.h \
|
||||
src/idle.h \
|
||||
|
@ -175,7 +176,6 @@ mpd_headers = \
|
|||
src/queue_save.h \
|
||||
src/replay_gain_config.h \
|
||||
src/replay_gain_info.h \
|
||||
src/replay_gain_state.h \
|
||||
src/sig_handlers.h \
|
||||
src/song.h \
|
||||
src/song_print.h \
|
||||
|
@ -306,7 +306,6 @@ src_mpd_SOURCES = \
|
|||
src/queue_save.c \
|
||||
src/replay_gain_config.c \
|
||||
src/replay_gain_info.c \
|
||||
src/replay_gain_state.c \
|
||||
src/sig_handlers.c \
|
||||
src/song.c \
|
||||
src/song_update.c \
|
||||
|
@ -744,6 +743,7 @@ FILTER_SRC = \
|
|||
src/filter/convert_filter_plugin.c \
|
||||
src/filter/route_filter_plugin.c \
|
||||
src/filter/normalize_filter_plugin.c \
|
||||
src/filter/replay_gain_filter_plugin.c \
|
||||
src/filter/volume_filter_plugin.c
|
||||
|
||||
|
||||
|
@ -900,6 +900,8 @@ test_run_filter_SOURCES = test/run_filter.c \
|
|||
src/audio_check.c \
|
||||
src/audio_format.c \
|
||||
src/audio_parser.c \
|
||||
src/replay_gain_config.c \
|
||||
src/replay_gain_info.c \
|
||||
src/AudioCompress/compress.c \
|
||||
$(FILTER_SRC)
|
||||
|
||||
|
@ -985,10 +987,13 @@ test_run_output_SOURCES = test/run_output.c \
|
|||
src/filter_config.c \
|
||||
src/filter/autoconvert_filter_plugin.c \
|
||||
src/filter/convert_filter_plugin.c \
|
||||
src/filter/replay_gain_filter_plugin.c \
|
||||
src/filter/normalize_filter_plugin.c \
|
||||
src/filter/volume_filter_plugin.c \
|
||||
src/pcm_volume.c \
|
||||
src/AudioCompress/compress.c \
|
||||
src/replay_gain_info.c \
|
||||
src/replay_gain_config.c \
|
||||
src/fd_util.c \
|
||||
$(OUTPUT_SRC)
|
||||
|
||||
|
|
2
NEWS
2
NEWS
|
@ -70,6 +70,8 @@ ver 0.16 (20??/??/??)
|
|||
- rescan after metadata_to_use change
|
||||
* normalize: upgraded to AudioCompress 2.0
|
||||
- automatically convert to 16 bit samples
|
||||
* replay gain:
|
||||
- reimplemented as a filter plugin
|
||||
* log unused/unknown block parameters
|
||||
* removed the deprecated "error_file" option
|
||||
* save state when stopped
|
||||
|
|
|
@ -29,6 +29,7 @@ music_chunk_init(struct music_chunk *chunk)
|
|||
{
|
||||
chunk->length = 0;
|
||||
chunk->tag = NULL;
|
||||
chunk->replay_gain_serial = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
15
src/chunk.h
15
src/chunk.h
|
@ -20,6 +20,8 @@
|
|||
#ifndef MPD_CHUNK_H
|
||||
#define MPD_CHUNK_H
|
||||
|
||||
#include "replay_gain_info.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include "audio_format.h"
|
||||
#endif
|
||||
|
@ -59,6 +61,19 @@ struct music_chunk {
|
|||
*/
|
||||
struct tag *tag;
|
||||
|
||||
/**
|
||||
* Replay gain information associated with this chunk.
|
||||
* Only valid if the serial is not 0.
|
||||
*/
|
||||
struct replay_gain_info replay_gain_info;
|
||||
|
||||
/**
|
||||
* A serial number for checking if replay gain info has
|
||||
* changed since the last chunk. The magic value 0 indicates
|
||||
* that there is no replay gain info available.
|
||||
*/
|
||||
unsigned replay_gain_serial;
|
||||
|
||||
/** the data (probably PCM) */
|
||||
char data[CHUNK_SIZE];
|
||||
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include "buffer.h"
|
||||
#include "pipe.h"
|
||||
#include "chunk.h"
|
||||
#include "replay_gain_state.h"
|
||||
#include "replay_gain_config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
|
@ -343,13 +341,6 @@ decoder_data(struct decoder *decoder,
|
|||
|
||||
memcpy(dest, data, nbytes);
|
||||
|
||||
/* apply replay gain or normalization */
|
||||
|
||||
replay_gain_state_set_mode(decoder->replay_gain,
|
||||
replay_gain_mode);
|
||||
replay_gain_state_apply(decoder->replay_gain,
|
||||
dest, nbytes, &dc->out_audio_format);
|
||||
|
||||
/* expand the music pipe chunk */
|
||||
|
||||
full = music_chunk_expand(chunk, &dc->out_audio_format, nbytes);
|
||||
|
@ -418,5 +409,21 @@ decoder_replay_gain(struct decoder *decoder,
|
|||
{
|
||||
assert(decoder != NULL);
|
||||
|
||||
replay_gain_state_set_info(decoder->replay_gain, replay_gain_info);
|
||||
if (replay_gain_info != NULL) {
|
||||
static unsigned serial;
|
||||
if (++serial == 0)
|
||||
serial = 1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -86,8 +86,15 @@ decoder_get_chunk(struct decoder *decoder, struct input_stream *is)
|
|||
|
||||
do {
|
||||
decoder->chunk = music_buffer_allocate(dc->buffer);
|
||||
if (decoder->chunk != NULL)
|
||||
if (decoder->chunk != NULL) {
|
||||
decoder->chunk->replay_gain_serial =
|
||||
decoder->replay_gain_serial;
|
||||
if (decoder->replay_gain_serial != 0)
|
||||
decoder->chunk->replay_gain_info =
|
||||
decoder->replay_gain_info;
|
||||
|
||||
return decoder->chunk;
|
||||
}
|
||||
|
||||
decoder_lock(dc);
|
||||
cmd = need_chunks(dc, is, true);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "decoder_command.h"
|
||||
#include "pcm_convert.h"
|
||||
#include "replay_gain_info.h"
|
||||
|
||||
struct input_stream;
|
||||
|
||||
|
@ -53,7 +54,13 @@ struct decoder {
|
|||
/** the chunk currently being written to */
|
||||
struct music_chunk *chunk;
|
||||
|
||||
struct replay_gain_state *replay_gain;
|
||||
struct replay_gain_info replay_gain_info;
|
||||
|
||||
/**
|
||||
* A positive serial number for checking if replay gain info
|
||||
* has changed since the last check.
|
||||
*/
|
||||
unsigned replay_gain_serial;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
#include "mapper.h"
|
||||
#include "path.h"
|
||||
#include "uri.h"
|
||||
#include "replay_gain_state.h"
|
||||
#include "replay_gain_config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
|
@ -351,8 +349,6 @@ decoder_run_song(struct decoder_control *dc,
|
|||
{
|
||||
struct decoder decoder = {
|
||||
.dc = dc,
|
||||
.replay_gain = replay_gain_state_new(replay_gain_preamp,
|
||||
replay_gain_missing_preamp),
|
||||
};
|
||||
int ret;
|
||||
|
||||
|
@ -380,8 +376,6 @@ decoder_run_song(struct decoder_control *dc,
|
|||
pcm_convert_deinit(&decoder.conv_state);
|
||||
|
||||
/* flush the last chunk */
|
||||
if (decoder.replay_gain != NULL)
|
||||
replay_gain_state_free(decoder.replay_gain);
|
||||
|
||||
if (decoder.chunk != NULL)
|
||||
decoder_flush_chunk(&decoder);
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2010 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "filter/replay_gain_filter_plugin.h"
|
||||
#include "filter_plugin.h"
|
||||
#include "filter_internal.h"
|
||||
#include "filter_registry.h"
|
||||
#include "audio_format.h"
|
||||
#include "pcm_buffer.h"
|
||||
#include "pcm_volume.h"
|
||||
#include "replay_gain_info.h"
|
||||
#include "replay_gain_config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "replay_gain"
|
||||
|
||||
struct replay_gain_filter {
|
||||
struct filter filter;
|
||||
|
||||
enum replay_gain_mode mode;
|
||||
|
||||
struct replay_gain_info info;
|
||||
|
||||
/**
|
||||
* The current volume, between 0 and #PCM_VOLUME_1 (both
|
||||
* including).
|
||||
*/
|
||||
unsigned volume;
|
||||
|
||||
struct audio_format audio_format;
|
||||
|
||||
struct pcm_buffer buffer;
|
||||
};
|
||||
|
||||
static inline GQuark
|
||||
replay_gain_quark(void)
|
||||
{
|
||||
return g_quark_from_static_string("replay_gain");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
static struct filter *
|
||||
replay_gain_filter_init(G_GNUC_UNUSED const struct config_param *param,
|
||||
G_GNUC_UNUSED GError **error_r)
|
||||
{
|
||||
struct replay_gain_filter *filter = g_new(struct replay_gain_filter, 1);
|
||||
|
||||
filter_init(&filter->filter, &replay_gain_filter_plugin);
|
||||
|
||||
filter->mode = replay_gain_mode;
|
||||
replay_gain_info_init(&filter->info);
|
||||
filter->volume = PCM_VOLUME_1;
|
||||
|
||||
return &filter->filter;
|
||||
}
|
||||
|
||||
static void
|
||||
replay_gain_filter_finish(struct filter *filter)
|
||||
{
|
||||
g_free(filter);
|
||||
}
|
||||
|
||||
static const struct audio_format *
|
||||
replay_gain_filter_open(struct filter *_filter,
|
||||
struct audio_format *audio_format,
|
||||
G_GNUC_UNUSED GError **error_r)
|
||||
{
|
||||
struct replay_gain_filter *filter =
|
||||
(struct replay_gain_filter *)_filter;
|
||||
|
||||
audio_format->reverse_endian = false;
|
||||
|
||||
filter->audio_format = *audio_format;
|
||||
pcm_buffer_init(&filter->buffer);
|
||||
|
||||
return &filter->audio_format;
|
||||
}
|
||||
|
||||
static void
|
||||
replay_gain_filter_close(struct filter *_filter)
|
||||
{
|
||||
struct replay_gain_filter *filter =
|
||||
(struct replay_gain_filter *)_filter;
|
||||
|
||||
pcm_buffer_deinit(&filter->buffer);
|
||||
}
|
||||
|
||||
static const void *
|
||||
replay_gain_filter_filter(struct filter *_filter,
|
||||
const void *src, size_t src_size,
|
||||
size_t *dest_size_r, GError **error_r)
|
||||
{
|
||||
struct replay_gain_filter *filter =
|
||||
(struct replay_gain_filter *)_filter;
|
||||
bool success;
|
||||
void *dest;
|
||||
|
||||
/* check if the mode has been changed since the last call */
|
||||
if (filter->mode != replay_gain_mode) {
|
||||
filter->mode = replay_gain_mode;
|
||||
replay_gain_filter_update(filter);
|
||||
}
|
||||
|
||||
*dest_size_r = src_size;
|
||||
|
||||
if (filter->volume >= PCM_VOLUME_1)
|
||||
/* optimized special case: 100% volume = no-op */
|
||||
return src;
|
||||
|
||||
dest = pcm_buffer_get(&filter->buffer, src_size);
|
||||
*dest_size_r = src_size;
|
||||
|
||||
if (filter->volume <= 0) {
|
||||
/* optimized special case: 0% volume = memset(0) */
|
||||
/* XXX is this valid for all sample formats? What
|
||||
about floating point? */
|
||||
memset(dest, 0, src_size);
|
||||
return dest;
|
||||
}
|
||||
|
||||
memcpy(dest, src, src_size);
|
||||
|
||||
success = pcm_volume(dest, src_size, &filter->audio_format,
|
||||
filter->volume);
|
||||
if (!success) {
|
||||
g_set_error(error_r, replay_gain_quark(), 0,
|
||||
"pcm_volume() has failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
const struct filter_plugin replay_gain_filter_plugin = {
|
||||
.name = "replay_gain",
|
||||
.init = replay_gain_filter_init,
|
||||
.finish = replay_gain_filter_finish,
|
||||
.open = replay_gain_filter_open,
|
||||
.close = replay_gain_filter_close,
|
||||
.filter = replay_gain_filter_filter,
|
||||
};
|
||||
|
||||
void
|
||||
replay_gain_filter_set_info(struct filter *_filter,
|
||||
const struct replay_gain_info *info)
|
||||
{
|
||||
struct replay_gain_filter *filter =
|
||||
(struct replay_gain_filter *)_filter;
|
||||
|
||||
if (info != NULL)
|
||||
filter->info = *info;
|
||||
else
|
||||
replay_gain_info_init(&filter->info);
|
||||
|
||||
replay_gain_filter_update(filter);
|
||||
}
|
|
@ -17,34 +17,21 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPD_REPLAY_GAIN_STATE_H
|
||||
#define MPD_REPLAY_GAIN_STATE_H
|
||||
#ifndef REPLAY_GAIN_FILTER_PLUGIN_H
|
||||
#define REPLAY_GAIN_FILTER_PLUGIN_H
|
||||
|
||||
#include "check.h"
|
||||
#include "replay_gain_info.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct replay_gain_state;
|
||||
struct audio_format;
|
||||
|
||||
struct replay_gain_state *
|
||||
replay_gain_state_new(float preamp, float missing_preamp);
|
||||
struct filter;
|
||||
|
||||
/**
|
||||
* Sets a new #replay_gain_info at the beginning of a new song.
|
||||
*
|
||||
* @param info the new #replay_gain_info value, or NULL if no replay
|
||||
* gain data is available for the current song
|
||||
*/
|
||||
void
|
||||
replay_gain_state_free(struct replay_gain_state *state);
|
||||
|
||||
void
|
||||
replay_gain_state_set_mode(struct replay_gain_state *state,
|
||||
enum replay_gain_mode mode);
|
||||
|
||||
void
|
||||
replay_gain_state_set_info(struct replay_gain_state *state,
|
||||
replay_gain_filter_set_info(struct filter *filter,
|
||||
const struct replay_gain_info *info);
|
||||
|
||||
void
|
||||
replay_gain_state_apply(const struct replay_gain_state *state,
|
||||
void *buffer, size_t size,
|
||||
const struct audio_format *format);
|
||||
|
||||
#endif
|
|
@ -29,6 +29,7 @@ const struct filter_plugin *const filter_plugins[] = {
|
|||
&route_filter_plugin,
|
||||
&normalize_filter_plugin,
|
||||
&volume_filter_plugin,
|
||||
&replay_gain_filter_plugin,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ extern const struct filter_plugin convert_filter_plugin;
|
|||
extern const struct filter_plugin route_filter_plugin;
|
||||
extern const struct filter_plugin normalize_filter_plugin;
|
||||
extern const struct filter_plugin volume_filter_plugin;
|
||||
extern const struct filter_plugin replay_gain_filter_plugin;
|
||||
|
||||
const struct filter_plugin *
|
||||
filter_plugin_by_name(const char *name);
|
||||
|
|
|
@ -194,6 +194,17 @@ audio_output_init(struct audio_output *ao, const struct config_param *param,
|
|||
ao->filter = filter_chain_new();
|
||||
assert(ao->filter != NULL);
|
||||
|
||||
/* create the replay_gain filter */
|
||||
|
||||
ao->replay_gain_filter = filter_new(&replay_gain_filter_plugin,
|
||||
param, NULL);
|
||||
assert(ao->replay_gain_filter != NULL);
|
||||
|
||||
filter_chain_append(ao->filter, ao->replay_gain_filter);
|
||||
ao->replay_gain_serial = 0;
|
||||
|
||||
/* create the normalization filter (if configured) */
|
||||
|
||||
if (config_get_bool(CONF_VOLUME_NORMALIZATION, false)) {
|
||||
struct filter *normalize_filter =
|
||||
filter_new(&normalize_filter_plugin, NULL, NULL);
|
||||
|
|
|
@ -134,6 +134,18 @@ struct audio_output {
|
|||
*/
|
||||
struct filter *filter;
|
||||
|
||||
/**
|
||||
* The replay_gain_filter_plugin instance of this audio
|
||||
* output.
|
||||
*/
|
||||
struct filter *replay_gain_filter;
|
||||
|
||||
/**
|
||||
* The serial number of the last replay gain info. 0 means no
|
||||
* replay gain info was available.
|
||||
*/
|
||||
unsigned replay_gain_serial;
|
||||
|
||||
/**
|
||||
* The convert_filter_plugin instance of this audio output.
|
||||
* It is the last item in the filter chain, and is responsible
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "player_control.h"
|
||||
#include "filter_plugin.h"
|
||||
#include "filter/convert_filter_plugin.h"
|
||||
#include "filter/replay_gain_filter_plugin.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
|
@ -261,6 +262,16 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
|
|||
g_mutex_lock(ao->mutex);
|
||||
}
|
||||
|
||||
/* update replay gain */
|
||||
|
||||
if (chunk->replay_gain_serial != ao->replay_gain_serial) {
|
||||
replay_gain_filter_set_info(ao->replay_gain_filter,
|
||||
chunk->replay_gain_serial != 0
|
||||
? &chunk->replay_gain_info
|
||||
: NULL);
|
||||
ao->replay_gain_serial = chunk->replay_gain_serial;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
return true;
|
||||
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2003-2010 The Music Player Daemon Project
|
||||
* http://www.musicpd.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "replay_gain_state.h"
|
||||
#include "pcm_volume.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
struct replay_gain_state {
|
||||
float preamp, missing_preamp;
|
||||
|
||||
enum replay_gain_mode mode;
|
||||
|
||||
struct replay_gain_info info;
|
||||
|
||||
float scale;
|
||||
};
|
||||
|
||||
struct replay_gain_state *
|
||||
replay_gain_state_new(float preamp, float missing_preamp)
|
||||
{
|
||||
struct replay_gain_state *state = g_new(struct replay_gain_state, 1);
|
||||
|
||||
state->preamp = preamp;
|
||||
state->scale = state->missing_preamp = missing_preamp;
|
||||
state->mode = REPLAY_GAIN_OFF;
|
||||
replay_gain_info_init(&state->info);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void
|
||||
replay_gain_state_free(struct replay_gain_state *state)
|
||||
{
|
||||
assert(state != NULL);
|
||||
|
||||
g_free(state);
|
||||
}
|
||||
|
||||
static void
|
||||
replay_gain_state_calc_scale(struct replay_gain_state *state)
|
||||
{
|
||||
assert(state != NULL);
|
||||
|
||||
if (state->mode == REPLAY_GAIN_OFF)
|
||||
return;
|
||||
|
||||
const struct replay_gain_tuple *tuple =
|
||||
&state->info.tuples[state->mode];
|
||||
if (replay_gain_tuple_defined(tuple)) {
|
||||
g_debug("computing ReplayGain scale with gain %f, peak %f",
|
||||
tuple->gain, tuple->peak);
|
||||
|
||||
state->scale = replay_gain_tuple_scale(tuple, state->preamp);
|
||||
} else
|
||||
state->scale = state->missing_preamp;
|
||||
}
|
||||
|
||||
void
|
||||
replay_gain_state_set_mode(struct replay_gain_state *state,
|
||||
enum replay_gain_mode mode)
|
||||
{
|
||||
assert(state != NULL);
|
||||
|
||||
if (mode == state->mode)
|
||||
return;
|
||||
|
||||
state->mode = mode;
|
||||
|
||||
replay_gain_state_calc_scale(state);
|
||||
}
|
||||
|
||||
void
|
||||
replay_gain_state_set_info(struct replay_gain_state *state,
|
||||
const struct replay_gain_info *info)
|
||||
{
|
||||
assert(state != NULL);
|
||||
|
||||
if (info != NULL)
|
||||
state->info = *info;
|
||||
else
|
||||
replay_gain_info_init(&state->info);
|
||||
|
||||
replay_gain_state_calc_scale(state);
|
||||
}
|
||||
|
||||
void
|
||||
replay_gain_state_apply(const struct replay_gain_state *state,
|
||||
void *buffer, size_t size,
|
||||
const struct audio_format *format)
|
||||
{
|
||||
assert(state != NULL);
|
||||
|
||||
if (state->mode == REPLAY_GAIN_OFF)
|
||||
return;
|
||||
|
||||
pcm_volume(buffer, size, format, pcm_float_to_volume(state->scale));
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
#include "audio_format.h"
|
||||
#include "filter_plugin.h"
|
||||
#include "pcm_volume.h"
|
||||
#include "idle.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
|
@ -31,6 +32,11 @@
|
|||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void
|
||||
idle_add(G_GNUC_UNUSED unsigned flags)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
my_log_func(const gchar *log_domain, G_GNUC_UNUSED GLogLevelFlags log_level,
|
||||
const gchar *message, G_GNUC_UNUSED gpointer user_data)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "filter_registry.h"
|
||||
#include "pcm_convert.h"
|
||||
#include "event_pipe.h"
|
||||
#include "idle.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
|
@ -33,6 +34,11 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void
|
||||
idle_add(G_GNUC_UNUSED unsigned flags)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
event_pipe_emit(G_GNUC_UNUSED enum pipe_event event)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue