Commit 5e0117b4 authored by Max Kellermann's avatar Max Kellermann

replay_gain_info: allocate the struct statically

Don't allocate each replay_gain_info object on the heap. Those objects who held a pointer now store a full replay_gain_info object. This reduces the number of allocations and heap fragmentation.
parent c05e6a12
...@@ -116,7 +116,7 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block, ...@@ -116,7 +116,7 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
if (data->unsupported) if (data->unsupported)
return; return;
struct replay_gain_info *rgi; struct replay_gain_info rgi;
switch (block->type) { switch (block->type) {
case FLAC__METADATA_TYPE_STREAMINFO: case FLAC__METADATA_TYPE_STREAMINFO:
...@@ -124,11 +124,8 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block, ...@@ -124,11 +124,8 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
break; break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT: case FLAC__METADATA_TYPE_VORBIS_COMMENT:
rgi = flac_parse_replay_gain(block); if (flac_parse_replay_gain(&rgi, block))
if (rgi != NULL) { decoder_replay_gain(data->decoder, &rgi);
decoder_replay_gain(data->decoder, rgi);
replay_gain_info_free(rgi);
}
if (data->tag != NULL) if (data->tag != NULL)
flac_vorbis_comments_to_tag(data->tag, NULL, flac_vorbis_comments_to_tag(data->tag, NULL,
......
...@@ -56,13 +56,13 @@ flac_find_float_comment(const FLAC__StreamMetadata *block, ...@@ -56,13 +56,13 @@ flac_find_float_comment(const FLAC__StreamMetadata *block,
return true; return true;
} }
struct replay_gain_info * bool
flac_parse_replay_gain(const FLAC__StreamMetadata *block) flac_parse_replay_gain(struct replay_gain_info *rgi,
const FLAC__StreamMetadata *block)
{ {
struct replay_gain_info *rgi;
bool found = false; bool found = false;
rgi = replay_gain_info_new(); replay_gain_info_init(rgi);
if (flac_find_float_comment(block, "replaygain_album_gain", if (flac_find_float_comment(block, "replaygain_album_gain",
&rgi->tuples[REPLAY_GAIN_ALBUM].gain)) &rgi->tuples[REPLAY_GAIN_ALBUM].gain))
...@@ -77,12 +77,7 @@ flac_parse_replay_gain(const FLAC__StreamMetadata *block) ...@@ -77,12 +77,7 @@ flac_parse_replay_gain(const FLAC__StreamMetadata *block)
&rgi->tuples[REPLAY_GAIN_TRACK].peak)) &rgi->tuples[REPLAY_GAIN_TRACK].peak))
found = true; found = true;
if (!found) { return found;
replay_gain_info_free(rgi);
rgi = NULL;
}
return rgi;
} }
/** /**
......
...@@ -20,9 +20,11 @@ ...@@ -20,9 +20,11 @@
#ifndef MPD_FLAC_METADATA_H #ifndef MPD_FLAC_METADATA_H
#define MPD_FLAC_METADATA_H #define MPD_FLAC_METADATA_H
#include <stdbool.h>
#include <FLAC/metadata.h> #include <FLAC/metadata.h>
struct tag; struct tag;
struct replay_gain_info;
static inline unsigned static inline unsigned
flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info) flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info)
...@@ -31,8 +33,9 @@ flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info) ...@@ -31,8 +33,9 @@ flac_duration(const FLAC__StreamMetadata_StreamInfo *stream_info)
stream_info->sample_rate; stream_info->sample_rate;
} }
struct replay_gain_info * bool
flac_parse_replay_gain(const FLAC__StreamMetadata *block); flac_parse_replay_gain(struct replay_gain_info *rgi,
const FLAC__StreamMetadata *block);
void void
flac_vorbis_comments_to_tag(struct tag *tag, const char *char_tnum, flac_vorbis_comments_to_tag(struct tag *tag, const char *char_tnum,
......
...@@ -300,17 +300,17 @@ static int parse_rva2(struct id3_tag * tag, struct replay_gain_info * replay_gai ...@@ -300,17 +300,17 @@ static int parse_rva2(struct id3_tag * tag, struct replay_gain_info * replay_gai
#endif #endif
#ifdef HAVE_ID3TAG #ifdef HAVE_ID3TAG
static struct replay_gain_info * static bool
parse_id3_replay_gain_info(struct id3_tag *tag) parse_id3_replay_gain_info(struct replay_gain_info *replay_gain_info,
struct id3_tag *tag)
{ {
int i; int i;
char *key; char *key;
char *value; char *value;
struct id3_frame *frame; struct id3_frame *frame;
bool found = false; bool found = false;
struct replay_gain_info *replay_gain_info;
replay_gain_info = replay_gain_info_new(); replay_gain_info_init(replay_gain_info);
for (i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) { for (i = 0; (frame = id3_tag_findframe(tag, "TXXX", i)); i++) {
if (frame->nfields < 3) if (frame->nfields < 3)
...@@ -341,15 +341,9 @@ parse_id3_replay_gain_info(struct id3_tag *tag) ...@@ -341,15 +341,9 @@ parse_id3_replay_gain_info(struct id3_tag *tag)
free(value); free(value);
} }
if (!found) { return found ||
/* fall back on RVA2 if no replaygain tags found */ /* fall back on RVA2 if no replaygain tags found */
found = parse_rva2(tag, replay_gain_info); parse_rva2(tag, replay_gain_info);
}
if (found)
return replay_gain_info;
replay_gain_info_free(replay_gain_info);
return NULL;
} }
#endif #endif
...@@ -408,11 +402,9 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize, ...@@ -408,11 +402,9 @@ static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
} }
if (data->decoder != NULL) { if (data->decoder != NULL) {
struct replay_gain_info *tmp_rgi = struct replay_gain_info rgi;
parse_id3_replay_gain_info(id3_tag); if (parse_id3_replay_gain_info(&rgi, id3_tag)) {
if (tmp_rgi != NULL) { decoder_replay_gain(data->decoder, &rgi);
decoder_replay_gain(data->decoder, tmp_rgi);
replay_gain_info_free(tmp_rgi);
data->found_replay_gain = true; data->found_replay_gain = true;
} }
} }
...@@ -879,15 +871,14 @@ mp3_decode_first_frame(struct mp3_data *data, struct tag **tag) ...@@ -879,15 +871,14 @@ mp3_decode_first_frame(struct mp3_data *data, struct tag **tag)
if (data->decoder != NULL && if (data->decoder != NULL &&
!data->found_replay_gain && !data->found_replay_gain &&
lame.track_gain) { lame.track_gain) {
struct replay_gain_info *rgi struct replay_gain_info rgi;
= replay_gain_info_new(); replay_gain_info_init(&rgi);
rgi->tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain; rgi.tuples[REPLAY_GAIN_TRACK].gain = lame.track_gain;
rgi->tuples[REPLAY_GAIN_TRACK].peak = lame.peak; rgi.tuples[REPLAY_GAIN_TRACK].peak = lame.peak;
decoder_replay_gain(data->decoder, rgi); decoder_replay_gain(data->decoder, &rgi);
replay_gain_info_free(rgi);
} }
} }
} }
if (!data->max_frames) if (!data->max_frames)
return false; return false;
......
...@@ -154,7 +154,6 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is) ...@@ -154,7 +154,6 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
long bit_rate = 0; long bit_rate = 0;
mpc_uint32_t vbr_update_acc; mpc_uint32_t vbr_update_acc;
mpc_uint32_t vbr_update_bits; mpc_uint32_t vbr_update_bits;
struct replay_gain_info *replay_gain_info = NULL;
enum decoder_command cmd = DECODE_COMMAND_NONE; enum decoder_command cmd = DECODE_COMMAND_NONE;
data.is = is; data.is = is;
...@@ -205,13 +204,13 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is) ...@@ -205,13 +204,13 @@ mpcdec_decode(struct decoder *mpd_decoder, struct input_stream *is)
return; return;
} }
replay_gain_info = replay_gain_info_new(); struct replay_gain_info replay_gain_info;
replay_gain_info->tuples[REPLAY_GAIN_ALBUM].gain = info.gain_album * 0.01; replay_gain_info_init(&replay_gain_info);
replay_gain_info->tuples[REPLAY_GAIN_ALBUM].peak = info.peak_album / 32767.0; replay_gain_info.tuples[REPLAY_GAIN_ALBUM].gain = info.gain_album * 0.01;
replay_gain_info->tuples[REPLAY_GAIN_TRACK].gain = info.gain_title * 0.01; replay_gain_info.tuples[REPLAY_GAIN_ALBUM].peak = info.peak_album / 32767.0;
replay_gain_info->tuples[REPLAY_GAIN_TRACK].peak = info.peak_title / 32767.0; replay_gain_info.tuples[REPLAY_GAIN_TRACK].gain = info.gain_title * 0.01;
decoder_replay_gain(mpd_decoder, replay_gain_info); replay_gain_info.tuples[REPLAY_GAIN_TRACK].peak = info.peak_title / 32767.0;
replay_gain_info_free(replay_gain_info); decoder_replay_gain(mpd_decoder, &replay_gain_info);
decoder_initialized(mpd_decoder, &audio_format, decoder_initialized(mpd_decoder, &audio_format,
is->seekable, is->seekable,
......
...@@ -134,14 +134,13 @@ vorbis_comment_value(const char *comment, const char *needle) ...@@ -134,14 +134,13 @@ vorbis_comment_value(const char *comment, const char *needle)
return NULL; return NULL;
} }
static struct replay_gain_info * static bool
vorbis_comments_to_replay_gain(char **comments) vorbis_comments_to_replay_gain(struct replay_gain_info *rgi, char **comments)
{ {
struct replay_gain_info *rgi;
const char *temp; const char *temp;
bool found = false; bool found = false;
rgi = replay_gain_info_new(); replay_gain_info_init(rgi);
while (*comments) { while (*comments) {
if ((temp = if ((temp =
...@@ -165,12 +164,7 @@ vorbis_comments_to_replay_gain(char **comments) ...@@ -165,12 +164,7 @@ vorbis_comments_to_replay_gain(char **comments)
comments++; comments++;
} }
if (!found) { return found;
replay_gain_info_free(rgi);
rgi = NULL;
}
return rgi;
} }
static const char *VORBIS_COMMENT_TRACK_KEY = "tracknumber"; static const char *VORBIS_COMMENT_TRACK_KEY = "tracknumber";
...@@ -334,7 +328,6 @@ vorbis_stream_decode(struct decoder *decoder, ...@@ -334,7 +328,6 @@ vorbis_stream_decode(struct decoder *decoder,
if (current_section != prev_section) { if (current_section != prev_section) {
char **comments; char **comments;
struct replay_gain_info *new_rgi;
vi = ov_info(&vf, -1); vi = ov_info(&vf, -1);
if (vi == NULL) { if (vi == NULL) {
...@@ -352,11 +345,10 @@ vorbis_stream_decode(struct decoder *decoder, ...@@ -352,11 +345,10 @@ vorbis_stream_decode(struct decoder *decoder,
comments = ov_comment(&vf, -1)->user_comments; comments = ov_comment(&vf, -1)->user_comments;
vorbis_send_comments(decoder, input_stream, comments); vorbis_send_comments(decoder, input_stream, comments);
new_rgi = vorbis_comments_to_replay_gain(comments);
if (new_rgi != NULL) { struct replay_gain_info rgi;
decoder_replay_gain(decoder, new_rgi); if (vorbis_comments_to_replay_gain(&rgi, comments))
replay_gain_info_free(new_rgi); decoder_replay_gain(decoder, &rgi);
}
prev_section = current_section; prev_section = current_section;
} }
......
...@@ -256,13 +256,13 @@ wavpack_tag_float(WavpackContext *wpc, const char *key, float *value_r) ...@@ -256,13 +256,13 @@ wavpack_tag_float(WavpackContext *wpc, const char *key, float *value_r)
return true; return true;
} }
static struct replay_gain_info * static bool
wavpack_replaygain(WavpackContext *wpc) wavpack_replaygain(struct replay_gain_info *replay_gain_info,
WavpackContext *wpc)
{ {
struct replay_gain_info *replay_gain_info;
bool found = false; bool found = false;
replay_gain_info = replay_gain_info_new(); replay_gain_info_init(replay_gain_info);
found |= wavpack_tag_float( found |= wavpack_tag_float(
wpc, "replaygain_track_gain", wpc, "replaygain_track_gain",
...@@ -281,13 +281,7 @@ wavpack_replaygain(WavpackContext *wpc) ...@@ -281,13 +281,7 @@ wavpack_replaygain(WavpackContext *wpc)
&replay_gain_info->tuples[REPLAY_GAIN_ALBUM].peak &replay_gain_info->tuples[REPLAY_GAIN_ALBUM].peak
); );
if (found) { return found;
return replay_gain_info;
}
replay_gain_info_free(replay_gain_info);
return NULL;
} }
/* /*
...@@ -554,7 +548,6 @@ wavpack_filedecode(struct decoder *decoder, const char *fname) ...@@ -554,7 +548,6 @@ wavpack_filedecode(struct decoder *decoder, const char *fname)
{ {
char error[ERRORLEN]; char error[ERRORLEN];
WavpackContext *wpc; WavpackContext *wpc;
struct replay_gain_info *replay_gain_info;
wpc = WavpackOpenFileInput( wpc = WavpackOpenFileInput(
fname, error, fname, error,
...@@ -568,11 +561,9 @@ wavpack_filedecode(struct decoder *decoder, const char *fname) ...@@ -568,11 +561,9 @@ wavpack_filedecode(struct decoder *decoder, const char *fname)
return; return;
} }
replay_gain_info = wavpack_replaygain(wpc); struct replay_gain_info replay_gain_info;
if (replay_gain_info != NULL) { if (wavpack_replaygain(&replay_gain_info, wpc))
decoder_replay_gain(decoder, replay_gain_info); decoder_replay_gain(decoder, &replay_gain_info);
replay_gain_info_free(replay_gain_info);
}
wavpack_decode(decoder, wpc, true); wavpack_decode(decoder, wpc, true);
......
...@@ -20,33 +20,6 @@ ...@@ -20,33 +20,6 @@
#include "config.h" #include "config.h"
#include "replay_gain_info.h" #include "replay_gain_info.h"
#include <glib.h>
struct replay_gain_info *
replay_gain_info_new(void)
{
struct replay_gain_info *ret = g_new(struct replay_gain_info, 1);
for (unsigned i = 0; i < G_N_ELEMENTS(ret->tuples); ++i) {
ret->tuples[i].gain = INFINITY;
ret->tuples[i].peak = 0.0;
}
return ret;
}
struct replay_gain_info *
replay_gain_info_dup(const struct replay_gain_info *src)
{
return g_memdup(src, sizeof(*src));
}
void
replay_gain_info_free(struct replay_gain_info *info)
{
g_free(info);
}
float float
replay_gain_tuple_scale(const struct replay_gain_tuple *tuple, float preamp) replay_gain_tuple_scale(const struct replay_gain_tuple *tuple, float preamp)
{ {
......
...@@ -40,17 +40,19 @@ struct replay_gain_info { ...@@ -40,17 +40,19 @@ struct replay_gain_info {
struct replay_gain_tuple tuples[2]; struct replay_gain_tuple tuples[2];
}; };
struct replay_gain_info * static inline void
replay_gain_info_new(void); replay_gain_tuple_init(struct replay_gain_tuple *tuple)
{
/** tuple->gain = INFINITY;
* Duplicate a #replay_gain_info object. tuple->peak = 0.0;
*/ }
struct replay_gain_info *
replay_gain_info_dup(const struct replay_gain_info *src);
void static inline void
replay_gain_info_free(struct replay_gain_info *info); replay_gain_info_init(struct replay_gain_info *info)
{
replay_gain_tuple_init(&info->tuples[REPLAY_GAIN_ALBUM]);
replay_gain_tuple_init(&info->tuples[REPLAY_GAIN_TRACK]);
}
static inline bool static inline bool
replay_gain_tuple_defined(const struct replay_gain_tuple *tuple) replay_gain_tuple_defined(const struct replay_gain_tuple *tuple)
......
...@@ -30,7 +30,7 @@ struct replay_gain_state { ...@@ -30,7 +30,7 @@ struct replay_gain_state {
enum replay_gain_mode mode; enum replay_gain_mode mode;
struct replay_gain_info *info; struct replay_gain_info info;
float scale; float scale;
}; };
...@@ -43,7 +43,7 @@ replay_gain_state_new(float preamp, float missing_preamp) ...@@ -43,7 +43,7 @@ replay_gain_state_new(float preamp, float missing_preamp)
state->preamp = preamp; state->preamp = preamp;
state->scale = state->missing_preamp = missing_preamp; state->scale = state->missing_preamp = missing_preamp;
state->mode = REPLAY_GAIN_OFF; state->mode = REPLAY_GAIN_OFF;
state->info = NULL; replay_gain_info_init(&state->info);
return state; return state;
} }
...@@ -53,9 +53,6 @@ replay_gain_state_free(struct replay_gain_state *state) ...@@ -53,9 +53,6 @@ replay_gain_state_free(struct replay_gain_state *state)
{ {
assert(state != NULL); assert(state != NULL);
if (state->info != NULL)
replay_gain_info_free(state->info);
g_free(state); g_free(state);
} }
...@@ -64,11 +61,11 @@ replay_gain_state_calc_scale(struct replay_gain_state *state) ...@@ -64,11 +61,11 @@ replay_gain_state_calc_scale(struct replay_gain_state *state)
{ {
assert(state != NULL); assert(state != NULL);
if (state->mode == REPLAY_GAIN_OFF || state->info == NULL) if (state->mode == REPLAY_GAIN_OFF)
return; return;
const struct replay_gain_tuple *tuple = const struct replay_gain_tuple *tuple =
&state->info->tuples[state->mode]; &state->info.tuples[state->mode];
if (replay_gain_tuple_defined(tuple)) { if (replay_gain_tuple_defined(tuple)) {
g_debug("computing ReplayGain scale with gain %f, peak %f", g_debug("computing ReplayGain scale with gain %f, peak %f",
tuple->gain, tuple->peak); tuple->gain, tuple->peak);
...@@ -98,12 +95,10 @@ replay_gain_state_set_info(struct replay_gain_state *state, ...@@ -98,12 +95,10 @@ replay_gain_state_set_info(struct replay_gain_state *state,
{ {
assert(state != NULL); assert(state != NULL);
if (state->info != NULL) if (info != NULL)
replay_gain_info_free(state->info); state->info = *info;
else
state->info = info != NULL replay_gain_info_init(&state->info);
? replay_gain_info_dup(info)
: NULL;
replay_gain_state_calc_scale(state); replay_gain_state_calc_scale(state);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment