id3v2mux: write RVA2 frames containing peak/gain volume data
This commit is contained in:
parent
f1fb1f80fa
commit
9b7c9208c3
@ -55,6 +55,7 @@
|
|||||||
#include <textidentificationframe.h>
|
#include <textidentificationframe.h>
|
||||||
#include <uniquefileidentifierframe.h>
|
#include <uniquefileidentifierframe.h>
|
||||||
#include <attachedpictureframe.h>
|
#include <attachedpictureframe.h>
|
||||||
|
#include <relativevolumeframe.h>
|
||||||
#include <commentsframe.h>
|
#include <commentsframe.h>
|
||||||
#include <unknownframe.h>
|
#include <unknownframe.h>
|
||||||
#include <id3v2synchdata.h>
|
#include <id3v2synchdata.h>
|
||||||
@ -560,6 +561,71 @@ add_uri_tag (ID3v2::Tag * id3v2tag, const GstTagList * list,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_relative_volume_tag (ID3v2::Tag * id3v2tag, const GstTagList * list,
|
||||||
|
const gchar * tag, guint num_tags, const gchar * frame_id)
|
||||||
|
{
|
||||||
|
const char *gain_tag_name;
|
||||||
|
const char *peak_tag_name;
|
||||||
|
gdouble peak_val;
|
||||||
|
gdouble gain_val;
|
||||||
|
ID3v2::RelativeVolumeFrame * frame;
|
||||||
|
|
||||||
|
frame = new ID3v2::RelativeVolumeFrame ();
|
||||||
|
|
||||||
|
/* figure out tag names and the identification string to use */
|
||||||
|
if (strcmp (tag, GST_TAG_TRACK_PEAK) == 0 ||
|
||||||
|
strcmp (tag, GST_TAG_TRACK_GAIN) == 0) {
|
||||||
|
gain_tag_name = GST_TAG_TRACK_GAIN;
|
||||||
|
peak_tag_name = GST_TAG_TRACK_PEAK;
|
||||||
|
frame->setIdentification ("track");
|
||||||
|
GST_DEBUG ("adding track relative-volume frame");
|
||||||
|
} else {
|
||||||
|
gain_tag_name = GST_TAG_ALBUM_GAIN;
|
||||||
|
peak_tag_name = GST_TAG_ALBUM_PEAK;
|
||||||
|
frame->setIdentification ("album");
|
||||||
|
GST_DEBUG ("adding album relative-volume frame");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the value for the paired tag (gain, if this is peak, and
|
||||||
|
* vice versa). if both tags exist, only write the frame when
|
||||||
|
* we're processing the peak tag.
|
||||||
|
*/
|
||||||
|
if (strcmp (tag, GST_TAG_TRACK_PEAK) == 0 ||
|
||||||
|
strcmp (tag, GST_TAG_ALBUM_PEAK) == 0) {
|
||||||
|
ID3v2::RelativeVolumeFrame::PeakVolume encoded_peak;
|
||||||
|
short peak_int;
|
||||||
|
|
||||||
|
gst_tag_list_get_double (list, tag, &peak_val);
|
||||||
|
|
||||||
|
if (gst_tag_list_get_tag_size (list, gain_tag_name) > 0) {
|
||||||
|
gst_tag_list_get_double (list, gain_tag_name, &gain_val);
|
||||||
|
GST_DEBUG ("setting volume adjustment %g", gain_val);
|
||||||
|
frame->setVolumeAdjustment (gain_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copying mutagen: always write as 16 bits for sanity. */
|
||||||
|
peak_int = (short)(peak_val * G_MAXSHORT);
|
||||||
|
encoded_peak.bitsRepresentingPeak = 16;
|
||||||
|
encoded_peak.peakVolume = ByteVector::fromShort(peak_int, true);
|
||||||
|
GST_DEBUG ("setting peak value %g", peak_val);
|
||||||
|
frame->setPeakVolume(encoded_peak);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
gst_tag_list_get_double (list, tag, &gain_val);
|
||||||
|
GST_DEBUG ("setting volume adjustment %g", gain_val);
|
||||||
|
frame->setVolumeAdjustment (gain_val);
|
||||||
|
|
||||||
|
if (gst_tag_list_get_tag_size (list, peak_tag_name) != 0) {
|
||||||
|
GST_DEBUG ("both gain and peak tags exist, not adding frame this time around");
|
||||||
|
delete frame;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id3v2tag->addFrame (frame);
|
||||||
|
}
|
||||||
|
|
||||||
/* id3demux produces these for frames it cannot parse */
|
/* id3demux produces these for frames it cannot parse */
|
||||||
#define GST_ID3_DEMUX_TAG_ID3V2_FRAME "private-id3v2-frame"
|
#define GST_ID3_DEMUX_TAG_ID3V2_FRAME "private-id3v2-frame"
|
||||||
|
|
||||||
@ -599,7 +665,11 @@ static const struct
|
|||||||
GST_TAG_ENCODER, add_encoder_tag, ""}, {
|
GST_TAG_ENCODER, add_encoder_tag, ""}, {
|
||||||
GST_TAG_ENCODER_VERSION, add_encoder_tag, ""}, {
|
GST_TAG_ENCODER_VERSION, add_encoder_tag, ""}, {
|
||||||
GST_TAG_COPYRIGHT_URI, add_uri_tag, "WCOP"}, {
|
GST_TAG_COPYRIGHT_URI, add_uri_tag, "WCOP"}, {
|
||||||
GST_TAG_LICENSE_URI, add_uri_tag, "WCOP"}
|
GST_TAG_LICENSE_URI, add_uri_tag, "WCOP"}, {
|
||||||
|
GST_TAG_TRACK_PEAK, add_relative_volume_tag, ""}, {
|
||||||
|
GST_TAG_TRACK_GAIN, add_relative_volume_tag, ""}, {
|
||||||
|
GST_TAG_ALBUM_PEAK, add_relative_volume_tag, ""}, {
|
||||||
|
GST_TAG_ALBUM_GAIN, add_relative_volume_tag, ""}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,9 +33,10 @@
|
|||||||
#define TEST_TRACK_COUNT 19
|
#define TEST_TRACK_COUNT 19
|
||||||
#define TEST_VOLUME_NUMBER 2
|
#define TEST_VOLUME_NUMBER 2
|
||||||
#define TEST_VOLUME_COUNT 3
|
#define TEST_VOLUME_COUNT 3
|
||||||
|
#define TEST_TRACK_GAIN 1.45
|
||||||
/* #define TEST_TRACK_GAIN 1.45 (not implemented yet) */
|
#define TEST_ALBUM_GAIN 0.78
|
||||||
/* #define TEST_ALBUM_GAIN 0.78 (not implemented yet) */
|
#define TEST_TRACK_PEAK 0.83
|
||||||
|
#define TEST_ALBUM_PEAK 0.18
|
||||||
|
|
||||||
/* for dummy mp3 frame sized MP3_FRAME_SIZE bytes,
|
/* for dummy mp3 frame sized MP3_FRAME_SIZE bytes,
|
||||||
* start: ff fb b0 44 00 00 08 00 00 4b 00 00 00 00 00 00 */
|
* start: ff fb b0 44 00 00 08 00 00 4b 00 00 00 00 00 00 */
|
||||||
@ -45,6 +46,18 @@ static const guint8 mp3_dummyhdr[] = { 0xff, 0xfb, 0xb0, 0x44, 0x00, 0x00,
|
|||||||
|
|
||||||
#define MP3_FRAME_SIZE 626
|
#define MP3_FRAME_SIZE 626
|
||||||
|
|
||||||
|
/* the peak and gain values are stored pretty roughly, so check that they're
|
||||||
|
* within 2% of the expected value.
|
||||||
|
*/
|
||||||
|
#define fail_unless_sorta_equals_float(a, b) \
|
||||||
|
G_STMT_START { \
|
||||||
|
double first = a; \
|
||||||
|
double second = b; \
|
||||||
|
fail_unless(fabs (first - second) < (0.02 * fabs (first)), \
|
||||||
|
"'" #a "' (%g) is not equal to '" #b "' (%g)", first, second); \
|
||||||
|
} G_STMT_END;
|
||||||
|
|
||||||
|
|
||||||
static GstTagList *
|
static GstTagList *
|
||||||
test_taglib_id3mux_create_tags (guint32 mask)
|
test_taglib_id3mux_create_tags (guint32 mask)
|
||||||
{
|
{
|
||||||
@ -88,12 +101,20 @@ test_taglib_id3mux_create_tags (guint32 mask)
|
|||||||
GST_TAG_ALBUM_VOLUME_COUNT, TEST_VOLUME_COUNT, NULL);
|
GST_TAG_ALBUM_VOLUME_COUNT, TEST_VOLUME_COUNT, NULL);
|
||||||
}
|
}
|
||||||
if (mask & (1 << 8)) {
|
if (mask & (1 << 8)) {
|
||||||
|
gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
|
||||||
|
GST_TAG_TRACK_GAIN, TEST_TRACK_GAIN, NULL);
|
||||||
}
|
}
|
||||||
if (mask & (1 << 9)) {
|
if (mask & (1 << 9)) {
|
||||||
|
gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
|
||||||
|
GST_TAG_ALBUM_GAIN, TEST_ALBUM_GAIN, NULL);
|
||||||
}
|
}
|
||||||
if (mask & (1 << 10)) {
|
if (mask & (1 << 10)) {
|
||||||
|
gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
|
||||||
|
GST_TAG_TRACK_PEAK, TEST_TRACK_PEAK, NULL);
|
||||||
}
|
}
|
||||||
if (mask & (1 << 11)) {
|
if (mask & (1 << 11)) {
|
||||||
|
gst_tag_list_add (tags, GST_TAG_MERGE_KEEP,
|
||||||
|
GST_TAG_ALBUM_PEAK, TEST_ALBUM_PEAK, NULL);
|
||||||
}
|
}
|
||||||
if (mask & (1 << 12)) {
|
if (mask & (1 << 12)) {
|
||||||
}
|
}
|
||||||
@ -193,23 +214,29 @@ test_taglib_id3mux_check_tags (GstTagList * tags, guint32 mask)
|
|||||||
&count));
|
&count));
|
||||||
fail_unless (count == TEST_VOLUME_COUNT);
|
fail_unless (count == TEST_VOLUME_COUNT);
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
if (mask & (1 << 8)) {
|
if (mask & (1 << 8)) {
|
||||||
gdouble gain;
|
gdouble gain;
|
||||||
|
|
||||||
fail_unless (gst_tag_list_get_double (tags, GST_TAG_TRACK_GAIN, &gain));
|
fail_unless (gst_tag_list_get_double (tags, GST_TAG_TRACK_GAIN, &gain));
|
||||||
fail_unless (gain == TEST_TRACK_GAIN);
|
fail_unless_sorta_equals_float (gain, TEST_TRACK_GAIN);
|
||||||
}
|
}
|
||||||
if (mask & (1 << 9)) {
|
if (mask & (1 << 9)) {
|
||||||
gdouble gain;
|
gdouble gain;
|
||||||
|
|
||||||
fail_unless (gst_tag_list_get_double (tags, GST_TAG_ALBUM_GAIN, &gain));
|
fail_unless (gst_tag_list_get_double (tags, GST_TAG_ALBUM_GAIN, &gain));
|
||||||
fail_unless (gain == TEST_ALBUM_GAIN);
|
fail_unless_sorta_equals_float (gain, TEST_ALBUM_GAIN);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (mask & (1 << 10)) {
|
if (mask & (1 << 10)) {
|
||||||
|
gdouble peak;
|
||||||
|
|
||||||
|
fail_unless (gst_tag_list_get_double (tags, GST_TAG_TRACK_PEAK, &peak));
|
||||||
|
fail_unless_sorta_equals_float (peak, TEST_TRACK_PEAK);
|
||||||
}
|
}
|
||||||
if (mask & (1 << 11)) {
|
if (mask & (1 << 11)) {
|
||||||
|
gdouble peak;
|
||||||
|
|
||||||
|
fail_unless (gst_tag_list_get_double (tags, GST_TAG_ALBUM_PEAK, &peak));
|
||||||
|
fail_unless_sorta_equals_float (peak, TEST_ALBUM_PEAK);
|
||||||
}
|
}
|
||||||
if (mask & (1 << 12)) {
|
if (mask & (1 << 12)) {
|
||||||
}
|
}
|
||||||
@ -269,6 +296,7 @@ got_buffer (GstElement * fakesink, GstBuffer * buf, GstPad * pad,
|
|||||||
memcpy (GST_BUFFER_DATA (*p_buf) + off, GST_BUFFER_DATA (buf), size);
|
memcpy (GST_BUFFER_DATA (*p_buf) + off, GST_BUFFER_DATA (buf), size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
demux_pad_added (GstElement * id3demux, GstPad * srcpad, GstBuffer ** p_outbuf)
|
demux_pad_added (GstElement * id3demux, GstPad * srcpad, GstBuffer ** p_outbuf)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user