1 /* Copyright (C) 1999--2005 Chris Vaill
2 This file is part of normalize.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA*/
17
18 #define _POSIX_C_SOURCE 2
19
20 #include "config.h"
21
22 #include <stdio.h>
23 #if STDC_HEADERS
24 # include <stdlib.h>
25 # include <string.h>
26 #else
27 # if HAVE_STDLIB_H
28 # include <stdlib.h>
29 # endif
30 # if HAVE_STRING_H
31 # include <string.h>
32 # else
33 # ifndef HAVE_STRCHR
34 # define strchr index
35 # define strrchr rindex
36 # endif
37 # ifndef HAVE_MEMCPY
38 # define memcpy(d,s,n) bcopy((s),(d),(n))
39 # define memmove(d,s,n) bcopy((s),(d),(n))
40 # endif
41 # endif
42 #endif
43 #if HAVE_MATH_H
44 # include <math.h>
45 #endif
46 #if HAVE_ERRNO_H
47 # include <errno.h>
48 #endif
49
50 #ifdef ENABLE_NLS
51 # define _(msgid) gettext (msgid)
52 # include <libintl.h>
53 #else
54 # define _(msgid) (msgid)
55 #endif
56 #define N_(msgid) (msgid)
57
58 #include "common.h"
59 #include "nid3.h"
60
61 extern void progress_callback(char *prefix, float fraction_completed);
62 extern char *basename(char *path);
63 extern void *xmalloc(size_t size);
64
65 extern char *progname;
66 extern int verbose;
67 extern int id3_compat;
68 extern int id3_unsync;
69 extern double adjust_thresh;
70 extern int batch_mode; /* FIXME: remove */
71
72
73 /* adjust_id3() takes gain in decibels */
74 static int
adjust_id3(char * fname,double gain)75 adjust_id3(char *fname, double gain)
76 {
77 id3_t tag;
78 id3_frame_t fr;
79 int ret = 1;
80 char prefix_buf[18];
81
82 /* initialize progress meter */
83 if (verbose >= VERBOSE_PROGRESS) {
84 strncpy(prefix_buf, basename(fname), 17);
85 prefix_buf[17] = '\0';
86 progress_callback(prefix_buf, 0.0);
87 }
88
89 tag = id3_open(fname, ID3_RDWR);
90 if (tag == NULL)
91 return -1;
92
93 if (fabs(gain) < adjust_thresh) {
94 /* gain is below the threshold, so we should *remove* any RVA2 frame */
95 fr = id3_get_frame_by_id(tag, "RVA2");
96 if (fr)
97 id3_frame_delete(fr);
98 fr = id3_get_frame_by_id(tag, "XRVA");
99 if (fr)
100 id3_frame_delete(fr);
101 } else if (id3_rva_set(tag, "normalize", ID3_CHANNEL_MASTER, gain) == -1) {
102 fprintf(stderr, _("%s: error reading ID3 tag\n"), progname);
103 ret = -1;
104 goto error_close;
105 }
106
107 if (id3_compat) {
108 if (id3_set_version(tag, ID3_VERSION_2_3) == -1) {
109 fprintf(stderr, _("%s: error converting tag\n"), progname);
110 ret = -1;
111 }
112 } else {
113 if (id3_set_version(tag, ID3_VERSION_2_4) == -1) {
114 fprintf(stderr, _("%s: error converting tag\n"), progname);
115 ret = -1;
116 }
117 }
118 if (id3_unsync)
119 id3_set_unsync(tag, 1);
120 if (id3_write(tag) == -1) {
121 fprintf(stderr, _("%s: error writing ID3 tag\n"), progname);
122 ret = -1;
123 }
124
125 error_close:
126 id3_close(tag);
127
128 /* update progress meter */
129 if (verbose >= VERBOSE_PROGRESS)
130 progress_callback(prefix_buf, 1.0);
131
132 return ret;
133 }
134
135
136 /*
137 * input is read from read_fd and output is written to write_fd:
138 * filename is used only for messages.
139 *
140 * The si pointer gives the peaks so we know if limiting is needed
141 * or not. It may be specified as NULL if this information is not
142 * available.
143 */
144 int
apply_gain_mp3(char * filename,double gain,struct signal_info * si)145 apply_gain_mp3(char *filename, double gain, struct signal_info *si)
146 {
147 int ret = 0;
148
149 gain = FRACTODB(gain); /* we want the gain in dB */
150
151 if (!batch_mode && verbose >= VERBOSE_PROGRESS)
152 fprintf(stderr, _("Applying adjustment of %0.2fdB to %s...\n"),
153 gain, filename);
154
155 /* either set RVA2 id3 tag or adjust scale factors */
156 #if 0
157 ret = adjust_scalefactors(filename, gain);
158 #else
159 ret = adjust_id3(filename, gain);
160 #endif
161
162 return ret;
163 }
164