|
1
|
1 #include "foobar2000-sdk-pch.h"
|
|
|
2 #include "replaygain.h"
|
|
|
3 #include "replaygain_scanner.h"
|
|
|
4
|
|
|
5 void t_replaygain_config::reset()
|
|
|
6 {
|
|
|
7 m_source_mode = source_mode_none;
|
|
|
8 m_processing_mode = processing_mode_none;
|
|
|
9 m_preamp_without_rg = 0;
|
|
|
10 m_preamp_with_rg = 0;
|
|
|
11 }
|
|
|
12
|
|
|
13 audio_sample t_replaygain_config::query_scale(const file_info & info) const
|
|
|
14 {
|
|
|
15 return query_scale(info.get_replaygain());
|
|
|
16 }
|
|
|
17
|
|
|
18 audio_sample t_replaygain_config::query_scale(const replaygain_info & info) const {
|
|
|
19 const audio_sample peak_margin = 1.0;//used to be 0.999 but it must not trigger on lossless
|
|
|
20
|
|
|
21 audio_sample peak = peak_margin;
|
|
|
22 audio_sample gain = 0;
|
|
|
23
|
|
|
24 bool have_rg_gain = false, have_rg_peak = false;
|
|
|
25
|
|
|
26 if (m_source_mode == source_mode_track || m_source_mode == source_mode_album)
|
|
|
27 {
|
|
|
28 if (m_source_mode == source_mode_track)
|
|
|
29 {
|
|
|
30 if (info.is_track_gain_present()) {gain = info.m_track_gain; have_rg_gain = true; }
|
|
|
31 else if (info.is_album_gain_present()) {gain = info.m_album_gain; have_rg_gain = true; }
|
|
|
32 if (info.is_track_peak_present()) {peak = info.m_track_peak; have_rg_peak = true; }
|
|
|
33 else if (info.is_album_peak_present()) {peak = info.m_album_peak; have_rg_peak = true; }
|
|
|
34 }
|
|
|
35 else
|
|
|
36 {
|
|
|
37 if (info.is_album_gain_present()) {gain = info.m_album_gain; have_rg_gain = true; }
|
|
|
38 else if (info.is_track_gain_present()) {gain = info.m_track_gain; have_rg_gain = true; }
|
|
|
39 if (info.is_album_peak_present()) {peak = info.m_album_peak; have_rg_peak = true; }
|
|
|
40 else if (info.is_track_peak_present()) {peak = info.m_track_peak; have_rg_peak = true; }
|
|
|
41 }
|
|
|
42 }
|
|
|
43
|
|
|
44 gain += have_rg_gain ? m_preamp_with_rg : m_preamp_without_rg;
|
|
|
45
|
|
|
46 audio_sample scale = 1.0;
|
|
|
47
|
|
|
48 if (m_processing_mode == processing_mode_gain || m_processing_mode == processing_mode_gain_and_peak)
|
|
|
49 {
|
|
|
50 scale *= (audio_sample) audio_math::gain_to_scale(gain);
|
|
|
51 }
|
|
|
52
|
|
|
53 if ((m_processing_mode == processing_mode_peak || m_processing_mode == processing_mode_gain_and_peak) && have_rg_peak)
|
|
|
54 {
|
|
|
55 if (scale * peak > peak_margin)
|
|
|
56 scale = (audio_sample)(peak_margin / peak);
|
|
|
57 }
|
|
|
58
|
|
|
59 return scale;
|
|
|
60 }
|
|
|
61
|
|
|
62 audio_sample t_replaygain_config::query_scale(const metadb_handle_ptr & p_object) const
|
|
|
63 {
|
|
|
64 return query_scale(p_object->get_async_info_ref()->info());
|
|
|
65 }
|
|
|
66
|
|
|
67 audio_sample replaygain_manager::core_settings_query_scale(const file_info & p_info)
|
|
|
68 {
|
|
|
69 t_replaygain_config temp;
|
|
|
70 get_core_settings(temp);
|
|
|
71 return temp.query_scale(p_info);
|
|
|
72 }
|
|
|
73
|
|
|
74 audio_sample replaygain_manager::core_settings_query_scale(const metadb_handle_ptr & info)
|
|
|
75 {
|
|
|
76 t_replaygain_config temp;
|
|
|
77 get_core_settings(temp);
|
|
|
78 return temp.query_scale(info);
|
|
|
79 }
|
|
|
80
|
|
|
81 //enum t_source_mode {source_mode_none,source_mode_track,source_mode_album};
|
|
|
82 //enum t_processing_mode {processing_mode_none,processing_mode_gain,processing_mode_gain_and_peak,processing_mode_peak};
|
|
|
83
|
|
|
84 static const char* querysign(int val) {
|
|
|
85 return val < 0 ? "-" : val>0 ? "+" : "\xc2\xb1";
|
|
|
86 }
|
|
|
87
|
|
|
88 static pfc::string_fixed_t<128> format_dbdelta(double p_val) {
|
|
|
89 pfc::string_fixed_t<128> ret;
|
|
|
90 int val = (int)pfc::rint32(p_val * 10);
|
|
|
91 ret << querysign(val) << (abs(val) / 10) << "." << (abs(val) % 10) << "dB";
|
|
|
92 return ret;
|
|
|
93 }
|
|
|
94 void t_replaygain_config::print_preamp(double val, pfc::string_base & out) {
|
|
|
95 out = format_dbdelta(val);
|
|
|
96 }
|
|
|
97 void t_replaygain_config::format_name(pfc::string_base & p_out) const
|
|
|
98 {
|
|
|
99 switch(m_processing_mode)
|
|
|
100 {
|
|
|
101 case processing_mode_none:
|
|
|
102 p_out = "None.";
|
|
|
103 break;
|
|
|
104 case processing_mode_gain:
|
|
|
105 switch(m_source_mode)
|
|
|
106 {
|
|
|
107 case source_mode_none:
|
|
|
108 if (m_preamp_without_rg == 0) p_out = "None.";
|
|
|
109 else p_out = PFC_string_formatter() << "Preamp : " << format_dbdelta(m_preamp_without_rg);
|
|
|
110 break;
|
|
|
111 case source_mode_track:
|
|
|
112 {
|
|
|
113 pfc::string_formatter fmt;
|
|
|
114 fmt << "Apply track gain";
|
|
|
115 if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
|
|
|
116 fmt << ".";
|
|
|
117 p_out = fmt;
|
|
|
118 }
|
|
|
119 break;
|
|
|
120 case source_mode_album:
|
|
|
121 {
|
|
|
122 pfc::string_formatter fmt;
|
|
|
123 fmt << "Apply album gain";
|
|
|
124 if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
|
|
|
125 fmt << ".";
|
|
|
126 p_out = fmt;
|
|
|
127 }
|
|
|
128 break;
|
|
|
129 };
|
|
|
130 break;
|
|
|
131 case processing_mode_gain_and_peak:
|
|
|
132 switch(m_source_mode)
|
|
|
133 {
|
|
|
134 case source_mode_none:
|
|
|
135 if (m_preamp_without_rg >= 0) p_out = "None.";
|
|
|
136 else p_out = PFC_string_formatter() << "Preamp : " << format_dbdelta(m_preamp_without_rg);
|
|
|
137 break;
|
|
|
138 case source_mode_track:
|
|
|
139 {
|
|
|
140 pfc::string_formatter fmt;
|
|
|
141 fmt << "Apply track gain";
|
|
|
142 if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
|
|
|
143 fmt << ", prevent clipping according to track peak.";
|
|
|
144 p_out = fmt;
|
|
|
145 }
|
|
|
146 break;
|
|
|
147 case source_mode_album:
|
|
|
148 {
|
|
|
149 pfc::string_formatter fmt;
|
|
|
150 fmt << "Apply album gain";
|
|
|
151 if (m_preamp_without_rg != 0 || m_preamp_with_rg != 0) fmt << ", with preamp";
|
|
|
152 fmt << ", prevent clipping according to album peak.";
|
|
|
153 p_out = fmt;
|
|
|
154 }
|
|
|
155 break;
|
|
|
156 };
|
|
|
157 break;
|
|
|
158 case processing_mode_peak:
|
|
|
159 switch(m_source_mode)
|
|
|
160 {
|
|
|
161 case source_mode_none:
|
|
|
162 p_out = "None.";
|
|
|
163 break;
|
|
|
164 case source_mode_track:
|
|
|
165 p_out = "Prevent clipping according to track peak.";
|
|
|
166 break;
|
|
|
167 case source_mode_album:
|
|
|
168 p_out = "Prevent clipping according to album peak.";
|
|
|
169 break;
|
|
|
170 };
|
|
|
171 break;
|
|
|
172 }
|
|
|
173 }
|
|
|
174
|
|
|
175 bool t_replaygain_config::is_active() const
|
|
|
176 {
|
|
|
177 switch(m_processing_mode)
|
|
|
178 {
|
|
|
179 case processing_mode_none:
|
|
|
180 return false;
|
|
|
181 case processing_mode_gain:
|
|
|
182 switch(m_source_mode)
|
|
|
183 {
|
|
|
184 case source_mode_none:
|
|
|
185 return m_preamp_without_rg != 0;
|
|
|
186 case source_mode_track:
|
|
|
187 return true;
|
|
|
188 case source_mode_album:
|
|
|
189 return true;
|
|
|
190 };
|
|
|
191 return false;
|
|
|
192 case processing_mode_gain_and_peak:
|
|
|
193 switch(m_source_mode)
|
|
|
194 {
|
|
|
195 case source_mode_none:
|
|
|
196 return m_preamp_without_rg < 0;
|
|
|
197 case source_mode_track:
|
|
|
198 return true;
|
|
|
199 case source_mode_album:
|
|
|
200 return true;
|
|
|
201 };
|
|
|
202 return false;
|
|
|
203 case processing_mode_peak:
|
|
|
204 switch(m_source_mode)
|
|
|
205 {
|
|
|
206 case source_mode_none:
|
|
|
207 return false;
|
|
|
208 case source_mode_track:
|
|
|
209 return true;
|
|
|
210 case source_mode_album:
|
|
|
211 return true;
|
|
|
212 };
|
|
|
213 return false;
|
|
|
214 default:
|
|
|
215 return false;
|
|
|
216 }
|
|
|
217 }
|
|
|
218
|
|
|
219
|
|
|
220 replaygain_scanner::ptr replaygain_scanner_entry::instantiate( uint32_t flags ) {
|
|
|
221 replaygain_scanner_entry_v2::ptr p2;
|
|
|
222 if ( p2 &= this ) return p2->instantiate( flags );
|
|
|
223 else return instantiate();
|
|
|
224 }
|
|
|
225
|
|
|
226 t_replaygain_config replaygain_manager::get_core_settings() {
|
|
|
227 t_replaygain_config cfg; get_core_settings(cfg); return cfg;
|
|
|
228 }
|